@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
package/dist/vue.d.cts CHANGED
@@ -61,6 +61,13 @@ declare class AgoClient {
61
61
  * Reject a tool call
62
62
  */
63
63
  rejectToolCall(toolCallId: string): Promise<void>;
64
+ /**
65
+ * Fetch a backend-stored form collector definition by name (the single source
66
+ * of truth for the form's description, schema, and submit target). Used by
67
+ * `loadFormCollector` / the name-only form of `useFormCollector` so the schema
68
+ * lives in the backend instead of being hardcoded in client code.
69
+ */
70
+ getFormCollector(name: string): Promise<FormCollectorDefinition>;
64
71
  /**
65
72
  * Relay a completed form collector's values to a server-configured destination.
66
73
  *
@@ -417,6 +424,30 @@ export declare interface Conversation {
417
424
  */
418
425
  declare type DynamicContextProvider = () => ContextEntry | null | undefined;
419
426
 
427
+ /**
428
+ * The backend-stored shape returned by `GET /api/sdk/v1/forms/{name}` (see
429
+ * {@link AgoClient.getFormCollector}). Mirrors the persistable subset of
430
+ * {@link CreateFormCollectorOptions}: the `submit` here is never the client-only
431
+ * `handler` variant (a function can't be stored server-side).
432
+ */
433
+ declare interface FormCollectorDefinition<V = Record<string, unknown>> {
434
+ name: string;
435
+ description: string;
436
+ schema: FormCollectorSchema;
437
+ /** Server-stored submit target, if any. Absent means collect-only. */
438
+ submit?: SubmitConfig<V>;
439
+ }
440
+
441
+ /**
442
+ * Shape of a form's fields. Mirrors a client function's `parameters` (so the same
443
+ * 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.
444
+ */
445
+ declare interface FormCollectorSchema {
446
+ type: "object";
447
+ properties: Record<string, FormFieldSchema>;
448
+ required?: string[];
449
+ }
450
+
420
451
  declare interface FormField {
421
452
  type: "string" | "number" | "boolean" | "array";
422
453
  title?: string;
@@ -433,6 +464,43 @@ declare interface FormField_2 {
433
464
  default?: unknown;
434
465
  }
435
466
 
467
+ /**
468
+ * A field's conditional-requiredness rule. The field becomes required exactly
469
+ * when the controlling `property` matches `value` against the answers collected
470
+ * so far:
471
+ * - a single `value`, no `op` — equality (compared as strings);
472
+ * - a single `value` with `op` — numeric comparison (both sides coerced to numbers);
473
+ * - an array `value`, no `op` — "one of": matches when the property equals any
474
+ * listed value.
475
+ *
476
+ * SDK-only — it is stripped from the schema before it reaches the LLM tool
477
+ */
478
+ declare interface FormFieldCondition {
479
+ /** The controlling field whose value the rule tests. */
480
+ property: string;
481
+ /** Comparison operator; omitted means equality. Ignored when `value` is an array. */
482
+ op?: ">=" | "<=" | ">" | "<";
483
+ /**
484
+ * The value(s) to test the controlling field against. A single value is an
485
+ * equality (or, with `op`, a numeric comparison); an array is an "is one of"
486
+ * membership test, e.g. `value: ["1", "2", "3"]`.
487
+ */
488
+ value: string | number | Array<string | number>;
489
+ }
490
+
491
+ /** A single field's schema: the wire-legal keys plus the SDK-only `requiredWhen`. */
492
+ declare interface FormFieldSchema {
493
+ type: string;
494
+ description?: string;
495
+ enum?: string[];
496
+ default?: unknown;
497
+ /**
498
+ * Makes the field required only while this condition holds. Drives the dynamic
499
+ * `missing` list; stripped before the LLM tool — see {@link toWireParameters}.
500
+ */
501
+ requiredWhen?: FormFieldCondition;
502
+ }
503
+
436
504
  /**
437
505
  * Form schema for tool calls requiring user input
438
506
  */
@@ -479,6 +547,27 @@ declare interface Store<T> {
479
547
  subscribe(listener: (state: T) => void): () => void;
480
548
  }
481
549
 
550
+ /**
551
+ * Where a completed form is sent.
552
+ * - `"https://..."` (a bare string) — shorthand for `{ via: "client", url }`: the browser
553
+ * POSTs the values to that URL.
554
+ * - `{ via: "client", url }` — same, written out.
555
+ * - `{ via: "client", handler }` — the browser runs your own submit logic.
556
+ * - `{ via: "backend", destination }` — the browser relays the values to the backend,
557
+ * which forwards them to the server-configured destination (URL + secret stay server-side).
558
+ * - `false` — collect only, no submit function.
559
+ */
560
+ declare type SubmitConfig<V = Record<string, unknown>> = string | {
561
+ via: "client";
562
+ url: string;
563
+ } | {
564
+ via: "client";
565
+ handler: (values: V) => Promise<unknown> | unknown;
566
+ } | {
567
+ via: "backend";
568
+ destination: string;
569
+ } | false;
570
+
482
571
  /**
483
572
  * Tool call data from SSE stream
484
573
  */
package/dist/vue.d.ts CHANGED
@@ -61,6 +61,13 @@ declare class AgoClient {
61
61
  * Reject a tool call
62
62
  */
63
63
  rejectToolCall(toolCallId: string): Promise<void>;
64
+ /**
65
+ * Fetch a backend-stored form collector definition by name (the single source
66
+ * of truth for the form's description, schema, and submit target). Used by
67
+ * `loadFormCollector` / the name-only form of `useFormCollector` so the schema
68
+ * lives in the backend instead of being hardcoded in client code.
69
+ */
70
+ getFormCollector(name: string): Promise<FormCollectorDefinition>;
64
71
  /**
65
72
  * Relay a completed form collector's values to a server-configured destination.
66
73
  *
@@ -417,6 +424,30 @@ export declare interface Conversation {
417
424
  */
418
425
  declare type DynamicContextProvider = () => ContextEntry | null | undefined;
419
426
 
427
+ /**
428
+ * The backend-stored shape returned by `GET /api/sdk/v1/forms/{name}` (see
429
+ * {@link AgoClient.getFormCollector}). Mirrors the persistable subset of
430
+ * {@link CreateFormCollectorOptions}: the `submit` here is never the client-only
431
+ * `handler` variant (a function can't be stored server-side).
432
+ */
433
+ declare interface FormCollectorDefinition<V = Record<string, unknown>> {
434
+ name: string;
435
+ description: string;
436
+ schema: FormCollectorSchema;
437
+ /** Server-stored submit target, if any. Absent means collect-only. */
438
+ submit?: SubmitConfig<V>;
439
+ }
440
+
441
+ /**
442
+ * Shape of a form's fields. Mirrors a client function's `parameters` (so the same
443
+ * 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.
444
+ */
445
+ declare interface FormCollectorSchema {
446
+ type: "object";
447
+ properties: Record<string, FormFieldSchema>;
448
+ required?: string[];
449
+ }
450
+
420
451
  declare interface FormField {
421
452
  type: "string" | "number" | "boolean" | "array";
422
453
  title?: string;
@@ -433,6 +464,43 @@ declare interface FormField_2 {
433
464
  default?: unknown;
434
465
  }
435
466
 
467
+ /**
468
+ * A field's conditional-requiredness rule. The field becomes required exactly
469
+ * when the controlling `property` matches `value` against the answers collected
470
+ * so far:
471
+ * - a single `value`, no `op` — equality (compared as strings);
472
+ * - a single `value` with `op` — numeric comparison (both sides coerced to numbers);
473
+ * - an array `value`, no `op` — "one of": matches when the property equals any
474
+ * listed value.
475
+ *
476
+ * SDK-only — it is stripped from the schema before it reaches the LLM tool
477
+ */
478
+ declare interface FormFieldCondition {
479
+ /** The controlling field whose value the rule tests. */
480
+ property: string;
481
+ /** Comparison operator; omitted means equality. Ignored when `value` is an array. */
482
+ op?: ">=" | "<=" | ">" | "<";
483
+ /**
484
+ * The value(s) to test the controlling field against. A single value is an
485
+ * equality (or, with `op`, a numeric comparison); an array is an "is one of"
486
+ * membership test, e.g. `value: ["1", "2", "3"]`.
487
+ */
488
+ value: string | number | Array<string | number>;
489
+ }
490
+
491
+ /** A single field's schema: the wire-legal keys plus the SDK-only `requiredWhen`. */
492
+ declare interface FormFieldSchema {
493
+ type: string;
494
+ description?: string;
495
+ enum?: string[];
496
+ default?: unknown;
497
+ /**
498
+ * Makes the field required only while this condition holds. Drives the dynamic
499
+ * `missing` list; stripped before the LLM tool — see {@link toWireParameters}.
500
+ */
501
+ requiredWhen?: FormFieldCondition;
502
+ }
503
+
436
504
  /**
437
505
  * Form schema for tool calls requiring user input
438
506
  */
@@ -479,6 +547,27 @@ declare interface Store<T> {
479
547
  subscribe(listener: (state: T) => void): () => void;
480
548
  }
481
549
 
550
+ /**
551
+ * Where a completed form is sent.
552
+ * - `"https://..."` (a bare string) — shorthand for `{ via: "client", url }`: the browser
553
+ * POSTs the values to that URL.
554
+ * - `{ via: "client", url }` — same, written out.
555
+ * - `{ via: "client", handler }` — the browser runs your own submit logic.
556
+ * - `{ via: "backend", destination }` — the browser relays the values to the backend,
557
+ * which forwards them to the server-configured destination (URL + secret stay server-side).
558
+ * - `false` — collect only, no submit function.
559
+ */
560
+ declare type SubmitConfig<V = Record<string, unknown>> = string | {
561
+ via: "client";
562
+ url: string;
563
+ } | {
564
+ via: "client";
565
+ handler: (values: V) => Promise<unknown> | unknown;
566
+ } | {
567
+ via: "backend";
568
+ destination: string;
569
+ } | false;
570
+
482
571
  /**
483
572
  * Tool call data from SSE stream
484
573
  */
package/dist/vue.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as A } from "./AgoClient-BrYhSO5M.js";
1
+ import { t as A } from "./AgoClient-CZYNL25R.js";
2
2
  import { computed as y, inject as F, onMounted as g, onScopeDispose as N, onUnmounted as I, ref as c, shallowRef as D } from "vue";
3
3
  var L = /* @__PURE__ */ Symbol("ago-client"), b = { install(t, n) {
4
4
  const e = new A(n);
package/dist/widget.cjs CHANGED
@@ -1,5 +1,5 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Ie=require("./AgoClient-CPqPT5s6.cjs"),Te=require("./createFormCollector-DaWZsBsI.cjs"),Ne=require("./createConversationSession-CGRO0bs2.cjs");var Oe={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};function H(o){return o.replace(/[&<>"']/g,n=>Oe[n])}function ce(o){const n=o.trim();return/^(https?:|mailto:|tel:|#|\/|\.\/|\.\.\/)/i.test(n)||!/^[a-z][a-z0-9+.-]*:/i.test(n)?n:null}var ge='"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace',q="";function L(o){const n=[],r=u=>(n.push(u),`${q}${n.length-1}${q}`);let e=o;return e=e.replace(/`([^`]+)`/g,(u,a)=>r(`<code style="background:#f0f2f5;padding:2px 5px;border-radius:4px;font-size:13px;font-family:${ge}">${H(a)}</code>`)),e=e.replace(/!\[([^\]]*)\]\(([^)\s]+)\)/g,(u,a,p)=>{const i=ce(p);return i?r(`<img alt="${H(a)}" src="${H(i)}" style="max-width:100%;border-radius:8px;margin:4px 0" />`):u}),e=e.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g,(u,a,p)=>{const i=ce(p);return i?r(`<a href="${H(i)}" target="_blank" rel="noopener noreferrer" style="color:#1b5fc4;text-decoration:underline">${L(a)}</a>`):u}),e=H(e),e=e.replace(/\*\*([^*]+?)\*\*/g,"<strong>$1</strong>").replace(/__([^_]+?)__/g,"<strong>$1</strong>").replace(/~~([^~]+?)~~/g,"<del>$1</del>").replace(/(^|[^*])\*(?!\s)([^*]+?)\*/g,"$1<em>$2</em>").replace(/(^|[^\w_])_(?!\s)([^_]+?)_/g,"$1<em>$2</em>"),e=e.replace(new RegExp(`${q}(\\d+)${q}`,"g"),(u,a)=>n[Number(a)]),e}function w(o,n,r){const e=document.createElement(o);return Object.assign(e.style,n),r!==void 0&&(e.innerHTML=r),e}var he=/^ {0,3}([-*_])( *\1){2,} *$/,me=/^ {0,3}(#{1,6})\s+(.*?)\s*#*\s*$/,xe=/^ {0,3}(```+|~~~+)/,X=/^ {0,3}>\s?/,B=/^(\s*)([-*+]|\d+[.)])\s+(.*)$/,Ae=["20px","18px","16px","15px","14px","13px"],J=o=>o.match(/^\s*/)?.[0].length??0;function Le(o){return o.trim()===""||he.test(o)||me.test(o)||xe.test(o)||X.test(o)||B.test(o)}function be(o){const n=o[0].match(B),r=n[1].length,e=/\d/.test(n[2]),u=w(e?"ol":"ul",{margin:"0 0 8px 0",paddingLeft:"20px",listStyleType:e?"decimal":"disc",listStylePosition:"outside"});let a=0;for(;a<o.length;){const p=o[a].match(B),i=[];for(a++;a<o.length&&J(o[a])>r;)i.push(o[a]),a++;const f=w("li",{display:"list-item",margin:"2px 0",lineHeight:"1.6"}),d=p[3].match(/^\[([ xX])\]\s+(.*)$/);d?(f.style.listStyleType="none",f.style.marginLeft="-20px",f.innerHTML=`<span style="margin-right:6px">${d[1].toLowerCase()==="x"?"☑":"☐"}</span>${L(d[2])}`):f.innerHTML=L(p[3]),i.filter(b=>B.test(b)).length>0&&f.appendChild(be(i.filter(b=>b.trim()!==""))),u.appendChild(f)}return u}function De(o){const n=i=>i.replace(/^\s*\|?/,"").replace(/\|?\s*$/,"").split("|").map(f=>f.trim()),r=w("div",{overflowX:"auto",margin:"0 0 8px 0"}),e=w("table",{borderCollapse:"collapse",width:"100%",fontSize:"13px"}),u=document.createElement("thead"),a=document.createElement("tr");for(const i of n(o[0]))a.appendChild(w("th",{border:"1px solid #dee3e8",padding:"6px 10px",textAlign:"left",backgroundColor:"#f5f7fa",fontWeight:"600"},L(i)));u.appendChild(a),e.appendChild(u);const p=document.createElement("tbody");for(const i of o.slice(2)){const f=document.createElement("tr");for(const d of n(i))f.appendChild(w("td",{border:"1px solid #dee3e8",padding:"6px 10px"},L(d)));p.appendChild(f)}return e.appendChild(p),r.appendChild(e),r}var Me=o=>!!o&&/^\s*\|?\s*:?-{1,}:?\s*(\|\s*:?-{1,}:?\s*)*\|?\s*$/.test(o);function ee(o){const n=document.createDocumentFragment(),r=o.replace(/\r\n?/g,`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Xe=require("./AgoClient-0x2Du_62.cjs"),$e=require("./createFormCollector-Ca8wRrxc.cjs"),Ke=require("./createConversationSession-BLZvXMmM.cjs");var Ve={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};function F(o){return o.replace(/[&<>"']/g,n=>Ve[n])}function Ie(o){const n=o.trim();return/^(https?:|mailto:|tel:|#|\/|\.\/|\.\.\/)/i.test(n)||!/^[a-z][a-z0-9+.-]*:/i.test(n)?n:null}var Te='"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace',Q="";function M(o){const n=[],r=u=>(n.push(u),`${Q}${n.length-1}${Q}`);let t=o;return t=t.replace(/`([^`]+)`/g,(u,i)=>r(`<code style="background:#f0f2f5;padding:2px 5px;border-radius:4px;font-size:13px;font-family:${Te}">${F(i)}</code>`)),t=t.replace(/!\[([^\]]*)\]\(([^)\s]+)\)/g,(u,i,f)=>{const s=Ie(f);return s?r(`<img alt="${F(i)}" src="${F(s)}" style="max-width:100%;border-radius:8px;margin:4px 0" />`):u}),t=t.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g,(u,i,f)=>{const s=Ie(f);return s?r(`<a href="${F(s)}" target="_blank" rel="noopener noreferrer" style="color:#1b5fc4;text-decoration:underline">${M(i)}</a>`):u}),t=F(t),t=t.replace(/\*\*([^*]+?)\*\*/g,"<strong>$1</strong>").replace(/__([^_]+?)__/g,"<strong>$1</strong>").replace(/~~([^~]+?)~~/g,"<del>$1</del>").replace(/(^|[^*])\*(?!\s)([^*]+?)\*/g,"$1<em>$2</em>").replace(/(^|[^\w_])_(?!\s)([^_]+?)_/g,"$1<em>$2</em>"),t=t.replace(new RegExp(`${Q}(\\d+)${Q}`,"g"),(u,i)=>n[Number(i)]),t}function R(o,n,r){const t=document.createElement(o);return Object.assign(t.style,n),r!==void 0&&(t.innerHTML=r),t}var De=/^ {0,3}([-*_])( *\1){2,} *$/,Me=/^ {0,3}(#{1,6})\s+(.*?)\s*#*\s*$/,Be=/^ {0,3}(```+|~~~+)/,Z=/^ {0,3}>\s?/,P=/^(\s*)([-*+]|\d+[.)])\s+(.*)$/,Qe=["20px","18px","16px","15px","14px","13px"],ce=o=>o.match(/^\s*/)?.[0].length??0;function Ye(o){return o.trim()===""||De.test(o)||Me.test(o)||Be.test(o)||Z.test(o)||P.test(o)}function ze(o){const n=o[0].match(P),r=n[1].length,t=/\d/.test(n[2]),u=R(t?"ol":"ul",{margin:"0 0 8px 0",paddingLeft:"20px",listStyleType:t?"decimal":"disc",listStylePosition:"outside"});let i=0;for(;i<o.length;){const f=o[i].match(P),s=[];for(i++;i<o.length&&ce(o[i])>r;)s.push(o[i]),i++;const p=R("li",{display:"list-item",margin:"2px 0",lineHeight:"1.6"}),c=f[3].match(/^\[([ xX])\]\s+(.*)$/);c?(p.style.listStyleType="none",p.style.marginLeft="-20px",p.innerHTML=`<span style="margin-right:6px">${c[1].toLowerCase()==="x"?"☑":"☐"}</span>${M(c[2])}`):p.innerHTML=M(f[3]),s.filter(m=>P.test(m)).length>0&&p.appendChild(ze(s.filter(m=>m.trim()!==""))),u.appendChild(p)}return u}function Ze(o){const n=s=>s.replace(/^\s*\|?/,"").replace(/\|?\s*$/,"").split("|").map(p=>p.trim()),r=R("div",{overflowX:"auto",margin:"0 0 8px 0"}),t=R("table",{borderCollapse:"collapse",width:"100%",fontSize:"13px"}),u=document.createElement("thead"),i=document.createElement("tr");for(const s of n(o[0]))i.appendChild(R("th",{border:"1px solid #dee3e8",padding:"6px 10px",textAlign:"left",backgroundColor:"#f5f7fa",fontWeight:"600"},M(s)));u.appendChild(i),t.appendChild(u);const f=document.createElement("tbody");for(const s of o.slice(2)){const p=document.createElement("tr");for(const c of n(s))p.appendChild(R("td",{border:"1px solid #dee3e8",padding:"6px 10px"},M(c)));f.appendChild(p)}return t.appendChild(f),r.appendChild(t),r}var Je=o=>!!o&&/^\s*\|?\s*:?-{1,}:?\s*(\|\s*:?-{1,}:?\s*)*\|?\s*$/.test(o);function ge(o){const n=document.createDocumentFragment(),r=o.replace(/\r\n?/g,`
2
2
  `).split(`
3
- `);let e=0;for(;e<r.length;){const a=r[e];if(a.trim()===""){e++;continue}const p=a.match(xe);if(p){const d=p[1][0],b=[];for(e++;e<r.length&&!new RegExp(`^ {0,3}${d==="`"?"`{3,}":"~{3,}"}\\s*$`).test(r[e]);)b.push(r[e]),e++;e++;const N=w("pre",{margin:"0 0 8px 0"});N.appendChild(w("code",{display:"block",background:"#f5f5f5",padding:"8px 12px",borderRadius:"6px",fontSize:"13px",overflowX:"auto",fontFamily:ge,whiteSpace:"pre"},H(b.join(`
4
- `)))),n.appendChild(N);continue}if(he.test(a)){n.appendChild(w("hr",{border:"none",borderTop:"1px solid #dee3e8",margin:"12px 0"})),e++;continue}const i=a.match(me);if(i){const d=i[1].length;n.appendChild(w(`h${d}`,{margin:"16px 0 8px 0",fontSize:Ae[d-1],fontWeight:"600",lineHeight:"1.3"},L(i[2]))),e++;continue}if(X.test(a)){const d=[];for(;e<r.length&&X.test(r[e]);)d.push(r[e].replace(X,"")),e++;const b=w("blockquote",{borderLeft:"4px solid #dee3e8",paddingLeft:"12px",margin:"0 0 8px 0",fontStyle:"italic",color:"#6b6d6f"});b.appendChild(ee(d.join(`
5
- `))),n.appendChild(b);continue}if(a.includes("|")&&Me(r[e+1])){const d=[a,r[e+1]];for(e+=2;e<r.length&&r[e].includes("|")&&r[e].trim();)d.push(r[e]),e++;n.appendChild(De(d));continue}if(B.test(a)){const d=[],b=J(a);for(;e<r.length&&r[e].trim()!=="";)if(B.test(r[e])||J(r[e])>b)d.push(r[e]),e++;else break;n.appendChild(be(d));continue}const f=[a];for(e++;e<r.length&&!Le(r[e]);)f.push(r[e]),e++;n.appendChild(w("p",{margin:"0 0 8px 0",lineHeight:"1.6"},f.map(d=>L(d)).join("<br>")))}const u=n.lastElementChild;return u&&(u.style.marginBottom="0"),n}var Ce='var(--ago-font, "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif)',pe={font:"--ago-font",radius:"--ago-radius",messageRadius:"--ago-message-radius",brand:"--ago-brand-color",brandText:"--ago-brand-text-color",headerBg:"--ago-header-background",headerText:"--ago-header-text-color",panelBg:"--ago-panel-background",messagesBg:"--ago-messages-background",text:"--ago-text-color",mutedText:"--ago-muted-text-color",border:"--ago-border-color",accent:"--ago-accent-color"},ve="var(--ago-brand-color, #03182f)",ye="var(--ago-brand-text-color, #fff)",He="var(--ago-header-background, var(--ago-brand-color, #03182f))",Be="var(--ago-header-text-color, #e8f0fe)",z="var(--ago-panel-background, #fff)",Ue="var(--ago-messages-background, #fbfbfb)",j="var(--ago-text-color, #30373e)",ze="var(--ago-muted-text-color, #6b6d6f)",$="var(--ago-border-color, #dee3e8)",Z="var(--ago-accent-color, #1b5fc4)",Fe="var(--ago-radius, 16px)",fe="var(--ago-message-radius, 16px)";function We(o,n){if(n)for(const r of Object.keys(pe)){const e=n[r];e!=null&&o.style.setProperty(pe[r],e)}}function S(o,n){Object.assign(o.style,n)}function x(o={}){const n=document.createElement("div");return S(n,o),n}var ue="ago-chat-widget-keyframes";function Pe(){if(typeof document>"u"||document.getElementById(ue))return;const o=document.createElement("style");o.id=ue,o.textContent="@keyframes ago-pulse { 0%, 80%, 100% { opacity: 0.3; transform: scale(0.8); } 40% { opacity: 1; transform: scale(1); } }",document.head.appendChild(o)}function Ge(o){const n=typeof o=="string"?document.querySelector(o):o;if(!n)throw new Error(`mountChatWidget: target "${String(o)}" not found.`);return n}function qe(o,n){const{title:r="Chat",welcomeMessage:e="Hello! How can I help you today?",placeholder:u="Type a message...",allowFiles:a=!1,height:p=500,logoUrl:i,showAgentName:f=!1,theme:d,loadThreads:b=!1,forms:N,onFollowUpClick:g,onMessageSent:_,onMessageReceived:F}=n;if(!n.client&&!n.config?.baseUrl)throw new Error("mountChatWidget requires either `client` or `config` (with a baseUrl).");const m=n.client??new Ie.AgoClient(n.config),O=Ge(o),W=n.persistConversation,D=W?Ne.createConversationSession(W===!0?{}:W):void 0;let R=n.conversationId??D?.getLastActiveThread()??void 0,l=[],I=!1,U=null;const P=[],M=x({display:"flex",flexDirection:"column",height:typeof p=="number"?`${p}px`:p,border:`1px solid ${$}`,borderRadius:Fe,overflow:"hidden",backgroundColor:z,fontFamily:Ce,textAlign:"left",boxShadow:"rgba(15, 15, 15, 0.08) 0px 2px 16px 0px"});M.className="ago-chat-widget",We(M,d);const G=x({padding:"14px 16px",borderBottom:`1px solid ${$}`,backgroundColor:He,color:Be,display:"flex",alignItems:"center",gap:"10px"});if(G.className="ago-chat-widget__header",i){const t=document.createElement("img");t.src=i,t.alt="Logo",S(t,{height:"24px",width:"auto"}),G.appendChild(t)}const K=document.createElement("h3");K.textContent=r,S(K,{margin:"0",fontSize:"15px",fontWeight:"600"}),G.appendChild(K);const T=x({flex:"1",overflow:"auto",padding:"16px",backgroundColor:Ue});T.className="ago-chat-widget__messages";const{inputRow:Ee,setDisabled:we,focus:Se}=je({placeholder:u,allowFiles:a,onSend:(t,s)=>{V(t,s)}});Pe(),M.append(G,T,Ee),O.appendChild(M);const te=g!==!1,ne=g===!1?void 0:g??(t=>{V(t)});function Re(t,s){const c=t.role==="user",E=x({display:"flex",flexDirection:"column",alignItems:c?"flex-end":"flex-start",marginBottom:"16px"});if(E.className=`ago-message ago-message--${t.role}`,!c&&f&&t.agent){const h=x({fontSize:"13px",fontWeight:"500",color:j,marginBottom:"6px",padding:"0 4px"});h.className="ago-message__agent",h.textContent=t.agent.displayName||t.agent.name,E.appendChild(h)}if(!c&&t.sources&&t.sources.length>0){const h=x({display:"grid",gridTemplateColumns:"1fr 1fr",gap:"6px",marginBottom:"10px",width:"100%",maxWidth:"85%"});h.className="ago-message__sources",t.sources.forEach((C,y)=>{const A=C.url?document.createElement("a"):document.createElement("div");C.url&&A instanceof HTMLAnchorElement&&(A.href=C.url,A.target="_blank",A.rel="noopener noreferrer"),S(A,{display:"flex",alignItems:"center",gap:"8px",padding:"8px 10px",border:`1px solid ${$}`,borderRadius:"8px",backgroundColor:z,textDecoration:"none",color:j,fontSize:"12px",overflow:"hidden"});const de=x({flexShrink:"0",width:"18px",height:"18px",borderRadius:"3px",border:`1px solid ${Z}`,color:Z,fontSize:"11px",fontWeight:"500",display:"flex",alignItems:"center",justifyContent:"center",backgroundColor:"#f0f4ff"});de.textContent=String(y+1);const Y=x({overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"});Y.textContent=C.title,Y.title=C.title,A.append(de,Y),h.appendChild(A)}),E.appendChild(h)}const v=x({maxWidth:c?"75%":"100%",padding:c?"10px 14px":"2px 8px",borderRadius:c?fe:"0",backgroundColor:c?ve:"transparent",color:c?ye:j,wordBreak:"break-word",fontSize:"14px",lineHeight:"1.6"});if(v.className="ago-message__content",t.content?v.appendChild(ee(t.content)):t.status==="IN_PROGRESS"&&v.appendChild(le()),E.appendChild(v),s&&I&&t.role==="assistant"&&t.status==="DONE"&&!(t.followUpReplies&&t.followUpReplies.length>0)){const h=x({marginTop:"10px",paddingLeft:"8px"});h.className="ago-message__followups-loading",h.appendChild(le()),E.appendChild(h)}if(s&&t.followUpReplies&&t.followUpReplies.length>0){const h=x({display:"flex",flexWrap:"wrap",gap:"8px",marginTop:"10px"});h.className="ago-message__followups";for(const C of t.followUpReplies){const y=document.createElement("button");y.type="button",y.className="ago-message__followup-btn",y.textContent=C,y.disabled=!te,S(y,{padding:"6px 14px",fontSize:"13px",borderRadius:fe,border:`1px solid ${$}`,backgroundColor:z,color:j,cursor:te?"pointer":"default",transition:"border-color 0.15s"}),ne&&y.addEventListener("click",()=>ne(C)),y.addEventListener("mouseenter",()=>{y.style.borderColor=Z}),y.addEventListener("mouseleave",()=>{y.style.borderColor=$}),h.appendChild(y)}E.appendChild(h)}return E}function k(){if(T.replaceChildren(),l.length===0){const s=x({textAlign:"center",color:ze,padding:"24px 16px",fontSize:"14px",lineHeight:"1.5"});s.textContent=e,T.appendChild(s)}else l.forEach((s,c)=>{T.appendChild(Re(s,c===l.length-1))});if(U){const s=x({padding:"10px 14px",backgroundColor:"#fef2f2",color:"#dc2626",borderRadius:"12px",marginTop:"8px",fontSize:"13px",border:"1px solid #fecaca"});s.textContent=U,T.appendChild(s)}T.scrollTop=T.scrollHeight;const t=l[l.length-1];we(I&&t?.role==="assistant"&&t.status==="IN_PROGRESS")}function _e(){for(let t=l.length-1;t>=0;t--){const s=l[t];if(s.role==="assistant"&&s.status==="IN_PROGRESS")return s}}const oe=t=>{R||(R=t.conversationId)},re=t=>{const s=_e();s&&(s.content+=t.content,k())},ae=t=>{const s=l.findIndex(c=>c.id===t.id||c.role==="assistant"&&c.status==="IN_PROGRESS");s>=0?l[s]=t:l.push(t),k()},se=t=>{const s=l.findIndex(c=>c.id===t.id||c.role==="assistant"&&c.status==="IN_PROGRESS");s>=0?l[s]=t:l.push(t),I=!1,k(),t.status==="DONE"&&F?.({id:t.id,content:t.content})},ie=t=>{U=t.error,I=!1,l=l.filter(s=>!s.id.startsWith("temp-")),k()};m.on("message:start",oe),m.on("message:chunk",re),m.on("message:answer-complete",ae),m.on("message:complete",se),m.on("message:error",ie);const ke=(N??[]).map(t=>Te.createFormCollector(t).install(m));async function V(t,s){const c=t.trim();if(!c&&!s?.length||I)return;_?.(c),I=!0,U=null;const E=Date.now();l.push({id:`temp-user-${E}`,conversationId:R||"",content:c,role:"user",status:"DONE",createdAt:new Date}),l.push({id:`temp-assistant-${E}`,conversationId:R||"",content:"",role:"assistant",status:"IN_PROGRESS",createdAt:new Date}),k();try{const v=await m.sendMessage(c,{conversationId:R,files:s});v.conversationId&&(R||(R=v.conversationId),D?.setActiveThread(v.conversationId,v.createdAt));const h=l.find(C=>C.id===`temp-user-${E}`);if(h&&(h.id=`user-${E}`,h.conversationId=v.conversationId),!l.some(C=>C.id===v.id)){const C=l.findIndex(y=>y.id===`temp-assistant-${E}`);C>=0?l[C]=v:l.push(v)}l=l.filter(C=>!C.id.startsWith("temp-")),I=!1,k(),b&&Q()}catch(v){U=v instanceof Error?v.message:"Failed to send message",I=!1,l=l.filter(h=>!h.id.startsWith("temp-")),k()}}async function Q(){try{const t=await m.getConversations();P.splice(0,P.length,...t)}catch{}return P}async function $e(t){try{const s=(await m.getConversation(t))?.messages??[];s.length>0&&l.length===0&&(l=s,k())}catch{l.length===0&&(D?.clear(),R=void 0)}}return k(),Se(),R&&$e(R),b&&Q(),{client:m,element:M,sendMessage:V,session:D,threads:P,refreshThreads:Q,destroy(){m.off("message:start",oe),m.off("message:chunk",re),m.off("message:answer-complete",ae),m.off("message:complete",se),m.off("message:error",ie),ke.forEach(t=>t()),M.remove(),n.client||m.destroy()}};function le(){const t=x({display:"flex",gap:"4px",padding:"4px 0"});for(let s=0;s<3;s++){const c=x({width:"6px",height:"6px",borderRadius:"50%",backgroundColor:"#b5bfc8",animation:"ago-pulse 1.2s ease-in-out infinite",animationDelay:`${s*.2}s`});t.appendChild(c)}return t}}function je(o){let n=[];const r=document.createElement("form");S(r,{display:"flex",flexDirection:"column",gap:"8px",padding:"12px",borderTop:`1px solid ${$}`,backgroundColor:z}),r.className="ago-chat-input";const e=x({display:"flex",flexWrap:"wrap",gap:"6px"}),u=x({display:"flex",gap:"8px",alignItems:"flex-end"}),a=document.createElement("textarea");a.placeholder=o.placeholder,a.rows=1,S(a,{flex:"1",resize:"none",padding:"10px 12px",border:`1px solid ${$}`,borderRadius:"12px",fontSize:"14px",fontFamily:Ce,lineHeight:"1.4",maxHeight:"120px",outline:"none"});const p=document.createElement("button");p.type="submit",p.textContent="Send",S(p,{padding:"10px 16px",border:"none",borderRadius:"12px",backgroundColor:ve,color:ye,fontSize:"14px",fontWeight:"500",cursor:"pointer"});let i=null,f=null;o.allowFiles&&(i=document.createElement("input"),i.type="file",i.multiple=!0,S(i,{display:"none"}),f=document.createElement("button"),f.type="button",f.textContent="📎",S(f,{padding:"10px 12px",border:`1px solid ${$}`,borderRadius:"12px",backgroundColor:z,cursor:"pointer",fontSize:"14px"}),f.addEventListener("click",()=>i?.click()),i.addEventListener("change",()=>{n=[...n,...Array.from(i?.files??[])],d()}));function d(){e.replaceChildren(),n.forEach((g,_)=>{const F=x({display:"flex",alignItems:"center",gap:"4px",padding:"4px 8px",backgroundColor:"#f0f4ff",border:`1px solid ${$}`,borderRadius:"8px",fontSize:"12px"}),m=document.createElement("span");m.textContent=g.name;const O=document.createElement("button");O.type="button",O.textContent="×",S(O,{border:"none",background:"transparent",cursor:"pointer",fontSize:"14px",lineHeight:"1"}),O.addEventListener("click",()=>{n=n.filter((W,D)=>D!==_),d()}),F.append(m,O),e.appendChild(F)})}const b=()=>{const g=a.value,_=n;return a.value="",n=[],d(),{content:g,files:_}},N=()=>{const{content:g,files:_}=b();(g.trim()||_.length>0)&&o.onSend(g.trim(),_.length>0?_:void 0)};return r.addEventListener("submit",g=>{g.preventDefault(),N()}),a.addEventListener("keydown",g=>{g.key==="Enter"&&!g.shiftKey&&(g.preventDefault(),N())}),f&&u.appendChild(f),u.append(a,p),i&&r.appendChild(i),r.append(e,u),{inputRow:r,getValueAndClear:b,setDisabled:g=>{a.disabled=g,p.disabled=g,p.style.opacity=g?"0.6":"1",p.style.cursor=g?"not-allowed":"pointer"},focus:()=>a.focus()}}exports.mountChatWidget=qe;exports.renderMarkdown=ee;
3
+ `);let t=0;for(;t<r.length;){const i=r[t];if(i.trim()===""){t++;continue}const f=i.match(Be);if(f){const c=f[1][0],m=[];for(t++;t<r.length&&!new RegExp(`^ {0,3}${c==="`"?"`{3,}":"~{3,}"}\\s*$`).test(r[t]);)m.push(r[t]),t++;t++;const L=R("pre",{margin:"0 0 8px 0"});L.appendChild(R("code",{display:"block",background:"#f5f5f5",padding:"8px 12px",borderRadius:"6px",fontSize:"13px",overflowX:"auto",fontFamily:Te,whiteSpace:"pre"},F(m.join(`
4
+ `)))),n.appendChild(L);continue}if(De.test(i)){n.appendChild(R("hr",{border:"none",borderTop:"1px solid #dee3e8",margin:"12px 0"})),t++;continue}const s=i.match(Me);if(s){const c=s[1].length;n.appendChild(R(`h${c}`,{margin:"16px 0 8px 0",fontSize:Qe[c-1],fontWeight:"600",lineHeight:"1.3"},M(s[2]))),t++;continue}if(Z.test(i)){const c=[];for(;t<r.length&&Z.test(r[t]);)c.push(r[t].replace(Z,"")),t++;const m=R("blockquote",{borderLeft:"4px solid #dee3e8",paddingLeft:"12px",margin:"0 0 8px 0",fontStyle:"italic",color:"#6b6d6f"});m.appendChild(ge(c.join(`
5
+ `))),n.appendChild(m);continue}if(i.includes("|")&&Je(r[t+1])){const c=[i,r[t+1]];for(t+=2;t<r.length&&r[t].includes("|")&&r[t].trim();)c.push(r[t]),t++;n.appendChild(Ze(c));continue}if(P.test(i)){const c=[],m=ce(i);for(;t<r.length&&r[t].trim()!=="";)if(P.test(r[t])||ce(r[t])>m)c.push(r[t]),t++;else break;n.appendChild(ze(c));continue}const p=[i];for(t++;t<r.length&&!Ye(r[t]);)p.push(r[t]),t++;n.appendChild(R("p",{margin:"0 0 8px 0",lineHeight:"1.6"},p.map(c=>M(c)).join("<br>")))}const u=n.lastElementChild;return u&&(u.style.marginBottom="0"),n}var pe='var(--ago-font, "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif)',Ae={font:"--ago-font",radius:"--ago-radius",messageRadius:"--ago-message-radius",brand:"--ago-brand-color",brandText:"--ago-brand-text-color",headerBg:"--ago-header-background",headerText:"--ago-header-text-color",panelBg:"--ago-panel-background",messagesBg:"--ago-messages-background",text:"--ago-text-color",mutedText:"--ago-muted-text-color",border:"--ago-border-color",accent:"--ago-accent-color"},fe="var(--ago-brand-color, #03182f)",ue="var(--ago-brand-text-color, #fff)",et="var(--ago-header-background, var(--ago-brand-color, #03182f))",Ne="var(--ago-header-text-color, #e8f0fe)",j="var(--ago-panel-background, #fff)",tt="var(--ago-messages-background, #fbfbfb)",Y="var(--ago-text-color, #30373e)",nt="var(--ago-muted-text-color, #6b6d6f)",$="var(--ago-border-color, #dee3e8)",de="var(--ago-accent-color, #1b5fc4)",ot="var(--ago-radius, 16px)",Le="var(--ago-message-radius, 16px)";function rt(o,n){if(n)for(const r of Object.keys(Ae)){const t=n[r];t!=null&&o.style.setProperty(Ae[r],t)}}function y(o,n){Object.assign(o.style,n)}function b(o={}){const n=document.createElement("div");return y(n,o),n}var Oe="ago-chat-widget-keyframes";function at(){if(typeof document>"u"||document.getElementById(Oe))return;const o=document.createElement("style");o.id=Oe,o.textContent="@keyframes ago-pulse { 0%, 80%, 100% { opacity: 0.3; transform: scale(0.8); } 40% { opacity: 1; transform: scale(1); } }",document.head.appendChild(o)}function it(o){const n=typeof o=="string"?document.querySelector(o):o;if(!n)throw new Error(`mountChatWidget: target "${String(o)}" not found.`);return n}function st(o,n){const{title:r="Chat",welcomeMessage:t="Hello! How can I help you today?",placeholder:u="Type a message...",allowFiles:i=!1,height:f=500,placement:s="inline",width:p=400,defaultOpen:c=!1,logoUrl:m,showAgentName:L=!1,theme:x,loadThreads:_=!1,forms:q,onFollowUpClick:B,onMessageSent:O,onMessageReceived:he}=n;if(!n.client&&!n.config?.baseUrl)throw new Error("mountChatWidget requires either `client` or `config` (with a baseUrl).");const h=n.client??new Xe.AgoClient(n.config),me=it(o),z=s==="left"||s==="right",He=z&&(n.launcher??!0);let H=z?c:!0;const J=n.persistConversation,X=J?Ke.createConversationSession(J===!0?{}:J):void 0;let k=n.conversationId??X?.getLastActiveThread()??void 0,d=[],A=!1,W=null;const K=[],U=b({display:"flex",flexDirection:"column",height:z?"100%":typeof f=="number"?`${f}px`:f,border:`1px solid ${$}`,borderRadius:ot,overflow:"hidden",backgroundColor:j,fontFamily:pe,textAlign:"left",boxShadow:"rgba(15, 15, 15, 0.08) 0px 2px 16px 0px"});U.className="ago-chat-widget",rt(U,x);const G=b({padding:"14px 16px",borderBottom:`1px solid ${$}`,backgroundColor:et,color:Ne,display:"flex",alignItems:"center",gap:"10px"});if(G.className="ago-chat-widget__header",m){const e=document.createElement("img");e.src=m,e.alt="Logo",y(e,{height:"24px",width:"auto"}),G.appendChild(e)}const ee=document.createElement("h3");if(ee.textContent=r,y(ee,{margin:"0",fontSize:"15px",fontWeight:"600"}),G.appendChild(ee),z){const e=document.createElement("button");e.type="button",e.className="ago-chat-widget__close",e.setAttribute("aria-label","Close"),e.textContent="×",y(e,{marginLeft:"auto",background:"transparent",border:"none",color:Ne,fontSize:"22px",lineHeight:"1",cursor:"pointer",padding:"0 2px"}),e.addEventListener("click",()=>se()),G.appendChild(e)}const N=b({flex:"1",overflow:"auto",padding:"16px",backgroundColor:tt});N.className="ago-chat-widget__messages";const{inputRow:Ue,setDisabled:Fe,focus:xe}=lt({placeholder:u,allowFiles:i,onSend:(e,a)=>{oe(e,a)}});at(),U.append(G,N,Ue);let V=U,T,E;const te=s==="left"?"left":"right";if(z&&(T=b({position:"fixed",top:"0",bottom:"0",[te]:"0",width:typeof p=="number"?`${p}px`:p,maxWidth:"100vw",display:"flex",zIndex:"2147483000",transition:"transform 0.3s ease",boxShadow:"rgba(15, 15, 15, 0.18) 0px 0px 24px 0px"}),T.className="ago-chat-widget-panel",y(U,{height:"100%",width:"100%",borderRadius:"0",border:"none",boxShadow:"none",[te==="left"?"borderRight":"borderLeft"]:`1px solid ${$}`}),T.appendChild(U),V=T),He){if(E=document.createElement("button"),E.type="button",E.className="ago-chat-widget-launcher",E.setAttribute("aria-label",`Open ${r}`),y(E,{position:"fixed",bottom:"20px",[te]:"20px",width:"56px",height:"56px",borderRadius:"50%",border:"none",backgroundColor:fe,color:ue,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",zIndex:"2147483000",boxShadow:"rgba(15, 15, 15, 0.2) 0px 4px 14px 0px",fontFamily:pe}),m){const e=document.createElement("img");e.src=m,e.alt="",y(e,{width:"26px",height:"26px",objectFit:"contain"}),E.appendChild(e)}else E.appendChild(qe());E.addEventListener("click",()=>ie())}me.appendChild(V),E&&me.appendChild(E),ae();const be=B!==!1,Ce=B===!1?void 0:B??(e=>{oe(e)});function Pe(e,a){const l=e.role==="user",S=b({display:"flex",flexDirection:"column",alignItems:l?"flex-end":"flex-start",marginBottom:"16px"});if(S.className=`ago-message ago-message--${e.role}`,!l&&L&&e.agent){const g=b({fontSize:"13px",fontWeight:"500",color:Y,marginBottom:"6px",padding:"0 4px"});g.className="ago-message__agent",g.textContent=e.agent.displayName||e.agent.name,S.appendChild(g)}if(!l&&e.sources&&e.sources.length>0){const g=b({display:"grid",gridTemplateColumns:"1fr 1fr",gap:"6px",marginBottom:"10px",width:"100%",maxWidth:"85%"});g.className="ago-message__sources",e.sources.forEach((C,w)=>{const D=C.url?document.createElement("a"):document.createElement("div");C.url&&D instanceof HTMLAnchorElement&&(D.href=C.url,D.target="_blank",D.rel="noopener noreferrer"),y(D,{display:"flex",alignItems:"center",gap:"8px",padding:"8px 10px",border:`1px solid ${$}`,borderRadius:"8px",backgroundColor:j,textDecoration:"none",color:Y,fontSize:"12px",overflow:"hidden"});const ke=b({flexShrink:"0",width:"18px",height:"18px",borderRadius:"3px",border:`1px solid ${de}`,color:de,fontSize:"11px",fontWeight:"500",display:"flex",alignItems:"center",justifyContent:"center",backgroundColor:"#f0f4ff"});ke.textContent=String(w+1);const le=b({overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"});le.textContent=C.title,le.title=C.title,D.append(ke,le),g.appendChild(D)}),S.appendChild(g)}const v=b({maxWidth:l?"75%":"100%",padding:l?"10px 14px":"2px 8px",borderRadius:l?Le:"0",backgroundColor:l?fe:"transparent",color:l?ue:Y,wordBreak:"break-word",fontSize:"14px",lineHeight:"1.6"});if(v.className="ago-message__content",e.content?v.appendChild(ge(e.content)):e.status==="IN_PROGRESS"&&v.appendChild(_e()),S.appendChild(v),a&&A&&e.role==="assistant"&&e.status==="DONE"&&!(e.followUpReplies&&e.followUpReplies.length>0)){const g=b({marginTop:"10px",paddingLeft:"8px"});g.className="ago-message__followups-loading",g.appendChild(_e()),S.appendChild(g)}if(a&&e.followUpReplies&&e.followUpReplies.length>0){const g=b({display:"flex",flexWrap:"wrap",gap:"8px",marginTop:"10px"});g.className="ago-message__followups";for(const C of e.followUpReplies){const w=document.createElement("button");w.type="button",w.className="ago-message__followup-btn",w.textContent=C,w.disabled=!be,y(w,{padding:"6px 14px",fontSize:"13px",borderRadius:Le,border:`1px solid ${$}`,backgroundColor:j,color:Y,cursor:be?"pointer":"default",transition:"border-color 0.15s"}),Ce&&w.addEventListener("click",()=>Ce(C)),w.addEventListener("mouseenter",()=>{w.style.borderColor=de}),w.addEventListener("mouseleave",()=>{w.style.borderColor=$}),g.appendChild(w)}S.appendChild(g)}return S}function I(){if(N.replaceChildren(),d.length===0){const a=b({textAlign:"center",color:nt,padding:"24px 16px",fontSize:"14px",lineHeight:"1.5"});a.textContent=t,N.appendChild(a)}else d.forEach((a,l)=>{N.appendChild(Pe(a,l===d.length-1))});if(W){const a=b({padding:"10px 14px",backgroundColor:"#fef2f2",color:"#dc2626",borderRadius:"12px",marginTop:"8px",fontSize:"13px",border:"1px solid #fecaca"});a.textContent=W,N.appendChild(a)}N.scrollTop=N.scrollHeight;const e=d[d.length-1];Fe(A&&e?.role==="assistant"&&e.status==="IN_PROGRESS")}function We(){for(let e=d.length-1;e>=0;e--){const a=d[e];if(a.role==="assistant"&&a.status==="IN_PROGRESS")return a}}const ve=e=>{k||(k=e.conversationId)},we=e=>{const a=We();a&&(a.content+=e.content,I())},ye=e=>{const a=d.findIndex(l=>l.id===e.id||l.role==="assistant"&&l.status==="IN_PROGRESS");a>=0?d[a]=e:d.push(e),I()},Ee=e=>{const a=d.findIndex(l=>l.id===e.id||l.role==="assistant"&&l.status==="IN_PROGRESS");a>=0?d[a]=e:d.push(e),A=!1,I(),e.status==="DONE"&&he?.({id:e.id,content:e.content})},Se=e=>{W=e.error,A=!1,d=d.filter(a=>!a.id.startsWith("temp-")),I()};h.on("message:start",ve),h.on("message:chunk",we),h.on("message:answer-complete",ye),h.on("message:complete",Ee),h.on("message:error",Se);const ne=[];let Re=!1;for(const e of q??[])e.schema!=null?ne.push($e.createFormCollector(e).install(h)):$e.loadFormCollector(h,e).then(a=>{Re||ne.push(a.install(h))}).catch(()=>{});async function oe(e,a){const l=e.trim();if(!l&&!a?.length||A)return;O?.(l),A=!0,W=null;const S=Date.now();d.push({id:`temp-user-${S}`,conversationId:k||"",content:l,role:"user",status:"DONE",createdAt:new Date}),d.push({id:`temp-assistant-${S}`,conversationId:k||"",content:"",role:"assistant",status:"IN_PROGRESS",createdAt:new Date}),I();try{const v=await h.sendMessage(l,{conversationId:k,files:a});v.conversationId&&(k||(k=v.conversationId),X?.setActiveThread(v.conversationId,v.createdAt));const g=d.find(C=>C.id===`temp-user-${S}`);if(g&&(g.id=`user-${S}`,g.conversationId=v.conversationId),!d.some(C=>C.id===v.id)){const C=d.findIndex(w=>w.id===`temp-assistant-${S}`);C>=0?d[C]=v:d.push(v)}d=d.filter(C=>!C.id.startsWith("temp-")),A=!1,I(),_&&re()}catch(v){W=v instanceof Error?v.message:"Failed to send message",A=!1,d=d.filter(g=>!g.id.startsWith("temp-")),I()}}async function re(){try{const e=await h.getConversations();K.splice(0,K.length,...e)}catch{}return K}async function Ge(e){try{const a=(await h.getConversation(e))?.messages??[];a.length>0&&d.length===0&&(d=a,I())}catch{d.length===0&&(X?.clear(),k=void 0)}}return I(),xe(),k&&Ge(k),_&&re(),{client:h,element:V,sendMessage:oe,...z?{open:ie,close:se,toggle:je}:{},session:X,threads:K,refreshThreads:re,destroy(){h.off("message:start",ve),h.off("message:chunk",we),h.off("message:answer-complete",ye),h.off("message:complete",Ee),h.off("message:error",Se),Re=!0,ne.forEach(e=>e()),V.remove(),E?.remove(),n.client||h.destroy()}};function ae(){if(!T)return;const e=s==="left"?"translateX(-100%)":"translateX(100%)";T.style.transform=H?"translateX(0)":e,T.setAttribute("aria-hidden",H?"false":"true"),E&&(E.style.display=H?"none":"flex")}function ie(){H=!0,ae(),xe()}function se(){H=!1,ae()}function je(){H?se():ie()}function qe(){const e="http://www.w3.org/2000/svg",a=document.createElementNS(e,"svg");a.setAttribute("width","26"),a.setAttribute("height","26"),a.setAttribute("viewBox","0 0 24 24"),a.setAttribute("fill","none");const l=document.createElementNS(e,"path");return l.setAttribute("d","M21 11.5a8.38 8.38 0 0 1-8.5 8.5 8.5 8.5 0 0 1-3.8-.9L3 21l1.9-5.7a8.5 8.5 0 0 1-.9-3.8 8.38 8.38 0 0 1 8.5-8.5 8.38 8.38 0 0 1 8.5 8.5z"),l.setAttribute("stroke","currentColor"),l.setAttribute("stroke-width","2"),l.setAttribute("stroke-linecap","round"),l.setAttribute("stroke-linejoin","round"),a.appendChild(l),a}function _e(){const e=b({display:"flex",gap:"4px",padding:"4px 0"});for(let a=0;a<3;a++){const l=b({width:"6px",height:"6px",borderRadius:"50%",backgroundColor:"#b5bfc8",animation:"ago-pulse 1.2s ease-in-out infinite",animationDelay:`${a*.2}s`});e.appendChild(l)}return e}}function lt(o){let n=[];const r=document.createElement("form");y(r,{display:"flex",flexDirection:"column",gap:"8px",padding:"12px",borderTop:`1px solid ${$}`,backgroundColor:j}),r.className="ago-chat-input";const t=b({display:"flex",flexWrap:"wrap",gap:"6px"}),u=b({display:"flex",gap:"8px",alignItems:"flex-end"}),i=document.createElement("textarea");i.placeholder=o.placeholder,i.rows=1,y(i,{flex:"1",resize:"none",padding:"10px 12px",border:`1px solid ${$}`,borderRadius:"12px",fontSize:"14px",fontFamily:pe,lineHeight:"1.4",maxHeight:"120px",outline:"none"});const f=document.createElement("button");f.type="submit",f.textContent="Send",y(f,{padding:"10px 16px",border:"none",borderRadius:"12px",backgroundColor:fe,color:ue,fontSize:"14px",fontWeight:"500",cursor:"pointer"});let s=null,p=null;o.allowFiles&&(s=document.createElement("input"),s.type="file",s.multiple=!0,y(s,{display:"none"}),p=document.createElement("button"),p.type="button",p.textContent="📎",y(p,{padding:"10px 12px",border:`1px solid ${$}`,borderRadius:"12px",backgroundColor:j,cursor:"pointer",fontSize:"14px"}),p.addEventListener("click",()=>s?.click()),s.addEventListener("change",()=>{n=[...n,...Array.from(s?.files??[])],c()}));function c(){t.replaceChildren(),n.forEach((x,_)=>{const q=b({display:"flex",alignItems:"center",gap:"4px",padding:"4px 8px",backgroundColor:"#f0f4ff",border:`1px solid ${$}`,borderRadius:"8px",fontSize:"12px"}),B=document.createElement("span");B.textContent=x.name;const O=document.createElement("button");O.type="button",O.textContent="×",y(O,{border:"none",background:"transparent",cursor:"pointer",fontSize:"14px",lineHeight:"1"}),O.addEventListener("click",()=>{n=n.filter((he,h)=>h!==_),c()}),q.append(B,O),t.appendChild(q)})}const m=()=>{const x=i.value,_=n;return i.value="",n=[],c(),{content:x,files:_}},L=()=>{const{content:x,files:_}=m();(x.trim()||_.length>0)&&o.onSend(x.trim(),_.length>0?_:void 0)};return r.addEventListener("submit",x=>{x.preventDefault(),L()}),i.addEventListener("keydown",x=>{x.key==="Enter"&&!x.shiftKey&&(x.preventDefault(),L())}),p&&u.appendChild(p),u.append(i,f),s&&r.appendChild(s),r.append(t,u),{inputRow:r,getValueAndClear:m,setDisabled:x=>{i.disabled=x,f.disabled=x,f.style.opacity=x?"0.6":"1",f.style.cursor=x?"not-allowed":"pointer"},focus:()=>i.focus()}}exports.mountChatWidget=st;exports.renderMarkdown=ge;
package/dist/widget.d.cts 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
  *
@@ -345,6 +352,13 @@ export declare interface ChatWidgetHandle {
345
352
  element: HTMLElement;
346
353
  /** Programmatically send a message (same path as the input). */
347
354
  sendMessage: (content: string, files?: File[]) => Promise<void>;
355
+ /**
356
+ * Open / close / toggle the side panel. Present only for
357
+ * `placement: "left" | "right"` (an inline panel is always visible).
358
+ */
359
+ open?: () => void;
360
+ close?: () => void;
361
+ toggle?: () => void;
348
362
  /**
349
363
  * The conversation-persistence session, present only when `persistConversation`
350
364
  * is set — exposes the stable `widgetId` and `session.clear()` to start a new thread.
@@ -520,6 +534,20 @@ export declare interface CreateFormCollectorOptions<V = Record<string, unknown>>
520
534
  */
521
535
  declare type DynamicContextProvider = () => ContextEntry | null | undefined;
522
536
 
537
+ /**
538
+ * The backend-stored shape returned by `GET /api/sdk/v1/forms/{name}` (see
539
+ * {@link AgoClient.getFormCollector}). Mirrors the persistable subset of
540
+ * {@link CreateFormCollectorOptions}: the `submit` here is never the client-only
541
+ * `handler` variant (a function can't be stored server-side).
542
+ */
543
+ declare interface FormCollectorDefinition<V = Record<string, unknown>> {
544
+ name: string;
545
+ description: string;
546
+ schema: FormCollectorSchema;
547
+ /** Server-stored submit target, if any. Absent means collect-only. */
548
+ submit?: SubmitConfig<V>;
549
+ }
550
+
523
551
  /**
524
552
  * Shape of a form's fields. Mirrors a client function's `parameters` (so the same
525
553
  * 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.
@@ -584,6 +612,16 @@ declare interface FormSchema {
584
612
  required?: string[];
585
613
  }
586
614
 
615
+ /**
616
+ * Options for {@link loadFormCollector} / the name-only form of `useFormCollector`:
617
+ * the `name` is required and the definition is fetched from the backend, while any
618
+ * field here overrides the fetched one — notably a client-only `submit` handler,
619
+ * which can't be stored server-side.
620
+ */
621
+ declare interface LoadFormCollectorOptions<V = Record<string, unknown>> extends Partial<Omit<CreateFormCollectorOptions<V>, "name">> {
622
+ name: string;
623
+ }
624
+
587
625
  declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCELED";
588
626
 
589
627
  /**
@@ -646,9 +684,37 @@ export declare interface MountChatWidgetOptions {
646
684
  placeholder?: string;
647
685
  /** Enable file attachments. */
648
686
  allowFiles?: boolean;
649
- /** Widget height (number → px). */
687
+ /** Widget height (number → px). Ignored when `placement` is `"left"`/`"right"`
688
+ * (a side panel is always full-height). */
650
689
  height?: string | number;
651
- /** URL of a logo shown in the header. */
690
+ /**
691
+ * Where the panel renders. `"inline"` (default) mounts it directly into the
692
+ * target element, filling it. `"left"` / `"right"` instead pin a **fixed,
693
+ * full-height side panel** to that edge of the viewport that slides open and
694
+ * closed; the target is only used as the DOM parent (pass `document.body` for
695
+ * a true page overlay). In side mode `height` is ignored and the width comes
696
+ * from {@link MountChatWidgetOptions.width}.
697
+ */
698
+ placement?: "inline" | "left" | "right";
699
+ /**
700
+ * Width of the side panel for `placement: "left" | "right"` (number → px).
701
+ * Capped at the viewport width so it never overflows on mobile. Ignored when
702
+ * `placement` is `"inline"`. Defaults to `400`.
703
+ */
704
+ width?: string | number;
705
+ /**
706
+ * For side placements, render the built-in floating launcher button that opens
707
+ * the panel (plus a close "×" in the header). Set `false` to drive open/close
708
+ * yourself via the handle's `open()`/`close()`/`toggle()`. Ignored when
709
+ * `placement` is `"inline"`. Defaults to `true`.
710
+ */
711
+ launcher?: boolean;
712
+ /**
713
+ * For side placements, whether the panel starts open. Ignored when `placement`
714
+ * is `"inline"` (an inline panel is always visible). Defaults to `false`.
715
+ */
716
+ defaultOpen?: boolean;
717
+ /** URL of a logo shown in the header (and on the launcher button, if shown). */
652
718
  logoUrl?: string;
653
719
  /** Show the agent name above assistant messages. Defaults to `false`. */
654
720
  showAgentName?: boolean;
@@ -665,10 +731,13 @@ export declare interface MountChatWidgetOptions {
665
731
  loadThreads?: boolean;
666
732
  /**
667
733
  * Conversational forms the agent can fill and submit during the chat. Each
668
- * config is installed as a {@link createFormCollector} for the lifetime of the
734
+ * entry is installed as a {@link createFormCollector} for the lifetime of the
669
735
  * widget (removed on `destroy()`).
736
+ *
737
+ * Pass a full config (with `schema`) to define it inline, or just `{ name }` to
738
+ * fetch the definition from the backend ({@link loadFormCollector}).
670
739
  */
671
- forms?: CreateFormCollectorOptions[];
740
+ forms?: Array<CreateFormCollectorOptions | LoadFormCollectorOptions>;
672
741
  /**
673
742
  * How clicking a suggested follow-up reply behaves. Defaults to sending the
674
743
  * reply as a new user message. Pass a handler to override, or `false` to
@@ -768,7 +837,7 @@ declare type ToolCallType = "form" | "confirmation_input" | "status_message" | "
768
837
 
769
838
  /**
770
839
  * Theme overrides for {@link mountChatWidget}. *
771
- * @see The `--ago-*` token reference in `docs/widget.md`.
840
+ * @see The `--ago-*` token reference in `docs/general/widget.md`.
772
841
  */
773
842
  export declare interface WidgetTheme {
774
843
  /** Font family for the whole panel. Pass `"inherit"` to adopt the page font. (`--ago-font`) */
package/dist/widget.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
  *
@@ -345,6 +352,13 @@ export declare interface ChatWidgetHandle {
345
352
  element: HTMLElement;
346
353
  /** Programmatically send a message (same path as the input). */
347
354
  sendMessage: (content: string, files?: File[]) => Promise<void>;
355
+ /**
356
+ * Open / close / toggle the side panel. Present only for
357
+ * `placement: "left" | "right"` (an inline panel is always visible).
358
+ */
359
+ open?: () => void;
360
+ close?: () => void;
361
+ toggle?: () => void;
348
362
  /**
349
363
  * The conversation-persistence session, present only when `persistConversation`
350
364
  * is set — exposes the stable `widgetId` and `session.clear()` to start a new thread.
@@ -520,6 +534,20 @@ export declare interface CreateFormCollectorOptions<V = Record<string, unknown>>
520
534
  */
521
535
  declare type DynamicContextProvider = () => ContextEntry | null | undefined;
522
536
 
537
+ /**
538
+ * The backend-stored shape returned by `GET /api/sdk/v1/forms/{name}` (see
539
+ * {@link AgoClient.getFormCollector}). Mirrors the persistable subset of
540
+ * {@link CreateFormCollectorOptions}: the `submit` here is never the client-only
541
+ * `handler` variant (a function can't be stored server-side).
542
+ */
543
+ declare interface FormCollectorDefinition<V = Record<string, unknown>> {
544
+ name: string;
545
+ description: string;
546
+ schema: FormCollectorSchema;
547
+ /** Server-stored submit target, if any. Absent means collect-only. */
548
+ submit?: SubmitConfig<V>;
549
+ }
550
+
523
551
  /**
524
552
  * Shape of a form's fields. Mirrors a client function's `parameters` (so the same
525
553
  * 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.
@@ -584,6 +612,16 @@ declare interface FormSchema {
584
612
  required?: string[];
585
613
  }
586
614
 
615
+ /**
616
+ * Options for {@link loadFormCollector} / the name-only form of `useFormCollector`:
617
+ * the `name` is required and the definition is fetched from the backend, while any
618
+ * field here overrides the fetched one — notably a client-only `submit` handler,
619
+ * which can't be stored server-side.
620
+ */
621
+ declare interface LoadFormCollectorOptions<V = Record<string, unknown>> extends Partial<Omit<CreateFormCollectorOptions<V>, "name">> {
622
+ name: string;
623
+ }
624
+
587
625
  declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCELED";
588
626
 
589
627
  /**
@@ -646,9 +684,37 @@ export declare interface MountChatWidgetOptions {
646
684
  placeholder?: string;
647
685
  /** Enable file attachments. */
648
686
  allowFiles?: boolean;
649
- /** Widget height (number → px). */
687
+ /** Widget height (number → px). Ignored when `placement` is `"left"`/`"right"`
688
+ * (a side panel is always full-height). */
650
689
  height?: string | number;
651
- /** URL of a logo shown in the header. */
690
+ /**
691
+ * Where the panel renders. `"inline"` (default) mounts it directly into the
692
+ * target element, filling it. `"left"` / `"right"` instead pin a **fixed,
693
+ * full-height side panel** to that edge of the viewport that slides open and
694
+ * closed; the target is only used as the DOM parent (pass `document.body` for
695
+ * a true page overlay). In side mode `height` is ignored and the width comes
696
+ * from {@link MountChatWidgetOptions.width}.
697
+ */
698
+ placement?: "inline" | "left" | "right";
699
+ /**
700
+ * Width of the side panel for `placement: "left" | "right"` (number → px).
701
+ * Capped at the viewport width so it never overflows on mobile. Ignored when
702
+ * `placement` is `"inline"`. Defaults to `400`.
703
+ */
704
+ width?: string | number;
705
+ /**
706
+ * For side placements, render the built-in floating launcher button that opens
707
+ * the panel (plus a close "×" in the header). Set `false` to drive open/close
708
+ * yourself via the handle's `open()`/`close()`/`toggle()`. Ignored when
709
+ * `placement` is `"inline"`. Defaults to `true`.
710
+ */
711
+ launcher?: boolean;
712
+ /**
713
+ * For side placements, whether the panel starts open. Ignored when `placement`
714
+ * is `"inline"` (an inline panel is always visible). Defaults to `false`.
715
+ */
716
+ defaultOpen?: boolean;
717
+ /** URL of a logo shown in the header (and on the launcher button, if shown). */
652
718
  logoUrl?: string;
653
719
  /** Show the agent name above assistant messages. Defaults to `false`. */
654
720
  showAgentName?: boolean;
@@ -665,10 +731,13 @@ export declare interface MountChatWidgetOptions {
665
731
  loadThreads?: boolean;
666
732
  /**
667
733
  * Conversational forms the agent can fill and submit during the chat. Each
668
- * config is installed as a {@link createFormCollector} for the lifetime of the
734
+ * entry is installed as a {@link createFormCollector} for the lifetime of the
669
735
  * widget (removed on `destroy()`).
736
+ *
737
+ * Pass a full config (with `schema`) to define it inline, or just `{ name }` to
738
+ * fetch the definition from the backend ({@link loadFormCollector}).
670
739
  */
671
- forms?: CreateFormCollectorOptions[];
740
+ forms?: Array<CreateFormCollectorOptions | LoadFormCollectorOptions>;
672
741
  /**
673
742
  * How clicking a suggested follow-up reply behaves. Defaults to sending the
674
743
  * reply as a new user message. Pass a handler to override, or `false` to
@@ -768,7 +837,7 @@ declare type ToolCallType = "form" | "confirmation_input" | "status_message" | "
768
837
 
769
838
  /**
770
839
  * Theme overrides for {@link mountChatWidget}. *
771
- * @see The `--ago-*` token reference in `docs/widget.md`.
840
+ * @see The `--ago-*` token reference in `docs/general/widget.md`.
772
841
  */
773
842
  export declare interface WidgetTheme {
774
843
  /** Font family for the whole panel. Pass `"inherit"` to adopt the page font. (`--ago-font`) */