@useago/sdk 0.3.4 → 0.4.1

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.
Files changed (41) hide show
  1. package/dist/AgoClient-B6PsfMeg.cjs +6 -0
  2. package/dist/{AgoClient-DF7M2WAz.js → AgoClient-BerJvssl.js} +235 -219
  3. package/dist/angular.cjs +1 -1
  4. package/dist/angular.d.cts +12 -0
  5. package/dist/angular.d.ts +12 -0
  6. package/dist/angular.js +1 -1
  7. package/dist/createConversationSession-CLZvxyuu.js +58 -0
  8. package/dist/createConversationSession-D3K5Gf1k.cjs +1 -0
  9. package/dist/createFormCollector-CD1rqRG4.js +208 -0
  10. package/dist/createFormCollector-D1FfiSgA.cjs +1 -0
  11. package/dist/createMockClient-DMFGIOtc.cjs +1 -0
  12. package/dist/{createMockClient-C50gjV0b.js → createMockClient-tVsApEAh.js} +1 -0
  13. package/dist/devtools.cjs +4 -4
  14. package/dist/devtools.d.cts +16 -26
  15. package/dist/devtools.d.ts +16 -26
  16. package/dist/devtools.js +35 -35
  17. package/dist/helpers.cjs +1 -1
  18. package/dist/helpers.js +1 -1
  19. package/dist/index.cjs +1 -1
  20. package/dist/index.d.cts +102 -1
  21. package/dist/index.d.ts +102 -1
  22. package/dist/index.js +44 -42
  23. package/dist/react.cjs +1 -1
  24. package/dist/react.d.cts +20 -0
  25. package/dist/react.d.ts +20 -0
  26. package/dist/react.js +4 -4
  27. package/dist/vue.cjs +1 -1
  28. package/dist/vue.d.cts +12 -0
  29. package/dist/vue.d.ts +12 -0
  30. package/dist/vue.js +1 -1
  31. package/dist/widget.cjs +1 -1
  32. package/dist/widget.d.cts +99 -0
  33. package/dist/widget.d.ts +99 -0
  34. package/dist/widget.js +170 -150
  35. package/package.json +58 -15
  36. package/dist/AgoClient-bjN-z2ZQ.cjs +0 -6
  37. package/dist/createFormCollector-ClzHfaBd.js +0 -185
  38. package/dist/createFormCollector-H4Me_2uj.cjs +0 -1
  39. package/dist/createMockClient-DQvFFWnc.cjs +0 -1
  40. /package/dist/{functions-CWSRi3xv.js → functions-C1-5vadY.js} +0 -0
  41. /package/dist/{functions-BH1X5kas.cjs → functions-DsmzgHjC.cjs} +0 -0
package/dist/helpers.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a, c as s, d as t, f as e, i as r, l as i, m as l, o as m, p as c, r as g, s as h, t as n, u as p } from "./functions-CWSRi3xv.js";
1
+ import { a, c as s, d as t, f as e, i as r, l as i, m as l, o as m, p as c, r as g, s as h, t as n, u as p } from "./functions-C1-5vadY.js";
2
2
  export {
3
3
  n as copyToClipboard,
4
4
  g as getLocalStorage,
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./AgoClient-bjN-z2ZQ.cjs"),p=require("./createFormCollector-H4Me_2uj.cjs"),A=require("./createMockClient-DQvFFWnc.cjs"),g=require("./functions-BH1X5kas.cjs");function h(e){return e}function C(e,o){return e.on("message:complete",o),()=>e.off("message:complete",o)}function E(e,o){return e.on("message:chunk",o),()=>e.off("message:chunk",o)}function y(e,o){return e.on("message:start",o),()=>e.off("message:start",o)}function S(e,o){return e.on("message:error",o),()=>e.off("message:error",o)}function b(e,o){return e.on("toolCall:received",o),()=>e.off("toolCall:received",o)}function M(e,o){return e.on("function:invoke",o),()=>e.off("function:invoke",o)}async function*k(e,o,l){const n=[];let r=null,a=!1;const c=s=>{n.push(s),r?.()},f=s=>c({type:"start",data:s}),t=s=>c({type:"chunk",data:s}),u=s=>{c({type:"complete",data:s}),a=!0,r?.()},m=s=>{c({type:"error",data:s}),a=!0,r?.()},d=s=>c({type:"toolCall",data:s});e.on("message:start",f),e.on("message:chunk",t),e.on("message:complete",u),e.on("message:error",m),e.on("toolCall:received",d),e.sendMessage(o,l).catch(()=>{a=!0,r?.()});try{for(;!a||n.length>0;)n.length>0?yield n.shift():(await new Promise(s=>{r=s}),r=null)}finally{e.off("message:start",f),e.off("message:chunk",t),e.off("message:complete",u),e.off("message:error",m),e.off("toolCall:received",d)}}function w(e){let o,l,n,r,a,c;if(typeof window<"u"&&window.AGO){const t=window.AGO;o=t.basepath,l=t.widgetId,n=t.agent||t.defaultAgent,r=t.permission,a=t.email,c=t.jwt}if(typeof document<"u"){const t=u=>document.querySelector(`meta[name="${u}"]`)?.getAttribute("content")||void 0;o=o||t("ago-base-url"),l=l||t("ago-widget-id"),n=n||t("ago-agent")||t("ago-agent-id"),r=r||t("ago-permission"),a=a||t("ago-user-email")}if(typeof document<"u"){const t=[document.body,...Array.from(document.querySelectorAll("script[data-ago-base-url]"))].filter(Boolean);for(const u of t)u&&(o=o||u.getAttribute("data-ago-base-url")||void 0,l=l||u.getAttribute("data-ago-widget-id")||void 0,n=n||u.getAttribute("data-ago-agent")||u.getAttribute("data-ago-agent-id")||void 0,r=r||u.getAttribute("data-ago-permission")||void 0,a=a||u.getAttribute("data-ago-user-email")||void 0)}o=e?.baseUrl||o,l=e?.widgetId||l,n=e?.agent||e?.defaultAgentId||n,r=e?.permission||r,a=e?.userEmail||a,c=e?.userJwt||c;const f=e?.debug;return o?{baseUrl:o,widgetId:l,agent:n,permission:r,userEmail:a,userJwt:c,debug:f}:null}function v(e){const o=w(e);if(!o)throw new Error('createAgo(): could not detect AGO configuration. Set window.AGO, add <meta name="ago-base-url">, or pass { baseUrl } explicitly.');return new i.AgoClient(o)}function F(e,o){return{...e,handler:o}}exports.AgoApiError=i.AgoApiError;exports.AgoClient=i.AgoClient;exports.AgoError=i.AgoError;exports.AgoFunctionError=i.AgoFunctionError;exports.AgoNetworkError=i.AgoNetworkError;exports.AgoStreamError=i.AgoStreamError;exports.ClientContextRegistry=i.ClientContextRegistry;exports.EventEmitter=i.EventEmitter;exports.FunctionRegistry=i.FunctionRegistry;exports.SSEHandler=i.SSEHandler;exports.autoDetectConfig=w;exports.copyToClipboard=g.copyToClipboard;exports.createAgo=v;exports.createFormCollector=p.createFormCollector;exports.createMessageStream=k;exports.createMockClient=A.createMockClient;exports.createStore=p.createStore;exports.defineFunction=h;exports.getLocalStorage=g.getLocalStorage;exports.getUserLocation=g.getUserLocation;exports.highlightElement=g.highlightElement;exports.isStreamNetworkError=i.isStreamNetworkError;exports.logger=i.logger;exports.onFunctionInvoke=M;exports.onMessage=C;exports.onMessageChunk=E;exports.onMessageError=S;exports.onMessageStart=y;exports.onToolCall=b;exports.openUrl=g.openUrl;exports.scrollToElement=g.scrollToElement;exports.setLocalStorage=g.setLocalStorage;exports.setTheme=g.setTheme;exports.showConfirmDialog=g.showConfirmDialog;exports.showNotification=g.showNotification;exports.showToast=g.showToast;exports.submitForm=g.submitForm;exports.trackEvent=g.trackEvent;exports.withHandler=F;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./AgoClient-B6PsfMeg.cjs"),p=require("./createFormCollector-D1FfiSgA.cjs"),A=require("./createConversationSession-D3K5Gf1k.cjs"),C=require("./createMockClient-DMFGIOtc.cjs"),g=require("./functions-DsmzgHjC.cjs");function h(e){return e}function E(e,o){return e.on("message:complete",o),()=>e.off("message:complete",o)}function S(e,o){return e.on("message:chunk",o),()=>e.off("message:chunk",o)}function y(e,o){return e.on("message:start",o),()=>e.off("message:start",o)}function b(e,o){return e.on("message:error",o),()=>e.off("message:error",o)}function v(e,o){return e.on("toolCall:received",o),()=>e.off("toolCall:received",o)}function M(e,o){return e.on("function:invoke",o),()=>e.off("function:invoke",o)}async function*k(e,o,l){const n=[];let r=null,a=!1;const c=s=>{n.push(s),r?.()},f=s=>c({type:"start",data:s}),t=s=>c({type:"chunk",data:s}),u=s=>{c({type:"complete",data:s}),a=!0,r?.()},m=s=>{c({type:"error",data:s}),a=!0,r?.()},d=s=>c({type:"toolCall",data:s});e.on("message:start",f),e.on("message:chunk",t),e.on("message:complete",u),e.on("message:error",m),e.on("toolCall:received",d),e.sendMessage(o,l).catch(()=>{a=!0,r?.()});try{for(;!a||n.length>0;)n.length>0?yield n.shift():(await new Promise(s=>{r=s}),r=null)}finally{e.off("message:start",f),e.off("message:chunk",t),e.off("message:complete",u),e.off("message:error",m),e.off("toolCall:received",d)}}function w(e){let o,l,n,r,a,c;if(typeof window<"u"&&window.AGO){const t=window.AGO;o=t.basepath,l=t.widgetId,n=t.agent||t.defaultAgent,r=t.permission,a=t.email,c=t.jwt}if(typeof document<"u"){const t=u=>document.querySelector(`meta[name="${u}"]`)?.getAttribute("content")||void 0;o=o||t("ago-base-url"),l=l||t("ago-widget-id"),n=n||t("ago-agent")||t("ago-agent-id"),r=r||t("ago-permission"),a=a||t("ago-user-email")}if(typeof document<"u"){const t=[document.body,...Array.from(document.querySelectorAll("script[data-ago-base-url]"))].filter(Boolean);for(const u of t)u&&(o=o||u.getAttribute("data-ago-base-url")||void 0,l=l||u.getAttribute("data-ago-widget-id")||void 0,n=n||u.getAttribute("data-ago-agent")||u.getAttribute("data-ago-agent-id")||void 0,r=r||u.getAttribute("data-ago-permission")||void 0,a=a||u.getAttribute("data-ago-user-email")||void 0)}o=e?.baseUrl||o,l=e?.widgetId||l,n=e?.agent||e?.defaultAgentId||n,r=e?.permission||r,a=e?.userEmail||a,c=e?.userJwt||c;const f=e?.debug;return o?{baseUrl:o,widgetId:l,agent:n,permission:r,userEmail:a,userJwt:c,debug:f}:null}function q(e){const o=w(e);if(!o)throw new Error('createAgo(): could not detect AGO configuration. Set window.AGO, add <meta name="ago-base-url">, or pass { baseUrl } explicitly.');return new i.AgoClient(o)}function F(e,o){return{...e,handler:o}}exports.AgoApiError=i.AgoApiError;exports.AgoClient=i.AgoClient;exports.AgoError=i.AgoError;exports.AgoFunctionError=i.AgoFunctionError;exports.AgoNetworkError=i.AgoNetworkError;exports.AgoStreamError=i.AgoStreamError;exports.ClientContextRegistry=i.ClientContextRegistry;exports.EventEmitter=i.EventEmitter;exports.FunctionRegistry=i.FunctionRegistry;exports.SSEHandler=i.SSEHandler;exports.autoDetectConfig=w;exports.copyToClipboard=g.copyToClipboard;exports.createAgo=q;exports.createConversationSession=A.createConversationSession;exports.createFormCollector=p.createFormCollector;exports.createMessageStream=k;exports.createMockClient=C.createMockClient;exports.createStore=p.createStore;exports.defineFunction=h;exports.getLocalStorage=g.getLocalStorage;exports.getUserLocation=g.getUserLocation;exports.highlightElement=g.highlightElement;exports.isStreamNetworkError=i.isStreamNetworkError;exports.logger=i.logger;exports.onFunctionInvoke=M;exports.onMessage=E;exports.onMessageChunk=S;exports.onMessageError=b;exports.onMessageStart=y;exports.onToolCall=v;exports.openUrl=g.openUrl;exports.scrollToElement=g.scrollToElement;exports.setLocalStorage=g.setLocalStorage;exports.setTheme=g.setTheme;exports.showConfirmDialog=g.showConfirmDialog;exports.showNotification=g.showNotification;exports.showToast=g.showToast;exports.submitForm=g.submitForm;exports.trackEvent=g.trackEvent;exports.withHandler=F;
package/dist/index.d.cts CHANGED
@@ -42,6 +42,12 @@ export declare class AgoClient {
42
42
  * Get a specific conversation with messages
43
43
  */
44
44
  getConversation(conversationId: string): Promise<Conversation>;
45
+ /**
46
+ * Map the backend's snake_case `tool_call_data` entries onto the camelCase
47
+ * {@link ToolCallData} shape used everywhere else in the SDK. Mirrors
48
+ * `SSEHandler.parseToolCall` so persisted and streamed tool calls match.
49
+ */
50
+ private static mapPersistedToolCalls;
45
51
  /**
46
52
  * Get messages for a conversation
47
53
  */
@@ -212,6 +218,12 @@ export declare interface AgoClientEvents {
212
218
  conversationId?: string;
213
219
  messageId?: string;
214
220
  };
221
+ /**
222
+ * A full conversation was loaded from the server (e.g. after a page reload).
223
+ * Carries the messages and their persisted tool calls so stateful helpers —
224
+ * notably `createFormCollector` — can replay them to restore their state.
225
+ */
226
+ "conversation:loaded": Conversation;
215
227
  "toolCall:received": ToolCallData;
216
228
  "toolCall:form": ToolCallData;
217
229
  "function:invoke": ClientFunctionInvocation;
@@ -498,6 +510,60 @@ export declare interface Conversation {
498
510
  messages?: AgoMessage[];
499
511
  }
500
512
 
513
+ export declare interface ConversationSession {
514
+ /**
515
+ * The stable widget id identifying this visitor. Generated once and persisted
516
+ * forever, so a returning visitor keeps the same id (and therefore the same
517
+ * server-side conversation history) across reloads.
518
+ */
519
+ readonly widgetId: string;
520
+ /**
521
+ * The last active thread id, decided **entirely on the front** so a reload costs
522
+ * no backend round-trip. Returns `null` when there is no cached thread, when its
523
+ * last message time is unknown, or when it has been idle longer than `ttlMs`.
524
+ */
525
+ getLastActiveThread(): string | null;
526
+ /**
527
+ * Record (and refresh) the active thread together with the time of its last
528
+ * message — call it once per turn. The `lastMessageAt` drives the sliding TTL;
529
+ * omit it and the thread won't be resumed (no time → not displayed).
530
+ */
531
+ setActiveThread(conversationId: string, lastMessageAt?: Date | number): void;
532
+ /** Forget the cached thread — e.g. on "new chat". */
533
+ clear(): void;
534
+ /** The resolved storage key holding the widget id — handy for debugging. */
535
+ readonly key: string;
536
+ }
537
+
538
+ export declare interface ConversationSessionOptions {
539
+ /**
540
+ * Storage backend. Defaults to `localStorage`, degrading to an in-memory store
541
+ * when storage is unavailable (SSR / disabled). Pass `sessionStorage` for a
542
+ * tab-scoped session, or any `{ getItem, setItem }` for a custom backend.
543
+ */
544
+ storage?: StorageLike;
545
+ /**
546
+ * Storage key for the widget id. Default `"ago_widget_id"` — the same key the
547
+ * HTTP client reads, so the visitor's id is shared across the SDK.
548
+ */
549
+ key?: string;
550
+ /**
551
+ * Explicit widget id to adopt (and persist) instead of reading or generating
552
+ * one — e.g. when the host app already has a stable visitor identifier.
553
+ */
554
+ widgetId?: string;
555
+ /** Storage key for the cached last active thread. Default `"ago_last_thread"`. */
556
+ threadKey?: string;
557
+ /**
558
+ * Maximum idle age of a thread to still resume it, in milliseconds, compared
559
+ * against the recorded time of its last message. Checked entirely on the front
560
+ * (no backend call): a thread idle longer than this — or one with no recorded
561
+ * last-message time — is not resumed (`getLastActiveThread` returns `null`).
562
+ * Default 2h. Pass `Infinity` to never expire.
563
+ */
564
+ ttlMs?: number;
565
+ }
566
+
501
567
  /**
502
568
  * Copy text to clipboard.
503
569
  */
@@ -529,6 +595,33 @@ export declare const copyToClipboard: ClientFunctionDefinition;
529
595
  */
530
596
  export declare function createAgo(overrides?: Partial<AgoConfig>): AgoClient;
531
597
 
598
+ /**
599
+ * Identify a returning visitor with a single, stable widget id — the same model as
600
+ * the frontend's `getOrGenerateWidgetId` — and resume their last active thread.
601
+ *
602
+ * There is no per-agent conversation id: the widget id is the identity, and the last
603
+ * active thread (its id + the time of its last message) is cached locally so resuming
604
+ * is a pure front-side decision — **no backend call** just to know whether the thread
605
+ * is still fresh. A thread idle longer than `ttlMs` (default 2h, sliding — refreshed
606
+ * by `setActiveThread`), or one with no recorded last-message time, is not resumed.
607
+ *
608
+ * ```ts
609
+ * const session = createConversationSession();
610
+ *
611
+ * // resume on load (front-only — no request):
612
+ * const conversationId = session.getLastActiveThread() ?? undefined;
613
+ *
614
+ * // record the thread once a turn completes:
615
+ * session.setActiveThread(reply.conversationId, reply.createdAt);
616
+ *
617
+ * session.clear(); // forget it — e.g. a "new chat" button
618
+ * ```
619
+ *
620
+ * Persistence is opt-in by storage backend: it defaults to `localStorage`, but pass
621
+ * `sessionStorage` for a tab-scoped session or omit storage in environments without it.
622
+ */
623
+ export declare function createConversationSession(options?: ConversationSessionOptions): ConversationSession;
624
+
532
625
  /**
533
626
  * Wire one schema into a conversational form: an observable store, an
534
627
  * `update_<name>` client function the agent calls to fill fields, a dynamic-context
@@ -675,6 +768,14 @@ export declare interface FormCollector<V = Record<string, unknown>> {
675
768
  contextProvider: () => ContextEntry;
676
769
  /** Register the functions + dynamic context on a client. Returns an uninstall fn. */
677
770
  install: (client: AgoClient) => () => void;
771
+ /**
772
+ * Rebuild the state by replaying the persisted `update_<name>` / `submit_<name>`
773
+ * tool-call arguments of a loaded conversation — restoring what the agent had
774
+ * collected after a page reload. Replays from the initial values, so it is
775
+ * idempotent. `install` wires this to the client's `conversation:loaded` event,
776
+ * so a custom front rarely needs to call it directly.
777
+ */
778
+ hydrate: (toolCalls: readonly ToolCallData[]) => void;
678
779
  /** Submit the form now (e.g. from a UI button). Blocks until required fields are filled. */
679
780
  submit: () => Promise<FormSubmitResult>;
680
781
  getValues: () => Partial<V>;
@@ -1054,7 +1155,7 @@ declare interface SSEHandlerCallbacks {
1054
1155
  }
1055
1156
 
1056
1157
  /** The slice of the Web Storage API that {@link createStore} relies on. */
1057
- declare type StorageLike = Pick<Storage, "getItem" | "setItem">;
1158
+ export declare type StorageLike = Pick<Storage, "getItem" | "setItem">;
1058
1159
 
1059
1160
  /**
1060
1161
  * A minimal observable store: one value, synchronous subscriptions, and
package/dist/index.d.ts CHANGED
@@ -42,6 +42,12 @@ export declare class AgoClient {
42
42
  * Get a specific conversation with messages
43
43
  */
44
44
  getConversation(conversationId: string): Promise<Conversation>;
45
+ /**
46
+ * Map the backend's snake_case `tool_call_data` entries onto the camelCase
47
+ * {@link ToolCallData} shape used everywhere else in the SDK. Mirrors
48
+ * `SSEHandler.parseToolCall` so persisted and streamed tool calls match.
49
+ */
50
+ private static mapPersistedToolCalls;
45
51
  /**
46
52
  * Get messages for a conversation
47
53
  */
@@ -212,6 +218,12 @@ export declare interface AgoClientEvents {
212
218
  conversationId?: string;
213
219
  messageId?: string;
214
220
  };
221
+ /**
222
+ * A full conversation was loaded from the server (e.g. after a page reload).
223
+ * Carries the messages and their persisted tool calls so stateful helpers —
224
+ * notably `createFormCollector` — can replay them to restore their state.
225
+ */
226
+ "conversation:loaded": Conversation;
215
227
  "toolCall:received": ToolCallData;
216
228
  "toolCall:form": ToolCallData;
217
229
  "function:invoke": ClientFunctionInvocation;
@@ -498,6 +510,60 @@ export declare interface Conversation {
498
510
  messages?: AgoMessage[];
499
511
  }
500
512
 
513
+ export declare interface ConversationSession {
514
+ /**
515
+ * The stable widget id identifying this visitor. Generated once and persisted
516
+ * forever, so a returning visitor keeps the same id (and therefore the same
517
+ * server-side conversation history) across reloads.
518
+ */
519
+ readonly widgetId: string;
520
+ /**
521
+ * The last active thread id, decided **entirely on the front** so a reload costs
522
+ * no backend round-trip. Returns `null` when there is no cached thread, when its
523
+ * last message time is unknown, or when it has been idle longer than `ttlMs`.
524
+ */
525
+ getLastActiveThread(): string | null;
526
+ /**
527
+ * Record (and refresh) the active thread together with the time of its last
528
+ * message — call it once per turn. The `lastMessageAt` drives the sliding TTL;
529
+ * omit it and the thread won't be resumed (no time → not displayed).
530
+ */
531
+ setActiveThread(conversationId: string, lastMessageAt?: Date | number): void;
532
+ /** Forget the cached thread — e.g. on "new chat". */
533
+ clear(): void;
534
+ /** The resolved storage key holding the widget id — handy for debugging. */
535
+ readonly key: string;
536
+ }
537
+
538
+ export declare interface ConversationSessionOptions {
539
+ /**
540
+ * Storage backend. Defaults to `localStorage`, degrading to an in-memory store
541
+ * when storage is unavailable (SSR / disabled). Pass `sessionStorage` for a
542
+ * tab-scoped session, or any `{ getItem, setItem }` for a custom backend.
543
+ */
544
+ storage?: StorageLike;
545
+ /**
546
+ * Storage key for the widget id. Default `"ago_widget_id"` — the same key the
547
+ * HTTP client reads, so the visitor's id is shared across the SDK.
548
+ */
549
+ key?: string;
550
+ /**
551
+ * Explicit widget id to adopt (and persist) instead of reading or generating
552
+ * one — e.g. when the host app already has a stable visitor identifier.
553
+ */
554
+ widgetId?: string;
555
+ /** Storage key for the cached last active thread. Default `"ago_last_thread"`. */
556
+ threadKey?: string;
557
+ /**
558
+ * Maximum idle age of a thread to still resume it, in milliseconds, compared
559
+ * against the recorded time of its last message. Checked entirely on the front
560
+ * (no backend call): a thread idle longer than this — or one with no recorded
561
+ * last-message time — is not resumed (`getLastActiveThread` returns `null`).
562
+ * Default 2h. Pass `Infinity` to never expire.
563
+ */
564
+ ttlMs?: number;
565
+ }
566
+
501
567
  /**
502
568
  * Copy text to clipboard.
503
569
  */
@@ -529,6 +595,33 @@ export declare const copyToClipboard: ClientFunctionDefinition;
529
595
  */
530
596
  export declare function createAgo(overrides?: Partial<AgoConfig>): AgoClient;
531
597
 
598
+ /**
599
+ * Identify a returning visitor with a single, stable widget id — the same model as
600
+ * the frontend's `getOrGenerateWidgetId` — and resume their last active thread.
601
+ *
602
+ * There is no per-agent conversation id: the widget id is the identity, and the last
603
+ * active thread (its id + the time of its last message) is cached locally so resuming
604
+ * is a pure front-side decision — **no backend call** just to know whether the thread
605
+ * is still fresh. A thread idle longer than `ttlMs` (default 2h, sliding — refreshed
606
+ * by `setActiveThread`), or one with no recorded last-message time, is not resumed.
607
+ *
608
+ * ```ts
609
+ * const session = createConversationSession();
610
+ *
611
+ * // resume on load (front-only — no request):
612
+ * const conversationId = session.getLastActiveThread() ?? undefined;
613
+ *
614
+ * // record the thread once a turn completes:
615
+ * session.setActiveThread(reply.conversationId, reply.createdAt);
616
+ *
617
+ * session.clear(); // forget it — e.g. a "new chat" button
618
+ * ```
619
+ *
620
+ * Persistence is opt-in by storage backend: it defaults to `localStorage`, but pass
621
+ * `sessionStorage` for a tab-scoped session or omit storage in environments without it.
622
+ */
623
+ export declare function createConversationSession(options?: ConversationSessionOptions): ConversationSession;
624
+
532
625
  /**
533
626
  * Wire one schema into a conversational form: an observable store, an
534
627
  * `update_<name>` client function the agent calls to fill fields, a dynamic-context
@@ -675,6 +768,14 @@ export declare interface FormCollector<V = Record<string, unknown>> {
675
768
  contextProvider: () => ContextEntry;
676
769
  /** Register the functions + dynamic context on a client. Returns an uninstall fn. */
677
770
  install: (client: AgoClient) => () => void;
771
+ /**
772
+ * Rebuild the state by replaying the persisted `update_<name>` / `submit_<name>`
773
+ * tool-call arguments of a loaded conversation — restoring what the agent had
774
+ * collected after a page reload. Replays from the initial values, so it is
775
+ * idempotent. `install` wires this to the client's `conversation:loaded` event,
776
+ * so a custom front rarely needs to call it directly.
777
+ */
778
+ hydrate: (toolCalls: readonly ToolCallData[]) => void;
678
779
  /** Submit the form now (e.g. from a UI button). Blocks until required fields are filled. */
679
780
  submit: () => Promise<FormSubmitResult>;
680
781
  getValues: () => Partial<V>;
@@ -1054,7 +1155,7 @@ declare interface SSEHandlerCallbacks {
1054
1155
  }
1055
1156
 
1056
1157
  /** The slice of the Web Storage API that {@link createStore} relies on. */
1057
- declare type StorageLike = Pick<Storage, "getItem" | "setItem">;
1158
+ export declare type StorageLike = Pick<Storage, "getItem" | "setItem">;
1058
1159
 
1059
1160
  /**
1060
1161
  * A minimal observable store: one value, synchronous subscriptions, and
package/dist/index.js CHANGED
@@ -1,29 +1,30 @@
1
- import { a as w, c as h, d as A, f as y, i as C, l as E, n as b, o as S, r as v, s as k, t as d, u as M } from "./AgoClient-DF7M2WAz.js";
2
- import { n as T, t as I } from "./createFormCollector-ClzHfaBd.js";
3
- import { t as G } from "./createMockClient-C50gjV0b.js";
4
- import { a as q, c as x, d as L, f as N, i as D, l as H, m as J, o as R, p as j, r as B, s as P, t as $, u as z } from "./functions-CWSRi3xv.js";
5
- function K(e) {
1
+ import { a as w, c as h, d as A, f as y, i as C, l as E, n as b, o as S, r as v, s as k, t as d, u as M } from "./AgoClient-BerJvssl.js";
2
+ import { n as T, t as I } from "./createFormCollector-CD1rqRG4.js";
3
+ import { t as G } from "./createConversationSession-CLZvxyuu.js";
4
+ import { t as q } from "./createMockClient-tVsApEAh.js";
5
+ import { a as L, c as N, d as D, f as H, i as J, l as R, m as j, o as B, p as P, r as $, s as z, t as K, u as Q } from "./functions-C1-5vadY.js";
6
+ function V(e) {
6
7
  return e;
7
8
  }
8
- function Q(e, t) {
9
+ function W(e, t) {
9
10
  return e.on("message:complete", t), () => e.off("message:complete", t);
10
11
  }
11
- function V(e, t) {
12
+ function X(e, t) {
12
13
  return e.on("message:chunk", t), () => e.off("message:chunk", t);
13
14
  }
14
- function W(e, t) {
15
+ function Y(e, t) {
15
16
  return e.on("message:start", t), () => e.off("message:start", t);
16
17
  }
17
- function X(e, t) {
18
+ function Z(e, t) {
18
19
  return e.on("message:error", t), () => e.off("message:error", t);
19
20
  }
20
- function Y(e, t) {
21
+ function _(e, t) {
21
22
  return e.on("toolCall:received", t), () => e.off("toolCall:received", t);
22
23
  }
23
- function Z(e, t) {
24
+ function ee(e, t) {
24
25
  return e.on("function:invoke", t), () => e.off("function:invoke", t);
25
26
  }
26
- async function* _(e, t, g) {
27
+ async function* te(e, t, g) {
27
28
  const n = [];
28
29
  let r = null, a = !1;
29
30
  const u = (s) => {
@@ -39,16 +40,16 @@ async function* _(e, t, g) {
39
40
  type: "complete",
40
41
  data: s
41
42
  }), a = !0, r?.();
42
- }, l = (s) => {
43
+ }, m = (s) => {
43
44
  u({
44
45
  type: "error",
45
46
  data: s
46
47
  }), a = !0, r?.();
47
- }, m = (s) => u({
48
+ }, l = (s) => u({
48
49
  type: "toolCall",
49
50
  data: s
50
51
  });
51
- e.on("message:start", f), e.on("message:chunk", o), e.on("message:complete", i), e.on("message:error", l), e.on("toolCall:received", m), e.sendMessage(t, g).catch(() => {
52
+ e.on("message:start", f), e.on("message:chunk", o), e.on("message:complete", i), e.on("message:error", m), e.on("toolCall:received", l), e.sendMessage(t, g).catch(() => {
52
53
  a = !0, r?.();
53
54
  });
54
55
  try {
@@ -56,7 +57,7 @@ async function* _(e, t, g) {
56
57
  r = s;
57
58
  }), r = null);
58
59
  } finally {
59
- e.off("message:start", f), e.off("message:chunk", o), e.off("message:complete", i), e.off("message:error", l), e.off("toolCall:received", m);
60
+ e.off("message:start", f), e.off("message:chunk", o), e.off("message:complete", i), e.off("message:error", m), e.off("toolCall:received", l);
60
61
  }
61
62
  }
62
63
  function c(e) {
@@ -86,12 +87,12 @@ function c(e) {
86
87
  debug: f
87
88
  } : null;
88
89
  }
89
- function ee(e) {
90
+ function oe(e) {
90
91
  const t = c(e);
91
92
  if (!t) throw new Error('createAgo(): could not detect AGO configuration. Set window.AGO, add <meta name="ago-base-url">, or pass { baseUrl } explicitly.');
92
93
  return new d(t);
93
94
  }
94
- function te(e, t) {
95
+ function re(e, t) {
95
96
  return {
96
97
  ...e,
97
98
  handler: t
@@ -109,32 +110,33 @@ export {
109
110
  S as FunctionRegistry,
110
111
  v as SSEHandler,
111
112
  c as autoDetectConfig,
112
- $ as copyToClipboard,
113
- ee as createAgo,
113
+ K as copyToClipboard,
114
+ oe as createAgo,
115
+ G as createConversationSession,
114
116
  I as createFormCollector,
115
- _ as createMessageStream,
116
- G as createMockClient,
117
+ te as createMessageStream,
118
+ q as createMockClient,
117
119
  T as createStore,
118
- K as defineFunction,
119
- B as getLocalStorage,
120
- D as getUserLocation,
121
- q as highlightElement,
120
+ V as defineFunction,
121
+ $ as getLocalStorage,
122
+ J as getUserLocation,
123
+ L as highlightElement,
122
124
  C as isStreamNetworkError,
123
125
  k as logger,
124
- Z as onFunctionInvoke,
125
- Q as onMessage,
126
- V as onMessageChunk,
127
- X as onMessageError,
128
- W as onMessageStart,
129
- Y as onToolCall,
130
- R as openUrl,
131
- P as scrollToElement,
132
- x as setLocalStorage,
133
- H as setTheme,
134
- z as showConfirmDialog,
135
- L as showNotification,
136
- N as showToast,
137
- j as submitForm,
138
- J as trackEvent,
139
- te as withHandler
126
+ ee as onFunctionInvoke,
127
+ W as onMessage,
128
+ X as onMessageChunk,
129
+ Z as onMessageError,
130
+ Y as onMessageStart,
131
+ _ as onToolCall,
132
+ B as openUrl,
133
+ z as scrollToElement,
134
+ N as setLocalStorage,
135
+ R as setTheme,
136
+ Q as showConfirmDialog,
137
+ D as showNotification,
138
+ H as showToast,
139
+ P as submitForm,
140
+ j as trackEvent,
141
+ re as withHandler
140
142
  };