@useago/sdk 0.4.6 → 1.0.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/LICENSE +201 -0
  3. package/NOTICE +10 -0
  4. package/README.md +19 -11
  5. package/dist/{AgoClient-rvTz2thR.js → AgoClient-BrYhSO5M.js} +32 -26
  6. package/dist/AgoClient-CPqPT5s6.cjs +6 -0
  7. package/dist/angular.cjs +1 -1
  8. package/dist/angular.d.cts +5 -0
  9. package/dist/angular.d.ts +5 -0
  10. package/dist/angular.js +1 -1
  11. package/dist/{createConversationSession-DGcM_Z3f.cjs → createConversationSession-CGRO0bs2.cjs} +1 -1
  12. package/dist/{createConversationSession-D-eq8VIo.js → createConversationSession-Dmqd80DX.js} +1 -1
  13. package/dist/{createFormCollector-DON4vdJV.js → createFormCollector-CPS2phYq.js} +51 -50
  14. package/dist/createFormCollector-DaWZsBsI.cjs +1 -0
  15. package/dist/devtools.cjs +3 -3
  16. package/dist/devtools.d.cts +7 -2
  17. package/dist/devtools.d.ts +7 -2
  18. package/dist/devtools.js +41 -35
  19. package/dist/index.cjs +1 -1
  20. package/dist/index.d.cts +14 -0
  21. package/dist/index.d.ts +14 -0
  22. package/dist/index.js +38 -37
  23. package/dist/react.cjs +19 -19
  24. package/dist/react.d.cts +16 -0
  25. package/dist/react.d.ts +16 -0
  26. package/dist/react.js +1516 -1490
  27. package/dist/testing.cjs +1 -0
  28. package/dist/testing.d.cts +482 -0
  29. package/dist/testing.d.ts +482 -0
  30. package/dist/testing.js +4 -0
  31. package/dist/vue.cjs +1 -1
  32. package/dist/vue.d.cts +5 -0
  33. package/dist/vue.d.ts +5 -0
  34. package/dist/vue.js +1 -1
  35. package/dist/widget.cjs +4 -4
  36. package/dist/widget.d.cts +6 -1
  37. package/dist/widget.d.ts +6 -1
  38. package/dist/widget.js +300 -286
  39. package/package.json +30 -9
  40. package/dist/AgoClient-D4EL6nva.cjs +0 -6
  41. package/dist/createFormCollector-IO6bfPQx.cjs +0 -1
@@ -1,23 +1,23 @@
1
- import { s as _ } from "./AgoClient-rvTz2thR.js";
1
+ import { s as _ } from "./AgoClient-BrYhSO5M.js";
2
2
  function E(n, e) {
3
3
  const l = e ? e.storage ?? (typeof localStorage < "u" ? localStorage : void 0) : void 0;
4
- let t = n;
4
+ let r = n;
5
5
  if (e && l) try {
6
6
  const c = l.getItem(e.key);
7
- c != null && (t = JSON.parse(c));
7
+ c != null && (r = JSON.parse(c));
8
8
  } catch {
9
9
  }
10
- const i = /* @__PURE__ */ new Set(), f = () => i.forEach((c) => c(t));
10
+ const i = /* @__PURE__ */ new Set(), f = () => i.forEach((c) => c(r));
11
11
  function m() {
12
12
  if (e && l) try {
13
- l.setItem(e.key, JSON.stringify(t));
13
+ l.setItem(e.key, JSON.stringify(r));
14
14
  } catch {
15
15
  }
16
16
  }
17
17
  return {
18
- get: () => t,
18
+ get: () => r,
19
19
  set: (c) => {
20
- t = c, m(), f();
20
+ r = c, m(), f();
21
21
  },
22
22
  subscribe: (c) => (i.add(c), () => {
23
23
  i.delete(c);
@@ -30,29 +30,29 @@ function F(n, e) {
30
30
  if (O(l)) return !1;
31
31
  if (Array.isArray(n.value)) return n.value.some((f) => String(l) === String(f));
32
32
  if (!n.op) return String(l) === String(n.value);
33
- const t = Number(l), i = Number(n.value);
34
- if (Number.isNaN(t) || Number.isNaN(i)) return !1;
33
+ const r = Number(l), i = Number(n.value);
34
+ if (Number.isNaN(r) || Number.isNaN(i)) return !1;
35
35
  switch (n.op) {
36
36
  case ">=":
37
- return t >= i;
37
+ return r >= i;
38
38
  case "<=":
39
- return t <= i;
39
+ return r <= i;
40
40
  case ">":
41
- return t > i;
41
+ return r > i;
42
42
  case "<":
43
- return t < i;
43
+ return r < i;
44
44
  default:
45
45
  return _.warn(`Unknown requiredWhen op "${n.op}"; treating as not required.`), !1;
46
46
  }
47
47
  }
48
48
  function y(n, e) {
49
- const l = n.properties ?? {}, t = /* @__PURE__ */ new Set();
49
+ const l = n.properties ?? {}, r = /* @__PURE__ */ new Set();
50
50
  for (const f of n.required ?? []) {
51
51
  const m = l[f]?.requiredWhen;
52
- (!m || F(m, e)) && t.add(f);
52
+ (!m || F(m, e)) && r.add(f);
53
53
  }
54
- for (const [f, m] of Object.entries(l)) m.requiredWhen && F(m.requiredWhen, e) && t.add(f);
55
- const i = [...t].filter((f) => O(e[f]));
54
+ for (const [f, m] of Object.entries(l)) m.requiredWhen && F(m.requiredWhen, e) && r.add(f);
55
+ const i = [...r].filter((f) => O(e[f]));
56
56
  return {
57
57
  missing: i,
58
58
  complete: i.length === 0
@@ -60,11 +60,11 @@ function y(n, e) {
60
60
  }
61
61
  function P(n) {
62
62
  const e = {};
63
- for (const [l, t] of Object.entries(n.properties ?? {})) e[l] = {
64
- type: t.type,
65
- ...t.description != null && { description: t.description },
66
- ...t.enum && { enum: t.enum },
67
- ...t.default !== void 0 && { default: t.default }
63
+ for (const [l, r] of Object.entries(n.properties ?? {})) e[l] = {
64
+ type: r.type,
65
+ ...r.description != null && { description: r.description },
66
+ ...r.enum && { enum: r.enum },
67
+ ...r.default !== void 0 && { default: r.default }
68
68
  };
69
69
  return {
70
70
  type: "object",
@@ -73,14 +73,14 @@ function P(n) {
73
73
  };
74
74
  }
75
75
  function I(n) {
76
- const { name: e, description: l, schema: t } = n;
76
+ const { name: e, description: l, schema: r } = n;
77
77
  if (!q.test(e)) throw new Error(`Invalid form collector name "${e}": must match ${q} (it becomes the update_/submit_ function names).`);
78
78
  const i = typeof n.submit == "string" ? n.submit ? {
79
79
  via: "client",
80
80
  url: n.submit
81
- } : !1 : n.submit ?? !1, f = t.properties ?? {}, m = (r) => {
81
+ } : !1 : n.submit ?? !1, f = r.properties ?? {}, m = (t) => {
82
82
  const s = {};
83
- for (const [a, o] of Object.entries(r)) {
83
+ for (const [a, o] of Object.entries(t)) {
84
84
  const u = f[a];
85
85
  if (u)
86
86
  if (o == null) s[a] = o;
@@ -93,19 +93,19 @@ function I(n) {
93
93
  }, c = n.initialValues ?? {}, d = E({
94
94
  values: c,
95
95
  submitted: !1
96
- }), v = (r) => {
96
+ }), v = (t) => {
97
97
  const s = d.get(), a = {
98
98
  ...s,
99
99
  values: {
100
100
  ...s.values,
101
- ...r
101
+ ...t
102
102
  }
103
103
  };
104
104
  return d.set(a), a;
105
105
  };
106
106
  let h = null;
107
107
  const N = async () => {
108
- const { values: r } = d.get(), { complete: s, missing: a } = y(t, r);
108
+ const { values: t } = d.get(), { complete: s, missing: a } = y(r, t);
109
109
  if (!s) return {
110
110
  ok: !1,
111
111
  missing: a
@@ -114,7 +114,7 @@ function I(n) {
114
114
  ok: !1,
115
115
  error: "No submit target configured for this form collector."
116
116
  };
117
- const o = r;
117
+ const o = t;
118
118
  try {
119
119
  let u;
120
120
  if (i.via === "client") if ("handler" in i) u = await i.handler(o);
@@ -156,9 +156,9 @@ function I(n) {
156
156
  }, $ = {
157
157
  name: `update_${e}`,
158
158
  description: `Fill or update fields of the "${e}" form. ${l} Pass any subset of fields; call it repeatedly to fill the form as the user provides information. Returns the current values and which required fields are still missing.`,
159
- parameters: P(t),
160
- handler: (r) => {
161
- const s = v(m(r)), { missing: a } = y(t, s.values);
159
+ parameters: P(r),
160
+ handler: (t) => {
161
+ const s = v(m(t)), { missing: a } = y(r, s.values);
162
162
  return {
163
163
  ok: !0,
164
164
  values: s.values,
@@ -175,13 +175,13 @@ function I(n) {
175
175
  },
176
176
  handler: () => N()
177
177
  });
178
- const T = "client__", S = i ? `submit_${e}` : null, x = (r) => {
179
- const s = r.functionName ?? r.toolName;
178
+ const T = "client__", S = i ? `submit_${e}` : null, x = (t) => {
179
+ const s = t.functionName ?? t.toolName;
180
180
  if (s)
181
181
  return s.startsWith(T) ? s.slice(8) : s;
182
- }, w = (r) => {
182
+ }, w = (t) => {
183
183
  let s = { ...c }, a = !1;
184
- for (const o of r) {
184
+ for (const o of t) {
185
185
  const u = x(o);
186
186
  u === $.name ? o.arguments && (s = {
187
187
  ...s,
@@ -193,18 +193,19 @@ function I(n) {
193
193
  submitted: a
194
194
  });
195
195
  }, g = `form:${e}`, C = () => {
196
- const { values: r, submitted: s } = d.get(), { missing: a, complete: o } = y(t, r), u = i ? ` When nothing is missing and the user confirms, call submit_${e}.` : "", p = s ? `The "${e}" form has been submitted.` : `You are currently collecting information from the user to fill the "${e}" form.`;
196
+ const { values: t, submitted: s } = d.get(), { missing: a, complete: o } = y(r, t), u = i ? ` When nothing is missing and the user confirms, call submit_${e}.` : "", p = s ? `The "${e}" form has been submitted.` : `You are currently collecting information from the user to fill the "${e}" form.`;
197
197
  return {
198
198
  name: `Form: ${e}`,
199
- description: `${p} ${l} There are conditionnals questions/values to collected, you can find this information with the requiredWhen field in the form. The form schema is the following: ${JSON.stringify(t)}. Data collected so far: ${JSON.stringify(r)}. Call update_${e} with any fields the user provides; ask only for what is still missing.${u}`,
199
+ description: `${p} ${l} There are conditionnals questions/values to collected, you can find this information with the requiredWhen field in the form. The form schema is the following: ${JSON.stringify(r)}. Data collected so far: ${JSON.stringify(t)}. Call update_${e} with any fields the user provides; ask only for what is still missing.${u}`,
200
200
  data: {
201
+ values: t,
201
202
  missing: a,
202
203
  complete: o,
203
204
  submitted: s
204
205
  }
205
206
  };
206
- }, k = (r) => {
207
- w((r.messages ?? []).flatMap((s) => s.toolCalls ?? []));
207
+ }, k = (t) => {
208
+ w((t.messages ?? []).flatMap((s) => s.toolCalls ?? []));
208
209
  };
209
210
  return {
210
211
  name: e,
@@ -212,22 +213,22 @@ function I(n) {
212
213
  functions: b,
213
214
  contextKey: g,
214
215
  contextProvider: C,
215
- install: (r) => {
216
- h = r;
217
- for (const a of b) r.register(a);
218
- r.addDynamicContext(g, C);
219
- const s = d.subscribe(() => r.notifyContextChanged());
220
- return r.on("conversation:loaded", k), () => {
216
+ install: (t) => {
217
+ h = t;
218
+ for (const a of b) t.register(a);
219
+ t.addDynamicContext(g, C);
220
+ const s = d.subscribe(() => t.notifyContextChanged());
221
+ return t.on("conversation:loaded", k), () => {
221
222
  s();
222
- for (const a of b) r.unregisterFunction(a.name);
223
- r.removeDynamicContext(g), r.off("conversation:loaded", k), h === r && (h = null);
223
+ for (const a of b) t.unregisterFunction(a.name);
224
+ t.removeDynamicContext(g), t.off("conversation:loaded", k), h === t && (h = null);
224
225
  };
225
226
  },
226
227
  hydrate: w,
227
228
  submit: N,
228
229
  getValues: () => d.get().values,
229
- setValues: (r) => {
230
- v(m(r));
230
+ setValues: (t) => {
231
+ v(m(t));
231
232
  },
232
233
  reset: () => {
233
234
  d.set({
@@ -0,0 +1 @@
1
+ const O=require("./AgoClient-CPqPT5s6.cjs");function _(o,e){const l=e?e.storage??(typeof localStorage<"u"?localStorage:void 0):void 0;let r=o;if(e&&l)try{const c=l.getItem(e.key);c!=null&&(r=JSON.parse(c))}catch{}const i=new Set,f=()=>i.forEach(c=>c(r));function m(){if(e&&l)try{l.setItem(e.key,JSON.stringify(r))}catch{}}return{get:()=>r,set:c=>{r=c,m(),f()},subscribe:c=>(i.add(c),()=>{i.delete(c)})}}var q=/^[a-zA-Z0-9_-]{1,40}$/,P=o=>o==null||o==="";function F(o,e){const l=e[o.property];if(P(l))return!1;if(Array.isArray(o.value))return o.value.some(f=>String(l)===String(f));if(!o.op)return String(l)===String(o.value);const r=Number(l),i=Number(o.value);if(Number.isNaN(r)||Number.isNaN(i))return!1;switch(o.op){case">=":return r>=i;case"<=":return r<=i;case">":return r>i;case"<":return r<i;default:return O.logger.warn(`Unknown requiredWhen op "${o.op}"; treating as not required.`),!1}}function g(o,e){const l=o.properties??{},r=new Set;for(const f of o.required??[]){const m=l[f]?.requiredWhen;(!m||F(m,e))&&r.add(f)}for(const[f,m]of Object.entries(l))m.requiredWhen&&F(m.requiredWhen,e)&&r.add(f);const i=[...r].filter(f=>P(e[f]));return{missing:i,complete:i.length===0}}function E(o){const e={};for(const[l,r]of Object.entries(o.properties??{}))e[l]={type:r.type,...r.description!=null&&{description:r.description},...r.enum&&{enum:r.enum},...r.default!==void 0&&{default:r.default}};return{type:"object",properties:e,required:[]}}function W(o){const{name:e,description:l,schema:r}=o;if(!q.test(e))throw new Error(`Invalid form collector name "${e}": must match ${q} (it becomes the update_/submit_ function names).`);const i=typeof o.submit=="string"?o.submit?{via:"client",url:o.submit}:!1:o.submit??!1,f=r.properties??{},m=t=>{const n={};for(const[a,s]of Object.entries(t)){const u=f[a];if(u)if(s==null)n[a]=s;else if(u.type==="number"||u.type==="integer"){const b=typeof s=="number"?s:Number(s);n[a]=Number.isNaN(b)?s:b}else u.type==="boolean"?n[a]=typeof s=="boolean"?s:s==="true"?!0:s==="false"?!1:!!s:n[a]=s}return n},c=o.initialValues??{},d=_({values:c,submitted:!1}),v=t=>{const n=d.get(),a={...n,values:{...n.values,...t}};return d.set(a),a};let p=null;const N=async()=>{const{values:t}=d.get(),{complete:n,missing:a}=g(r,t);if(!n)return{ok:!1,missing:a};if(!i)return{ok:!1,error:"No submit target configured for this form collector."};const s=t;try{let u;if(i.via==="client")if("handler"in i)u=await i.handler(s);else{const b=await fetch(i.url,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(s)});if(!b.ok)return{ok:!1,error:`Submit failed: HTTP ${b.status}`};u=await b.json().catch(()=>{})}else{if(!p)return{ok:!1,error:"Backend submit requires install(client) (or useFormCollector) first."};u=await p.submitFormCollector(i.destination,s)}return d.set({...d.get(),submitted:!0}),{ok:!0,result:u}}catch(u){const b=u instanceof Error?u.message:"Submit failed";return O.logger.error(`FormCollector "${e}" submit failed:`,u),{ok:!1,error:b}}},S={name:`update_${e}`,description:`Fill or update fields of the "${e}" form. ${l} Pass any subset of fields; call it repeatedly to fill the form as the user provides information. Returns the current values and which required fields are still missing.`,parameters:E(r),handler:t=>{const n=v(m(t)),{missing:a}=g(r,n.values);return{ok:!0,values:n.values,missing:a}}},h=[S];i&&h.push({name:`submit_${e}`,description:`Submit the completed "${e}" form. Only call this once every required field is collected and the user has confirmed. If fields are missing it returns them instead of submitting.`,parameters:{type:"object",properties:{}},handler:()=>N()});const T="client__",$=i?`submit_${e}`:null,j=t=>{const n=t.functionName??t.toolName;if(n)return n.startsWith(T)?n.slice(8):n},w=t=>{let n={...c},a=!1;for(const s of t){const u=j(s);u===S.name?s.arguments&&(n={...n,...m(s.arguments)}):$&&u===$&&s.status?.toLowerCase()==="done"&&(a=!0)}d.set({values:n,submitted:a})},y=`form:${e}`,C=()=>{const{values:t,submitted:n}=d.get(),{missing:a,complete:s}=g(r,t),u=i?` When nothing is missing and the user confirms, call submit_${e}.`:"",b=n?`The "${e}" form has been submitted.`:`You are currently collecting information from the user to fill the "${e}" form.`;return{name:`Form: ${e}`,description:`${b} ${l} There are conditionnals questions/values to collected, you can find this information with the requiredWhen field in the form. The form schema is the following: ${JSON.stringify(r)}. Data collected so far: ${JSON.stringify(t)}. Call update_${e} with any fields the user provides; ask only for what is still missing.${u}`,data:{values:t,missing:a,complete:s,submitted:n}}},k=t=>{w((t.messages??[]).flatMap(n=>n.toolCalls??[]))};return{name:e,store:d,functions:h,contextKey:y,contextProvider:C,install:t=>{p=t;for(const a of h)t.register(a);t.addDynamicContext(y,C);const n=d.subscribe(()=>t.notifyContextChanged());return t.on("conversation:loaded",k),()=>{n();for(const a of h)t.unregisterFunction(a.name);t.removeDynamicContext(y),t.off("conversation:loaded",k),p===t&&(p=null)}},hydrate:w,submit:N,getValues:()=>d.get().values,setValues:t=>{v(m(t))},reset:()=>{d.set({values:c,submitted:!1})}}}Object.defineProperty(exports,"createFormCollector",{enumerable:!0,get:function(){return W}});Object.defineProperty(exports,"createStore",{enumerable:!0,get:function(){return _}});Object.defineProperty(exports,"deriveFormStatus",{enumerable:!0,get:function(){return g}});
package/dist/devtools.cjs CHANGED
@@ -1,17 +1,17 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var c,d,v=()=>({});function i(){c&&(c.textContent=JSON.stringify(v(),null,2))}function s(l,e){if(!d)return;const o=document.createElement("div");o.className=`dev-log-line dev-log-${e}`,o.textContent=`${new Date().toLocaleTimeString()} ${l}`,d.appendChild(o),d.scrollTop=d.scrollHeight}var x="ago_dev_panel_collapsed";function r(l,e){l.classList.toggle("collapsed",e);const o=l.querySelector(".dev-toggle");o&&(o.textContent=e?"▢":"—",o.title=e?"Expand dev tools":"Collapse dev tools",o.setAttribute("aria-expanded",String(!e)));try{localStorage.setItem(x,e?"1":"0")}catch{}}function h(l){const{client:e,target:o}=l;v=()=>e.getContextSnapshot()?.entries??{},b();const u=typeof o=="string"?document.querySelector(o):o instanceof Element?o:document.body,t=document.createElement("aside");t.id="ago-dev-panel",(u??document.body).appendChild(t),t.innerHTML=`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var p,d,x=()=>({});function i(){p&&(p.textContent=JSON.stringify(x(),null,2))}function s(n,e){if(!d)return;const o=document.createElement("div");o.className=`dev-log-line dev-log-${e}`,o.textContent=`${new Date().toLocaleTimeString()} ${n}`,d.appendChild(o),d.scrollTop=d.scrollHeight}var u="ago_dev_panel_collapsed";function c(n,e){n.classList.toggle("collapsed",e);const o=n.querySelector(".dev-toggle");o&&(o.textContent=e?"▢":"—",o.title=e?"Expand dev tools":"Collapse dev tools",o.setAttribute("aria-expanded",String(!e)));try{localStorage.setItem(u,e?"1":"0")}catch{}}function h(n){const{client:e,target:o}=n;x=()=>{const t=e.getContextSnapshot()?.entries??{};return Object.fromEntries(Object.entries(t).map(([l,{name:r,data:b}])=>[l,{name:r,data:b}]))},m();const f=typeof o=="string"?document.querySelector(o):o instanceof Element?o:document.body,a=document.createElement("aside");a.id="ago-dev-panel",(f??document.body).appendChild(a),a.innerHTML=`
2
2
  <div class="dev-head">
3
3
  <span class="dev-badge">DEV</span>
4
4
  <span class="dev-title">DEV TOOLS · client-side function state — not for production</span>
5
5
  <button type="button" class="dev-toggle" aria-label="Toggle dev tools">—</button>
6
6
  </div>
7
7
  <div class="dev-body">
8
- <div class="dev-fns">Registered functions: <code>${(e.getRegisteredFunctions?.()??[]).map(a=>a.name).join(", ")||"—"}</code></div>
8
+ <div class="dev-fns">Registered functions: <code>${(e.getRegisteredFunctions?.()??[]).map(t=>t.name).join(", ")||"—"}</code></div>
9
9
  <div class="dev-section-label">JSON object (built by the agent)</div>
10
10
  <pre class="dev-state" id="ago-dev-state"></pre>
11
11
  <div class="dev-section-label">Function calls</div>
12
12
  <div class="dev-log" id="ago-dev-log"></div>
13
13
  </div>
14
- `,c=t.querySelector("#ago-dev-state"),d=t.querySelector("#ago-dev-log"),t.querySelector(".dev-toggle")?.addEventListener("click",a=>{a.stopPropagation(),r(t,!t.classList.contains("collapsed"))}),t.addEventListener("click",()=>{t.classList.contains("collapsed")&&r(t,!1)});let p=!1;try{p=localStorage.getItem(x)==="1"}catch{}r(t,p),e.on("function:invoke",({functionName:a,arguments:n})=>{s(`→ ${a}(${JSON.stringify(n??{})})`,"invoke")}),e.on("function:result",({result:a,error:n})=>{s(n?`✗ error: ${n}`:`← ${JSON.stringify(a)}`,n?"error":"result"),i()}),e.on("context:changed",i),e.on("conversation:loaded",a=>{const n=(a.messages??[]).flatMap(f=>f.toolCalls??[]);s(`⟳ hydrated "${a.title||a.id}" — replayed ${n.length} tool call${n.length===1?"":"s"}`,"hydrate"),i()}),i()}var g="ago-dev-panel-styles";function b(){if(document.getElementById(g))return;const l=document.createElement("style");l.id=g,l.textContent=m,document.head.appendChild(l)}var m=`
14
+ `,p=a.querySelector("#ago-dev-state"),d=a.querySelector("#ago-dev-log"),a.querySelector(".dev-toggle")?.addEventListener("click",t=>{t.stopPropagation(),c(a,!a.classList.contains("collapsed"))}),a.addEventListener("click",()=>{a.classList.contains("collapsed")&&c(a,!1)});let g=!1;try{g=localStorage.getItem(u)==="1"}catch{}c(a,g),e.on("function:invoke",({functionName:t,arguments:l})=>{s(`→ ${t}(${JSON.stringify(l??{})})`,"invoke")}),e.on("function:result",({result:t,error:l})=>{s(l?`✗ error: ${l}`:`← ${JSON.stringify(t)}`,l?"error":"result"),i()}),e.on("context:changed",i),e.on("conversation:loaded",t=>{const l=(t.messages??[]).flatMap(r=>r.toolCalls??[]);s(`⟳ hydrated "${t.title||t.id}" — replayed ${l.length} tool call${l.length===1?"":"s"}`,"hydrate"),i()}),i()}var v="ago-dev-panel-styles";function m(){if(document.getElementById(v))return;const n=document.createElement("style");n.id=v,n.textContent=y,document.head.appendChild(n)}var y=`
15
15
  #ago-dev-panel {
16
16
  position: fixed;
17
17
  top: 16px;
@@ -216,6 +216,11 @@ declare interface AgoClientEvents {
216
216
  conversationId: string;
217
217
  messageId: string;
218
218
  };
219
+ /**
220
+ * The main answer text is done (backend emitted `status: "DONE"`), but follow-up
221
+ * replies may still be pending. Fires once, before `message:complete`.
222
+ */
223
+ "message:answer-complete": AgoMessage;
219
224
  "message:complete": AgoMessage;
220
225
  "message:error": {
221
226
  error: string;
@@ -379,8 +384,8 @@ declare interface Conversation {
379
384
  export declare interface DevPanelOptions {
380
385
  /**
381
386
  * The AGO client to debug. The panel lists its registered functions, logs its
382
- * function events, and renders its live context snapshot
383
- * (`client.getContextSnapshot()`)
387
+ * function events, and renders the name + data of each entry in its live context
388
+ * snapshot (`client.getContextSnapshot()`)
384
389
  */
385
390
  client: Pick<AgoClient, "on" | "getRegisteredFunctions" | "getContextSnapshot">;
386
391
  /** Where to mount: a CSS selector, an Element, or `document.body` (default). */
@@ -216,6 +216,11 @@ declare interface AgoClientEvents {
216
216
  conversationId: string;
217
217
  messageId: string;
218
218
  };
219
+ /**
220
+ * The main answer text is done (backend emitted `status: "DONE"`), but follow-up
221
+ * replies may still be pending. Fires once, before `message:complete`.
222
+ */
223
+ "message:answer-complete": AgoMessage;
219
224
  "message:complete": AgoMessage;
220
225
  "message:error": {
221
226
  error: string;
@@ -379,8 +384,8 @@ declare interface Conversation {
379
384
  export declare interface DevPanelOptions {
380
385
  /**
381
386
  * The AGO client to debug. The panel lists its registered functions, logs its
382
- * function events, and renders its live context snapshot
383
- * (`client.getContextSnapshot()`)
387
+ * function events, and renders the name + data of each entry in its live context
388
+ * snapshot (`client.getContextSnapshot()`)
384
389
  */
385
390
  client: Pick<AgoClient, "on" | "getRegisteredFunctions" | "getContextSnapshot">;
386
391
  /** Where to mount: a CSS selector, an Element, or `document.body` (default). */
package/dist/devtools.js CHANGED
@@ -1,65 +1,71 @@
1
- var c, d, v = () => ({});
1
+ var p, d, x = () => ({});
2
2
  function i() {
3
- c && (c.textContent = JSON.stringify(v(), null, 2));
3
+ p && (p.textContent = JSON.stringify(x(), null, 2));
4
4
  }
5
- function s(l, e) {
5
+ function r(n, e) {
6
6
  if (!d) return;
7
7
  const o = document.createElement("div");
8
- o.className = `dev-log-line dev-log-${e}`, o.textContent = `${(/* @__PURE__ */ new Date()).toLocaleTimeString()} ${l}`, d.appendChild(o), d.scrollTop = d.scrollHeight;
8
+ o.className = `dev-log-line dev-log-${e}`, o.textContent = `${(/* @__PURE__ */ new Date()).toLocaleTimeString()} ${n}`, d.appendChild(o), d.scrollTop = d.scrollHeight;
9
9
  }
10
- var x = "ago_dev_panel_collapsed";
11
- function r(l, e) {
12
- l.classList.toggle("collapsed", e);
13
- const o = l.querySelector(".dev-toggle");
10
+ var f = "ago_dev_panel_collapsed";
11
+ function c(n, e) {
12
+ n.classList.toggle("collapsed", e);
13
+ const o = n.querySelector(".dev-toggle");
14
14
  o && (o.textContent = e ? "▢" : "—", o.title = e ? "Expand dev tools" : "Collapse dev tools", o.setAttribute("aria-expanded", String(!e)));
15
15
  try {
16
- localStorage.setItem(x, e ? "1" : "0");
16
+ localStorage.setItem(f, e ? "1" : "0");
17
17
  } catch {
18
18
  }
19
19
  }
20
- function m(l) {
21
- const { client: e, target: o } = l;
22
- v = () => e.getContextSnapshot()?.entries ?? {}, h();
23
- const f = typeof o == "string" ? document.querySelector(o) : o instanceof Element ? o : document.body, t = document.createElement("aside");
24
- t.id = "ago-dev-panel", (f ?? document.body).appendChild(t), t.innerHTML = `
20
+ function y(n) {
21
+ const { client: e, target: o } = n;
22
+ x = () => {
23
+ const t = e.getContextSnapshot()?.entries ?? {};
24
+ return Object.fromEntries(Object.entries(t).map(([l, { name: s, data: h }]) => [l, {
25
+ name: s,
26
+ data: h
27
+ }]));
28
+ }, b();
29
+ const u = typeof o == "string" ? document.querySelector(o) : o instanceof Element ? o : document.body, a = document.createElement("aside");
30
+ a.id = "ago-dev-panel", (u ?? document.body).appendChild(a), a.innerHTML = `
25
31
  <div class="dev-head">
26
32
  <span class="dev-badge">DEV</span>
27
33
  <span class="dev-title">DEV TOOLS · client-side function state — not for production</span>
28
34
  <button type="button" class="dev-toggle" aria-label="Toggle dev tools">—</button>
29
35
  </div>
30
36
  <div class="dev-body">
31
- <div class="dev-fns">Registered functions: <code>${(e.getRegisteredFunctions?.() ?? []).map((a) => a.name).join(", ") || "—"}</code></div>
37
+ <div class="dev-fns">Registered functions: <code>${(e.getRegisteredFunctions?.() ?? []).map((t) => t.name).join(", ") || "—"}</code></div>
32
38
  <div class="dev-section-label">JSON object (built by the agent)</div>
33
39
  <pre class="dev-state" id="ago-dev-state"></pre>
34
40
  <div class="dev-section-label">Function calls</div>
35
41
  <div class="dev-log" id="ago-dev-log"></div>
36
42
  </div>
37
- `, c = t.querySelector("#ago-dev-state"), d = t.querySelector("#ago-dev-log"), t.querySelector(".dev-toggle")?.addEventListener("click", (a) => {
38
- a.stopPropagation(), r(t, !t.classList.contains("collapsed"));
39
- }), t.addEventListener("click", () => {
40
- t.classList.contains("collapsed") && r(t, !1);
43
+ `, p = a.querySelector("#ago-dev-state"), d = a.querySelector("#ago-dev-log"), a.querySelector(".dev-toggle")?.addEventListener("click", (t) => {
44
+ t.stopPropagation(), c(a, !a.classList.contains("collapsed"));
45
+ }), a.addEventListener("click", () => {
46
+ a.classList.contains("collapsed") && c(a, !1);
41
47
  });
42
- let p = !1;
48
+ let g = !1;
43
49
  try {
44
- p = localStorage.getItem(x) === "1";
50
+ g = localStorage.getItem(f) === "1";
45
51
  } catch {
46
52
  }
47
- r(t, p), e.on("function:invoke", ({ functionName: a, arguments: n }) => {
48
- s(`→ ${a}(${JSON.stringify(n ?? {})})`, "invoke");
49
- }), e.on("function:result", ({ result: a, error: n }) => {
50
- s(n ? `✗ error: ${n}` : `← ${JSON.stringify(a)}`, n ? "error" : "result"), i();
51
- }), e.on("context:changed", i), e.on("conversation:loaded", (a) => {
52
- const n = (a.messages ?? []).flatMap((u) => u.toolCalls ?? []);
53
- s(`⟳ hydrated "${a.title || a.id}" — replayed ${n.length} tool call${n.length === 1 ? "" : "s"}`, "hydrate"), i();
53
+ c(a, g), e.on("function:invoke", ({ functionName: t, arguments: l }) => {
54
+ r(`→ ${t}(${JSON.stringify(l ?? {})})`, "invoke");
55
+ }), e.on("function:result", ({ result: t, error: l }) => {
56
+ r(l ? `✗ error: ${l}` : `← ${JSON.stringify(t)}`, l ? "error" : "result"), i();
57
+ }), e.on("context:changed", i), e.on("conversation:loaded", (t) => {
58
+ const l = (t.messages ?? []).flatMap((s) => s.toolCalls ?? []);
59
+ r(`⟳ hydrated "${t.title || t.id}" — replayed ${l.length} tool call${l.length === 1 ? "" : "s"}`, "hydrate"), i();
54
60
  }), i();
55
61
  }
56
- var g = "ago-dev-panel-styles";
57
- function h() {
58
- if (document.getElementById(g)) return;
59
- const l = document.createElement("style");
60
- l.id = g, l.textContent = b, document.head.appendChild(l);
62
+ var v = "ago-dev-panel-styles";
63
+ function b() {
64
+ if (document.getElementById(v)) return;
65
+ const n = document.createElement("style");
66
+ n.id = v, n.textContent = m, document.head.appendChild(n);
61
67
  }
62
- var b = `
68
+ var m = `
63
69
  #ago-dev-panel {
64
70
  position: fixed;
65
71
  top: 16px;
@@ -156,5 +162,5 @@ var b = `
156
162
  #ago-dev-panel .dev-log-hydrate { color: #d8b4fe; }
157
163
  `;
158
164
  export {
159
- m as initDevPanel
165
+ y as initDevPanel
160
166
  };
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./AgoClient-D4EL6nva.cjs"),m=require("./createFormCollector-IO6bfPQx.cjs"),A=require("./createConversationSession-DGcM_Z3f.cjs"),C=require("./createMockClient-zHQ0cjUH.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?.()},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 F(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 q(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=F;exports.createConversationSession=A.createConversationSession;exports.createFormCollector=m.createFormCollector;exports.createMessageStream=k;exports.createMockClient=C.createMockClient;exports.createStore=m.createStore;exports.defineFunction=h;exports.deriveFormStatus=m.deriveFormStatus;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=q;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./AgoClient-CPqPT5s6.cjs"),m=require("./createFormCollector-DaWZsBsI.cjs"),A=require("./createConversationSession-CGRO0bs2.cjs"),C=require("./createMockClient-zHQ0cjUH.cjs");require("./testing.cjs");const 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?.()},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 F(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 q(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=F;exports.createConversationSession=A.createConversationSession;exports.createFormCollector=m.createFormCollector;exports.createMessageStream=k;exports.createMockClient=C.createMockClient;exports.createStore=m.createStore;exports.defineFunction=h;exports.deriveFormStatus=m.deriveFormStatus;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=q;
package/dist/index.d.cts CHANGED
@@ -227,6 +227,11 @@ export declare interface AgoClientEvents {
227
227
  conversationId: string;
228
228
  messageId: string;
229
229
  };
230
+ /**
231
+ * The main answer text is done (backend emitted `status: "DONE"`), but follow-up
232
+ * replies may still be pending. Fires once, before `message:complete`.
233
+ */
234
+ "message:answer-complete": AgoMessage;
230
235
  "message:complete": AgoMessage;
231
236
  "message:error": {
232
237
  error: string;
@@ -1194,6 +1199,7 @@ export declare class SSEHandler {
1194
1199
  private sources;
1195
1200
  private followUpReplies;
1196
1201
  private isFirstChunk;
1202
+ private answerCompleteEmitted;
1197
1203
  constructor(callbacks: SSEHandlerCallbacks);
1198
1204
  /**
1199
1205
  * Process a streaming response
@@ -1202,6 +1208,8 @@ export declare class SSEHandler {
1202
1208
  private processBuffer;
1203
1209
  private handleChunk;
1204
1210
  private parseToolCall;
1211
+ /** Snapshot the accumulated message. Shared by the answer-complete and final builds. */
1212
+ private buildMessage;
1205
1213
  private buildFinalMessage;
1206
1214
  }
1207
1215
 
@@ -1222,6 +1230,12 @@ declare interface SSEHandlerCallbacks {
1222
1230
  arguments: Record<string, unknown>;
1223
1231
  conversationId: string;
1224
1232
  }) => void;
1233
+ /**
1234
+ * The main answer text is finished (the backend emitted `status: "DONE"`) but
1235
+ * follow-up replies may still be streaming. Fires once, before {@link onComplete},
1236
+ * with the message as it stands at that moment (no `followUpReplies` yet).
1237
+ */
1238
+ onAnswerComplete?: (message: AgoMessage) => void;
1225
1239
  onComplete?: (message: AgoMessage) => void;
1226
1240
  onError?: (error: Error) => void;
1227
1241
  }
package/dist/index.d.ts CHANGED
@@ -227,6 +227,11 @@ export declare interface AgoClientEvents {
227
227
  conversationId: string;
228
228
  messageId: string;
229
229
  };
230
+ /**
231
+ * The main answer text is done (backend emitted `status: "DONE"`), but follow-up
232
+ * replies may still be pending. Fires once, before `message:complete`.
233
+ */
234
+ "message:answer-complete": AgoMessage;
230
235
  "message:complete": AgoMessage;
231
236
  "message:error": {
232
237
  error: string;
@@ -1194,6 +1199,7 @@ export declare class SSEHandler {
1194
1199
  private sources;
1195
1200
  private followUpReplies;
1196
1201
  private isFirstChunk;
1202
+ private answerCompleteEmitted;
1197
1203
  constructor(callbacks: SSEHandlerCallbacks);
1198
1204
  /**
1199
1205
  * Process a streaming response
@@ -1202,6 +1208,8 @@ export declare class SSEHandler {
1202
1208
  private processBuffer;
1203
1209
  private handleChunk;
1204
1210
  private parseToolCall;
1211
+ /** Snapshot the accumulated message. Shared by the answer-complete and final builds. */
1212
+ private buildMessage;
1205
1213
  private buildFinalMessage;
1206
1214
  }
1207
1215
 
@@ -1222,6 +1230,12 @@ declare interface SSEHandlerCallbacks {
1222
1230
  arguments: Record<string, unknown>;
1223
1231
  conversationId: string;
1224
1232
  }) => void;
1233
+ /**
1234
+ * The main answer text is finished (the backend emitted `status: "DONE"`) but
1235
+ * follow-up replies may still be streaming. Fires once, before {@link onComplete},
1236
+ * with the message as it stands at that moment (no `followUpReplies` yet).
1237
+ */
1238
+ onAnswerComplete?: (message: AgoMessage) => void;
1225
1239
  onComplete?: (message: AgoMessage) => void;
1226
1240
  onError?: (error: Error) => void;
1227
1241
  }