@useago/sdk 0.4.3 → 0.4.5

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.
@@ -1 +1 @@
1
- const d=require("./createFormCollector-Wb8Rr-U2.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-BMTdfhHg.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 { n as d } from "./createFormCollector-BwvkKi48.js";
1
+ import { r as d } from "./createFormCollector-Cujr7hW4.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 @@
1
+ const q=require("./AgoClient-D4EL6nva.cjs");function O(s,t){const u=t?t.storage??(typeof localStorage<"u"?localStorage:void 0):void 0;let r=s;if(t&&u)try{const c=u.getItem(t.key);c!=null&&(r=JSON.parse(c))}catch{}const i=new Set,f=()=>i.forEach(c=>c(r));function m(){if(t&&u)try{u.setItem(t.key,JSON.stringify(r))}catch{}}return{get:()=>r,set:c=>{r=c,m(),f()},subscribe:c=>(i.add(c),()=>{i.delete(c)})}}var F=/^[a-zA-Z0-9_-]{1,40}$/,P=s=>s==null||s==="";function _(s,t){const u=t[s.property];if(P(u))return!1;if(Array.isArray(s.value))return s.value.some(f=>String(u)===String(f));if(!s.op)return String(u)===String(s.value);const r=Number(u),i=Number(s.value);if(Number.isNaN(r)||Number.isNaN(i))return!1;switch(s.op){case">=":return r>=i;case"<=":return r<=i;case">":return r>i;case"<":return r<i;default:return q.logger.warn(`Unknown requiredWhen op "${s.op}"; treating as not required.`),!1}}function y(s,t){const u=s.properties??{},r=new Set;for(const f of s.required??[]){const m=u[f]?.requiredWhen;(!m||_(m,t))&&r.add(f)}for(const[f,m]of Object.entries(u))m.requiredWhen&&_(m.requiredWhen,t)&&r.add(f);const i=[...r].filter(f=>P(t[f]));return{missing:i,complete:i.length===0}}function T(s){const t={};for(const[u,r]of Object.entries(s.properties??{}))t[u]={type:r.type,...r.description!=null&&{description:r.description},...r.enum&&{enum:r.enum},...r.default!==void 0&&{default:r.default}};return{type:"object",properties:t,required:[]}}function x(s){const{name:t,description:u,schema:r}=s;if(!F.test(t))throw new Error(`Invalid form collector name "${t}": must match ${F} (it becomes the update_/submit_ function names).`);const i=typeof s.submit=="string"?s.submit?{via:"client",url:s.submit}:!1:s.submit??!1,f=r.properties??{},m=e=>{const n={};for(const[a,o]of Object.entries(e)){const l=f[a];if(l)if(o==null)n[a]=o;else if(l.type==="number"||l.type==="integer"){const b=typeof o=="number"?o:Number(o);n[a]=Number.isNaN(b)?o:b}else l.type==="boolean"?n[a]=typeof o=="boolean"?o:o==="true"?!0:o==="false"?!1:!!o:n[a]=o}return n},c=s.initialValues??{},d=O({values:c,submitted:!1}),v=e=>{const n=d.get(),a={...n,values:{...n.values,...e}};return d.set(a),a};let p=null;const N=async()=>{const{values:e}=d.get(),{complete:n,missing:a}=y(r,e);if(!n)return{ok:!1,missing:a};if(!i)return{ok:!1,error:"No submit target configured for this form collector."};const o=e;try{let l;if(i.via==="client")if("handler"in i)l=await i.handler(o);else{const b=await fetch(i.url,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(o)});if(!b.ok)return{ok:!1,error:`Submit failed: HTTP ${b.status}`};l=await b.json().catch(()=>{})}else{if(!p)return{ok:!1,error:"Backend submit requires install(client) (or useFormCollector) first."};l=await p.submitFormCollector(i.destination,o)}return d.set({...d.get(),submitted:!0}),{ok:!0,result:l}}catch(l){const b=l instanceof Error?l.message:"Submit failed";return q.logger.error(`FormCollector "${t}" submit failed:`,l),{ok:!1,error:b}}},S={name:`update_${t}`,description:`Fill or update fields of the "${t}" form. ${u} 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:T(r),handler:e=>{const n=v(m(e)),{missing:a}=y(r,n.values);return{ok:!0,values:n.values,missing:a}}},g=[S];i&&g.push({name:`submit_${t}`,description:`Submit the completed "${t}" 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 j="client__",C=i?`submit_${t}`:null,E=e=>{const n=e.functionName??e.toolName;if(n)return n.startsWith(j)?n.slice(8):n},w=e=>{let n={...c},a=!1;for(const o of e){const l=E(o);l===S.name?o.arguments&&(n={...n,...m(o.arguments)}):C&&l===C&&o.status?.toLowerCase()==="done"&&(a=!0)}d.set({values:n,submitted:a})},h=`form:${t}`,$=()=>{const{values:e,submitted:n}=d.get(),{missing:a}=y(r,e),o=i?` When nothing is missing and the user confirms, call submit_${t}.`:"";return{name:`Form: ${t}`,description:`Form being filled conversationally. ${u} Call update_${t} with any fields the user provides; ask only for what is still missing.${o}`,data:{values:e,missing:a,submitted:n}}},k=e=>{w((e.messages??[]).flatMap(n=>n.toolCalls??[]))};return{name:t,store:d,functions:g,contextKey:h,contextProvider:$,install:e=>{p=e;for(const a of g)e.register(a);e.addDynamicContext(h,$);const n=d.subscribe(()=>e.notifyContextChanged());return e.on("conversation:loaded",k),()=>{n();for(const a of g)e.unregisterFunction(a.name);e.removeDynamicContext(h),e.off("conversation:loaded",k),p===e&&(p=null)}},hydrate:w,submit:N,getValues:()=>d.get().values,setValues:e=>{v(m(e))},reset:()=>{d.set({values:c,submitted:!1})}}}Object.defineProperty(exports,"createFormCollector",{enumerable:!0,get:function(){return x}});Object.defineProperty(exports,"createStore",{enumerable:!0,get:function(){return O}});Object.defineProperty(exports,"deriveFormStatus",{enumerable:!0,get:function(){return y}});
@@ -0,0 +1,244 @@
1
+ import { s as q } from "./AgoClient-rvTz2thR.js";
2
+ function P(n, t) {
3
+ const u = t ? t.storage ?? (typeof localStorage < "u" ? localStorage : void 0) : void 0;
4
+ let r = n;
5
+ if (t && u) try {
6
+ const c = u.getItem(t.key);
7
+ c != null && (r = JSON.parse(c));
8
+ } catch {
9
+ }
10
+ const i = /* @__PURE__ */ new Set(), f = () => i.forEach((c) => c(r));
11
+ function m() {
12
+ if (t && u) try {
13
+ u.setItem(t.key, JSON.stringify(r));
14
+ } catch {
15
+ }
16
+ }
17
+ return {
18
+ get: () => r,
19
+ set: (c) => {
20
+ r = c, m(), f();
21
+ },
22
+ subscribe: (c) => (i.add(c), () => {
23
+ i.delete(c);
24
+ })
25
+ };
26
+ }
27
+ var F = /^[a-zA-Z0-9_-]{1,40}$/, O = (n) => n == null || n === "";
28
+ function _(n, t) {
29
+ const u = t[n.property];
30
+ if (O(u)) return !1;
31
+ if (Array.isArray(n.value)) return n.value.some((f) => String(u) === String(f));
32
+ if (!n.op) return String(u) === String(n.value);
33
+ const r = Number(u), i = Number(n.value);
34
+ if (Number.isNaN(r) || Number.isNaN(i)) return !1;
35
+ switch (n.op) {
36
+ case ">=":
37
+ return r >= i;
38
+ case "<=":
39
+ return r <= i;
40
+ case ">":
41
+ return r > i;
42
+ case "<":
43
+ return r < i;
44
+ default:
45
+ return q.warn(`Unknown requiredWhen op "${n.op}"; treating as not required.`), !1;
46
+ }
47
+ }
48
+ function y(n, t) {
49
+ const u = n.properties ?? {}, r = /* @__PURE__ */ new Set();
50
+ for (const f of n.required ?? []) {
51
+ const m = u[f]?.requiredWhen;
52
+ (!m || _(m, t)) && r.add(f);
53
+ }
54
+ for (const [f, m] of Object.entries(u)) m.requiredWhen && _(m.requiredWhen, t) && r.add(f);
55
+ const i = [...r].filter((f) => O(t[f]));
56
+ return {
57
+ missing: i,
58
+ complete: i.length === 0
59
+ };
60
+ }
61
+ function T(n) {
62
+ const t = {};
63
+ for (const [u, r] of Object.entries(n.properties ?? {})) t[u] = {
64
+ type: r.type,
65
+ ...r.description != null && { description: r.description },
66
+ ...r.enum && { enum: r.enum },
67
+ ...r.default !== void 0 && { default: r.default }
68
+ };
69
+ return {
70
+ type: "object",
71
+ properties: t,
72
+ required: []
73
+ };
74
+ }
75
+ function W(n) {
76
+ const { name: t, description: u, schema: r } = n;
77
+ if (!F.test(t)) throw new Error(`Invalid form collector name "${t}": must match ${F} (it becomes the update_/submit_ function names).`);
78
+ const i = typeof n.submit == "string" ? n.submit ? {
79
+ via: "client",
80
+ url: n.submit
81
+ } : !1 : n.submit ?? !1, f = r.properties ?? {}, m = (e) => {
82
+ const s = {};
83
+ for (const [a, o] of Object.entries(e)) {
84
+ const l = f[a];
85
+ if (l)
86
+ if (o == null) s[a] = o;
87
+ else if (l.type === "number" || l.type === "integer") {
88
+ const p = typeof o == "number" ? o : Number(o);
89
+ s[a] = Number.isNaN(p) ? o : p;
90
+ } else l.type === "boolean" ? s[a] = typeof o == "boolean" ? o : o === "true" ? !0 : o === "false" ? !1 : !!o : s[a] = o;
91
+ }
92
+ return s;
93
+ }, c = n.initialValues ?? {}, d = P({
94
+ values: c,
95
+ submitted: !1
96
+ }), v = (e) => {
97
+ const s = d.get(), a = {
98
+ ...s,
99
+ values: {
100
+ ...s.values,
101
+ ...e
102
+ }
103
+ };
104
+ return d.set(a), a;
105
+ };
106
+ let b = null;
107
+ const N = async () => {
108
+ const { values: e } = d.get(), { complete: s, missing: a } = y(r, e);
109
+ if (!s) return {
110
+ ok: !1,
111
+ missing: a
112
+ };
113
+ if (!i) return {
114
+ ok: !1,
115
+ error: "No submit target configured for this form collector."
116
+ };
117
+ const o = e;
118
+ try {
119
+ let l;
120
+ if (i.via === "client") if ("handler" in i) l = await i.handler(o);
121
+ else {
122
+ const p = await fetch(i.url, {
123
+ method: "POST",
124
+ headers: { "Content-Type": "application/json" },
125
+ credentials: "include",
126
+ body: JSON.stringify(o)
127
+ });
128
+ if (!p.ok) return {
129
+ ok: !1,
130
+ error: `Submit failed: HTTP ${p.status}`
131
+ };
132
+ l = await p.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(i.destination, o);
141
+ }
142
+ return d.set({
143
+ ...d.get(),
144
+ submitted: !0
145
+ }), {
146
+ ok: !0,
147
+ result: l
148
+ };
149
+ } catch (l) {
150
+ const p = l instanceof Error ? l.message : "Submit failed";
151
+ return q.error(`FormCollector "${t}" submit failed:`, l), {
152
+ ok: !1,
153
+ error: p
154
+ };
155
+ }
156
+ }, S = {
157
+ name: `update_${t}`,
158
+ description: `Fill or update fields of the "${t}" form. ${u} 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: T(r),
160
+ handler: (e) => {
161
+ const s = v(m(e)), { missing: a } = y(r, s.values);
162
+ return {
163
+ ok: !0,
164
+ values: s.values,
165
+ missing: a
166
+ };
167
+ }
168
+ }, g = [S];
169
+ i && g.push({
170
+ name: `submit_${t}`,
171
+ description: `Submit the completed "${t}" 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 x = "client__", w = i ? `submit_${t}` : null, E = (e) => {
179
+ const s = e.functionName ?? e.toolName;
180
+ if (s)
181
+ return s.startsWith(x) ? s.slice(8) : s;
182
+ }, C = (e) => {
183
+ let s = { ...c }, a = !1;
184
+ for (const o of e) {
185
+ const l = E(o);
186
+ l === S.name ? o.arguments && (s = {
187
+ ...s,
188
+ ...m(o.arguments)
189
+ }) : w && l === w && o.status?.toLowerCase() === "done" && (a = !0);
190
+ }
191
+ d.set({
192
+ values: s,
193
+ submitted: a
194
+ });
195
+ }, h = `form:${t}`, $ = () => {
196
+ const { values: e, submitted: s } = d.get(), { missing: a } = y(r, e), o = i ? ` When nothing is missing and the user confirms, call submit_${t}.` : "";
197
+ return {
198
+ name: `Form: ${t}`,
199
+ description: `Form being filled conversationally. ${u} Call update_${t} with any fields the user provides; ask only for what is still missing.${o}`,
200
+ data: {
201
+ values: e,
202
+ missing: a,
203
+ submitted: s
204
+ }
205
+ };
206
+ }, k = (e) => {
207
+ C((e.messages ?? []).flatMap((s) => s.toolCalls ?? []));
208
+ };
209
+ return {
210
+ name: t,
211
+ store: d,
212
+ functions: g,
213
+ contextKey: h,
214
+ contextProvider: $,
215
+ install: (e) => {
216
+ b = e;
217
+ for (const a of g) e.register(a);
218
+ e.addDynamicContext(h, $);
219
+ const s = d.subscribe(() => e.notifyContextChanged());
220
+ return e.on("conversation:loaded", k), () => {
221
+ s();
222
+ for (const a of g) e.unregisterFunction(a.name);
223
+ e.removeDynamicContext(h), e.off("conversation:loaded", k), b === e && (b = null);
224
+ };
225
+ },
226
+ hydrate: C,
227
+ submit: N,
228
+ getValues: () => d.get().values,
229
+ setValues: (e) => {
230
+ v(m(e));
231
+ },
232
+ reset: () => {
233
+ d.set({
234
+ values: c,
235
+ submitted: !1
236
+ });
237
+ }
238
+ };
239
+ }
240
+ export {
241
+ y as n,
242
+ P as r,
243
+ W as t
244
+ };
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./AgoClient-D4EL6nva.cjs"),p=require("./createFormCollector-Wb8Rr-U2.cjs"),A=require("./createConversationSession-DtaeA418.cjs"),C=require("./createMockClient-zHQ0cjUH.cjs"),g=require("./functions-DsmzgHjC.cjs");function h(e){return e}function E(e,o){return e.on("message:complete",o),()=>e.off("message:complete",o)}function S(e,o){return e.on("message:chunk",o),()=>e.off("message:chunk",o)}function y(e,o){return e.on("message:start",o),()=>e.off("message:start",o)}function b(e,o){return e.on("message:error",o),()=>e.off("message:error",o)}function v(e,o){return e.on("toolCall:received",o),()=>e.off("toolCall:received",o)}function M(e,o){return e.on("function:invoke",o),()=>e.off("function:invoke",o)}async function*k(e,o,l){const n=[];let r=null,a=!1;const c=s=>{n.push(s),r?.()},f=s=>c({type:"start",data:s}),t=s=>c({type:"chunk",data:s}),u=s=>{c({type:"complete",data:s}),a=!0,r?.()},m=s=>{c({type:"error",data:s}),a=!0,r?.()},d=s=>c({type:"toolCall",data:s});e.on("message:start",f),e.on("message:chunk",t),e.on("message:complete",u),e.on("message:error",m),e.on("toolCall:received",d),e.sendMessage(o,l).catch(()=>{a=!0,r?.()});try{for(;!a||n.length>0;)n.length>0?yield n.shift():(await new Promise(s=>{r=s}),r=null)}finally{e.off("message:start",f),e.off("message:chunk",t),e.off("message:complete",u),e.off("message:error",m),e.off("toolCall:received",d)}}function w(e){let o,l,n,r,a,c;if(typeof window<"u"&&window.AGO){const t=window.AGO;o=t.basepath,l=t.widgetId,n=t.agent||t.defaultAgent,r=t.permission,a=t.email,c=t.jwt}if(typeof document<"u"){const t=u=>document.querySelector(`meta[name="${u}"]`)?.getAttribute("content")||void 0;o=o||t("ago-base-url"),l=l||t("ago-widget-id"),n=n||t("ago-agent")||t("ago-agent-id"),r=r||t("ago-permission"),a=a||t("ago-user-email")}if(typeof document<"u"){const t=[document.body,...Array.from(document.querySelectorAll("script[data-ago-base-url]"))].filter(Boolean);for(const u of t)u&&(o=o||u.getAttribute("data-ago-base-url")||void 0,l=l||u.getAttribute("data-ago-widget-id")||void 0,n=n||u.getAttribute("data-ago-agent")||u.getAttribute("data-ago-agent-id")||void 0,r=r||u.getAttribute("data-ago-permission")||void 0,a=a||u.getAttribute("data-ago-user-email")||void 0)}o=e?.baseUrl||o,l=e?.widgetId||l,n=e?.agent||e?.defaultAgentId||n,r=e?.permission||r,a=e?.userEmail||a,c=e?.userJwt||c;const f=e?.debug;return o?{baseUrl:o,widgetId:l,agent:n,permission:r,userEmail:a,userJwt:c,debug:f}:null}function q(e){const o=w(e);if(!o)throw new Error('createAgo(): could not detect AGO configuration. Set window.AGO, add <meta name="ago-base-url">, or pass { baseUrl } explicitly.');return new i.AgoClient(o)}function F(e,o){return{...e,handler:o}}exports.AgoApiError=i.AgoApiError;exports.AgoClient=i.AgoClient;exports.AgoError=i.AgoError;exports.AgoFunctionError=i.AgoFunctionError;exports.AgoNetworkError=i.AgoNetworkError;exports.AgoStreamError=i.AgoStreamError;exports.ClientContextRegistry=i.ClientContextRegistry;exports.EventEmitter=i.EventEmitter;exports.FunctionRegistry=i.FunctionRegistry;exports.SSEHandler=i.SSEHandler;exports.autoDetectConfig=w;exports.copyToClipboard=g.copyToClipboard;exports.createAgo=q;exports.createConversationSession=A.createConversationSession;exports.createFormCollector=p.createFormCollector;exports.createMessageStream=k;exports.createMockClient=C.createMockClient;exports.createStore=p.createStore;exports.defineFunction=h;exports.getLocalStorage=g.getLocalStorage;exports.getUserLocation=g.getUserLocation;exports.highlightElement=g.highlightElement;exports.isStreamNetworkError=i.isStreamNetworkError;exports.logger=i.logger;exports.onFunctionInvoke=M;exports.onMessage=E;exports.onMessageChunk=S;exports.onMessageError=b;exports.onMessageStart=y;exports.onToolCall=v;exports.openUrl=g.openUrl;exports.scrollToElement=g.scrollToElement;exports.setLocalStorage=g.setLocalStorage;exports.setTheme=g.setTheme;exports.showConfirmDialog=g.showConfirmDialog;exports.showNotification=g.showNotification;exports.showToast=g.showToast;exports.submitForm=g.submitForm;exports.trackEvent=g.trackEvent;exports.withHandler=F;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./AgoClient-D4EL6nva.cjs"),m=require("./createFormCollector-BMTdfhHg.cjs"),A=require("./createConversationSession-0F_OXdQB.cjs"),C=require("./createMockClient-zHQ0cjUH.cjs"),g=require("./functions-DsmzgHjC.cjs");function h(e){return e}function E(e,o){return e.on("message:complete",o),()=>e.off("message:complete",o)}function S(e,o){return e.on("message:chunk",o),()=>e.off("message:chunk",o)}function y(e,o){return e.on("message:start",o),()=>e.off("message:start",o)}function b(e,o){return e.on("message:error",o),()=>e.off("message:error",o)}function v(e,o){return e.on("toolCall:received",o),()=>e.off("toolCall:received",o)}function M(e,o){return e.on("function:invoke",o),()=>e.off("function:invoke",o)}async function*k(e,o,l){const n=[];let r=null,a=!1;const c=s=>{n.push(s),r?.()},f=s=>c({type:"start",data:s}),t=s=>c({type:"chunk",data:s}),u=s=>{c({type:"complete",data:s}),a=!0,r?.()},d=s=>{c({type:"error",data:s}),a=!0,r?.()},p=s=>c({type:"toolCall",data:s});e.on("message:start",f),e.on("message:chunk",t),e.on("message:complete",u),e.on("message:error",d),e.on("toolCall:received",p),e.sendMessage(o,l).catch(()=>{a=!0,r?.()});try{for(;!a||n.length>0;)n.length>0?yield n.shift():(await new Promise(s=>{r=s}),r=null)}finally{e.off("message:start",f),e.off("message:chunk",t),e.off("message:complete",u),e.off("message:error",d),e.off("toolCall:received",p)}}function w(e){let o,l,n,r,a,c;if(typeof window<"u"&&window.AGO){const t=window.AGO;o=t.basepath,l=t.widgetId,n=t.agent||t.defaultAgent,r=t.permission,a=t.email,c=t.jwt}if(typeof document<"u"){const t=u=>document.querySelector(`meta[name="${u}"]`)?.getAttribute("content")||void 0;o=o||t("ago-base-url"),l=l||t("ago-widget-id"),n=n||t("ago-agent")||t("ago-agent-id"),r=r||t("ago-permission"),a=a||t("ago-user-email")}if(typeof document<"u"){const t=[document.body,...Array.from(document.querySelectorAll("script[data-ago-base-url]"))].filter(Boolean);for(const u of t)u&&(o=o||u.getAttribute("data-ago-base-url")||void 0,l=l||u.getAttribute("data-ago-widget-id")||void 0,n=n||u.getAttribute("data-ago-agent")||u.getAttribute("data-ago-agent-id")||void 0,r=r||u.getAttribute("data-ago-permission")||void 0,a=a||u.getAttribute("data-ago-user-email")||void 0)}o=e?.baseUrl||o,l=e?.widgetId||l,n=e?.agent||e?.defaultAgentId||n,r=e?.permission||r,a=e?.userEmail||a,c=e?.userJwt||c;const f=e?.debug;return o?{baseUrl:o,widgetId:l,agent:n,permission:r,userEmail:a,userJwt:c,debug:f}:null}function F(e){const o=w(e);if(!o)throw new Error('createAgo(): could not detect AGO configuration. Set window.AGO, add <meta name="ago-base-url">, or pass { baseUrl } explicitly.');return new i.AgoClient(o)}function q(e,o){return{...e,handler:o}}exports.AgoApiError=i.AgoApiError;exports.AgoClient=i.AgoClient;exports.AgoError=i.AgoError;exports.AgoFunctionError=i.AgoFunctionError;exports.AgoNetworkError=i.AgoNetworkError;exports.AgoStreamError=i.AgoStreamError;exports.ClientContextRegistry=i.ClientContextRegistry;exports.EventEmitter=i.EventEmitter;exports.FunctionRegistry=i.FunctionRegistry;exports.SSEHandler=i.SSEHandler;exports.autoDetectConfig=w;exports.copyToClipboard=g.copyToClipboard;exports.createAgo=F;exports.createConversationSession=A.createConversationSession;exports.createFormCollector=m.createFormCollector;exports.createMessageStream=k;exports.createMockClient=C.createMockClient;exports.createStore=m.createStore;exports.defineFunction=h;exports.deriveFormStatus=m.deriveFormStatus;exports.getLocalStorage=g.getLocalStorage;exports.getUserLocation=g.getUserLocation;exports.highlightElement=g.highlightElement;exports.isStreamNetworkError=i.isStreamNetworkError;exports.logger=i.logger;exports.onFunctionInvoke=M;exports.onMessage=E;exports.onMessageChunk=S;exports.onMessageError=b;exports.onMessageStart=y;exports.onToolCall=v;exports.openUrl=g.openUrl;exports.scrollToElement=g.scrollToElement;exports.setLocalStorage=g.setLocalStorage;exports.setTheme=g.setTheme;exports.showConfirmDialog=g.showConfirmDialog;exports.showNotification=g.showNotification;exports.showToast=g.showToast;exports.submitForm=g.submitForm;exports.trackEvent=g.trackEvent;exports.withHandler=q;
package/dist/index.d.cts CHANGED
@@ -740,6 +740,19 @@ export declare function createStore<T>(initial: T, persist?: PersistOptions): St
740
740
  */
741
741
  export declare function defineFunction(definition: ClientFunctionDefinition): ClientFunctionDefinition;
742
742
 
743
+ /**
744
+ * Compute which required fields are still empty and whether the form is complete.
745
+ * Pure — the single home for the "required + non-empty" rule, shared by the update
746
+ * handler, submit, the dynamic context, and the React hook. Derived on read so the
747
+ * store only ever holds canonical state ({@link FormCollectorState}).
748
+ *
749
+ * Requiredness is answer-dependent: a field listed in `required` is required unless
750
+ * it carries a `requiredWhen` that doesn't currently hold, and any field whose
751
+ * `requiredWhen` holds becomes required. So conditional fields surface in `missing`
752
+ * exactly when the answers make them relevant.
753
+ */
754
+ export declare function deriveFormStatus(schema: FormCollectorSchema, values: Partial<Record<string, unknown>>): FormCollectorStatus;
755
+
743
756
  /**
744
757
  * A function that returns a fresh context entry on demand.
745
758
  * Evaluated every time a message is sent — use it to pull data from stores,
@@ -799,22 +812,29 @@ export declare interface FormCollector<V = Record<string, unknown>> {
799
812
  }
800
813
 
801
814
  /**
802
- * JSON-schema shape of a form's fields — identical to a client function's
803
- * `parameters`, so one schema feeds the store, the update function, and the
804
- * dynamic context with no second type.
815
+ * Shape of a form's fields. Mirrors a client function's `parameters` (so the same
816
+ * 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.
805
817
  */
806
- export declare type FormCollectorSchema = ClientFunctionSchema["parameters"];
818
+ export declare interface FormCollectorSchema {
819
+ type: "object";
820
+ properties: Record<string, FormFieldSchema>;
821
+ required?: string[];
822
+ }
807
823
 
808
- /** Live state held in the collector's store. */
824
+ /** Canonical, source-of-truth state held in the collector's store. */
809
825
  export declare interface FormCollectorState<V = Record<string, unknown>> {
810
826
  /** Field values collected so far. */
811
827
  values: Partial<V>;
828
+ /** True once a submit succeeded. */
829
+ submitted: boolean;
830
+ }
831
+
832
+ /** Completeness status derived from values + schema — computed on read, never stored. */
833
+ export declare interface FormCollectorStatus {
812
834
  /** Required field names still empty. */
813
835
  missing: string[];
814
836
  /** True when no required field is missing. */
815
837
  complete: boolean;
816
- /** True once a submit succeeded. */
817
- submitted: boolean;
818
838
  }
819
839
 
820
840
  export declare interface FormField {
@@ -825,6 +845,43 @@ export declare interface FormField {
825
845
  default?: unknown;
826
846
  }
827
847
 
848
+ /**
849
+ * A field's conditional-requiredness rule. The field becomes required exactly
850
+ * when the controlling `property` matches `value` against the answers collected
851
+ * so far:
852
+ * - a single `value`, no `op` — equality (compared as strings);
853
+ * - a single `value` with `op` — numeric comparison (both sides coerced to numbers);
854
+ * - an array `value`, no `op` — "one of": matches when the property equals any
855
+ * listed value.
856
+ *
857
+ * SDK-only — it is stripped from the schema before it reaches the LLM tool
858
+ */
859
+ declare interface FormFieldCondition {
860
+ /** The controlling field whose value the rule tests. */
861
+ property: string;
862
+ /** Comparison operator; omitted means equality. Ignored when `value` is an array. */
863
+ op?: ">=" | "<=" | ">" | "<";
864
+ /**
865
+ * The value(s) to test the controlling field against. A single value is an
866
+ * equality (or, with `op`, a numeric comparison); an array is an "is one of"
867
+ * membership test, e.g. `value: ["1", "2", "3"]`.
868
+ */
869
+ value: string | number | Array<string | number>;
870
+ }
871
+
872
+ /** A single field's schema: the wire-legal keys plus the SDK-only `requiredWhen`. */
873
+ declare interface FormFieldSchema {
874
+ type: string;
875
+ description?: string;
876
+ enum?: string[];
877
+ default?: unknown;
878
+ /**
879
+ * Makes the field required only while this condition holds. Drives the dynamic
880
+ * `missing` list; stripped before the LLM tool — see {@link toWireParameters}.
881
+ */
882
+ requiredWhen?: FormFieldCondition;
883
+ }
884
+
828
885
  /**
829
886
  * Form schema for tool calls requiring user input
830
887
  */
package/dist/index.d.ts CHANGED
@@ -740,6 +740,19 @@ export declare function createStore<T>(initial: T, persist?: PersistOptions): St
740
740
  */
741
741
  export declare function defineFunction(definition: ClientFunctionDefinition): ClientFunctionDefinition;
742
742
 
743
+ /**
744
+ * Compute which required fields are still empty and whether the form is complete.
745
+ * Pure — the single home for the "required + non-empty" rule, shared by the update
746
+ * handler, submit, the dynamic context, and the React hook. Derived on read so the
747
+ * store only ever holds canonical state ({@link FormCollectorState}).
748
+ *
749
+ * Requiredness is answer-dependent: a field listed in `required` is required unless
750
+ * it carries a `requiredWhen` that doesn't currently hold, and any field whose
751
+ * `requiredWhen` holds becomes required. So conditional fields surface in `missing`
752
+ * exactly when the answers make them relevant.
753
+ */
754
+ export declare function deriveFormStatus(schema: FormCollectorSchema, values: Partial<Record<string, unknown>>): FormCollectorStatus;
755
+
743
756
  /**
744
757
  * A function that returns a fresh context entry on demand.
745
758
  * Evaluated every time a message is sent — use it to pull data from stores,
@@ -799,22 +812,29 @@ export declare interface FormCollector<V = Record<string, unknown>> {
799
812
  }
800
813
 
801
814
  /**
802
- * JSON-schema shape of a form's fields — identical to a client function's
803
- * `parameters`, so one schema feeds the store, the update function, and the
804
- * dynamic context with no second type.
815
+ * Shape of a form's fields. Mirrors a client function's `parameters` (so the same
816
+ * 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.
805
817
  */
806
- export declare type FormCollectorSchema = ClientFunctionSchema["parameters"];
818
+ export declare interface FormCollectorSchema {
819
+ type: "object";
820
+ properties: Record<string, FormFieldSchema>;
821
+ required?: string[];
822
+ }
807
823
 
808
- /** Live state held in the collector's store. */
824
+ /** Canonical, source-of-truth state held in the collector's store. */
809
825
  export declare interface FormCollectorState<V = Record<string, unknown>> {
810
826
  /** Field values collected so far. */
811
827
  values: Partial<V>;
828
+ /** True once a submit succeeded. */
829
+ submitted: boolean;
830
+ }
831
+
832
+ /** Completeness status derived from values + schema — computed on read, never stored. */
833
+ export declare interface FormCollectorStatus {
812
834
  /** Required field names still empty. */
813
835
  missing: string[];
814
836
  /** True when no required field is missing. */
815
837
  complete: boolean;
816
- /** True once a submit succeeded. */
817
- submitted: boolean;
818
838
  }
819
839
 
820
840
  export declare interface FormField {
@@ -825,6 +845,43 @@ export declare interface FormField {
825
845
  default?: unknown;
826
846
  }
827
847
 
848
+ /**
849
+ * A field's conditional-requiredness rule. The field becomes required exactly
850
+ * when the controlling `property` matches `value` against the answers collected
851
+ * so far:
852
+ * - a single `value`, no `op` — equality (compared as strings);
853
+ * - a single `value` with `op` — numeric comparison (both sides coerced to numbers);
854
+ * - an array `value`, no `op` — "one of": matches when the property equals any
855
+ * listed value.
856
+ *
857
+ * SDK-only — it is stripped from the schema before it reaches the LLM tool
858
+ */
859
+ declare interface FormFieldCondition {
860
+ /** The controlling field whose value the rule tests. */
861
+ property: string;
862
+ /** Comparison operator; omitted means equality. Ignored when `value` is an array. */
863
+ op?: ">=" | "<=" | ">" | "<";
864
+ /**
865
+ * The value(s) to test the controlling field against. A single value is an
866
+ * equality (or, with `op`, a numeric comparison); an array is an "is one of"
867
+ * membership test, e.g. `value: ["1", "2", "3"]`.
868
+ */
869
+ value: string | number | Array<string | number>;
870
+ }
871
+
872
+ /** A single field's schema: the wire-legal keys plus the SDK-only `requiredWhen`. */
873
+ declare interface FormFieldSchema {
874
+ type: string;
875
+ description?: string;
876
+ enum?: string[];
877
+ default?: unknown;
878
+ /**
879
+ * Makes the field required only while this condition holds. Drives the dynamic
880
+ * `missing` list; stripped before the LLM tool — see {@link toWireParameters}.
881
+ */
882
+ requiredWhen?: FormFieldCondition;
883
+ }
884
+
828
885
  /**
829
886
  * Form schema for tool calls requiring user input
830
887
  */