@useago/sdk 0.4.7 → 1.0.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 (39) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/LICENSE +201 -0
  3. package/NOTICE +10 -0
  4. package/README.md +107 -70
  5. package/dist/{AgoClient-CPqPT5s6.cjs → AgoClient-0x2Du_62.cjs} +1 -1
  6. package/dist/{AgoClient-BrYhSO5M.js → AgoClient-CZYNL25R.js} +29 -20
  7. package/dist/angular.cjs +1 -1
  8. package/dist/angular.d.cts +89 -0
  9. package/dist/angular.d.ts +89 -0
  10. package/dist/angular.js +1 -1
  11. package/dist/{createConversationSession-CGRO0bs2.cjs → createConversationSession-BLZvXMmM.cjs} +1 -1
  12. package/dist/{createConversationSession-Dmqd80DX.js → createConversationSession-Bmqj2rSS.js} +1 -1
  13. package/dist/createFormCollector-Bk0DRhUf.js +257 -0
  14. package/dist/createFormCollector-Ca8wRrxc.cjs +1 -0
  15. package/dist/devtools.d.cts +89 -0
  16. package/dist/devtools.d.ts +89 -0
  17. package/dist/index.cjs +1 -1
  18. package/dist/index.d.cts +47 -0
  19. package/dist/index.d.ts +47 -0
  20. package/dist/index.js +70 -68
  21. package/dist/react.cjs +23 -23
  22. package/dist/react.d.cts +74 -23
  23. package/dist/react.d.ts +74 -23
  24. package/dist/react.js +2154 -2075
  25. package/dist/testing.cjs +1 -0
  26. package/dist/testing.d.cts +571 -0
  27. package/dist/testing.d.ts +571 -0
  28. package/dist/testing.js +4 -0
  29. package/dist/vue.cjs +1 -1
  30. package/dist/vue.d.cts +89 -0
  31. package/dist/vue.d.ts +89 -0
  32. package/dist/vue.js +1 -1
  33. package/dist/widget.cjs +4 -4
  34. package/dist/widget.d.cts +74 -5
  35. package/dist/widget.d.ts +74 -5
  36. package/dist/widget.js +410 -317
  37. package/package.json +30 -9
  38. package/dist/createFormCollector-CPS2phYq.js +0 -245
  39. package/dist/createFormCollector-DaWZsBsI.cjs +0 -1
@@ -14,11 +14,11 @@ var d = class extends Error {
14
14
  constructor(e, t) {
15
15
  super(e, "network_error"), this.originalError = t, this.name = "AgoNetworkError";
16
16
  }
17
- }, g = class extends d {
17
+ }, m = class extends d {
18
18
  constructor(e) {
19
19
  super(e, "stream_error"), this.name = "AgoStreamError";
20
20
  }
21
- }, m = class extends d {
21
+ }, g = class extends d {
22
22
  constructor(e, t, s) {
23
23
  super(e, "function_error"), this.functionName = t, this.originalError = s, this.name = "AgoFunctionError";
24
24
  }
@@ -133,10 +133,10 @@ var E = class {
133
133
  }
134
134
  register(e, t, s) {
135
135
  if (typeof e == "object") {
136
- const { name: i, handler: o, description: a, parameters: l } = e;
136
+ const { name: i, handler: o, description: a, parameters: c } = e;
137
137
  return this.register(i, o, {
138
138
  description: a,
139
- parameters: l
139
+ parameters: c
140
140
  });
141
141
  }
142
142
  const r = e;
@@ -164,13 +164,13 @@ var E = class {
164
164
  }
165
165
  async execute(e, t) {
166
166
  const s = this.functions.get(e);
167
- if (!s) throw new m(`Function "${e}" is not registered`, e);
167
+ if (!s) throw new g(`Function "${e}" is not registered`, e);
168
168
  n.log(`Executing function: ${e}`, t);
169
169
  try {
170
170
  const r = await s.handler(t);
171
171
  return n.log(`Function ${e} completed:`, r), r;
172
172
  } catch (r) {
173
- throw n.error(`Function ${e} failed:`, r), new m(`Function "${e}" execution failed: ${r instanceof Error ? r.message : "Unknown error"}`, e, r instanceof Error ? r : void 0);
173
+ throw n.error(`Function ${e} failed:`, r), new g(`Function "${e}" execution failed: ${r instanceof Error ? r.message : "Unknown error"}`, e, r instanceof Error ? r : void 0);
174
174
  }
175
175
  }
176
176
  clear() {
@@ -217,7 +217,7 @@ var E = class {
217
217
  this.callbacks = e, this.buffer = "", this.message = {}, this.toolCalls = [], this.sources = [], this.followUpReplies = [], this.isFirstChunk = !0, this.answerCompleteEmitted = !1;
218
218
  }
219
219
  async processStream(e) {
220
- if (!e.body) throw new g("Response has no body");
220
+ if (!e.body) throw new m("Response has no body");
221
221
  const t = e.body.getReader(), s = new TextDecoder();
222
222
  try {
223
223
  for (; ; ) {
@@ -228,7 +228,7 @@ var E = class {
228
228
  }
229
229
  return this.buffer.trim() && this.processBuffer(), this.buildFinalMessage();
230
230
  } catch (r) {
231
- const i = r instanceof Error ? r : new g("Stream processing failed");
231
+ const i = r instanceof Error ? r : new m("Stream processing failed");
232
232
  throw this.callbacks.onError?.(i), i;
233
233
  } finally {
234
234
  t.releaseLock();
@@ -376,14 +376,14 @@ var S = class {
376
376
  agent_id: s?.agentId || o
377
377
  };
378
378
  r.length > 0 && (a.client_functions = r), i && (a.client_context = i);
379
- let l;
379
+ let c;
380
380
  if (s?.files && s.files.length > 0) {
381
- const c = new FormData();
382
- c.append("content", t), s.conversationId && c.append("conversation_id", s.conversationId), (s.agentId || o) && c.append("agent_id", s.agentId || o || ""), r.length > 0 && c.append("client_functions", JSON.stringify(r)), i && c.append("client_context", JSON.stringify(i));
383
- for (const v of s.files) c.append("files", v);
384
- l = await this.httpClient.postFormData("/api/sdk/v1/messages", c);
385
- } else l = await this.httpClient.postStream("/api/sdk/v1/messages", a);
386
- return this.processSSEResponse(l);
381
+ const l = new FormData();
382
+ l.append("content", t), s.conversationId && l.append("conversation_id", s.conversationId), (s.agentId || o) && l.append("agent_id", s.agentId || o || ""), r.length > 0 && l.append("client_functions", JSON.stringify(r)), i && l.append("client_context", JSON.stringify(i));
383
+ for (const v of s.files) l.append("files", v);
384
+ c = await this.httpClient.postFormData("/api/sdk/v1/messages", l);
385
+ } else c = await this.httpClient.postStream("/api/sdk/v1/messages", a);
386
+ return this.processSSEResponse(c);
387
387
  }
388
388
  async processSSEResponse(t) {
389
389
  return new k({
@@ -483,6 +483,15 @@ var S = class {
483
483
  async rejectToolCall(t) {
484
484
  await this.httpClient.post(`/api/tool-calls/${t}/reject/`);
485
485
  }
486
+ async getFormCollector(t) {
487
+ const s = await this.httpClient.get(`/api/sdk/v1/forms/${encodeURIComponent(t)}`);
488
+ return {
489
+ name: s.name,
490
+ description: s.description,
491
+ schema: s.schema,
492
+ submit: s.submit ?? void 0
493
+ };
494
+ }
486
495
  async submitFormCollector(t, s) {
487
496
  return this.httpClient.post("/api/sdk/v1/forms/submit", {
488
497
  destination: t,
@@ -509,10 +518,10 @@ var S = class {
509
518
  const r = s.map((o) => o.name), i = s.map((o) => `- "${o.name}": ${o.description}`).join(`
510
519
  `);
511
520
  this.registerFunction("navigateToPage", async (o) => {
512
- const a = o.page, l = s.find((c) => c.name === a);
513
- return l ? (t(l.path), {
521
+ const a = o.page, c = s.find((l) => l.name === a);
522
+ return c ? (t(c.path), {
514
523
  success: !0,
515
- navigatedTo: l.path
524
+ navigatedTo: c.path
516
525
  }) : {
517
526
  success: !1,
518
527
  error: `Unknown page: ${a}`
@@ -590,7 +599,7 @@ export {
590
599
  _ as a,
591
600
  h as c,
592
601
  u as d,
593
- g as f,
602
+ m as f,
594
603
  x as i,
595
604
  d as l,
596
605
  S as n,
@@ -598,5 +607,5 @@ export {
598
607
  k as r,
599
608
  n as s,
600
609
  $ as t,
601
- m as u
610
+ g as u
602
611
  };
package/dist/angular.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./AgoClient-CPqPT5s6.cjs");var n=class{constructor(e){this.client=new o.AgoClient(e),this.messages$=this.fromEvent("message:complete"),this.chunks$=this.fromEvent("message:chunk"),this.errors$=this.fromEvent("message:error"),this.messageStart$=this.fromEvent("message:start")}fromEvent(e){const t=this.client;return{subscribe(i){const s=r=>{i.next?.(r)};return t.on(e,s),{unsubscribe:()=>t.off(e,s)}}}}sendMessage(e,t){return this.client.sendMessage(e,t)}getConversations(){return this.client.getConversations()}getConversation(e){return this.client.getConversation(e)}getMessages(e){return this.client.getMessages(e)}submitToolCallForm(e,t){return this.client.submitToolCallForm(e,t)}confirmToolCall(e){return this.client.confirmToolCall(e)}rejectToolCall(e){return this.client.rejectToolCall(e)}submitFeedback(e,t){return this.client.submitFeedback(e,t)}registerFunction(e,t,i){typeof e=="object"?this.client.registerFunction(e):this.client.registerFunction(e,t,i)}unregisterFunction(e){return this.client.unregisterFunction(e)}registerNavigationFunction(e,t){this.client.registerNavigationFunction(e,t)}on(e,t){this.client.on(e,t)}off(e,t){this.client.off(e,t)}updateConfig(e){this.client.updateConfig(e)}getClient(){return this.client}destroy(){this.client.destroy()}};function c(e){return{provide:n,useValue:new n(e)}}exports.AgoService=n;exports.provideAgo=c;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./AgoClient-0x2Du_62.cjs");var n=class{constructor(e){this.client=new o.AgoClient(e),this.messages$=this.fromEvent("message:complete"),this.chunks$=this.fromEvent("message:chunk"),this.errors$=this.fromEvent("message:error"),this.messageStart$=this.fromEvent("message:start")}fromEvent(e){const t=this.client;return{subscribe(i){const s=r=>{i.next?.(r)};return t.on(e,s),{unsubscribe:()=>t.off(e,s)}}}}sendMessage(e,t){return this.client.sendMessage(e,t)}getConversations(){return this.client.getConversations()}getConversation(e){return this.client.getConversation(e)}getMessages(e){return this.client.getMessages(e)}submitToolCallForm(e,t){return this.client.submitToolCallForm(e,t)}confirmToolCall(e){return this.client.confirmToolCall(e)}rejectToolCall(e){return this.client.rejectToolCall(e)}submitFeedback(e,t){return this.client.submitFeedback(e,t)}registerFunction(e,t,i){typeof e=="object"?this.client.registerFunction(e):this.client.registerFunction(e,t,i)}unregisterFunction(e){return this.client.unregisterFunction(e)}registerNavigationFunction(e,t){this.client.registerNavigationFunction(e,t)}on(e,t){this.client.on(e,t)}off(e,t){this.client.off(e,t)}updateConfig(e){this.client.updateConfig(e)}getClient(){return this.client}destroy(){this.client.destroy()}};function c(e){return{provide:n,useValue:new n(e)}}exports.AgoService=n;exports.provideAgo=c;
@@ -53,6 +53,13 @@ declare class AgoClient {
53
53
  * Reject a tool call
54
54
  */
55
55
  rejectToolCall(toolCallId: string): Promise<void>;
56
+ /**
57
+ * Fetch a backend-stored form collector definition by name (the single source
58
+ * of truth for the form's description, schema, and submit target). Used by
59
+ * `loadFormCollector` / the name-only form of `useFormCollector` so the schema
60
+ * lives in the backend instead of being hardcoded in client code.
61
+ */
62
+ getFormCollector(name: string): Promise<FormCollectorDefinition>;
56
63
  /**
57
64
  * Relay a completed form collector's values to a server-configured destination.
58
65
  *
@@ -477,6 +484,30 @@ export declare interface Conversation {
477
484
  */
478
485
  declare type DynamicContextProvider = () => ContextEntry | null | undefined;
479
486
 
487
+ /**
488
+ * The backend-stored shape returned by `GET /api/sdk/v1/forms/{name}` (see
489
+ * {@link AgoClient.getFormCollector}). Mirrors the persistable subset of
490
+ * {@link CreateFormCollectorOptions}: the `submit` here is never the client-only
491
+ * `handler` variant (a function can't be stored server-side).
492
+ */
493
+ declare interface FormCollectorDefinition<V = Record<string, unknown>> {
494
+ name: string;
495
+ description: string;
496
+ schema: FormCollectorSchema;
497
+ /** Server-stored submit target, if any. Absent means collect-only. */
498
+ submit?: SubmitConfig<V>;
499
+ }
500
+
501
+ /**
502
+ * Shape of a form's fields. Mirrors a client function's `parameters` (so the same
503
+ * object feeds the store, the update function, and the dynamic context). Additionally allows the SDK-only per-field `requiredWhen`, which {@link toWireParameters} removes before the schema reaches the LLM.
504
+ */
505
+ declare interface FormCollectorSchema {
506
+ type: "object";
507
+ properties: Record<string, FormFieldSchema>;
508
+ required?: string[];
509
+ }
510
+
480
511
  declare interface FormField {
481
512
  type: "string" | "number" | "boolean" | "array";
482
513
  title?: string;
@@ -485,6 +516,43 @@ declare interface FormField {
485
516
  default?: unknown;
486
517
  }
487
518
 
519
+ /**
520
+ * A field's conditional-requiredness rule. The field becomes required exactly
521
+ * when the controlling `property` matches `value` against the answers collected
522
+ * so far:
523
+ * - a single `value`, no `op` — equality (compared as strings);
524
+ * - a single `value` with `op` — numeric comparison (both sides coerced to numbers);
525
+ * - an array `value`, no `op` — "one of": matches when the property equals any
526
+ * listed value.
527
+ *
528
+ * SDK-only — it is stripped from the schema before it reaches the LLM tool
529
+ */
530
+ declare interface FormFieldCondition {
531
+ /** The controlling field whose value the rule tests. */
532
+ property: string;
533
+ /** Comparison operator; omitted means equality. Ignored when `value` is an array. */
534
+ op?: ">=" | "<=" | ">" | "<";
535
+ /**
536
+ * The value(s) to test the controlling field against. A single value is an
537
+ * equality (or, with `op`, a numeric comparison); an array is an "is one of"
538
+ * membership test, e.g. `value: ["1", "2", "3"]`.
539
+ */
540
+ value: string | number | Array<string | number>;
541
+ }
542
+
543
+ /** A single field's schema: the wire-legal keys plus the SDK-only `requiredWhen`. */
544
+ declare interface FormFieldSchema {
545
+ type: string;
546
+ description?: string;
547
+ enum?: string[];
548
+ default?: unknown;
549
+ /**
550
+ * Makes the field required only while this condition holds. Drives the dynamic
551
+ * `missing` list; stripped before the LLM tool — see {@link toWireParameters}.
552
+ */
553
+ requiredWhen?: FormFieldCondition;
554
+ }
555
+
488
556
  /**
489
557
  * Form schema for tool calls requiring user input
490
558
  */
@@ -541,6 +609,27 @@ declare interface SendMessageOptions {
541
609
  files?: File[];
542
610
  }
543
611
 
612
+ /**
613
+ * Where a completed form is sent.
614
+ * - `"https://..."` (a bare string) — shorthand for `{ via: "client", url }`: the browser
615
+ * POSTs the values to that URL.
616
+ * - `{ via: "client", url }` — same, written out.
617
+ * - `{ via: "client", handler }` — the browser runs your own submit logic.
618
+ * - `{ via: "backend", destination }` — the browser relays the values to the backend,
619
+ * which forwards them to the server-configured destination (URL + secret stay server-side).
620
+ * - `false` — collect only, no submit function.
621
+ */
622
+ declare type SubmitConfig<V = Record<string, unknown>> = string | {
623
+ via: "client";
624
+ url: string;
625
+ } | {
626
+ via: "client";
627
+ handler: (values: V) => Promise<unknown> | unknown;
628
+ } | {
629
+ via: "backend";
630
+ destination: string;
631
+ } | false;
632
+
544
633
  /**
545
634
  * Tool call data from SSE stream
546
635
  */
package/dist/angular.d.ts CHANGED
@@ -53,6 +53,13 @@ declare class AgoClient {
53
53
  * Reject a tool call
54
54
  */
55
55
  rejectToolCall(toolCallId: string): Promise<void>;
56
+ /**
57
+ * Fetch a backend-stored form collector definition by name (the single source
58
+ * of truth for the form's description, schema, and submit target). Used by
59
+ * `loadFormCollector` / the name-only form of `useFormCollector` so the schema
60
+ * lives in the backend instead of being hardcoded in client code.
61
+ */
62
+ getFormCollector(name: string): Promise<FormCollectorDefinition>;
56
63
  /**
57
64
  * Relay a completed form collector's values to a server-configured destination.
58
65
  *
@@ -477,6 +484,30 @@ export declare interface Conversation {
477
484
  */
478
485
  declare type DynamicContextProvider = () => ContextEntry | null | undefined;
479
486
 
487
+ /**
488
+ * The backend-stored shape returned by `GET /api/sdk/v1/forms/{name}` (see
489
+ * {@link AgoClient.getFormCollector}). Mirrors the persistable subset of
490
+ * {@link CreateFormCollectorOptions}: the `submit` here is never the client-only
491
+ * `handler` variant (a function can't be stored server-side).
492
+ */
493
+ declare interface FormCollectorDefinition<V = Record<string, unknown>> {
494
+ name: string;
495
+ description: string;
496
+ schema: FormCollectorSchema;
497
+ /** Server-stored submit target, if any. Absent means collect-only. */
498
+ submit?: SubmitConfig<V>;
499
+ }
500
+
501
+ /**
502
+ * Shape of a form's fields. Mirrors a client function's `parameters` (so the same
503
+ * object feeds the store, the update function, and the dynamic context). Additionally allows the SDK-only per-field `requiredWhen`, which {@link toWireParameters} removes before the schema reaches the LLM.
504
+ */
505
+ declare interface FormCollectorSchema {
506
+ type: "object";
507
+ properties: Record<string, FormFieldSchema>;
508
+ required?: string[];
509
+ }
510
+
480
511
  declare interface FormField {
481
512
  type: "string" | "number" | "boolean" | "array";
482
513
  title?: string;
@@ -485,6 +516,43 @@ declare interface FormField {
485
516
  default?: unknown;
486
517
  }
487
518
 
519
+ /**
520
+ * A field's conditional-requiredness rule. The field becomes required exactly
521
+ * when the controlling `property` matches `value` against the answers collected
522
+ * so far:
523
+ * - a single `value`, no `op` — equality (compared as strings);
524
+ * - a single `value` with `op` — numeric comparison (both sides coerced to numbers);
525
+ * - an array `value`, no `op` — "one of": matches when the property equals any
526
+ * listed value.
527
+ *
528
+ * SDK-only — it is stripped from the schema before it reaches the LLM tool
529
+ */
530
+ declare interface FormFieldCondition {
531
+ /** The controlling field whose value the rule tests. */
532
+ property: string;
533
+ /** Comparison operator; omitted means equality. Ignored when `value` is an array. */
534
+ op?: ">=" | "<=" | ">" | "<";
535
+ /**
536
+ * The value(s) to test the controlling field against. A single value is an
537
+ * equality (or, with `op`, a numeric comparison); an array is an "is one of"
538
+ * membership test, e.g. `value: ["1", "2", "3"]`.
539
+ */
540
+ value: string | number | Array<string | number>;
541
+ }
542
+
543
+ /** A single field's schema: the wire-legal keys plus the SDK-only `requiredWhen`. */
544
+ declare interface FormFieldSchema {
545
+ type: string;
546
+ description?: string;
547
+ enum?: string[];
548
+ default?: unknown;
549
+ /**
550
+ * Makes the field required only while this condition holds. Drives the dynamic
551
+ * `missing` list; stripped before the LLM tool — see {@link toWireParameters}.
552
+ */
553
+ requiredWhen?: FormFieldCondition;
554
+ }
555
+
488
556
  /**
489
557
  * Form schema for tool calls requiring user input
490
558
  */
@@ -541,6 +609,27 @@ declare interface SendMessageOptions {
541
609
  files?: File[];
542
610
  }
543
611
 
612
+ /**
613
+ * Where a completed form is sent.
614
+ * - `"https://..."` (a bare string) — shorthand for `{ via: "client", url }`: the browser
615
+ * POSTs the values to that URL.
616
+ * - `{ via: "client", url }` — same, written out.
617
+ * - `{ via: "client", handler }` — the browser runs your own submit logic.
618
+ * - `{ via: "backend", destination }` — the browser relays the values to the backend,
619
+ * which forwards them to the server-configured destination (URL + secret stay server-side).
620
+ * - `false` — collect only, no submit function.
621
+ */
622
+ declare type SubmitConfig<V = Record<string, unknown>> = string | {
623
+ via: "client";
624
+ url: string;
625
+ } | {
626
+ via: "client";
627
+ handler: (values: V) => Promise<unknown> | unknown;
628
+ } | {
629
+ via: "backend";
630
+ destination: string;
631
+ } | false;
632
+
544
633
  /**
545
634
  * Tool call data from SSE stream
546
635
  */
package/dist/angular.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as o } from "./AgoClient-BrYhSO5M.js";
1
+ import { t as o } from "./AgoClient-CZYNL25R.js";
2
2
  var n = class {
3
3
  constructor(t) {
4
4
  this.client = new o(t), this.messages$ = this.fromEvent("message:complete"), this.chunks$ = this.fromEvent("message:chunk"), this.errors$ = this.fromEvent("message:error"), this.messageStart$ = this.fromEvent("message:start");
@@ -1 +1 @@
1
- const d=require("./createFormCollector-DaWZsBsI.cjs");var f="ago_widget_id",g="ago_last_thread",y=7200*1e3;function v(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const r=Math.floor(Math.random()*16);return(e==="x"?r:r&3|8).toString(16)})}function _(e={}){const r=e.key??f,i=e.threadKey??g,u=e.ttlMs??y,l=e.storage??(typeof localStorage<"u"?localStorage:void 0);let n=e.widgetId??"";if(!n&&l)try{n=l.getItem(r)??""}catch{}if(n||(n=v()),l)try{l.setItem(r,n)}catch{}const o=d.createStore({value:null,lastMessageAt:null},{key:i,storage:l}),c=o.get();c.value!==null&&s(c.lastMessageAt)&&o.set({value:null,lastMessageAt:null});function s(t){return t===null?!0:Number.isFinite(u)?Date.now()-t>u:!1}return{widgetId:n,key:r,getLastActiveThread(){const{value:t,lastMessageAt:a}=o.get();return t===null||s(a)?null:t},setActiveThread(t,a){const x=a==null?null:a instanceof Date?a.getTime():a;o.set({value:t,lastMessageAt:x})},clear(){o.set({value:null,lastMessageAt:null})}}}Object.defineProperty(exports,"createConversationSession",{enumerable:!0,get:function(){return _}});
1
+ const d=require("./createFormCollector-Ca8wRrxc.cjs");var f="ago_widget_id",g="ago_last_thread",y=7200*1e3;function v(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const r=Math.floor(Math.random()*16);return(e==="x"?r:r&3|8).toString(16)})}function _(e={}){const r=e.key??f,i=e.threadKey??g,u=e.ttlMs??y,l=e.storage??(typeof localStorage<"u"?localStorage:void 0);let n=e.widgetId??"";if(!n&&l)try{n=l.getItem(r)??""}catch{}if(n||(n=v()),l)try{l.setItem(r,n)}catch{}const o=d.createStore({value:null,lastMessageAt:null},{key:i,storage:l}),c=o.get();c.value!==null&&s(c.lastMessageAt)&&o.set({value:null,lastMessageAt:null});function s(t){return t===null?!0:Number.isFinite(u)?Date.now()-t>u:!1}return{widgetId:n,key:r,getLastActiveThread(){const{value:t,lastMessageAt:a}=o.get();return t===null||s(a)?null:t},setActiveThread(t,a){const x=a==null?null:a instanceof Date?a.getTime():a;o.set({value:t,lastMessageAt:x})},clear(){o.set({value:null,lastMessageAt:null})}}}Object.defineProperty(exports,"createConversationSession",{enumerable:!0,get:function(){return _}});
@@ -1,4 +1,4 @@
1
- import { r as d } from "./createFormCollector-CPS2phYq.js";
1
+ import { i as d } from "./createFormCollector-Bk0DRhUf.js";
2
2
  var f = "ago_widget_id", g = "ago_last_thread", y = 7200 * 1e3;
3
3
  function v() {
4
4
  return typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (e) => {
@@ -0,0 +1,257 @@
1
+ import { s as _ } from "./AgoClient-CZYNL25R.js";
2
+ function E(n, e) {
3
+ const i = e ? e.storage ?? (typeof localStorage < "u" ? localStorage : void 0) : void 0;
4
+ let t = n;
5
+ if (e && i) try {
6
+ const c = i.getItem(e.key);
7
+ c != null && (t = JSON.parse(c));
8
+ } catch {
9
+ }
10
+ const a = /* @__PURE__ */ new Set(), f = () => a.forEach((c) => c(t));
11
+ function d() {
12
+ if (e && i) try {
13
+ i.setItem(e.key, JSON.stringify(t));
14
+ } catch {
15
+ }
16
+ }
17
+ return {
18
+ get: () => t,
19
+ set: (c) => {
20
+ t = c, d(), f();
21
+ },
22
+ subscribe: (c) => (a.add(c), () => {
23
+ a.delete(c);
24
+ })
25
+ };
26
+ }
27
+ var F = /^[a-zA-Z0-9_-]{1,40}$/, O = (n) => n == null || n === "";
28
+ function q(n, e) {
29
+ const i = e[n.property];
30
+ if (O(i)) return !1;
31
+ if (Array.isArray(n.value)) return n.value.some((f) => String(i) === String(f));
32
+ if (!n.op) return String(i) === String(n.value);
33
+ const t = Number(i), a = Number(n.value);
34
+ if (Number.isNaN(t) || Number.isNaN(a)) return !1;
35
+ switch (n.op) {
36
+ case ">=":
37
+ return t >= a;
38
+ case "<=":
39
+ return t <= a;
40
+ case ">":
41
+ return t > a;
42
+ case "<":
43
+ return t < a;
44
+ default:
45
+ return _.warn(`Unknown requiredWhen op "${n.op}"; treating as not required.`), !1;
46
+ }
47
+ }
48
+ function g(n, e) {
49
+ const i = n.properties ?? {}, t = /* @__PURE__ */ new Set();
50
+ for (const f of n.required ?? []) {
51
+ const d = i[f]?.requiredWhen;
52
+ (!d || q(d, e)) && t.add(f);
53
+ }
54
+ for (const [f, d] of Object.entries(i)) d.requiredWhen && q(d.requiredWhen, e) && t.add(f);
55
+ const a = [...t].filter((f) => O(e[f]));
56
+ return {
57
+ missing: a,
58
+ complete: a.length === 0
59
+ };
60
+ }
61
+ function P(n) {
62
+ const e = {};
63
+ for (const [i, t] of Object.entries(n.properties ?? {})) e[i] = {
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 }
68
+ };
69
+ return {
70
+ type: "object",
71
+ properties: e,
72
+ required: []
73
+ };
74
+ }
75
+ function W(n) {
76
+ const { name: e, description: i, schema: t } = n;
77
+ if (!F.test(e)) throw new Error(`Invalid form collector name "${e}": must match ${F} (it becomes the update_/submit_ function names).`);
78
+ const a = typeof n.submit == "string" ? n.submit ? {
79
+ via: "client",
80
+ url: n.submit
81
+ } : !1 : n.submit ?? !1, f = t.properties ?? {}, d = (r) => {
82
+ const s = {};
83
+ for (const [u, o] of Object.entries(r)) {
84
+ const l = f[u];
85
+ if (l)
86
+ if (o == null) s[u] = o;
87
+ else if (l.type === "number" || l.type === "integer") {
88
+ const h = typeof o == "number" ? o : Number(o);
89
+ s[u] = Number.isNaN(h) ? o : h;
90
+ } else l.type === "boolean" ? s[u] = typeof o == "boolean" ? o : o === "true" ? !0 : o === "false" ? !1 : !!o : s[u] = o;
91
+ }
92
+ return s;
93
+ }, c = n.initialValues ?? {}, m = E({
94
+ values: c,
95
+ submitted: !1
96
+ }), v = (r) => {
97
+ const s = m.get(), u = {
98
+ ...s,
99
+ values: {
100
+ ...s.values,
101
+ ...r
102
+ }
103
+ };
104
+ return m.set(u), u;
105
+ };
106
+ let b = null;
107
+ const N = async () => {
108
+ const { values: r } = m.get(), { complete: s, missing: u } = g(t, r);
109
+ if (!s) return {
110
+ ok: !1,
111
+ missing: u
112
+ };
113
+ if (!a) return {
114
+ ok: !1,
115
+ error: "No submit target configured for this form collector."
116
+ };
117
+ const o = r;
118
+ try {
119
+ let l;
120
+ if (a.via === "client") if ("handler" in a) l = await a.handler(o);
121
+ else {
122
+ const h = await fetch(a.url, {
123
+ method: "POST",
124
+ headers: { "Content-Type": "application/json" },
125
+ credentials: "include",
126
+ body: JSON.stringify(o)
127
+ });
128
+ if (!h.ok) return {
129
+ ok: !1,
130
+ error: `Submit failed: HTTP ${h.status}`
131
+ };
132
+ l = await h.json().catch(() => {
133
+ });
134
+ }
135
+ else {
136
+ if (!b) return {
137
+ ok: !1,
138
+ error: "Backend submit requires install(client) (or useFormCollector) first."
139
+ };
140
+ l = await b.submitFormCollector(a.destination, o);
141
+ }
142
+ return m.set({
143
+ ...m.get(),
144
+ submitted: !0
145
+ }), {
146
+ ok: !0,
147
+ result: l
148
+ };
149
+ } catch (l) {
150
+ const h = l instanceof Error ? l.message : "Submit failed";
151
+ return _.error(`FormCollector "${e}" submit failed:`, l), {
152
+ ok: !1,
153
+ error: h
154
+ };
155
+ }
156
+ }, $ = {
157
+ name: `update_${e}`,
158
+ description: `Fill or update fields of the "${e}" form. ${i} 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(d(r)), { missing: u } = g(t, s.values);
162
+ return {
163
+ ok: !0,
164
+ values: s.values,
165
+ missing: u
166
+ };
167
+ }
168
+ }, p = [$];
169
+ a && p.push({
170
+ name: `submit_${e}`,
171
+ 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.`,
172
+ parameters: {
173
+ type: "object",
174
+ properties: {}
175
+ },
176
+ handler: () => N()
177
+ });
178
+ const T = "client__", S = a ? `submit_${e}` : null, x = (r) => {
179
+ const s = r.functionName ?? r.toolName;
180
+ if (s)
181
+ return s.startsWith(T) ? s.slice(8) : s;
182
+ }, w = (r) => {
183
+ let s = { ...c }, u = !1;
184
+ for (const o of r) {
185
+ const l = x(o);
186
+ l === $.name ? o.arguments && (s = {
187
+ ...s,
188
+ ...d(o.arguments)
189
+ }) : S && l === S && o.status?.toLowerCase() === "done" && (u = !0);
190
+ }
191
+ m.set({
192
+ values: s,
193
+ submitted: u
194
+ });
195
+ }, y = `form:${e}`, C = () => {
196
+ const { values: r, submitted: s } = m.get(), { missing: u, complete: o } = g(t, r), l = a ? ` When nothing is missing and the user confirms, call submit_${e}.` : "", h = s ? `The "${e}" form has been submitted.` : `You are currently collecting information from the user to fill the "${e}" form.`;
197
+ return {
198
+ name: `Form: ${e}`,
199
+ description: `${h} ${i} 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.${l}`,
200
+ data: {
201
+ values: r,
202
+ missing: u,
203
+ complete: o,
204
+ submitted: s
205
+ }
206
+ };
207
+ }, k = (r) => {
208
+ w((r.messages ?? []).flatMap((s) => s.toolCalls ?? []));
209
+ };
210
+ return {
211
+ name: e,
212
+ store: m,
213
+ functions: p,
214
+ contextKey: y,
215
+ contextProvider: C,
216
+ install: (r) => {
217
+ b = r;
218
+ for (const u of p) r.register(u);
219
+ r.addDynamicContext(y, C);
220
+ const s = m.subscribe(() => r.notifyContextChanged());
221
+ return r.on("conversation:loaded", k), () => {
222
+ s();
223
+ for (const u of p) r.unregisterFunction(u.name);
224
+ r.removeDynamicContext(y), r.off("conversation:loaded", k), b === r && (b = null);
225
+ };
226
+ },
227
+ hydrate: w,
228
+ submit: N,
229
+ getValues: () => m.get().values,
230
+ setValues: (r) => {
231
+ v(d(r));
232
+ },
233
+ reset: () => {
234
+ m.set({
235
+ values: c,
236
+ submitted: !1
237
+ });
238
+ },
239
+ getStatus: () => g(t, m.get().values)
240
+ };
241
+ }
242
+ async function V(n, e) {
243
+ const i = await n.getFormCollector(e.name);
244
+ return W({
245
+ name: i.name,
246
+ description: e.description ?? i.description,
247
+ schema: e.schema ?? i.schema,
248
+ submit: e.submit ?? i.submit,
249
+ initialValues: e.initialValues
250
+ });
251
+ }
252
+ export {
253
+ E as i,
254
+ g as n,
255
+ V as r,
256
+ W as t
257
+ };
@@ -0,0 +1 @@
1
+ const O=require("./AgoClient-0x2Du_62.cjs");function _(o,e){const i=e?e.storage??(typeof localStorage<"u"?localStorage:void 0):void 0;let t=o;if(e&&i)try{const c=i.getItem(e.key);c!=null&&(t=JSON.parse(c))}catch{}const a=new Set,f=()=>a.forEach(c=>c(t));function d(){if(e&&i)try{i.setItem(e.key,JSON.stringify(t))}catch{}}return{get:()=>t,set:c=>{t=c,d(),f()},subscribe:c=>(a.add(c),()=>{a.delete(c)})}}var k=/^[a-zA-Z0-9_-]{1,40}$/,P=o=>o==null||o==="";function q(o,e){const i=e[o.property];if(P(i))return!1;if(Array.isArray(o.value))return o.value.some(f=>String(i)===String(f));if(!o.op)return String(i)===String(o.value);const t=Number(i),a=Number(o.value);if(Number.isNaN(t)||Number.isNaN(a))return!1;switch(o.op){case">=":return t>=a;case"<=":return t<=a;case">":return t>a;case"<":return t<a;default:return O.logger.warn(`Unknown requiredWhen op "${o.op}"; treating as not required.`),!1}}function p(o,e){const i=o.properties??{},t=new Set;for(const f of o.required??[]){const d=i[f]?.requiredWhen;(!d||q(d,e))&&t.add(f)}for(const[f,d]of Object.entries(i))d.requiredWhen&&q(d.requiredWhen,e)&&t.add(f);const a=[...t].filter(f=>P(e[f]));return{missing:a,complete:a.length===0}}function W(o){const e={};for(const[i,t]of Object.entries(o.properties??{}))e[i]={type:t.type,...t.description!=null&&{description:t.description},...t.enum&&{enum:t.enum},...t.default!==void 0&&{default:t.default}};return{type:"object",properties:e,required:[]}}function j(o){const{name:e,description:i,schema:t}=o;if(!k.test(e))throw new Error(`Invalid form collector name "${e}": must match ${k} (it becomes the update_/submit_ function names).`);const a=typeof o.submit=="string"?o.submit?{via:"client",url:o.submit}:!1:o.submit??!1,f=t.properties??{},d=r=>{const n={};for(const[u,s]of Object.entries(r)){const l=f[u];if(l)if(s==null)n[u]=s;else if(l.type==="number"||l.type==="integer"){const b=typeof s=="number"?s:Number(s);n[u]=Number.isNaN(b)?s:b}else l.type==="boolean"?n[u]=typeof s=="boolean"?s:s==="true"?!0:s==="false"?!1:!!s:n[u]=s}return n},c=o.initialValues??{},m=_({values:c,submitted:!1}),v=r=>{const n=m.get(),u={...n,values:{...n.values,...r}};return m.set(u),u};let h=null;const N=async()=>{const{values:r}=m.get(),{complete:n,missing:u}=p(t,r);if(!n)return{ok:!1,missing:u};if(!a)return{ok:!1,error:"No submit target configured for this form collector."};const s=r;try{let l;if(a.via==="client")if("handler"in a)l=await a.handler(s);else{const b=await fetch(a.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}`};l=await b.json().catch(()=>{})}else{if(!h)return{ok:!1,error:"Backend submit requires install(client) (or useFormCollector) first."};l=await h.submitFormCollector(a.destination,s)}return m.set({...m.get(),submitted:!0}),{ok:!0,result:l}}catch(l){const b=l instanceof Error?l.message:"Submit failed";return O.logger.error(`FormCollector "${e}" submit failed:`,l),{ok:!1,error:b}}},S={name:`update_${e}`,description:`Fill or update fields of the "${e}" form. ${i} 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:W(t),handler:r=>{const n=v(d(r)),{missing:u}=p(t,n.values);return{ok:!0,values:n.values,missing:u}}},g=[S];a&&g.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__",C=a?`submit_${e}`:null,E=r=>{const n=r.functionName??r.toolName;if(n)return n.startsWith(T)?n.slice(8):n},$=r=>{let n={...c},u=!1;for(const s of r){const l=E(s);l===S.name?s.arguments&&(n={...n,...d(s.arguments)}):C&&l===C&&s.status?.toLowerCase()==="done"&&(u=!0)}m.set({values:n,submitted:u})},y=`form:${e}`,w=()=>{const{values:r,submitted:n}=m.get(),{missing:u,complete:s}=p(t,r),l=a?` 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} ${i} 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.${l}`,data:{values:r,missing:u,complete:s,submitted:n}}},F=r=>{$((r.messages??[]).flatMap(n=>n.toolCalls??[]))};return{name:e,store:m,functions:g,contextKey:y,contextProvider:w,install:r=>{h=r;for(const u of g)r.register(u);r.addDynamicContext(y,w);const n=m.subscribe(()=>r.notifyContextChanged());return r.on("conversation:loaded",F),()=>{n();for(const u of g)r.unregisterFunction(u.name);r.removeDynamicContext(y),r.off("conversation:loaded",F),h===r&&(h=null)}},hydrate:$,submit:N,getValues:()=>m.get().values,setValues:r=>{v(d(r))},reset:()=>{m.set({values:c,submitted:!1})},getStatus:()=>p(t,m.get().values)}}async function x(o,e){const i=await o.getFormCollector(e.name);return j({name:i.name,description:e.description??i.description,schema:e.schema??i.schema,submit:e.submit??i.submit,initialValues:e.initialValues})}Object.defineProperty(exports,"createFormCollector",{enumerable:!0,get:function(){return j}});Object.defineProperty(exports,"createStore",{enumerable:!0,get:function(){return _}});Object.defineProperty(exports,"deriveFormStatus",{enumerable:!0,get:function(){return p}});Object.defineProperty(exports,"loadFormCollector",{enumerable:!0,get:function(){return x}});