@agent-cards/commerce-sdk 0.11.0 → 0.13.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/README.md +123 -6
- package/dist/ack.d.ts +12 -0
- package/dist/ack.js +29 -1
- package/dist/action-links.d.ts +64 -0
- package/dist/action-links.js +77 -0
- package/dist/browser.d.ts +106 -0
- package/dist/browser.js +118 -0
- package/dist/buy-tool.d.ts +119 -16
- package/dist/buy-tool.js +466 -33
- package/dist/client.d.ts +51 -1
- package/dist/client.js +79 -7
- package/dist/definition.js +24 -2
- package/dist/index.d.ts +6 -5
- package/dist/index.js +5 -4
- package/dist/message.d.ts +4 -1
- package/dist/messages.d.ts +9 -9
- package/dist/messages.js +6 -6
- package/dist/model-view.d.ts +49 -0
- package/dist/model-view.js +81 -4
- package/dist/shopper-message.d.ts +15 -0
- package/dist/shopper-message.js +11 -0
- package/package.json +5 -1
package/dist/browser.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@agent-cards/commerce-sdk/browser`: the part of the package that runs in the shopper's browser.
|
|
3
|
+
* It imports no Node module, so any bundler takes it.
|
|
4
|
+
*
|
|
5
|
+
* `actionWindows` opens each step the shopper takes outside the chat (adding a card, signing in to a
|
|
6
|
+
* store, approving a payment) in a pop-up window over the chat, and closes it the moment the shopper
|
|
7
|
+
* message that ends the step arrives. On a phone, where a browser opens the pop-up as a tab, it
|
|
8
|
+
* closes that tab the same way.
|
|
9
|
+
*/
|
|
10
|
+
import { actionLinkId, actionLinkOutcome, isActionLink } from './action-links.js';
|
|
11
|
+
export { ACTION_LINK_ENDINGS, ACTION_LINK_KINDS, actionLinkId, actionLinkOutcome, isActionLink, } from './action-links.js';
|
|
12
|
+
const DEFAULT_WIDTH = 480;
|
|
13
|
+
const DEFAULT_HEIGHT = 760;
|
|
14
|
+
const DEFAULT_POLL_MS = 500;
|
|
15
|
+
/** `width=…,height=…,left=…,top=…` for a pop-up centered over the opener, kept on its screen. */
|
|
16
|
+
function featuresFor(win, width, height) {
|
|
17
|
+
const availWidth = win.screen?.availWidth ?? width;
|
|
18
|
+
const availHeight = win.screen?.availHeight ?? height;
|
|
19
|
+
const w = Math.max(320, Math.min(width, availWidth));
|
|
20
|
+
const h = Math.max(400, Math.min(height, availHeight));
|
|
21
|
+
const left = Math.max(0, Math.round((win.screenX ?? 0) + ((win.outerWidth ?? w) - w) / 2));
|
|
22
|
+
const top = Math.max(0, Math.round((win.screenY ?? 0) + ((win.outerHeight ?? h) - h) / 2));
|
|
23
|
+
return `popup=yes,width=${w},height=${h},left=${left},top=${top}`;
|
|
24
|
+
}
|
|
25
|
+
const view = (t) => t.step;
|
|
26
|
+
/**
|
|
27
|
+
* Opens each step outside the chat in a pop-up and closes it when the step ends. One per chat page.
|
|
28
|
+
* The pop-up keeps its opener, deliberately: a window opened with `noopener` hands back no handle,
|
|
29
|
+
* so the chat could neither close it nor tell when the shopper closed it.
|
|
30
|
+
*/
|
|
31
|
+
export function actionWindows(options = {}) {
|
|
32
|
+
const open = new Map();
|
|
33
|
+
let timer = null;
|
|
34
|
+
const win = () => options.window ?? (globalThis.window ?? null);
|
|
35
|
+
const stopIfIdle = () => {
|
|
36
|
+
if (open.size === 0 && timer !== null) {
|
|
37
|
+
win()?.clearInterval(timer);
|
|
38
|
+
timer = null;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const poll = () => {
|
|
42
|
+
for (const [id, tracked] of open) {
|
|
43
|
+
if (!tracked.popup.closed)
|
|
44
|
+
continue;
|
|
45
|
+
open.delete(id);
|
|
46
|
+
tracked.step.open = false;
|
|
47
|
+
options.onClosed?.(view(tracked));
|
|
48
|
+
}
|
|
49
|
+
stopIfIdle();
|
|
50
|
+
};
|
|
51
|
+
const idOf = (link) => link.id ?? actionLinkId(link);
|
|
52
|
+
return {
|
|
53
|
+
open(link) {
|
|
54
|
+
if (!isActionLink(link))
|
|
55
|
+
return null;
|
|
56
|
+
const w = win();
|
|
57
|
+
if (!w)
|
|
58
|
+
return null;
|
|
59
|
+
const id = idOf(link);
|
|
60
|
+
const known = open.get(id);
|
|
61
|
+
if (known && !known.popup.closed) {
|
|
62
|
+
known.popup.focus();
|
|
63
|
+
return view(known);
|
|
64
|
+
}
|
|
65
|
+
let popup = null;
|
|
66
|
+
try {
|
|
67
|
+
// A window named for the step: tapping the link again reaches the same window, never a second one.
|
|
68
|
+
popup = w.open(link.url, `agentcard_${id}`, featuresFor(w, options.width ?? DEFAULT_WIDTH, options.height ?? DEFAULT_HEIGHT));
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
popup = null;
|
|
72
|
+
}
|
|
73
|
+
if (!popup)
|
|
74
|
+
return null;
|
|
75
|
+
const tracked = { step: { id, kind: link.kind, url: link.url, store: link.store ?? null, open: true }, popup };
|
|
76
|
+
open.set(id, tracked);
|
|
77
|
+
try {
|
|
78
|
+
popup.focus();
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
/* a browser that refuses focus still shows the window */
|
|
82
|
+
}
|
|
83
|
+
timer ??= w.setInterval(poll, options.pollMs ?? DEFAULT_POLL_MS);
|
|
84
|
+
return view(tracked);
|
|
85
|
+
},
|
|
86
|
+
settle(message) {
|
|
87
|
+
const ended = [];
|
|
88
|
+
for (const [id, tracked] of open) {
|
|
89
|
+
const outcome = actionLinkOutcome(tracked.step, message);
|
|
90
|
+
if (!outcome)
|
|
91
|
+
continue;
|
|
92
|
+
open.delete(id);
|
|
93
|
+
tracked.step.open = false;
|
|
94
|
+
try {
|
|
95
|
+
tracked.popup.close();
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
/* already gone */
|
|
99
|
+
}
|
|
100
|
+
ended.push({ step: view(tracked), outcome });
|
|
101
|
+
}
|
|
102
|
+
stopIfIdle();
|
|
103
|
+
for (const { step, outcome } of ended)
|
|
104
|
+
options.onEnded?.(step, outcome);
|
|
105
|
+
return ended;
|
|
106
|
+
},
|
|
107
|
+
get(link) {
|
|
108
|
+
if (!isActionLink(link))
|
|
109
|
+
return null;
|
|
110
|
+
const tracked = open.get(idOf(link));
|
|
111
|
+
return tracked && !tracked.popup.closed ? view(tracked) : null;
|
|
112
|
+
},
|
|
113
|
+
dispose() {
|
|
114
|
+
open.clear();
|
|
115
|
+
stopIfIdle();
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
package/dist/buy-tool.d.ts
CHANGED
|
@@ -31,11 +31,11 @@
|
|
|
31
31
|
* messages and links as one sequence, in the order they happened, and spaces
|
|
32
32
|
* the messages like someone texting.
|
|
33
33
|
*/
|
|
34
|
-
import { AgentcardClient, type BuyCart, type BuyFlightItinerary, type BuyDeliveryAddress, type BuyNextAction, type BuyPick, type BuyProgress, type BuyStorePick, type BuyTurn, type FetchLike } from './client.js';
|
|
34
|
+
import { AgentcardClient, type BuyCart, type BuyCartBuilding, type BuyFlightItinerary, type BuyDeliveryAddress, type BuyNextAction, type BuyPick, type BuyProgress, type BuyStorePick, type BuyTurn, type FetchLike } from './client.js';
|
|
35
35
|
import { type BuyToolDefinition, type BuyToolInput, type BuyToolInputSchema, type BuyToolStandardSchema, type OpenAIBuyTool } from './definition.js';
|
|
36
36
|
import { type BuyToolModelView } from './model-view.js';
|
|
37
37
|
import { type MessagePace, type MessageStream } from './messages.js';
|
|
38
|
-
import type
|
|
38
|
+
import { type ShopperMessage } from './shopper-message.js';
|
|
39
39
|
/**
|
|
40
40
|
* Where the purchase stands:
|
|
41
41
|
* - `needs_input`: Agentcard asks the shopper something, or shows a cart.
|
|
@@ -51,13 +51,21 @@ export type BuyToolStatus = 'needs_input' | 'needs_card' | 'approval_sent' | 'pl
|
|
|
51
51
|
* card. `approval`: the page where they approve this purchase. `store_login`:
|
|
52
52
|
* the page where they sign in to the store named in `store`, before Agentcard
|
|
53
53
|
* can buy there. `product`: a product's page at its store, with its `title`,
|
|
54
|
-
* `price`, `productId` and `
|
|
54
|
+
* `price`, `productId`, `imageUrl` and `images`. The page is `url`; `productId` holds no link.
|
|
55
55
|
* A flight option is a `product` link too, with a null `url`, since a flight has no page.
|
|
56
56
|
* `store`: a store's page at the merchant, for a store the shopper can pick, with
|
|
57
57
|
* its name in `title`, `storeId`, `etaMinutes` and `imageUrl`.
|
|
58
58
|
*/
|
|
59
59
|
export interface BuyToolLink {
|
|
60
60
|
kind: 'vault' | 'approval' | 'store_login' | 'product' | 'store';
|
|
61
|
+
/**
|
|
62
|
+
* On a `vault`, `approval` or `store_login` link, a step the shopper takes outside the chat: a stable
|
|
63
|
+
* id for the link (`actionLinkId`), the same each time the same link is handed over, with no part of
|
|
64
|
+
* the URL in it. `actionLinkOutcome(link, message)` says whether a shopper message ended the step,
|
|
65
|
+
* and `actionWindows` from `@agent-cards/commerce-sdk/browser` opens it in a pop-up that closes then.
|
|
66
|
+
* Absent on product and store links.
|
|
67
|
+
*/
|
|
68
|
+
id?: string;
|
|
61
69
|
/**
|
|
62
70
|
* The page the link opens. Null only on a product link for a product with no page at a store, a
|
|
63
71
|
* flight option: show its card with no link to open, and let `productId` pick it.
|
|
@@ -65,11 +73,19 @@ export interface BuyToolLink {
|
|
|
65
73
|
url: string | null;
|
|
66
74
|
/** When the link stops working, as an ISO 8601 timestamp, or null when Agentcard did not say. Always null on a product link. */
|
|
67
75
|
expiresAt: string | null;
|
|
68
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* On a store login link: the store's name, or null when Agentcard named none. On an approval link:
|
|
78
|
+
* the store whose cart it approves, when the answer names the cart.
|
|
79
|
+
*/
|
|
69
80
|
store?: string | null;
|
|
70
81
|
/** On a product link: the product's name. */
|
|
71
82
|
title?: string;
|
|
72
|
-
/**
|
|
83
|
+
/**
|
|
84
|
+
* On a product link: what taking the product does, so a button can say it. `reserve` is a table the
|
|
85
|
+
* shopper reserves, `book` a flight, room, class or ticket they book, and `buy` anything they buy.
|
|
86
|
+
*/
|
|
87
|
+
action?: BuyToolProductAction;
|
|
88
|
+
/** On a product link: the price as the shopper reads it, such as `$12.99`, or `from $10.69` for a product priced by a size or another required choice, or null when Agentcard named none. */
|
|
73
89
|
price?: string | null;
|
|
74
90
|
/**
|
|
75
91
|
* On a product link: Agentcard's id for the product, with no link in it. It is the `product_id` the
|
|
@@ -82,6 +98,11 @@ export interface BuyToolLink {
|
|
|
82
98
|
* the merchant. Null when Agentcard sent none. Show it beside the title.
|
|
83
99
|
*/
|
|
84
100
|
imageUrl?: string | null;
|
|
101
|
+
/**
|
|
102
|
+
* On a product link: every photo of the product, `imageUrl` first, at most eight; one entry for a product
|
|
103
|
+
* with one photo and none for a product with none. Show the others as thumbnails that swap the main picture.
|
|
104
|
+
*/
|
|
105
|
+
images?: string[];
|
|
85
106
|
/**
|
|
86
107
|
* On a store link: Agentcard's id for the store, with no link in it. It is the `store_id` the model
|
|
87
108
|
* reads for the same store, and the tool takes it as `store_id`, so a "Order here" button can hand it
|
|
@@ -106,17 +127,27 @@ export interface BuyToolStore {
|
|
|
106
127
|
linkSent: boolean;
|
|
107
128
|
}
|
|
108
129
|
/** A product the last search found. */
|
|
130
|
+
/** What taking a product does: `reserve` a table, `book` a flight, room, class or ticket, `buy` anything else. */
|
|
131
|
+
export type BuyToolProductAction = 'buy' | 'reserve' | 'book';
|
|
132
|
+
/** The action a product of `merchant` takes (BuyToolProductAction). */
|
|
133
|
+
export declare function productAction(merchant: string | null | undefined): BuyToolProductAction;
|
|
109
134
|
export interface BuyToolProduct {
|
|
110
135
|
flight?: BuyFlightItinerary;
|
|
136
|
+
/** What taking it does: `reserve` a table, `book` a flight, room, class or ticket, `buy` anything else. */
|
|
137
|
+
action: BuyToolProductAction;
|
|
111
138
|
id: string;
|
|
112
139
|
/** Agentcard's link-free id for the product, which the model passes as `product_id` when the shopper picks it; null from an older API. */
|
|
113
140
|
ref: string | null;
|
|
114
141
|
name: string;
|
|
115
142
|
/** The price in the minor unit of `currency`. */
|
|
116
143
|
priceCents: number | null;
|
|
144
|
+
/** True when `priceCents` is the lowest price of a product priced by a required choice, which reads `from $10.69`. */
|
|
145
|
+
priceFrom?: true;
|
|
117
146
|
/** The ISO 4217 code the store prices the product in, or null when Agentcard sent none. */
|
|
118
147
|
currency: string | null;
|
|
119
148
|
imageUrl: string | null;
|
|
149
|
+
/** Every photo of the product, `imageUrl` first, at most eight; empty when it has none. */
|
|
150
|
+
images: string[];
|
|
120
151
|
store: string | null;
|
|
121
152
|
/** The product's page at its store, or null when Agentcard sent none. */
|
|
122
153
|
url: string | null;
|
|
@@ -165,12 +196,17 @@ export interface BuyToolResult {
|
|
|
165
196
|
next_action: BuyNextAction | null;
|
|
166
197
|
/** The product the model's `product_id` picked, by its catalog id, and whether the cart now holds it; null when the call picked none. */
|
|
167
198
|
pick: BuyPick | null;
|
|
168
|
-
/** The stores the reply presents to choose from, at most
|
|
199
|
+
/** The stores the reply presents to choose from, at most eight, in the order the reply names them; empty when it presents none. */
|
|
169
200
|
stores: BuyToolStore[];
|
|
170
201
|
/** The store the model's `store_id` picked, or the shopper's `the second one` did, and whether Agentcard selected it; null when none was picked. */
|
|
171
202
|
store_pick: BuyStorePick | null;
|
|
172
203
|
/** Every cart hash in this answer. */
|
|
173
204
|
hashes: string[];
|
|
205
|
+
/**
|
|
206
|
+
* The cart the store's checkout is still building after this answer, or null: its cart and total reach the shopper as a
|
|
207
|
+
* message from Agentcard, and only the shopper's yes to that total confirms it.
|
|
208
|
+
*/
|
|
209
|
+
cart_building?: BuyCartBuilding | null;
|
|
174
210
|
/** Agentcard's answer as it came: the purchase answer, or the body of the refusal. */
|
|
175
211
|
envelope: Record<string, unknown>;
|
|
176
212
|
}
|
|
@@ -265,6 +301,13 @@ export interface BuyToolOptions {
|
|
|
265
301
|
* outside the first three.
|
|
266
302
|
*/
|
|
267
303
|
earlyCards?: boolean;
|
|
304
|
+
/**
|
|
305
|
+
* `true` sets `turn.replyAsWritten` on every turn this tool opens, unless the turn says otherwise:
|
|
306
|
+
* Agentcard's reply, when an answer only asks the shopper something (`replyAsWritten`). Show it as
|
|
307
|
+
* the turn's answer and skip the model call that would reword it. Off by default, so your model
|
|
308
|
+
* writes every answer.
|
|
309
|
+
*/
|
|
310
|
+
replyAsWritten?: boolean;
|
|
268
311
|
}
|
|
269
312
|
/**
|
|
270
313
|
* The buy tool, in the shape every agent framework takes, because their field
|
|
@@ -338,6 +381,26 @@ export interface BuyTool {
|
|
|
338
381
|
* built with.
|
|
339
382
|
*/
|
|
340
383
|
turn(shopperText: string, options?: BuyToolTurnOptions): BuyToolTurn;
|
|
384
|
+
/**
|
|
385
|
+
* Opens the turn your agent takes on its own once the shopper finished a step outside the chat, such
|
|
386
|
+
* as saving a card or signing in to the store: a message whose `advances` is true. Pass it to your
|
|
387
|
+
* model as you pass `buy.turn`, with `turn.messages(history)` as the messages, and the model's answer
|
|
388
|
+
* is the shopper's next message, the step after the one they took, so they never have to say "ok"
|
|
389
|
+
* or "done" first. Post that answer in place of `message.text`, which the shopper then never reads.
|
|
390
|
+
*
|
|
391
|
+
* The turn moves the purchase only up to the shopper's own decision. Its calls never reach Agentcard
|
|
392
|
+
* with an ask, so nothing in it can place an order, confirm a cart or charge a card for the shopper.
|
|
393
|
+
* Each call reads where the purchase stands and answers with the next step: the card link, or the
|
|
394
|
+
* cart and the ask for the shopper's yes. The one exception is the yes the shopper already gave in the
|
|
395
|
+
* chat for this exact cart, when that confirm stopped for the step they just finished: it goes in for
|
|
396
|
+
* that cart's hash alone, and Agentcard refuses it if the cart changed.
|
|
397
|
+
*
|
|
398
|
+
* Returns null when there is no next step to take: a message whose `advances` is false, a message
|
|
399
|
+
* for another shopper or one whose link closed, a message this tool already took a turn for, and a
|
|
400
|
+
* message that arrives while a call for the shopper's own message is still running, since that
|
|
401
|
+
* call's answer tells the model where the purchase stands. Post `message.text` then, as before.
|
|
402
|
+
*/
|
|
403
|
+
nextStep(message: ShopperMessage, options?: BuyToolTurnOptions): BuyToolTurn | null;
|
|
341
404
|
}
|
|
342
405
|
/**
|
|
343
406
|
* One thing a turn hands the shopper: a message, such as the instant reply or a paragraph your model
|
|
@@ -356,21 +419,34 @@ export interface BuyToolTurnOptions {
|
|
|
356
419
|
* Hears everything the turn hands the shopper, one item at a time and in the order it happened: the
|
|
357
420
|
* instant reply and each message your model writes through `turn.messageStream()` or `turn.say()` as
|
|
358
421
|
* `text` items, and each link as a `link` item. Show each item below the one before it, and the chat
|
|
359
|
-
* reads in the order it happened: a search's cards, then the model's words about them.
|
|
422
|
+
* reads in the order it happened: a search's cards, then the model's words about them. A step link
|
|
423
|
+
* (`vault`, `approval`, `store_login`) is the one exception: it waits for the message that asks for
|
|
424
|
+
* it, and goes out right after that message, so the shopper reads the ask, then taps. Each item
|
|
360
425
|
* waits for the one before it to settle. With `onItem`, the turn hands no link to a `sendLink` and
|
|
361
426
|
* no instant reply to an `onWorking`, the tool's included: pass `onItem`, or those, to the turn.
|
|
362
427
|
*/
|
|
363
428
|
onItem?: (item: BuyToolTurnItem) => void | Promise<void>;
|
|
364
429
|
/**
|
|
365
|
-
* With `onItem`:
|
|
366
|
-
*
|
|
367
|
-
*
|
|
368
|
-
*
|
|
369
|
-
* milliseconds for a message.
|
|
430
|
+
* With `onItem` or `onMessage`: how the turn's messages are spaced. Default `false`: each message goes
|
|
431
|
+
* out the moment it is ready. `true` spaces them like someone texting: a message waits until
|
|
432
|
+
* `typingDelay` of it has passed since the item before it went out, and time the model spent writing
|
|
433
|
+
* counts toward the pause. A function returns the pause in milliseconds for a message. Links never wait.
|
|
370
434
|
*/
|
|
371
435
|
pace?: MessagePace;
|
|
372
|
-
/**
|
|
436
|
+
/**
|
|
437
|
+
* `true` sets `turn.replyAsWritten` when an answer only asks the shopper something; `false` leaves it
|
|
438
|
+
* null, so your model rewords every answer. Default: the tool's `replyAsWritten`.
|
|
439
|
+
*/
|
|
440
|
+
replyAsWritten?: boolean;
|
|
441
|
+
/** With `onItem` or `onMessage`: hears `true` when the pause before a message starts and `false` the moment that message goes out, for a typing indicator. */
|
|
373
442
|
onTyping?: (typing: boolean) => void;
|
|
443
|
+
/**
|
|
444
|
+
* Without `onItem`: hears each message your model writes through `turn.messageStream()` or
|
|
445
|
+
* `turn.say()`, paced by `pace`, in the same order as the links `sendLink` hears. Write the model's
|
|
446
|
+
* text through the turn, and a step link (`vault`, `approval`, `store_login`) reaches `sendLink`
|
|
447
|
+
* after the message that asks for it, never before.
|
|
448
|
+
*/
|
|
449
|
+
onMessage?: (message: string) => void | Promise<void>;
|
|
374
450
|
/**
|
|
375
451
|
* Delivers a link of this turn to the shopper, as the tool's `sendLink` does. Each call waits for it.
|
|
376
452
|
* Without one, `turn.links` still takes each link, and the model reads that it went out, so return
|
|
@@ -392,7 +468,15 @@ export interface BuyToolTurnOptions {
|
|
|
392
468
|
* belong to this turn alone. `ack`, `links` and `results` are read-only, and JSON leaves them out, so a
|
|
393
469
|
* tool runner that sends the tool to its API sends the same fields as before.
|
|
394
470
|
*/
|
|
395
|
-
export interface BuyToolTurn extends Omit<BuyTool, 'instantAck' | 'instantReaction' | 'turn'> {
|
|
471
|
+
export interface BuyToolTurn extends Omit<BuyTool, 'instantAck' | 'instantReaction' | 'turn' | 'nextStep'> {
|
|
472
|
+
/** For a turn `buy.nextStep` opened, the message whose step the shopper finished; null for a turn of a shopper message. */
|
|
473
|
+
readonly event: ShopperMessage | null;
|
|
474
|
+
/**
|
|
475
|
+
* For a turn `buy.nextStep` opened that your agent could not finish: call it before you post `message.text` instead.
|
|
476
|
+
* The message's text then reaches later turns as words the shopper read (`agentcard.delivered`), and a later
|
|
477
|
+
* `buy.nextStep` for the same event opens a turn again, as on a webhook's redelivery. Does nothing on another turn.
|
|
478
|
+
*/
|
|
479
|
+
release(): void;
|
|
396
480
|
/** The instant reply this turn sent to `onWorking` when it opened, or null when it sent none, as with a reaction. */
|
|
397
481
|
readonly ack: string | null;
|
|
398
482
|
/** The reaction this turn put on the shopper's message, `👀`, when it opened or once a call ran slow, or null while it put none or when `onReaction` threw. */
|
|
@@ -422,6 +506,15 @@ export interface BuyToolTurn extends Omit<BuyTool, 'instantAck' | 'instantReacti
|
|
|
422
506
|
readonly links: BuyToolLink[];
|
|
423
507
|
/** The whole answer of each call this turn made, in the order the calls returned. Each read returns a new array. */
|
|
424
508
|
readonly results: BuyToolResult[];
|
|
509
|
+
/**
|
|
510
|
+
* With `replyAsWritten` on: Agentcard's reply when the turn's last answer only asks the shopper
|
|
511
|
+
* something, such as a product list, a size or a cart's total and the ask for their yes, with every
|
|
512
|
+
* link taken out. Read it after the tool runs. When it is set, show it with `say()` and end the turn
|
|
513
|
+
* without calling your model again: the reply already says what the model would. Null when the option
|
|
514
|
+
* is off, before any call, after an answer your model has to word, and after a line the tool wrote
|
|
515
|
+
* itself for your model, such as the note that the cart changed or a `nextStep` turn's ask for the yes.
|
|
516
|
+
*/
|
|
517
|
+
readonly replyAsWritten: string | null;
|
|
425
518
|
/**
|
|
426
519
|
* Every message and link the turn handed over, in the order they went out: the instant reply, each
|
|
427
520
|
* link, and each message written through `messageStream()` or `say()`. An item its send threw on is
|
|
@@ -431,10 +524,14 @@ export interface BuyToolTurn extends Omit<BuyTool, 'instantAck' | 'instantReacti
|
|
|
431
524
|
/**
|
|
432
525
|
* A message stream whose messages become this turn's `text` items, after the items before them, as
|
|
433
526
|
* `messageStream` cuts them: push your model's text as it streams, then `end` it. Start one for each
|
|
434
|
-
* model message. With `onItem`, the turn spaces them by its `pace`.
|
|
527
|
+
* model message. With `onItem`, the turn spaces them by its `pace`. `end` resolves once the messages and the step links
|
|
528
|
+
* held for them went out, and rejects with the first that failed to send.
|
|
435
529
|
*/
|
|
436
530
|
messageStream(): MessageStream;
|
|
437
|
-
/**
|
|
531
|
+
/**
|
|
532
|
+
* Cuts a whole text into messages, as `toMessages` does, and hands each one over as a `text` item. Resolves once every
|
|
533
|
+
* one, and every step link held for it, went out, and rejects with the first that failed to send.
|
|
534
|
+
*/
|
|
438
535
|
say(text: string): Promise<void>;
|
|
439
536
|
}
|
|
440
537
|
/** A message in the one shape the Anthropic, OpenAI and Vercel AI SDK message lists all take. */
|
|
@@ -452,6 +549,12 @@ export type BuyToolTurnMessage = {
|
|
|
452
549
|
* or an OpenAI Responses item, they come as an assistant message of their own.
|
|
453
550
|
*/
|
|
454
551
|
export declare function turnMessages<M extends object>(history: readonly M[] | null | undefined, told: readonly string[], shopperText: string): Array<M | BuyToolTurnMessage>;
|
|
552
|
+
/**
|
|
553
|
+
* The words a `nextStep` turn hands the model as the user's message: the event, marked as no one's
|
|
554
|
+
* typing, and the instruction to take the next step now in one short message, without the filler of
|
|
555
|
+
* a step announced and a question about what comes next.
|
|
556
|
+
*/
|
|
557
|
+
export declare function nextStepPrompt(message: ShopperMessage): string;
|
|
455
558
|
/** Shared with the merchant monitor so link eligibility uses the tool's product mapping. */
|
|
456
559
|
export declare function productsOf(turn: BuyTurn): BuyToolProduct[];
|
|
457
560
|
/**
|