@agent-cards/commerce-sdk 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +38 -0
- package/README.md +320 -2
- package/dist/adapters.d.ts +35 -0
- package/dist/adapters.js +23 -0
- package/dist/buy-tool.d.ts +186 -0
- package/dist/buy-tool.js +619 -0
- package/dist/client.d.ts +272 -0
- package/dist/client.js +431 -0
- package/dist/definition.d.ts +100 -0
- package/dist/definition.js +104 -0
- package/dist/handler.d.ts +48 -0
- package/dist/handler.js +190 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +9 -0
- package/dist/message.d.ts +78 -0
- package/dist/message.js +76 -0
- package/dist/messages.d.ts +48 -0
- package/dist/messages.js +206 -0
- package/dist/model-view.d.ts +73 -0
- package/dist/model-view.js +111 -0
- package/dist/verify.d.ts +41 -0
- package/dist/verify.js +137 -0
- package/examples/anthropic.mjs +55 -0
- package/examples/openrouter.mjs +53 -0
- package/examples/walkthrough.mjs +97 -0
- package/package.json +41 -4
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/** The fetch the client calls: Node 18 and later have one built in. */
|
|
2
|
+
export type FetchLike = (url: string, init: {
|
|
3
|
+
method: string;
|
|
4
|
+
headers: Record<string, string>;
|
|
5
|
+
body?: string;
|
|
6
|
+
signal?: AbortSignal;
|
|
7
|
+
}) => Promise<{
|
|
8
|
+
status: number;
|
|
9
|
+
ok: boolean;
|
|
10
|
+
text(): Promise<string>;
|
|
11
|
+
}>;
|
|
12
|
+
export declare const DEFAULT_BASE_URL = "https://api.agentcard.sh";
|
|
13
|
+
/** The wait for one purchase turn: past Agentcard's own 110-second budget, so a slow turn answers `turn_timeout` rather than aborting here. */
|
|
14
|
+
export declare const BUY_TURN_TIMEOUT_MS = 130000;
|
|
15
|
+
/** A company's client credentials, or one shopper's own access token. */
|
|
16
|
+
export type AgentcardClientOptions = {
|
|
17
|
+
baseUrl?: string;
|
|
18
|
+
fetch?: FetchLike;
|
|
19
|
+
} & ({
|
|
20
|
+
clientId: string;
|
|
21
|
+
clientSecret: string;
|
|
22
|
+
accessToken?: undefined;
|
|
23
|
+
} | {
|
|
24
|
+
accessToken: string;
|
|
25
|
+
clientId?: undefined;
|
|
26
|
+
clientSecret?: undefined;
|
|
27
|
+
});
|
|
28
|
+
/** Who a call is for. A company names the shopper by its own id or by Agentcard's user id. Under a shopper's own token, leave both out. */
|
|
29
|
+
export interface Shopper {
|
|
30
|
+
externalUserId?: string;
|
|
31
|
+
userId?: string;
|
|
32
|
+
}
|
|
33
|
+
/** A delivery address the company already holds for the shopper; the cart is built for it and the shopper is asked for none of it. */
|
|
34
|
+
export interface BuyDeliveryAddress {
|
|
35
|
+
street: string;
|
|
36
|
+
city: string;
|
|
37
|
+
state: string;
|
|
38
|
+
zip: string;
|
|
39
|
+
address2?: string;
|
|
40
|
+
phone?: string;
|
|
41
|
+
name?: string;
|
|
42
|
+
country?: string;
|
|
43
|
+
can_leave_at_door?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/** One `POST /buy`, as sent. */
|
|
46
|
+
export interface BuyRequest {
|
|
47
|
+
ask?: string;
|
|
48
|
+
/** A cart hash from an earlier answer, or true for the cart Agentcard last answered with. */
|
|
49
|
+
confirm?: string | true;
|
|
50
|
+
/** Continue the shopper's newest open conversation instead of starting one. */
|
|
51
|
+
resume?: true;
|
|
52
|
+
/** Drop the cart on the table and start a new order. */
|
|
53
|
+
new_order?: true;
|
|
54
|
+
payment_source?: 'vault';
|
|
55
|
+
delivery_address?: BuyDeliveryAddress;
|
|
56
|
+
external_user_id?: string;
|
|
57
|
+
user_id?: string;
|
|
58
|
+
}
|
|
59
|
+
export type BuyStatus = 'needs_input' | 'needs_approval' | 'order_placed' | 'partially_placed' | 'declined';
|
|
60
|
+
export interface BuyStore {
|
|
61
|
+
id: string;
|
|
62
|
+
name?: string;
|
|
63
|
+
}
|
|
64
|
+
export interface BuyCartLine {
|
|
65
|
+
name: string;
|
|
66
|
+
qty: number;
|
|
67
|
+
priceCents?: number;
|
|
68
|
+
product_id: string | null;
|
|
69
|
+
/** The product's page at its store, as an http or https address, or null when Agentcard sent none. */
|
|
70
|
+
url: string | null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A cart as Agentcard answers it. `totalCents` is the all-in figure the shopper sees; `hash` is what a confirm names.
|
|
74
|
+
* Every amount is in the minor unit of `currency`, the store's ISO 4217 code.
|
|
75
|
+
*/
|
|
76
|
+
export interface BuyCart {
|
|
77
|
+
merchant: string;
|
|
78
|
+
merchant_name: string;
|
|
79
|
+
store: BuyStore | null;
|
|
80
|
+
items: BuyCartLine[];
|
|
81
|
+
serviceFeesCents: number;
|
|
82
|
+
tipCents: number;
|
|
83
|
+
totalCents: number;
|
|
84
|
+
/** The ISO 4217 code the store prices the cart in, or null when Agentcard sent none. */
|
|
85
|
+
currency: string | null;
|
|
86
|
+
approvedCeilingCents: number | null;
|
|
87
|
+
hash: string;
|
|
88
|
+
}
|
|
89
|
+
/** A product a search found. `priceCents` is in the minor unit of `currency`, the store's ISO 4217 code. */
|
|
90
|
+
/** Supplier facts only. Missing facts stay null; fare cabin does not establish segment cabins. */
|
|
91
|
+
export interface BuyFlightItinerary {
|
|
92
|
+
fareCabinClass?: string | null;
|
|
93
|
+
legs: Array<{
|
|
94
|
+
origin: string | null;
|
|
95
|
+
destination: string | null;
|
|
96
|
+
departureAt: string | null;
|
|
97
|
+
arrivalAt: string | null;
|
|
98
|
+
cabinClasses: Array<string | null>;
|
|
99
|
+
}>;
|
|
100
|
+
}
|
|
101
|
+
export interface BuyCatalogItem {
|
|
102
|
+
flight?: BuyFlightItinerary;
|
|
103
|
+
id: string;
|
|
104
|
+
name: string | null;
|
|
105
|
+
priceCents: number | null;
|
|
106
|
+
/** The ISO 4217 code the store prices the product in, or null when Agentcard sent none. */
|
|
107
|
+
currency: string | null;
|
|
108
|
+
image_url: string | null;
|
|
109
|
+
store: BuyStore | null;
|
|
110
|
+
/** The product's page at its store, as an http or https address, or null when Agentcard sent none. */
|
|
111
|
+
url: string | null;
|
|
112
|
+
}
|
|
113
|
+
/** The products the last search found. */
|
|
114
|
+
export interface BuyCatalog {
|
|
115
|
+
merchant: string;
|
|
116
|
+
merchant_name: string;
|
|
117
|
+
items: BuyCatalogItem[];
|
|
118
|
+
}
|
|
119
|
+
export interface BuyPaymentSource {
|
|
120
|
+
source: string;
|
|
121
|
+
brand: string | null;
|
|
122
|
+
last4: string | null;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The one thing the shopper does next, as Agentcard names it, in the order a purchase asks for them:
|
|
126
|
+
* `shipping_details` (a shipping address and phone), `guest_details` (a name, email and phone for a
|
|
127
|
+
* booking), `add_card` (a card in their Vault), `confirm` (their yes to the cart), `verification_code`
|
|
128
|
+
* (the code a booking texted them), then `approve` (the approval link). A value this version does
|
|
129
|
+
* not know reads as null.
|
|
130
|
+
*/
|
|
131
|
+
export type BuyNextAction = 'shipping_details' | 'guest_details' | 'add_card' | 'confirm' | 'verification_code' | 'approve';
|
|
132
|
+
/** One turn's answer, every field read for its type; a field an older API does not send reads as null. */
|
|
133
|
+
export interface BuyTurn {
|
|
134
|
+
conversation_id: string;
|
|
135
|
+
/** A status Agentcard adds later reads as `needs_input`. */
|
|
136
|
+
status: BuyStatus;
|
|
137
|
+
reply: string;
|
|
138
|
+
messages: string[];
|
|
139
|
+
cart: BuyCart | null;
|
|
140
|
+
carts: BuyCart[];
|
|
141
|
+
catalog: BuyCatalog | null;
|
|
142
|
+
order_id: string | null;
|
|
143
|
+
payment_source: BuyPaymentSource | null;
|
|
144
|
+
decline_code: string | null;
|
|
145
|
+
approval_url: string | null;
|
|
146
|
+
charge_status: string | null;
|
|
147
|
+
error_code: string | null;
|
|
148
|
+
authorization_id: string | null;
|
|
149
|
+
merchant_total_cents: number | null;
|
|
150
|
+
merchant_currency: string | null;
|
|
151
|
+
add_card_url: string | null;
|
|
152
|
+
add_card_expires_at: string | null;
|
|
153
|
+
placement_announced: boolean | null;
|
|
154
|
+
approval_expires_at: string | null;
|
|
155
|
+
approval_in_progress: boolean | null;
|
|
156
|
+
/** The one step the shopper takes next, or null when nothing waits on them or Agentcard named none. */
|
|
157
|
+
next_action: BuyNextAction | null;
|
|
158
|
+
/** The page where the shopper signs in to a store's own account before Agentcard can buy there. */
|
|
159
|
+
store_login_url: string | null;
|
|
160
|
+
store_login_expires_at: string | null;
|
|
161
|
+
/** The store that page signs in to. */
|
|
162
|
+
store_login_merchant_name: string | null;
|
|
163
|
+
/** The answer as Agentcard sent it. */
|
|
164
|
+
raw: Record<string, unknown>;
|
|
165
|
+
}
|
|
166
|
+
export interface BuyOrder {
|
|
167
|
+
order_id: string | null;
|
|
168
|
+
merchant: string;
|
|
169
|
+
merchant_name: string;
|
|
170
|
+
status: string;
|
|
171
|
+
total_cents: number;
|
|
172
|
+
placed_at: string | null;
|
|
173
|
+
}
|
|
174
|
+
export interface BuyLastCheckout {
|
|
175
|
+
at: string;
|
|
176
|
+
merchant: string;
|
|
177
|
+
merchant_name: string;
|
|
178
|
+
status: string;
|
|
179
|
+
code: string | null;
|
|
180
|
+
message: string | null;
|
|
181
|
+
order_id: string | null;
|
|
182
|
+
decline_code: string | null;
|
|
183
|
+
approval_url: string | null;
|
|
184
|
+
approval_expires_at: string | null;
|
|
185
|
+
placement_announced: boolean | null;
|
|
186
|
+
approval_in_progress: boolean | null;
|
|
187
|
+
/** The add-card link a checkout that found no card made, and when it stops working. */
|
|
188
|
+
add_card_url: string | null;
|
|
189
|
+
add_card_expires_at: string | null;
|
|
190
|
+
total_cents: number | null;
|
|
191
|
+
}
|
|
192
|
+
/** Where one conversation stands: whether a turn is running, the last checkout, the orders it placed, the carts on the table. */
|
|
193
|
+
export interface BuyConversation {
|
|
194
|
+
conversation_id: string;
|
|
195
|
+
status: 'open' | 'closed';
|
|
196
|
+
turn_in_progress: boolean;
|
|
197
|
+
last_checkout: BuyLastCheckout | null;
|
|
198
|
+
orders: BuyOrder[];
|
|
199
|
+
carts: BuyCart[];
|
|
200
|
+
raw: Record<string, unknown>;
|
|
201
|
+
}
|
|
202
|
+
/** A Vault link: the page where a shopper connects and adds a card. */
|
|
203
|
+
export interface VaultLink {
|
|
204
|
+
id: string;
|
|
205
|
+
url: string;
|
|
206
|
+
/** When the link stops working, as an ISO 8601 timestamp. */
|
|
207
|
+
expiresAt: string | null;
|
|
208
|
+
/** True when Agentcard returned a link it had already opened for this shopper. */
|
|
209
|
+
reused: boolean;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* A refusal, or a failure to reach Agentcard. `code` is the API's own
|
|
213
|
+
* (`user_not_connected`, `external_user_id_ambiguous`, `turn_in_progress`,
|
|
214
|
+
* `user_id_mismatch`), one read from the shape of the answer
|
|
215
|
+
* (`cart_changed`, `nothing_to_confirm`, `conversation_closed`,
|
|
216
|
+
* `conversation_not_found`), or the client's (`unreachable`, `timeout`,
|
|
217
|
+
* `oauth_failed`, `unauthorized`, `http_<status>`). `status` is 0 when
|
|
218
|
+
* Agentcard never answered.
|
|
219
|
+
*/
|
|
220
|
+
export declare class AgentcardApiError extends Error {
|
|
221
|
+
readonly status: number;
|
|
222
|
+
readonly code: string;
|
|
223
|
+
/** The error body as Agentcard sent it. */
|
|
224
|
+
readonly body: Record<string, unknown>;
|
|
225
|
+
readonly conversationId: string | null;
|
|
226
|
+
/** The carts as they stand, when the refusal names them: a changed cart's fresh hash is here. */
|
|
227
|
+
readonly carts: BuyCart[];
|
|
228
|
+
constructor(status: number, code: string, message: string, body?: Record<string, unknown>, cause?: unknown);
|
|
229
|
+
}
|
|
230
|
+
/** A turn as Agentcard answers it. */
|
|
231
|
+
export declare function turnOf(body: Record<string, unknown>): BuyTurn;
|
|
232
|
+
/** The client every shopper's buy tool shares. Build one per set of credentials and keep it. */
|
|
233
|
+
export declare class AgentcardClient {
|
|
234
|
+
readonly baseUrl: string;
|
|
235
|
+
private readonly fetchFn;
|
|
236
|
+
private readonly credentials;
|
|
237
|
+
private readonly shopperToken;
|
|
238
|
+
private token;
|
|
239
|
+
private inflight;
|
|
240
|
+
private learnedSandbox;
|
|
241
|
+
constructor(options: AgentcardClientOptions);
|
|
242
|
+
/** True when the client buys for many shoppers with a company's credentials; false under one shopper's own token. */
|
|
243
|
+
get company(): boolean;
|
|
244
|
+
/** True for a sandbox client, as the token exchange said; null until the first exchange, and under a shopper's token. */
|
|
245
|
+
get sandbox(): boolean | null;
|
|
246
|
+
/** The access token the client sends: the shopper's own, or the company's, exchanged once and renewed a minute before it expires. */
|
|
247
|
+
bearer(): Promise<string>;
|
|
248
|
+
/**
|
|
249
|
+
* One purchase turn, sent once with a 130-second wait. A turn is a model run
|
|
250
|
+
* against live stores, so a lost answer is never sent again: read the
|
|
251
|
+
* conversation instead. Only a 401 is sent again, once, with a fresh token,
|
|
252
|
+
* because Agentcard refused it before anything ran.
|
|
253
|
+
*/
|
|
254
|
+
buy(body: BuyRequest): Promise<BuyTurn>;
|
|
255
|
+
/** One read of a conversation: whether a turn is running, the last checkout, the orders it placed, the carts on the table. */
|
|
256
|
+
conversation(conversationId: string, who?: Shopper): Promise<BuyConversation>;
|
|
257
|
+
/**
|
|
258
|
+
* The Vault link a shopper opens to connect to your company and add a card.
|
|
259
|
+
* Agentcard returns the link it already opened for this shopper while that
|
|
260
|
+
* link has time left, so a shopper who asks twice gets one link. Sent once.
|
|
261
|
+
*/
|
|
262
|
+
mintVaultLink(input: {
|
|
263
|
+
externalUserId: string;
|
|
264
|
+
}): Promise<VaultLink>;
|
|
265
|
+
/** A company names the shopper exactly once; a shopper's own token already names them. */
|
|
266
|
+
private checkShopper;
|
|
267
|
+
private call;
|
|
268
|
+
private send;
|
|
269
|
+
/** After a 401: the token another call already renewed, or one new exchange, however many calls were refused at once. */
|
|
270
|
+
private renewAfter;
|
|
271
|
+
private exchange;
|
|
272
|
+
}
|