@useago/sdk 0.3.3 → 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 (40) 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-tVsApEAh.js +72 -0
  13. package/dist/devtools.cjs +26 -26
  14. package/dist/devtools.d.cts +16 -26
  15. package/dist/devtools.d.ts +16 -26
  16. package/dist/devtools.js +55 -55
  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 +46 -43
  23. package/dist/react.cjs +19 -19
  24. package/dist/react.d.cts +67 -8
  25. package/dist/react.d.ts +67 -8
  26. package/dist/react.js +1066 -1051
  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 -0
  32. package/dist/widget.d.cts +635 -0
  33. package/dist/widget.d.ts +635 -0
  34. package/dist/widget.js +418 -0
  35. package/package.json +58 -15
  36. package/dist/AgoClient-bjN-z2ZQ.cjs +0 -6
  37. package/dist/createMockClient-D6uVh-B9.js +0 -254
  38. package/dist/createMockClient-DecMEUcK.cjs +0 -1
  39. /package/dist/{functions-DdROP6Ui.js → functions-C1-5vadY.js} +0 -0
  40. /package/dist/{functions-Bz-1Bs3I.cjs → functions-DsmzgHjC.cjs} +0 -0
@@ -31,6 +31,12 @@ declare class AgoClient {
31
31
  * Get a specific conversation with messages
32
32
  */
33
33
  getConversation(conversationId: string): Promise<Conversation>;
34
+ /**
35
+ * Map the backend's snake_case `tool_call_data` entries onto the camelCase
36
+ * {@link ToolCallData} shape used everywhere else in the SDK. Mirrors
37
+ * `SSEHandler.parseToolCall` so persisted and streamed tool calls match.
38
+ */
39
+ private static mapPersistedToolCalls;
34
40
  /**
35
41
  * Get messages for a conversation
36
42
  */
@@ -201,6 +207,12 @@ declare interface AgoClientEvents {
201
207
  conversationId?: string;
202
208
  messageId?: string;
203
209
  };
210
+ /**
211
+ * A full conversation was loaded from the server (e.g. after a page reload).
212
+ * Carries the messages and their persisted tool calls so stateful helpers —
213
+ * notably `createFormCollector` — can replay them to restore their state.
214
+ */
215
+ "conversation:loaded": Conversation;
204
216
  "toolCall:received": ToolCallData;
205
217
  "toolCall:form": ToolCallData;
206
218
  "function:invoke": ClientFunctionInvocation;
@@ -350,13 +362,12 @@ declare interface Conversation {
350
362
 
351
363
  /** Options for {@link initDevPanel}. */
352
364
  export declare interface DevPanelOptions {
353
- /** The store whose state the panel renders live. */
354
- store: Store<unknown>;
355
365
  /**
356
- * Client to read registered functions from and listen to function events on.
357
- * Typed structurally so a mock client works too.
366
+ * The AGO client to debug. The panel lists its registered functions, logs its
367
+ * function events, and renders its live context snapshot
368
+ * (`client.getContextSnapshot()`)
358
369
  */
359
- client: Pick<AgoClient, "on" | "getRegisteredFunctions">;
370
+ client: Pick<AgoClient, "on" | "getRegisteredFunctions" | "getContextSnapshot">;
360
371
  /** Where to mount: a CSS selector, an Element, or `document.body` (default). */
361
372
  target?: string | Element;
362
373
  }
@@ -401,27 +412,6 @@ declare interface SendMessageOptions {
401
412
  files?: File[];
402
413
  }
403
414
 
404
- /**
405
- * A minimal observable store: one value, synchronous subscriptions, and
406
- * optional persistence via {@link PersistOptions} (localStorage by default).
407
- *
408
- * ```ts
409
- * const store = createStore({ count: 0 });
410
- * store.subscribe((state) => save(state));
411
- * store.set({ count: 1 }); // listeners fire synchronously
412
- *
413
- * const cart = createStore({ items: [] }, { key: "cart" }); // persisted
414
- * ```
415
- */
416
- declare interface Store<T> {
417
- /** Current state. */
418
- get(): T;
419
- /** Replace the state and notify subscribers synchronously. */
420
- set(next: T): void;
421
- /** Register a listener; returns a function that removes it. */
422
- subscribe(listener: (state: T) => void): () => void;
423
- }
424
-
425
415
  /**
426
416
  * Tool call data from SSE stream
427
417
  */
package/dist/devtools.js CHANGED
@@ -1,63 +1,63 @@
1
- var r, d, x = () => ({});
2
- function p() {
3
- r && (r.textContent = JSON.stringify(x(), null, 2));
1
+ var s, d, v = () => ({});
2
+ function c() {
3
+ s && (s.textContent = JSON.stringify(v(), null, 2));
4
4
  }
5
- function v(o, n) {
5
+ function p(a, o) {
6
6
  if (!d) return;
7
7
  const e = document.createElement("div");
8
- e.className = `dev-log-line dev-log-${n}`, e.textContent = `${(/* @__PURE__ */ new Date()).toLocaleTimeString()} ${o}`, d.appendChild(e), d.scrollTop = d.scrollHeight;
8
+ e.className = `dev-log-line dev-log-${o}`, e.textContent = `${(/* @__PURE__ */ new Date()).toLocaleTimeString()} ${a}`, d.appendChild(e), d.scrollTop = d.scrollHeight;
9
9
  }
10
- var u = "devPanelCollapsed";
11
- function s(o, n) {
12
- o.classList.toggle("collapsed", n);
13
- const e = o.querySelector(".dev-toggle");
14
- e && (e.textContent = n ? "▢" : "—", e.title = n ? "Expand dev tools" : "Collapse dev tools", e.setAttribute("aria-expanded", String(!n)));
10
+ var x = "ago_dev_panel_collapsed";
11
+ function i(a, o) {
12
+ a.classList.toggle("collapsed", o);
13
+ const e = a.querySelector(".dev-toggle");
14
+ e && (e.textContent = o ? "▢" : "—", e.title = o ? "Expand dev tools" : "Collapse dev tools", e.setAttribute("aria-expanded", String(!o)));
15
15
  try {
16
- localStorage.setItem(u, n ? "1" : "0");
16
+ localStorage.setItem(x, o ? "1" : "0");
17
17
  } catch {
18
18
  }
19
19
  }
20
- function m(o) {
21
- const { store: n, client: e, target: i } = o;
22
- x = n.get, b();
23
- const f = typeof i == "string" ? document.querySelector(i) : i instanceof Element ? i : document.body, t = document.createElement("aside");
24
- t.id = "dev-panel", (f ?? document.body).appendChild(t), t.innerHTML = `
20
+ function h(a) {
21
+ const { client: o, target: e } = a;
22
+ v = () => o.getContextSnapshot()?.entries ?? {}, f();
23
+ const u = typeof e == "string" ? document.querySelector(e) : e instanceof Element ? e : document.body, t = document.createElement("aside");
24
+ t.id = "ago-dev-panel", (u ?? document.body).appendChild(t), t.innerHTML = `
25
25
  <div class="dev-head">
26
26
  <span class="dev-badge">DEV</span>
27
27
  <span class="dev-title">DEV TOOLS · client-side function state — not for production</span>
28
28
  <button type="button" class="dev-toggle" aria-label="Toggle dev tools">—</button>
29
29
  </div>
30
30
  <div class="dev-body">
31
- <div class="dev-fns">Registered functions: <code>${(e.getRegisteredFunctions?.() ?? []).map((l) => l.name).join(", ") || "—"}</code></div>
31
+ <div class="dev-fns">Registered functions: <code>${(o.getRegisteredFunctions?.() ?? []).map((n) => n.name).join(", ") || "—"}</code></div>
32
32
  <div class="dev-section-label">JSON object (built by the agent)</div>
33
- <pre class="dev-state" id="dev-state"></pre>
33
+ <pre class="dev-state" id="ago-dev-state"></pre>
34
34
  <div class="dev-section-label">Function calls</div>
35
- <div class="dev-log" id="dev-log"></div>
35
+ <div class="dev-log" id="ago-dev-log"></div>
36
36
  </div>
37
- `, r = t.querySelector("#dev-state"), d = t.querySelector("#dev-log"), t.querySelector(".dev-toggle")?.addEventListener("click", (l) => {
38
- l.stopPropagation(), s(t, !t.classList.contains("collapsed"));
37
+ `, s = t.querySelector("#ago-dev-state"), d = t.querySelector("#ago-dev-log"), t.querySelector(".dev-toggle")?.addEventListener("click", (n) => {
38
+ n.stopPropagation(), i(t, !t.classList.contains("collapsed"));
39
39
  }), t.addEventListener("click", () => {
40
- t.classList.contains("collapsed") && s(t, !1);
40
+ t.classList.contains("collapsed") && i(t, !1);
41
41
  });
42
- let c = !1;
42
+ let r = !1;
43
43
  try {
44
- c = localStorage.getItem(u) === "1";
44
+ r = localStorage.getItem(x) === "1";
45
45
  } catch {
46
46
  }
47
- s(t, c), e.on("function:invoke", ({ functionName: l, arguments: a }) => {
48
- v(`→ ${l}(${JSON.stringify(a ?? {})})`, "invoke");
49
- }), e.on("function:result", ({ result: l, error: a }) => {
50
- v(a ? `✗ error: ${a}` : `← ${JSON.stringify(l)}`, a ? "error" : "result");
51
- }), n.subscribe(p), p();
47
+ i(t, r), o.on("function:invoke", ({ functionName: n, arguments: l }) => {
48
+ p(`→ ${n}(${JSON.stringify(l ?? {})})`, "invoke");
49
+ }), o.on("function:result", ({ result: n, error: l }) => {
50
+ p(l ? `✗ error: ${l}` : `← ${JSON.stringify(n)}`, l ? "error" : "result"), c();
51
+ }), c();
52
52
  }
53
- var g = "dev-panel-styles";
54
- function b() {
53
+ var g = "ago-dev-panel-styles";
54
+ function f() {
55
55
  if (document.getElementById(g)) return;
56
- const o = document.createElement("style");
57
- o.id = g, o.textContent = h, document.head.appendChild(o);
56
+ const a = document.createElement("style");
57
+ a.id = g, a.textContent = b, document.head.appendChild(a);
58
58
  }
59
- var h = `
60
- #dev-panel {
59
+ var b = `
60
+ #ago-dev-panel {
61
61
  position: fixed;
62
62
  top: 16px;
63
63
  right: 16px;
@@ -78,8 +78,8 @@ var h = `
78
78
  font-size: 12px;
79
79
  z-index: 1000;
80
80
  }
81
- #dev-panel .dev-head { display: flex; align-items: center; gap: 8px; }
82
- #dev-panel .dev-toggle {
81
+ #ago-dev-panel .dev-head { display: flex; align-items: center; gap: 8px; }
82
+ #ago-dev-panel .dev-toggle {
83
83
  margin-left: auto;
84
84
  flex: none;
85
85
  width: 22px;
@@ -95,19 +95,19 @@ var h = `
95
95
  line-height: 1;
96
96
  cursor: pointer;
97
97
  }
98
- #dev-panel .dev-toggle:hover { color: #d7e0e8; border-color: #3a4655; }
99
- #dev-panel .dev-body { display: flex; flex-direction: column; gap: 8px; }
98
+ #ago-dev-panel .dev-toggle:hover { color: #d7e0e8; border-color: #3a4655; }
99
+ #ago-dev-panel .dev-body { display: flex; flex-direction: column; gap: 8px; }
100
100
 
101
101
  /* Collapsed: shrink to a small clickable widget showing only the DEV badge. */
102
- #dev-panel.collapsed {
102
+ #ago-dev-panel.collapsed {
103
103
  width: auto;
104
104
  cursor: pointer;
105
105
  padding: 8px 10px;
106
106
  }
107
- #dev-panel.collapsed .dev-title,
108
- #dev-panel.collapsed .dev-body { display: none; }
109
- #dev-panel.collapsed .dev-toggle { margin-left: 6px; }
110
- #dev-panel .dev-badge {
107
+ #ago-dev-panel.collapsed .dev-title,
108
+ #ago-dev-panel.collapsed .dev-body { display: none; }
109
+ #ago-dev-panel.collapsed .dev-toggle { margin-left: 6px; }
110
+ #ago-dev-panel .dev-badge {
111
111
  background: #f59e0b;
112
112
  color: #1c1206;
113
113
  font-weight: 700;
@@ -116,17 +116,17 @@ var h = `
116
116
  padding: 2px 6px;
117
117
  border-radius: 5px;
118
118
  }
119
- #dev-panel .dev-title { color: #f59e0b; font-size: 11px; line-height: 1.3; }
120
- #dev-panel .dev-fns { color: #7c8a99; font-size: 11px; }
121
- #dev-panel .dev-fns code { color: #9ecbff; }
122
- #dev-panel .dev-section-label {
119
+ #ago-dev-panel .dev-title { color: #f59e0b; font-size: 11px; line-height: 1.3; }
120
+ #ago-dev-panel .dev-fns { color: #7c8a99; font-size: 11px; }
121
+ #ago-dev-panel .dev-fns code { color: #9ecbff; }
122
+ #ago-dev-panel .dev-section-label {
123
123
  color: #7c8a99;
124
124
  text-transform: uppercase;
125
125
  letter-spacing: .08em;
126
126
  font-size: 10px;
127
127
  margin-top: 4px;
128
128
  }
129
- #dev-panel .dev-state {
129
+ #ago-dev-panel .dev-state {
130
130
  margin: 0;
131
131
  padding: 8px;
132
132
  background: #060a0e;
@@ -136,7 +136,7 @@ var h = `
136
136
  white-space: pre;
137
137
  color: #c8e6c9;
138
138
  }
139
- #dev-panel .dev-log {
139
+ #ago-dev-panel .dev-log {
140
140
  display: flex;
141
141
  flex-direction: column;
142
142
  gap: 2px;
@@ -146,11 +146,11 @@ var h = `
146
146
  border-radius: 8px;
147
147
  padding: 6px 8px;
148
148
  }
149
- #dev-panel .dev-log-line { white-space: pre-wrap; word-break: break-word; line-height: 1.4; }
150
- #dev-panel .dev-log-invoke { color: #9ecbff; }
151
- #dev-panel .dev-log-result { color: #86efac; }
152
- #dev-panel .dev-log-error { color: #fca5a5; }
149
+ #ago-dev-panel .dev-log-line { white-space: pre-wrap; word-break: break-word; line-height: 1.4; }
150
+ #ago-dev-panel .dev-log-invoke { color: #9ecbff; }
151
+ #ago-dev-panel .dev-log-result { color: #86efac; }
152
+ #ago-dev-panel .dev-log-error { color: #fca5a5; }
153
153
  `;
154
154
  export {
155
- m as initDevPanel
155
+ h as initDevPanel
156
156
  };
package/dist/helpers.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./functions-Bz-1Bs3I.cjs");exports.copyToClipboard=o.copyToClipboard;exports.getLocalStorage=o.getLocalStorage;exports.getUserLocation=o.getUserLocation;exports.highlightElement=o.highlightElement;exports.openUrl=o.openUrl;exports.scrollToElement=o.scrollToElement;exports.setLocalStorage=o.setLocalStorage;exports.setTheme=o.setTheme;exports.showConfirmDialog=o.showConfirmDialog;exports.showNotification=o.showNotification;exports.showToast=o.showToast;exports.submitForm=o.submitForm;exports.trackEvent=o.trackEvent;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./functions-DsmzgHjC.cjs");exports.copyToClipboard=o.copyToClipboard;exports.getLocalStorage=o.getLocalStorage;exports.getUserLocation=o.getUserLocation;exports.highlightElement=o.highlightElement;exports.openUrl=o.openUrl;exports.scrollToElement=o.scrollToElement;exports.setLocalStorage=o.setLocalStorage;exports.setTheme=o.setTheme;exports.showConfirmDialog=o.showConfirmDialog;exports.showNotification=o.showNotification;exports.showToast=o.showToast;exports.submitForm=o.submitForm;exports.trackEvent=o.trackEvent;
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-DdROP6Ui.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"),m=require("./createMockClient-DecMEUcK.cjs"),g=require("./functions-Bz-1Bs3I.cjs");function A(e){return e}function h(e,o){return e.on("message:complete",o),()=>e.off("message:complete",o)}function C(e,o){return e.on("message:chunk",o),()=>e.off("message:chunk",o)}function E(e,o){return e.on("message:start",o),()=>e.off("message:start",o)}function y(e,o){return e.on("message:error",o),()=>e.off("message:error",o)}function S(e,o){return e.on("toolCall:received",o),()=>e.off("toolCall:received",o)}function b(e,o){return e.on("function:invoke",o),()=>e.off("function:invoke",o)}async function*M(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?.()},d=s=>{c({type:"error",data:s}),a=!0,r?.()},p=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",d),e.on("toolCall:received",p),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",d),e.off("toolCall:received",p)}}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 k(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 v(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=k;exports.createFormCollector=m.createFormCollector;exports.createMessageStream=M;exports.createMockClient=m.createMockClient;exports.createStore=m.createStore;exports.defineFunction=A;exports.getLocalStorage=g.getLocalStorage;exports.getUserLocation=g.getUserLocation;exports.highlightElement=g.highlightElement;exports.isStreamNetworkError=i.isStreamNetworkError;exports.logger=i.logger;exports.onFunctionInvoke=b;exports.onMessage=h;exports.onMessageChunk=C;exports.onMessageError=y;exports.onMessageStart=E;exports.onToolCall=S;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=v;
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