@useago/sdk 0.4.1 → 0.4.3

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 (35) hide show
  1. package/dist/{AgoClient-B6PsfMeg.cjs → AgoClient-D4EL6nva.cjs} +3 -3
  2. package/dist/{AgoClient-BerJvssl.js → AgoClient-rvTz2thR.js} +19 -14
  3. package/dist/angular.cjs +1 -1
  4. package/dist/angular.d.cts +15 -0
  5. package/dist/angular.d.ts +15 -0
  6. package/dist/angular.js +1 -1
  7. package/dist/{createConversationSession-CLZvxyuu.js → createConversationSession-D9FesBQS.js} +1 -1
  8. package/dist/{createConversationSession-D3K5Gf1k.cjs → createConversationSession-DtaeA418.cjs} +1 -1
  9. package/dist/{createFormCollector-CD1rqRG4.js → createFormCollector-BwvkKi48.js} +32 -29
  10. package/dist/createFormCollector-Wb8Rr-U2.cjs +1 -0
  11. package/dist/{createMockClient-tVsApEAh.js → createMockClient-DwdxNwEn.js} +4 -2
  12. package/dist/createMockClient-zHQ0cjUH.cjs +1 -0
  13. package/dist/devtools.cjs +5 -4
  14. package/dist/devtools.d.cts +15 -0
  15. package/dist/devtools.d.ts +15 -0
  16. package/dist/devtools.js +35 -31
  17. package/dist/index.cjs +1 -1
  18. package/dist/index.d.cts +15 -0
  19. package/dist/index.d.ts +15 -0
  20. package/dist/index.js +4 -4
  21. package/dist/react.cjs +1 -1
  22. package/dist/react.d.cts +15 -0
  23. package/dist/react.d.ts +15 -0
  24. package/dist/react.js +3 -3
  25. package/dist/vue.cjs +1 -1
  26. package/dist/vue.d.cts +15 -0
  27. package/dist/vue.d.ts +15 -0
  28. package/dist/vue.js +1 -1
  29. package/dist/widget.cjs +1 -1
  30. package/dist/widget.d.cts +50 -0
  31. package/dist/widget.d.ts +50 -0
  32. package/dist/widget.js +203 -183
  33. package/package.json +1 -1
  34. package/dist/createFormCollector-D1FfiSgA.cjs +0 -1
  35. package/dist/createMockClient-DMFGIOtc.cjs +0 -1
@@ -1,6 +1,6 @@
1
- var h=class extends Error{constructor(e,t,r){super(e),this.code=t,this.statusCode=r,this.name="AgoError"}},u=class p extends h{constructor(t,r,s,n,o,a){super(t,r,s),this.type=n,this.param=o,this.docUrl=a,this.name="AgoApiError"}static fromResponse(t,r){const s=t.error;return new p(s.message,s.code,r,s.type,s.param,s.doc_url)}},d=class extends h{constructor(e,t){super(e,"network_error"),this.originalError=t,this.name="AgoNetworkError"}},g=class extends h{constructor(e){super(e,"stream_error"),this.name="AgoStreamError"}},m=class extends h{constructor(e,t,r){super(e,"function_error"),this.functionName=t,this.originalError=r,this.name="AgoFunctionError"}},_=class{constructor(e=!1){this.enabled=e}enable(){this.enabled=!0}disable(){this.enabled=!1}log(...e){this.enabled&&console.log("[AGO SDK]",...e)}warn(...e){this.enabled&&console.warn("[AGO SDK]",...e)}error(...e){console.error("[AGO SDK]",...e)}debug(...e){this.enabled&&console.debug("[AGO SDK]",...e)}},i=new _,f="ago_widget_id";function S(){if(typeof localStorage<"u"){const t=localStorage.getItem(f);if(t)return t}const e=crypto.randomUUID();if(typeof localStorage<"u")try{localStorage.setItem(f,e)}catch{}return e}var k=class{constructor(e){this.baseUrl=e.baseUrl.replace(/\/$/,""),this.headers={"X-Widget-Id":e.widgetId||S()},e.userEmail&&(this.headers["X-User-Email"]=e.userEmail),e.userJwt&&(this.headers.Authorization=`Bearer ${e.userJwt}`),e.permission&&(this.headers["X-Widget-Permission"]=e.permission)}updateConfig(e){e.baseUrl&&(this.baseUrl=e.baseUrl.replace(/\/$/,"")),e.widgetId&&(this.headers["X-Widget-Id"]=e.widgetId),e.userEmail&&(this.headers["X-User-Email"]=e.userEmail),e.userJwt&&(this.headers.Authorization=`Bearer ${e.userJwt}`),e.permission!==void 0&&(e.permission?this.headers["X-Widget-Permission"]=e.permission:delete this.headers["X-Widget-Permission"])}async get(e){return this.request("GET",e)}async post(e,t){return this.request("POST",e,t)}async postStream(e,t){const r=`${this.baseUrl}${e}`;i.debug("POST (stream)",r,t);try{const s=await fetch(r,{method:"POST",headers:{...this.headers,"Content-Type":"application/json"},body:t?JSON.stringify(t):void 0});return s.ok||await this.handleErrorResponse(s),s}catch(s){throw s instanceof u?s:new d(`Network error: ${s instanceof Error?s.message:"Unknown error"}`,s instanceof Error?s:void 0)}}async postFormData(e,t){const r=`${this.baseUrl}${e}`;i.debug("POST (formData)",r);const s={...this.headers};try{const n=await fetch(r,{method:"POST",headers:s,body:t});return n.ok||await this.handleErrorResponse(n),n}catch(n){throw n instanceof u?n:new d(`Network error: ${n instanceof Error?n.message:"Unknown error"}`,n instanceof Error?n:void 0)}}async request(e,t,r){const s=`${this.baseUrl}${t}`;i.debug(e,s,r);try{const n=await fetch(s,{method:e,headers:{...this.headers,"Content-Type":"application/json"},body:r?JSON.stringify(r):void 0});return n.ok||await this.handleErrorResponse(n),n.status===204?void 0:n.json()}catch(n){throw n instanceof u?n:new d(`Network error: ${n instanceof Error?n.message:"Unknown error"}`,n instanceof Error?n:void 0)}}async handleErrorResponse(e){let t;try{t=await e.json()}catch{}throw t?.error?u.fromResponse(t,e.status):new u(`HTTP ${e.status}: ${e.statusText}`,"http_error",e.status,"api_error")}},y=class{constructor(){this.functions=new Map}register(e,t,r){if(typeof e=="object"){const{name:n,handler:o,description:a,parameters:c}=e;return this.register(n,o,{description:a,parameters:c})}const s=e;if(!t||!r)throw new Error("handler and schema are required");this.functions.has(s)&&i.warn(`Function "${s}" is being overwritten`),this.functions.set(s,{schema:{...r,name:s},handler:t}),i.log(`Registered function: ${s}`)}unregister(e){const t=this.functions.delete(e);return t&&i.log(`Unregistered function: ${e}`),t}get(e){return this.functions.get(e)}has(e){return this.functions.has(e)}getSchemas(){return Array.from(this.functions.values()).map(e=>e.schema)}async execute(e,t){const r=this.functions.get(e);if(!r)throw new m(`Function "${e}" is not registered`,e);i.log(`Executing function: ${e}`,t);try{const s=await r.handler(t);return i.log(`Function ${e} completed:`,s),s}catch(s){throw i.error(`Function ${e} failed:`,s),new m(`Function "${e}" execution failed: ${s instanceof Error?s.message:"Unknown error"}`,e,s instanceof Error?s:void 0)}}clear(){this.functions.clear(),i.log("Cleared all registered functions")}get size(){return this.functions.size}},v=class{constructor(){this.entries=new Map,this.dynamicProviders=new Map}set(e,t){this.entries.set(e,t),i.log(`ClientContext set: ${e}`)}remove(e){const t=this.entries.delete(e);return t&&i.log(`ClientContext removed: ${e}`),t}addDynamicProvider(e,t){this.dynamicProviders.set(e,t),i.log(`DynamicContext provider added: ${e}`)}removeDynamicProvider(e){const t=this.dynamicProviders.delete(e);return t&&i.log(`DynamicContext provider removed: ${e}`),t}getSnapshot(){if(this.entries.size===0&&this.dynamicProviders.size===0)return null;const e={};for(const[t,r]of this.entries)e[t]=r;for(const[t,r]of this.dynamicProviders)try{const s=r();s&&(e[t]=s)}catch(s){i.error(`DynamicContext provider "${t}" threw:`,s)}return Object.keys(e).length===0?null:{entries:e}}clear(){this.entries.clear(),this.dynamicProviders.clear(),i.log("ClientContext cleared")}},w=class{constructor(e){this.callbacks=e,this.buffer="",this.message={},this.toolCalls=[],this.sources=[],this.followUpReplies=[],this.isFirstChunk=!0}async processStream(e){if(!e.body)throw new g("Response has no body");const t=e.body.getReader(),r=new TextDecoder;try{for(;;){const{done:s,value:n}=await t.read();if(s)break;const o=r.decode(n,{stream:!0});this.buffer+=o,this.processBuffer()}return this.buffer.trim()&&this.processBuffer(),this.buildFinalMessage()}catch(s){const n=s instanceof Error?s:new g("Stream processing failed");throw this.callbacks.onError?.(n),n}finally{t.releaseLock()}}processBuffer(){const e=this.buffer.split(`
1
+ var u=class extends Error{constructor(e,t,r){super(e),this.code=t,this.statusCode=r,this.name="AgoError"}},h=class p extends u{constructor(t,r,s,n,o,a){super(t,r,s),this.type=n,this.param=o,this.docUrl=a,this.name="AgoApiError"}static fromResponse(t,r){const s=t.error;return new p(s.message,s.code,r,s.type,s.param,s.doc_url)}},d=class extends u{constructor(e,t){super(e,"network_error"),this.originalError=t,this.name="AgoNetworkError"}},g=class extends u{constructor(e){super(e,"stream_error"),this.name="AgoStreamError"}},f=class extends u{constructor(e,t,r){super(e,"function_error"),this.functionName=t,this.originalError=r,this.name="AgoFunctionError"}},_=class{constructor(e=!1){this.enabled=e}enable(){this.enabled=!0}disable(){this.enabled=!1}log(...e){this.enabled&&console.log("[AGO SDK]",...e)}warn(...e){this.enabled&&console.warn("[AGO SDK]",...e)}error(...e){console.error("[AGO SDK]",...e)}debug(...e){this.enabled&&console.debug("[AGO SDK]",...e)}},i=new _,m="ago_widget_id";function S(){if(typeof localStorage<"u"){const t=localStorage.getItem(m);if(t)return t}const e=crypto.randomUUID();if(typeof localStorage<"u")try{localStorage.setItem(m,e)}catch{}return e}var k=class{constructor(e){this.baseUrl=e.baseUrl.replace(/\/$/,""),this.headers={"X-Widget-Id":e.widgetId||S()},e.userEmail&&(this.headers["X-User-Email"]=e.userEmail),e.userJwt&&(this.headers.Authorization=`Bearer ${e.userJwt}`),e.permission&&(this.headers["X-Widget-Permission"]=e.permission)}updateConfig(e){e.baseUrl&&(this.baseUrl=e.baseUrl.replace(/\/$/,"")),e.widgetId&&(this.headers["X-Widget-Id"]=e.widgetId),e.userEmail&&(this.headers["X-User-Email"]=e.userEmail),e.userJwt&&(this.headers.Authorization=`Bearer ${e.userJwt}`),e.permission!==void 0&&(e.permission?this.headers["X-Widget-Permission"]=e.permission:delete this.headers["X-Widget-Permission"])}async get(e){return this.request("GET",e)}async post(e,t){return this.request("POST",e,t)}async postStream(e,t){const r=`${this.baseUrl}${e}`;i.debug("POST (stream)",r,t);try{const s=await fetch(r,{method:"POST",headers:{...this.headers,"Content-Type":"application/json"},body:t?JSON.stringify(t):void 0});return s.ok||await this.handleErrorResponse(s),s}catch(s){throw s instanceof h?s:new d(`Network error: ${s instanceof Error?s.message:"Unknown error"}`,s instanceof Error?s:void 0)}}async postFormData(e,t){const r=`${this.baseUrl}${e}`;i.debug("POST (formData)",r);const s={...this.headers};try{const n=await fetch(r,{method:"POST",headers:s,body:t});return n.ok||await this.handleErrorResponse(n),n}catch(n){throw n instanceof h?n:new d(`Network error: ${n instanceof Error?n.message:"Unknown error"}`,n instanceof Error?n:void 0)}}async request(e,t,r){const s=`${this.baseUrl}${t}`;i.debug(e,s,r);try{const n=await fetch(s,{method:e,headers:{...this.headers,"Content-Type":"application/json"},body:r?JSON.stringify(r):void 0});return n.ok||await this.handleErrorResponse(n),n.status===204?void 0:n.json()}catch(n){throw n instanceof h?n:new d(`Network error: ${n instanceof Error?n.message:"Unknown error"}`,n instanceof Error?n:void 0)}}async handleErrorResponse(e){let t;try{t=await e.json()}catch{}throw t?.error?h.fromResponse(t,e.status):new h(`HTTP ${e.status}: ${e.statusText}`,"http_error",e.status,"api_error")}},y=class{constructor(){this.functions=new Map}register(e,t,r){if(typeof e=="object"){const{name:n,handler:o,description:a,parameters:c}=e;return this.register(n,o,{description:a,parameters:c})}const s=e;if(!t||!r)throw new Error("handler and schema are required");this.functions.has(s)&&i.warn(`Function "${s}" is being overwritten`),this.functions.set(s,{schema:{...r,name:s},handler:t}),i.log(`Registered function: ${s}`)}unregister(e){const t=this.functions.delete(e);return t&&i.log(`Unregistered function: ${e}`),t}get(e){return this.functions.get(e)}has(e){return this.functions.has(e)}getSchemas(){return Array.from(this.functions.values()).map(e=>e.schema)}async execute(e,t){const r=this.functions.get(e);if(!r)throw new f(`Function "${e}" is not registered`,e);i.log(`Executing function: ${e}`,t);try{const s=await r.handler(t);return i.log(`Function ${e} completed:`,s),s}catch(s){throw i.error(`Function ${e} failed:`,s),new f(`Function "${e}" execution failed: ${s instanceof Error?s.message:"Unknown error"}`,e,s instanceof Error?s:void 0)}}clear(){this.functions.clear(),i.log("Cleared all registered functions")}get size(){return this.functions.size}},v=class{constructor(){this.entries=new Map,this.dynamicProviders=new Map}set(e,t){this.entries.set(e,t),i.log(`ClientContext set: ${e}`)}remove(e){const t=this.entries.delete(e);return t&&i.log(`ClientContext removed: ${e}`),t}addDynamicProvider(e,t){this.dynamicProviders.set(e,t),i.log(`DynamicContext provider added: ${e}`)}removeDynamicProvider(e){const t=this.dynamicProviders.delete(e);return t&&i.log(`DynamicContext provider removed: ${e}`),t}getSnapshot(){if(this.entries.size===0&&this.dynamicProviders.size===0)return null;const e={};for(const[t,r]of this.entries)e[t]=r;for(const[t,r]of this.dynamicProviders)try{const s=r();s&&(e[t]=s)}catch(s){i.error(`DynamicContext provider "${t}" threw:`,s)}return Object.keys(e).length===0?null:{entries:e}}clear(){this.entries.clear(),this.dynamicProviders.clear(),i.log("ClientContext cleared")}},w=class{constructor(e){this.callbacks=e,this.buffer="",this.message={},this.toolCalls=[],this.sources=[],this.followUpReplies=[],this.isFirstChunk=!0}async processStream(e){if(!e.body)throw new g("Response has no body");const t=e.body.getReader(),r=new TextDecoder;try{for(;;){const{done:s,value:n}=await t.read();if(s)break;const o=r.decode(n,{stream:!0});this.buffer+=o,this.processBuffer()}return this.buffer.trim()&&this.processBuffer(),this.buildFinalMessage()}catch(s){const n=s instanceof Error?s:new g("Stream processing failed");throw this.callbacks.onError?.(n),n}finally{t.releaseLock()}}processBuffer(){const e=this.buffer.split(`
2
2
 
3
3
  `);this.buffer=e.pop()||"";for(const t of e){if(!t.trim())continue;const r=t.split(`
4
- `);for(const s of r)if(!s.startsWith(": ")&&s.startsWith("data: ")){const n=s.slice(6);try{const o=JSON.parse(n);this.handleChunk(o)}catch(o){i.warn("Failed to parse SSE data:",n,o)}}}}handleChunk(e){if(e.message_id&&!this.message.id&&(this.message.id=e.message_id),e.thread?.id&&(this.message.conversationId=e.thread.id,this.isFirstChunk&&this.message.id&&(this.isFirstChunk=!1,this.callbacks.onStart?.({conversationId:this.message.conversationId,messageId:this.message.id}))),e.content!==void 0&&(this.message.content=(this.message.content||"")+e.content,this.message.conversationId&&this.message.id&&this.callbacks.onChunk?.({content:e.content,conversationId:this.message.conversationId,messageId:this.message.id})),e.full_content!==void 0&&(this.message.content=e.full_content),e.status&&(this.message.status=e.status),e.agent&&(this.message.agent={id:e.agent.id,name:e.agent.name,displayName:e.agent.display_name}),e.knowledge_sources&&(this.sources=e.knowledge_sources.map(t=>{const r=t.knowledge_document;return{id:r.id,title:r.title,url:r.use_external_link?r.external_link_url:r.internal_link_url}})),e.type==="client_function"&&e.function_name&&this.callbacks.onClientFunction?.({invocationId:e.id||"",functionName:e.function_name,arguments:e.arguments||{},conversationId:this.message.conversationId||""}),e.tool_call_data&&e.type&&e.type!=="client_function"){const t=this.parseToolCall(e);this.callbacks.onToolCall?.(t);const r=this.toolCalls.findIndex(s=>s.id===t.id);r>=0?this.toolCalls[r]=t:this.toolCalls.push(t)}e.follow_up_replies&&(this.followUpReplies=e.follow_up_replies)}parseToolCall(e){return{id:e.id||"",type:e.type||"status_message",status:e.status||"unknown",toolName:e.tool_name||"",toolDisplayName:e.tool_display_name,message:e.message,formSchema:e.form_schema,data:e.data,functionName:e.function_name,arguments:e.arguments}}buildFinalMessage(){const e={id:this.message.id||"",conversationId:this.message.conversationId||"",content:this.message.content||"",role:"assistant",status:this.message.status||"DONE",agent:this.message.agent,sources:this.sources.length>0?this.sources:void 0,toolCalls:this.toolCalls.length>0?this.toolCalls:void 0,followUpReplies:this.followUpReplies.length>0?this.followUpReplies:void 0,createdAt:new Date};return this.callbacks.onComplete?.(e),e}};function x(e){const t=e.message.toLowerCase();return t.includes("load failed")||t.includes("failed to fetch")||t.includes("network")||t.includes("abort")}var b=class{constructor(){this.handlers=new Map}on(e,t){this.handlers.has(e)||this.handlers.set(e,new Set),this.handlers.get(e).add(t)}off(e,t){const r=this.handlers.get(e);r&&r.delete(t)}emit(e,t){const r=this.handlers.get(e);r&&r.forEach(s=>{try{s(t)}catch(n){console.error(`Error in event handler for ${String(e)}:`,n)}})}once(e,t){const r=(s=>{this.off(e,r),t(s)});this.on(e,r)}waitFor(e,t){return new Promise((r,s)=>{let n;const o=(a=>{n&&clearTimeout(n),r(a)});this.once(e,o),t?.timeout&&(n=setTimeout(()=>{this.off(e,o),s(new Error(`waitFor("${String(e)}") timed out after ${t.timeout}ms`))},t.timeout))})}removeAllListeners(e){e?this.handlers.delete(e):this.handlers.clear()}},A=class C{constructor(t){this.config=t,this.httpClient=new k(t),this.functionRegistry=new y,this.contextRegistry=new v,this.eventEmitter=new b,t.debug&&i.enable(),i.log("AgoClient initialized")}async sendMessage(t,r){const s=this.functionRegistry.getSchemas(),n=this.contextRegistry.getSnapshot(),o=this.config.agent||this.config.defaultAgentId,a={content:t,conversation_id:r?.conversationId,agent_id:r?.agentId||o};s.length>0&&(a.client_functions=s),n&&(a.client_context=n);let c;if(r?.files&&r.files.length>0){const l=new FormData;l.append("content",t),r.conversationId&&l.append("conversation_id",r.conversationId),(r.agentId||o)&&l.append("agent_id",r.agentId||o||""),s.length>0&&l.append("client_functions",JSON.stringify(s)),n&&l.append("client_context",JSON.stringify(n));for(const E of r.files)l.append("files",E);c=await this.httpClient.postFormData("/api/sdk/v1/messages",l)}else c=await this.httpClient.postStream("/api/sdk/v1/messages",a);return this.processSSEResponse(c)}async processSSEResponse(t){return new w({onStart:r=>{this.eventEmitter.emit("message:start",r)},onChunk:r=>{this.eventEmitter.emit("message:chunk",r)},onToolCall:r=>{this.eventEmitter.emit("toolCall:received",r),r.type==="form"&&this.eventEmitter.emit("toolCall:form",r)},onClientFunction:async r=>{this.eventEmitter.emit("function:invoke",r),await this.handleClientFunctionInvocation(r)},onComplete:r=>{this.eventEmitter.emit("message:complete",r)},onError:r=>{this.eventEmitter.emit("message:error",{error:r.message})}}).processStream(t)}async handleClientFunctionInvocation(t){let r,s;try{r=await this.functionRegistry.execute(t.functionName,t.arguments)}catch(n){s=n instanceof Error?n.message:"Unknown error",i.error("Client function execution failed:",n)}if(t.invocationId)try{await this.submitToolCallForm(t.invocationId,{result:r,error:s,_type:"client_function_result"})}catch(n){i.error("Failed to submit function result:",n)}this.eventEmitter.emit("function:result",{invocationId:t.invocationId,result:r,error:s})}async getConversations(){return(await this.httpClient.get("/api/sdk/v1/conversations")).items.map(t=>({id:t.id,title:t.title,lastMessageDate:new Date(t.last_message_date)}))}async getConversation(t){const r=await this.httpClient.get(`/api/sdk/v1/conversations/${t}`),s={id:r.id,title:r.title,lastMessageDate:new Date(r.last_message_date),messages:r.messages.map(n=>({id:n.id,conversationId:r.id,content:n.content,role:n.role,status:n.status,createdAt:new Date(n.created_at),toolCalls:C.mapPersistedToolCalls(n.tool_call_data)}))};return this.eventEmitter.emit("conversation:loaded",s),s}static mapPersistedToolCalls(t){if(!(!t||t.length===0))return t.map(r=>({id:String(r.id??""),type:r.type??"status_message",status:String(r.status??"unknown"),toolName:r.tool_name??"",toolDisplayName:r.tool_display_name,message:r.message,formSchema:r.form_schema,data:r.data,functionName:r.function_name,arguments:r.arguments}))}async getMessages(t){return(await this.getConversation(t)).messages||[]}async submitToolCallForm(t,r){await this.httpClient.post(`/api/sdk/v1/tool-calls/${t}/submit`,{formData:r})}async confirmToolCall(t){await this.httpClient.post(`/api/tool-calls/${t}/confirm/`)}async rejectToolCall(t){await this.httpClient.post(`/api/tool-calls/${t}/reject/`)}async submitFormCollector(t,r){return this.httpClient.post("/api/sdk/v1/forms/submit",{destination:t,values:r})}async submitFeedback(t,r){await this.httpClient.post(`/api/sdk/v1/messages/${t}/feedback`,{rating:r})}registerFunction(t,r,s){typeof t=="object"?this.functionRegistry.register(t):this.functionRegistry.register(t,r,s)}register(t){if(Array.isArray(t))for(const r of t)this.functionRegistry.register(r);else this.functionRegistry.register(t)}unregisterFunction(t){return this.functionRegistry.unregister(t)}getRegisteredFunctions(){return this.functionRegistry.getSchemas()}registerNavigationFunction(t,r){const s=r.map(o=>o.name),n=r.map(o=>`- "${o.name}": ${o.description}`).join(`
4
+ `);for(const s of r)if(!s.startsWith(": ")&&s.startsWith("data: ")){const n=s.slice(6);try{const o=JSON.parse(n);this.handleChunk(o)}catch(o){i.warn("Failed to parse SSE data:",n,o)}}}}handleChunk(e){if(e.message_id&&!this.message.id&&(this.message.id=e.message_id),e.thread?.id&&(this.message.conversationId=e.thread.id,this.isFirstChunk&&this.message.id&&(this.isFirstChunk=!1,this.callbacks.onStart?.({conversationId:this.message.conversationId,messageId:this.message.id}))),e.content!==void 0&&(this.message.content=(this.message.content||"")+e.content,this.message.conversationId&&this.message.id&&this.callbacks.onChunk?.({content:e.content,conversationId:this.message.conversationId,messageId:this.message.id})),e.full_content!==void 0&&(this.message.content=e.full_content),e.status&&(this.message.status=e.status),e.agent&&(this.message.agent={id:e.agent.id,name:e.agent.name,displayName:e.agent.display_name}),e.knowledge_sources&&(this.sources=e.knowledge_sources.map(t=>{const r=t.knowledge_document;return{id:r.id,title:r.title,url:r.use_external_link?r.external_link_url:r.internal_link_url}})),e.type==="client_function"&&e.function_name&&this.callbacks.onClientFunction?.({invocationId:e.id||"",functionName:e.function_name,arguments:e.arguments||{},conversationId:this.message.conversationId||""}),e.tool_call_data&&e.type&&e.type!=="client_function"){const t=this.parseToolCall(e);this.callbacks.onToolCall?.(t);const r=this.toolCalls.findIndex(s=>s.id===t.id);r>=0?this.toolCalls[r]=t:this.toolCalls.push(t)}e.follow_up_replies&&(this.followUpReplies=e.follow_up_replies)}parseToolCall(e){return{id:e.id||"",type:e.type||"status_message",status:e.status||"unknown",toolName:e.tool_name||"",toolDisplayName:e.tool_display_name,message:e.message,formSchema:e.form_schema,data:e.data,functionName:e.function_name,arguments:e.arguments}}buildFinalMessage(){const e={id:this.message.id||"",conversationId:this.message.conversationId||"",content:this.message.content||"",role:"assistant",status:this.message.status||"DONE",agent:this.message.agent,sources:this.sources.length>0?this.sources:void 0,toolCalls:this.toolCalls.length>0?this.toolCalls:void 0,followUpReplies:this.followUpReplies.length>0?this.followUpReplies:void 0,createdAt:new Date};return this.callbacks.onComplete?.(e),e}};function x(e){const t=e.message.toLowerCase();return t.includes("load failed")||t.includes("failed to fetch")||t.includes("network")||t.includes("abort")}var C=class{constructor(){this.handlers=new Map}on(e,t){this.handlers.has(e)||this.handlers.set(e,new Set),this.handlers.get(e).add(t)}off(e,t){const r=this.handlers.get(e);r&&r.delete(t)}emit(e,t){const r=this.handlers.get(e);r&&r.forEach(s=>{try{s(t)}catch(n){console.error(`Error in event handler for ${String(e)}:`,n)}})}once(e,t){const r=(s=>{this.off(e,r),t(s)});this.on(e,r)}waitFor(e,t){return new Promise((r,s)=>{let n;const o=(a=>{n&&clearTimeout(n),r(a)});this.once(e,o),t?.timeout&&(n=setTimeout(()=>{this.off(e,o),s(new Error(`waitFor("${String(e)}") timed out after ${t.timeout}ms`))},t.timeout))})}removeAllListeners(e){e?this.handlers.delete(e):this.handlers.clear()}},A=class b{constructor(t){this.config=t,this.httpClient=new k(t),this.functionRegistry=new y,this.contextRegistry=new v,this.eventEmitter=new C,t.debug&&i.enable(),i.log("AgoClient initialized")}async sendMessage(t,r){const s=this.functionRegistry.getSchemas(),n=this.contextRegistry.getSnapshot(),o=this.config.agent||this.config.defaultAgentId,a={content:t,conversation_id:r?.conversationId,agent_id:r?.agentId||o};s.length>0&&(a.client_functions=s),n&&(a.client_context=n);let c;if(r?.files&&r.files.length>0){const l=new FormData;l.append("content",t),r.conversationId&&l.append("conversation_id",r.conversationId),(r.agentId||o)&&l.append("agent_id",r.agentId||o||""),s.length>0&&l.append("client_functions",JSON.stringify(s)),n&&l.append("client_context",JSON.stringify(n));for(const E of r.files)l.append("files",E);c=await this.httpClient.postFormData("/api/sdk/v1/messages",l)}else c=await this.httpClient.postStream("/api/sdk/v1/messages",a);return this.processSSEResponse(c)}async processSSEResponse(t){return new w({onStart:r=>{this.eventEmitter.emit("message:start",r)},onChunk:r=>{this.eventEmitter.emit("message:chunk",r)},onToolCall:r=>{this.eventEmitter.emit("toolCall:received",r),r.type==="form"&&this.eventEmitter.emit("toolCall:form",r)},onClientFunction:async r=>{this.eventEmitter.emit("function:invoke",r),await this.handleClientFunctionInvocation(r)},onComplete:r=>{this.eventEmitter.emit("message:complete",r)},onError:r=>{this.eventEmitter.emit("message:error",{error:r.message})}}).processStream(t)}async handleClientFunctionInvocation(t){let r,s;try{r=await this.functionRegistry.execute(t.functionName,t.arguments)}catch(n){s=n instanceof Error?n.message:"Unknown error",i.error("Client function execution failed:",n)}if(t.invocationId)try{await this.submitToolCallForm(t.invocationId,{result:r,error:s,_type:"client_function_result"})}catch(n){i.error("Failed to submit function result:",n)}this.eventEmitter.emit("function:result",{invocationId:t.invocationId,result:r,error:s})}async getConversations(){return(await this.httpClient.get("/api/sdk/v1/conversations")).items.map(t=>({id:t.id,title:t.title,lastMessageDate:new Date(t.last_message_date)}))}async getConversation(t){const r=await this.httpClient.get(`/api/sdk/v1/conversations/${t}`),s={id:r.id,title:r.title,lastMessageDate:new Date(r.last_message_date),messages:r.messages.map(n=>({id:n.id,conversationId:r.id,content:n.content,role:n.role,status:n.status,createdAt:new Date(n.created_at),toolCalls:b.mapPersistedToolCalls(n.tool_call_data)}))};return this.eventEmitter.emit("conversation:loaded",s),s}static mapPersistedToolCalls(t){if(!(!t||t.length===0))return t.map(r=>({id:String(r.id??""),type:r.type??"status_message",status:String(r.status??"unknown"),toolName:r.tool_name??"",toolDisplayName:r.tool_display_name,message:r.message,formSchema:r.form_schema,data:r.data,functionName:r.function_name,arguments:r.arguments}))}async getMessages(t){return(await this.getConversation(t)).messages||[]}async submitToolCallForm(t,r){await this.httpClient.post(`/api/sdk/v1/tool-calls/${t}/submit`,{formData:r})}async confirmToolCall(t){await this.httpClient.post(`/api/tool-calls/${t}/confirm/`)}async rejectToolCall(t){await this.httpClient.post(`/api/tool-calls/${t}/reject/`)}async submitFormCollector(t,r){return this.httpClient.post("/api/sdk/v1/forms/submit",{destination:t,values:r})}async submitFeedback(t,r){await this.httpClient.post(`/api/sdk/v1/messages/${t}/feedback`,{rating:r})}registerFunction(t,r,s){typeof t=="object"?this.functionRegistry.register(t):this.functionRegistry.register(t,r,s)}register(t){if(Array.isArray(t))for(const r of t)this.functionRegistry.register(r);else this.functionRegistry.register(t)}unregisterFunction(t){return this.functionRegistry.unregister(t)}getRegisteredFunctions(){return this.functionRegistry.getSchemas()}registerNavigationFunction(t,r){const s=r.map(o=>o.name),n=r.map(o=>`- "${o.name}": ${o.description}`).join(`
5
5
  `);this.registerFunction("navigateToPage",async o=>{const a=o.page,c=r.find(l=>l.name===a);return c?(t(c.path),{success:!0,navigatedTo:c.path}):{success:!1,error:`Unknown page: ${a}`}},{description:`Navigate the user to a page in the application. Available pages:
6
- ${n}`,parameters:{type:"object",properties:{page:{type:"string",description:"The page to navigate to",enum:s}},required:["page"]}})}setContext(t,r){this.contextRegistry.set(t,r)}removeContext(t){return this.contextRegistry.remove(t)}addDynamicContext(t,r){this.contextRegistry.addDynamicProvider(t,r)}removeDynamicContext(t){return this.contextRegistry.removeDynamicProvider(t)}enableAutoPageContext(){this.contextRegistry.addDynamicProvider("browser-page",()=>{const t=typeof window<"u"?window.location.href:void 0,r=typeof document<"u"?document.title:void 0;return!t&&!r?null:{name:"Browser page",description:"Current page the user is viewing",data:{url:t,title:r}}})}getContextSnapshot(){return this.contextRegistry.getSnapshot()}on(t,r){this.eventEmitter.on(t,r)}off(t,r){this.eventEmitter.off(t,r)}once(t,r){this.eventEmitter.once(t,r)}waitFor(t,r){return this.eventEmitter.waitFor(t,r)}updateConfig(t){this.config={...this.config,...t},this.httpClient.updateConfig(t),t.debug!==void 0&&(t.debug?i.enable():i.disable())}destroy(){this.eventEmitter.removeAllListeners(),this.functionRegistry.clear(),this.contextRegistry.clear(),i.log("AgoClient destroyed")}};Object.defineProperty(exports,"AgoApiError",{enumerable:!0,get:function(){return u}});Object.defineProperty(exports,"AgoClient",{enumerable:!0,get:function(){return A}});Object.defineProperty(exports,"AgoError",{enumerable:!0,get:function(){return h}});Object.defineProperty(exports,"AgoFunctionError",{enumerable:!0,get:function(){return m}});Object.defineProperty(exports,"AgoNetworkError",{enumerable:!0,get:function(){return d}});Object.defineProperty(exports,"AgoStreamError",{enumerable:!0,get:function(){return g}});Object.defineProperty(exports,"ClientContextRegistry",{enumerable:!0,get:function(){return v}});Object.defineProperty(exports,"EventEmitter",{enumerable:!0,get:function(){return b}});Object.defineProperty(exports,"FunctionRegistry",{enumerable:!0,get:function(){return y}});Object.defineProperty(exports,"SSEHandler",{enumerable:!0,get:function(){return w}});Object.defineProperty(exports,"isStreamNetworkError",{enumerable:!0,get:function(){return x}});Object.defineProperty(exports,"logger",{enumerable:!0,get:function(){return i}});
6
+ ${n}`,parameters:{type:"object",properties:{page:{type:"string",description:"The page to navigate to",enum:s}},required:["page"]}})}setContext(t,r){this.contextRegistry.set(t,r),this.notifyContextChanged()}removeContext(t){const r=this.contextRegistry.remove(t);return r&&this.notifyContextChanged(),r}addDynamicContext(t,r){this.contextRegistry.addDynamicProvider(t,r),this.notifyContextChanged()}removeDynamicContext(t){const r=this.contextRegistry.removeDynamicProvider(t);return r&&this.notifyContextChanged(),r}notifyContextChanged(){this.eventEmitter.emit("context:changed",this.contextRegistry.getSnapshot())}enableAutoPageContext(){this.addDynamicContext("browser-page",()=>{const t=typeof window<"u"?window.location.href:void 0,r=typeof document<"u"?document.title:void 0;return!t&&!r?null:{name:"Browser page",description:"Current page the user is viewing",data:{url:t,title:r}}})}getContextSnapshot(){return this.contextRegistry.getSnapshot()}on(t,r){this.eventEmitter.on(t,r)}off(t,r){this.eventEmitter.off(t,r)}once(t,r){this.eventEmitter.once(t,r)}waitFor(t,r){return this.eventEmitter.waitFor(t,r)}updateConfig(t){this.config={...this.config,...t},this.httpClient.updateConfig(t),t.debug!==void 0&&(t.debug?i.enable():i.disable())}destroy(){this.eventEmitter.removeAllListeners(),this.functionRegistry.clear(),this.contextRegistry.clear(),i.log("AgoClient destroyed")}};Object.defineProperty(exports,"AgoApiError",{enumerable:!0,get:function(){return h}});Object.defineProperty(exports,"AgoClient",{enumerable:!0,get:function(){return A}});Object.defineProperty(exports,"AgoError",{enumerable:!0,get:function(){return u}});Object.defineProperty(exports,"AgoFunctionError",{enumerable:!0,get:function(){return f}});Object.defineProperty(exports,"AgoNetworkError",{enumerable:!0,get:function(){return d}});Object.defineProperty(exports,"AgoStreamError",{enumerable:!0,get:function(){return g}});Object.defineProperty(exports,"ClientContextRegistry",{enumerable:!0,get:function(){return v}});Object.defineProperty(exports,"EventEmitter",{enumerable:!0,get:function(){return C}});Object.defineProperty(exports,"FunctionRegistry",{enumerable:!0,get:function(){return y}});Object.defineProperty(exports,"SSEHandler",{enumerable:!0,get:function(){return w}});Object.defineProperty(exports,"isStreamNetworkError",{enumerable:!0,get:function(){return x}});Object.defineProperty(exports,"logger",{enumerable:!0,get:function(){return i}});
@@ -22,7 +22,7 @@ var d = class extends Error {
22
22
  constructor(e, t, s) {
23
23
  super(e, "function_error"), this.functionName = t, this.originalError = s, this.name = "AgoFunctionError";
24
24
  }
25
- }, y = class {
25
+ }, w = class {
26
26
  constructor(e = !1) {
27
27
  this.enabled = e;
28
28
  }
@@ -44,7 +44,7 @@ var d = class extends Error {
44
44
  debug(...e) {
45
45
  this.enabled && console.debug("[AGO SDK]", ...e);
46
46
  }
47
- }, n = new y(), f = "ago_widget_id";
47
+ }, n = new w(), f = "ago_widget_id";
48
48
  function C() {
49
49
  if (typeof localStorage < "u") {
50
50
  const t = localStorage.getItem(f);
@@ -212,7 +212,7 @@ var E = class {
212
212
  clear() {
213
213
  this.entries.clear(), this.dynamicProviders.clear(), n.log("ClientContext cleared");
214
214
  }
215
- }, k = class {
215
+ }, S = class {
216
216
  constructor(e) {
217
217
  this.callbacks = e, this.buffer = "", this.message = {}, this.toolCalls = [], this.sources = [], this.followUpReplies = [], this.isFirstChunk = !0;
218
218
  }
@@ -321,7 +321,7 @@ function x(e) {
321
321
  const t = e.message.toLowerCase();
322
322
  return t.includes("load failed") || t.includes("failed to fetch") || t.includes("network") || t.includes("abort");
323
323
  }
324
- var S = class {
324
+ var k = class {
325
325
  constructor() {
326
326
  this.handlers = /* @__PURE__ */ new Map();
327
327
  }
@@ -364,7 +364,7 @@ var S = class {
364
364
  }
365
365
  }, $ = class v {
366
366
  constructor(t) {
367
- this.config = t, this.httpClient = new E(t), this.functionRegistry = new b(), this.contextRegistry = new _(), this.eventEmitter = new S(), t.debug && n.enable(), n.log("AgoClient initialized");
367
+ this.config = t, this.httpClient = new E(t), this.functionRegistry = new b(), this.contextRegistry = new _(), this.eventEmitter = new k(), t.debug && n.enable(), n.log("AgoClient initialized");
368
368
  }
369
369
  async sendMessage(t, s) {
370
370
  const r = this.functionRegistry.getSchemas(), i = this.contextRegistry.getSnapshot(), o = this.config.agent || this.config.defaultAgentId, a = {
@@ -377,13 +377,13 @@ var S = class {
377
377
  if (s?.files && s.files.length > 0) {
378
378
  const l = new FormData();
379
379
  l.append("content", t), s.conversationId && l.append("conversation_id", s.conversationId), (s.agentId || o) && l.append("agent_id", s.agentId || o || ""), r.length > 0 && l.append("client_functions", JSON.stringify(r)), i && l.append("client_context", JSON.stringify(i));
380
- for (const w of s.files) l.append("files", w);
380
+ for (const y of s.files) l.append("files", y);
381
381
  c = await this.httpClient.postFormData("/api/sdk/v1/messages", l);
382
382
  } else c = await this.httpClient.postStream("/api/sdk/v1/messages", a);
383
383
  return this.processSSEResponse(c);
384
384
  }
385
385
  async processSSEResponse(t) {
386
- return new k({
386
+ return new S({
387
387
  onStart: (s) => {
388
388
  this.eventEmitter.emit("message:start", s);
389
389
  },
@@ -526,19 +526,24 @@ ${i}`,
526
526
  });
527
527
  }
528
528
  setContext(t, s) {
529
- this.contextRegistry.set(t, s);
529
+ this.contextRegistry.set(t, s), this.notifyContextChanged();
530
530
  }
531
531
  removeContext(t) {
532
- return this.contextRegistry.remove(t);
532
+ const s = this.contextRegistry.remove(t);
533
+ return s && this.notifyContextChanged(), s;
533
534
  }
534
535
  addDynamicContext(t, s) {
535
- this.contextRegistry.addDynamicProvider(t, s);
536
+ this.contextRegistry.addDynamicProvider(t, s), this.notifyContextChanged();
536
537
  }
537
538
  removeDynamicContext(t) {
538
- return this.contextRegistry.removeDynamicProvider(t);
539
+ const s = this.contextRegistry.removeDynamicProvider(t);
540
+ return s && this.notifyContextChanged(), s;
541
+ }
542
+ notifyContextChanged() {
543
+ this.eventEmitter.emit("context:changed", this.contextRegistry.getSnapshot());
539
544
  }
540
545
  enableAutoPageContext() {
541
- this.contextRegistry.addDynamicProvider("browser-page", () => {
546
+ this.addDynamicContext("browser-page", () => {
542
547
  const t = typeof window < "u" ? window.location.href : void 0, s = typeof document < "u" ? document.title : void 0;
543
548
  return !t && !s ? null : {
544
549
  name: "Browser page",
@@ -582,9 +587,9 @@ export {
582
587
  g as f,
583
588
  x as i,
584
589
  d as l,
585
- S as n,
590
+ k as n,
586
591
  b as o,
587
- k as r,
592
+ S as r,
588
593
  n as s,
589
594
  $ as t,
590
595
  m as u
package/dist/angular.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./AgoClient-B6PsfMeg.cjs");var n=class{constructor(e){this.client=new o.AgoClient(e),this.messages$=this.fromEvent("message:complete"),this.chunks$=this.fromEvent("message:chunk"),this.errors$=this.fromEvent("message:error"),this.messageStart$=this.fromEvent("message:start")}fromEvent(e){const t=this.client;return{subscribe(i){const s=r=>{i.next?.(r)};return t.on(e,s),{unsubscribe:()=>t.off(e,s)}}}}sendMessage(e,t){return this.client.sendMessage(e,t)}getConversations(){return this.client.getConversations()}getConversation(e){return this.client.getConversation(e)}getMessages(e){return this.client.getMessages(e)}submitToolCallForm(e,t){return this.client.submitToolCallForm(e,t)}confirmToolCall(e){return this.client.confirmToolCall(e)}rejectToolCall(e){return this.client.rejectToolCall(e)}submitFeedback(e,t){return this.client.submitFeedback(e,t)}registerFunction(e,t,i){typeof e=="object"?this.client.registerFunction(e):this.client.registerFunction(e,t,i)}unregisterFunction(e){return this.client.unregisterFunction(e)}registerNavigationFunction(e,t){this.client.registerNavigationFunction(e,t)}on(e,t){this.client.on(e,t)}off(e,t){this.client.off(e,t)}updateConfig(e){this.client.updateConfig(e)}getClient(){return this.client}destroy(){this.client.destroy()}};function c(e){return{provide:n,useValue:new n(e)}}exports.AgoService=n;exports.provideAgo=c;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./AgoClient-D4EL6nva.cjs");var n=class{constructor(e){this.client=new o.AgoClient(e),this.messages$=this.fromEvent("message:complete"),this.chunks$=this.fromEvent("message:chunk"),this.errors$=this.fromEvent("message:error"),this.messageStart$=this.fromEvent("message:start")}fromEvent(e){const t=this.client;return{subscribe(i){const s=r=>{i.next?.(r)};return t.on(e,s),{unsubscribe:()=>t.off(e,s)}}}}sendMessage(e,t){return this.client.sendMessage(e,t)}getConversations(){return this.client.getConversations()}getConversation(e){return this.client.getConversation(e)}getMessages(e){return this.client.getMessages(e)}submitToolCallForm(e,t){return this.client.submitToolCallForm(e,t)}confirmToolCall(e){return this.client.confirmToolCall(e)}rejectToolCall(e){return this.client.rejectToolCall(e)}submitFeedback(e,t){return this.client.submitFeedback(e,t)}registerFunction(e,t,i){typeof e=="object"?this.client.registerFunction(e):this.client.registerFunction(e,t,i)}unregisterFunction(e){return this.client.unregisterFunction(e)}registerNavigationFunction(e,t){this.client.registerNavigationFunction(e,t)}on(e,t){this.client.on(e,t)}off(e,t){this.client.off(e,t)}updateConfig(e){this.client.updateConfig(e)}getClient(){return this.client}destroy(){this.client.destroy()}};function c(e){return{provide:n,useValue:new n(e)}}exports.AgoService=n;exports.provideAgo=c;
@@ -147,6 +147,13 @@ declare class AgoClient {
147
147
  * Remove a dynamic context provider.
148
148
  */
149
149
  removeDynamicContext(key: string): boolean;
150
+ /**
151
+ * Broadcast that the client-side context changed by emitting `context:changed`
152
+ * with the fresh snapshot. The context-mutating methods call this automatically;
153
+ * stateful helpers whose context lives in a store (e.g. `createFormCollector`)
154
+ * call it when their store updates so observers like the dev panel stay live.
155
+ */
156
+ notifyContextChanged(): void;
150
157
  /**
151
158
  * Enable automatic capture of the current browser page (URL + title).
152
159
  * Injected as a dynamic context entry named `browser-page`.
@@ -192,6 +199,14 @@ declare class AgoClient {
192
199
  * SDK Events
193
200
  */
194
201
  export declare interface AgoClientEvents {
202
+ /**
203
+ * The client-side context changed: a context entry or dynamic provider was
204
+ * added/removed, or a stateful helper (e.g. `createFormCollector`) updated its
205
+ * store. Carries the fresh snapshot so observers — notably the dev panel — can
206
+ * repaint without waiting for the next message. Fires for the form collector's
207
+ * initial install too, so its missing fields show from the start of a conversation.
208
+ */
209
+ "context:changed": ContextSnapshot | null;
195
210
  "message:start": {
196
211
  conversationId: string;
197
212
  messageId: string;
package/dist/angular.d.ts CHANGED
@@ -147,6 +147,13 @@ declare class AgoClient {
147
147
  * Remove a dynamic context provider.
148
148
  */
149
149
  removeDynamicContext(key: string): boolean;
150
+ /**
151
+ * Broadcast that the client-side context changed by emitting `context:changed`
152
+ * with the fresh snapshot. The context-mutating methods call this automatically;
153
+ * stateful helpers whose context lives in a store (e.g. `createFormCollector`)
154
+ * call it when their store updates so observers like the dev panel stay live.
155
+ */
156
+ notifyContextChanged(): void;
150
157
  /**
151
158
  * Enable automatic capture of the current browser page (URL + title).
152
159
  * Injected as a dynamic context entry named `browser-page`.
@@ -192,6 +199,14 @@ declare class AgoClient {
192
199
  * SDK Events
193
200
  */
194
201
  export declare interface AgoClientEvents {
202
+ /**
203
+ * The client-side context changed: a context entry or dynamic provider was
204
+ * added/removed, or a stateful helper (e.g. `createFormCollector`) updated its
205
+ * store. Carries the fresh snapshot so observers — notably the dev panel — can
206
+ * repaint without waiting for the next message. Fires for the form collector's
207
+ * initial install too, so its missing fields show from the start of a conversation.
208
+ */
209
+ "context:changed": ContextSnapshot | null;
195
210
  "message:start": {
196
211
  conversationId: string;
197
212
  messageId: string;
package/dist/angular.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as o } from "./AgoClient-BerJvssl.js";
1
+ import { t as o } from "./AgoClient-rvTz2thR.js";
2
2
  var n = class {
3
3
  constructor(t) {
4
4
  this.client = new o(t), this.messages$ = this.fromEvent("message:complete"), this.chunks$ = this.fromEvent("message:chunk"), this.errors$ = this.fromEvent("message:error"), this.messageStart$ = this.fromEvent("message:start");
@@ -1,4 +1,4 @@
1
- import { n as d } from "./createFormCollector-CD1rqRG4.js";
1
+ import { n as d } from "./createFormCollector-BwvkKi48.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) => {
@@ -1 +1 @@
1
- const d=require("./createFormCollector-D1FfiSgA.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-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,4 +1,4 @@
1
- import { s as I } from "./AgoClient-BerJvssl.js";
1
+ import { s as I } from "./AgoClient-rvTz2thR.js";
2
2
  function O(u, o) {
3
3
  const m = o ? o.storage ?? (typeof localStorage < "u" ? localStorage : void 0) : void 0;
4
4
  let c = u;
@@ -7,7 +7,7 @@ function O(u, o) {
7
7
  a != null && (c = JSON.parse(a));
8
8
  } catch {
9
9
  }
10
- const r = /* @__PURE__ */ new Set(), h = () => r.forEach((a) => a(c));
10
+ const r = /* @__PURE__ */ new Set(), p = () => r.forEach((a) => a(c));
11
11
  function y() {
12
12
  if (o && m) try {
13
13
  m.setItem(o.key, JSON.stringify(c));
@@ -17,24 +17,24 @@ function O(u, o) {
17
17
  return {
18
18
  get: () => c,
19
19
  set: (a) => {
20
- c = a, y(), h();
20
+ c = a, y(), p();
21
21
  },
22
22
  subscribe: (a) => (r.add(a), () => {
23
23
  r.delete(a);
24
24
  })
25
25
  };
26
26
  }
27
- var T = /^[a-zA-Z0-9_-]{1,40}$/;
27
+ var E = /^[a-zA-Z0-9_-]{1,40}$/;
28
28
  function M(u) {
29
29
  const { name: o, description: m, schema: c } = u;
30
- if (!T.test(o)) throw new Error(`Invalid form collector name "${o}": must match ${T} (it becomes the update_/submit_ function names).`);
30
+ if (!E.test(o)) throw new Error(`Invalid form collector name "${o}": must match ${E} (it becomes the update_/submit_ function names).`);
31
31
  const r = typeof u.submit == "string" ? u.submit ? {
32
32
  via: "client",
33
33
  url: u.submit
34
- } : !1 : u.submit ?? !1, h = c.properties ?? {}, y = c.required ?? [], a = (e) => e == null || e === "", p = (e) => y.filter((t) => a(e[t])), v = (e) => {
34
+ } : !1 : u.submit ?? !1, p = c.properties ?? {}, y = c.required ?? [], a = (e) => e == null || e === "", b = (e) => y.filter((t) => a(e[t])), v = (e) => {
35
35
  const t = {};
36
36
  for (const [n, s] of Object.entries(e)) {
37
- const i = h[n];
37
+ const i = p[n];
38
38
  if (i)
39
39
  if (s == null) t[n] = s;
40
40
  else if (i.type === "number" || i.type === "integer") {
@@ -43,16 +43,16 @@ function M(u) {
43
43
  } else i.type === "boolean" ? t[n] = typeof s == "boolean" ? s : s === "true" ? !0 : s === "false" ? !1 : !!s : t[n] = s;
44
44
  }
45
45
  return t;
46
- }, f = u.initialValues ?? {}, $ = p(f), l = O({
46
+ }, f = u.initialValues ?? {}, N = b(f), l = O({
47
47
  values: f,
48
- missing: $,
49
- complete: $.length === 0,
48
+ missing: N,
49
+ complete: N.length === 0,
50
50
  submitted: !1
51
- }), C = (e) => {
51
+ }), $ = (e) => {
52
52
  const t = l.get(), n = {
53
53
  ...t.values,
54
54
  ...e
55
- }, s = p(n), i = {
55
+ }, s = b(n), i = {
56
56
  ...t,
57
57
  values: n,
58
58
  missing: s,
@@ -118,7 +118,7 @@ function M(u) {
118
118
  required: []
119
119
  },
120
120
  handler: (e) => {
121
- const t = C(v(e));
121
+ const t = $(v(e));
122
122
  return {
123
123
  ok: !0,
124
124
  values: t.values,
@@ -126,8 +126,8 @@ function M(u) {
126
126
  complete: t.complete
127
127
  };
128
128
  }
129
- }, b = [w];
130
- r && b.push({
129
+ }, h = [w];
130
+ r && h.push({
131
131
  name: `submit_${o}`,
132
132
  description: `Submit the completed "${o}" 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.`,
133
133
  parameters: {
@@ -136,27 +136,27 @@ function M(u) {
136
136
  },
137
137
  handler: () => k()
138
138
  });
139
- const q = "client__", S = r ? `submit_${o}` : null, x = (e) => {
139
+ const T = "client__", S = r ? `submit_${o}` : null, q = (e) => {
140
140
  const t = e.functionName ?? e.toolName;
141
141
  if (t)
142
- return t.startsWith(q) ? t.slice(8) : t;
142
+ return t.startsWith(T) ? t.slice(8) : t;
143
143
  }, _ = (e) => {
144
144
  let t = { ...f }, n = !1;
145
145
  for (const i of e) {
146
- const g = x(i);
146
+ const g = q(i);
147
147
  g === w.name ? i.arguments && (t = {
148
148
  ...t,
149
149
  ...v(i.arguments)
150
150
  }) : S && g === S && i.status?.toLowerCase() === "done" && (n = !0);
151
151
  }
152
- const s = p(t);
152
+ const s = b(t);
153
153
  l.set({
154
154
  values: t,
155
155
  missing: s,
156
156
  complete: s.length === 0,
157
157
  submitted: n
158
158
  });
159
- }, N = `form:${o}`, F = () => {
159
+ }, C = `form:${o}`, F = () => {
160
160
  const e = l.get(), t = r ? ` When all required fields are present and the user confirms, call submit_${o}.` : "";
161
161
  return {
162
162
  name: `Form: ${o}`,
@@ -168,31 +168,34 @@ function M(u) {
168
168
  submitted: e.submitted
169
169
  }
170
170
  };
171
- }, E = (e) => {
171
+ }, x = (e) => {
172
172
  _((e.messages ?? []).flatMap((t) => t.toolCalls ?? []));
173
173
  };
174
174
  return {
175
175
  name: o,
176
176
  store: l,
177
- functions: b,
178
- contextKey: N,
177
+ functions: h,
178
+ contextKey: C,
179
179
  contextProvider: F,
180
180
  install: (e) => {
181
181
  d = e;
182
- for (const t of b) e.register(t);
183
- return e.addDynamicContext(N, F), e.on("conversation:loaded", E), () => {
184
- for (const t of b) e.unregisterFunction(t.name);
185
- e.removeDynamicContext(N), e.off("conversation:loaded", E), d === e && (d = null);
182
+ for (const n of h) e.register(n);
183
+ e.addDynamicContext(C, F);
184
+ const t = l.subscribe(() => e.notifyContextChanged());
185
+ return e.on("conversation:loaded", x), () => {
186
+ t();
187
+ for (const n of h) e.unregisterFunction(n.name);
188
+ e.removeDynamicContext(C), e.off("conversation:loaded", x), d === e && (d = null);
186
189
  };
187
190
  },
188
191
  hydrate: _,
189
192
  submit: k,
190
193
  getValues: () => l.get().values,
191
194
  setValues: (e) => {
192
- C(v(e));
195
+ $(v(e));
193
196
  },
194
197
  reset: () => {
195
- const e = p(f);
198
+ const e = b(f);
196
199
  l.set({
197
200
  values: f,
198
201
  missing: e,
@@ -0,0 +1 @@
1
+ const x=require("./AgoClient-D4EL6nva.cjs");function P(u,n){const m=n?n.storage??(typeof localStorage<"u"?localStorage:void 0):void 0;let c=u;if(n&&m)try{const a=m.getItem(n.key);a!=null&&(c=JSON.parse(a))}catch{}const o=new Set,p=()=>o.forEach(a=>a(c));function y(){if(n&&m)try{m.setItem(n.key,JSON.stringify(c))}catch{}}return{get:()=>c,set:a=>{c=a,y(),p()},subscribe:a=>(o.add(a),()=>{o.delete(a)})}}var O=/^[a-zA-Z0-9_-]{1,40}$/;function I(u){const{name:n,description:m,schema:c}=u;if(!O.test(n))throw new Error(`Invalid form collector name "${n}": must match ${O} (it becomes the update_/submit_ function names).`);const o=typeof u.submit=="string"?u.submit?{via:"client",url:u.submit}:!1:u.submit??!1,p=c.properties??{},y=c.required??[],a=e=>e==null||e==="",b=e=>y.filter(t=>a(e[t])),v=e=>{const t={};for(const[r,s]of Object.entries(e)){const i=p[r];if(i)if(s==null)t[r]=s;else if(i.type==="number"||i.type==="integer"){const g=typeof s=="number"?s:Number(s);t[r]=Number.isNaN(g)?s:g}else i.type==="boolean"?t[r]=typeof s=="boolean"?s:s==="true"?!0:s==="false"?!1:!!s:t[r]=s}return t},f=u.initialValues??{},N=b(f),l=P({values:f,missing:N,complete:N.length===0,submitted:!1}),$=e=>{const t=l.get(),r={...t.values,...e},s=b(r),i={...t,values:r,missing:s,complete:s.length===0};return l.set(i),i};let d=null;const S=async()=>{const e=l.get();if(!e.complete)return{ok:!1,missing:e.missing};if(!o)return{ok:!1,error:"No submit target configured for this form collector."};const t=e.values;try{let r;if(o.via==="client")if("handler"in o)r=await o.handler(t);else{const s=await fetch(o.url,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(t)});if(!s.ok)return{ok:!1,error:`Submit failed: HTTP ${s.status}`};r=await s.json().catch(()=>{})}else{if(!d)return{ok:!1,error:"Backend submit requires install(client) (or useFormCollector) first."};r=await d.submitFormCollector(o.destination,t)}return l.set({...l.get(),submitted:!0}),{ok:!0,result:r}}catch(r){const s=r instanceof Error?r.message:"Submit failed";return x.logger.error(`FormCollector "${n}" submit failed:`,r),{ok:!1,error:s}}},_={name:`update_${n}`,description:`Fill or update fields of the "${n}" form. ${m} 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:{...c,required:[]},handler:e=>{const t=$(v(e));return{ok:!0,values:t.values,missing:t.missing,complete:t.complete}}},h=[_];o&&h.push({name:`submit_${n}`,description:`Submit the completed "${n}" 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:()=>S()});const E="client__",k=o?`submit_${n}`:null,T=e=>{const t=e.functionName??e.toolName;if(t)return t.startsWith(E)?t.slice(8):t},w=e=>{let t={...f},r=!1;for(const i of e){const g=T(i);g===_.name?i.arguments&&(t={...t,...v(i.arguments)}):k&&g===k&&i.status?.toLowerCase()==="done"&&(r=!0)}const s=b(t);l.set({values:t,missing:s,complete:s.length===0,submitted:r})},C=`form:${n}`,F=()=>{const e=l.get(),t=o?` When all required fields are present and the user confirms, call submit_${n}.`:"";return{name:`Form: ${n}`,description:`Conversational form the assistant is helping fill. ${m} Use update_${n} to record fields; ask the user only for what is still missing.${t}`,data:{values:e.values,missing:e.missing,complete:e.complete,submitted:e.submitted}}},q=e=>{w((e.messages??[]).flatMap(t=>t.toolCalls??[]))};return{name:n,store:l,functions:h,contextKey:C,contextProvider:F,install:e=>{d=e;for(const r of h)e.register(r);e.addDynamicContext(C,F);const t=l.subscribe(()=>e.notifyContextChanged());return e.on("conversation:loaded",q),()=>{t();for(const r of h)e.unregisterFunction(r.name);e.removeDynamicContext(C),e.off("conversation:loaded",q),d===e&&(d=null)}},hydrate:w,submit:S,getValues:()=>l.get().values,setValues:e=>{$(v(e))},reset:()=>{const e=b(f);l.set({values:f,missing:e,complete:e.length===0,submitted:!1})}}}Object.defineProperty(exports,"createFormCollector",{enumerable:!0,get:function(){return I}});Object.defineProperty(exports,"createStore",{enumerable:!0,get:function(){return P}});
@@ -1,4 +1,4 @@
1
- function w(g = {}) {
1
+ function C(g = {}) {
2
2
  const { overrides: m = {} } = g, d = {
3
3
  id: "mock-msg-1",
4
4
  conversationId: "mock-conv-1",
@@ -28,6 +28,8 @@ function w(g = {}) {
28
28
  unregisterFunction: () => !0,
29
29
  getRegisteredFunctions: () => [],
30
30
  getContextSnapshot: () => null,
31
+ notifyContextChanged: () => {
32
+ },
31
33
  registerNavigationFunction: () => {
32
34
  },
33
35
  on: (e, o) => {
@@ -68,5 +70,5 @@ function w(g = {}) {
68
70
  }, n;
69
71
  }
70
72
  export {
71
- w as t
73
+ C as t
72
74
  };
@@ -0,0 +1 @@
1
+ function C(g={}){const{overrides:u={}}=g,d={id:"mock-msg-1",conversationId:"mock-conv-1",content:"Mock response",role:"assistant",status:"DONE",createdAt:new Date},l={id:"mock-conv-1",title:"Mock Conversation",lastMessageDate:new Date},t=new Map,r=[],m={sendMessage:async()=>d,getConversations:async()=>[l],getConversation:async()=>l,getMessages:async()=>[d],submitToolCallForm:async()=>{},confirmToolCall:async()=>{},rejectToolCall:async()=>{},submitFeedback:async()=>{},registerFunction:()=>{},unregisterFunction:()=>!0,getRegisteredFunctions:()=>[],getContextSnapshot:()=>null,notifyContextChanged:()=>{},registerNavigationFunction:()=>{},on:(e,o)=>{t.has(e)||t.set(e,new Set),t.get(e).add(o)},off:(e,o)=>{t.get(e)?.delete(o)},once:(e,o)=>{const n=(...i)=>{t.get(e)?.delete(n),o(...i)};t.has(e)||t.set(e,new Set),t.get(e).add(n)},waitFor:(e,o)=>new Promise((n,i)=>{let a;const c=f=>{a&&clearTimeout(a),t.get(e)?.delete(c),n(f)};t.has(e)||t.set(e,new Set),t.get(e).add(c),o?.timeout&&(a=setTimeout(()=>{t.get(e)?.delete(c),i(new Error(`waitFor("${e}") timed out after ${o.timeout}ms`))},o.timeout))}),updateConfig:()=>{},destroy:()=>{t.clear()},...u},s={};for(const[e,o]of Object.entries(m))s[e]=(...n)=>(r.push({method:e,args:n}),o(...n));return s.__calls=r,s.__callsFor=e=>r.filter(o=>o.method===e),s.__emitEvent=(e,o)=>{const n=t.get(e);n&&[...n].forEach(i=>i(o))},s}Object.defineProperty(exports,"createMockClient",{enumerable:!0,get:function(){return C}});
package/dist/devtools.cjs CHANGED
@@ -1,17 +1,17 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var r,d,v=()=>({});function c(){r&&(r.textContent=JSON.stringify(v(),null,2))}function p(a,o){if(!d)return;const e=document.createElement("div");e.className=`dev-log-line dev-log-${o}`,e.textContent=`${new Date().toLocaleTimeString()} ${a}`,d.appendChild(e),d.scrollTop=d.scrollHeight}var x="ago_dev_panel_collapsed";function i(a,o){a.classList.toggle("collapsed",o);const e=a.querySelector(".dev-toggle");e&&(e.textContent=o?"▢":"—",e.title=o?"Expand dev tools":"Collapse dev tools",e.setAttribute("aria-expanded",String(!o)));try{localStorage.setItem(x,o?"1":"0")}catch{}}function f(a){const{client:o,target:e}=a;v=()=>o.getContextSnapshot()?.entries??{},b();const u=typeof e=="string"?document.querySelector(e):e instanceof Element?e:document.body,t=document.createElement("aside");t.id="ago-dev-panel",(u??document.body).appendChild(t),t.innerHTML=`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var c,d,v=()=>({});function i(){c&&(c.textContent=JSON.stringify(v(),null,2))}function s(l,e){if(!d)return;const o=document.createElement("div");o.className=`dev-log-line dev-log-${e}`,o.textContent=`${new Date().toLocaleTimeString()} ${l}`,d.appendChild(o),d.scrollTop=d.scrollHeight}var x="ago_dev_panel_collapsed";function r(l,e){l.classList.toggle("collapsed",e);const o=l.querySelector(".dev-toggle");o&&(o.textContent=e?"▢":"—",o.title=e?"Expand dev tools":"Collapse dev tools",o.setAttribute("aria-expanded",String(!e)));try{localStorage.setItem(x,e?"1":"0")}catch{}}function h(l){const{client:e,target:o}=l;v=()=>e.getContextSnapshot()?.entries??{},b();const u=typeof o=="string"?document.querySelector(o):o instanceof Element?o:document.body,t=document.createElement("aside");t.id="ago-dev-panel",(u??document.body).appendChild(t),t.innerHTML=`
2
2
  <div class="dev-head">
3
3
  <span class="dev-badge">DEV</span>
4
4
  <span class="dev-title">DEV TOOLS · client-side function state — not for production</span>
5
5
  <button type="button" class="dev-toggle" aria-label="Toggle dev tools">—</button>
6
6
  </div>
7
7
  <div class="dev-body">
8
- <div class="dev-fns">Registered functions: <code>${(o.getRegisteredFunctions?.()??[]).map(n=>n.name).join(", ")||"—"}</code></div>
8
+ <div class="dev-fns">Registered functions: <code>${(e.getRegisteredFunctions?.()??[]).map(a=>a.name).join(", ")||"—"}</code></div>
9
9
  <div class="dev-section-label">JSON object (built by the agent)</div>
10
10
  <pre class="dev-state" id="ago-dev-state"></pre>
11
11
  <div class="dev-section-label">Function calls</div>
12
12
  <div class="dev-log" id="ago-dev-log"></div>
13
13
  </div>
14
- `,r=t.querySelector("#ago-dev-state"),d=t.querySelector("#ago-dev-log"),t.querySelector(".dev-toggle")?.addEventListener("click",n=>{n.stopPropagation(),i(t,!t.classList.contains("collapsed"))}),t.addEventListener("click",()=>{t.classList.contains("collapsed")&&i(t,!1)});let s=!1;try{s=localStorage.getItem(x)==="1"}catch{}i(t,s),o.on("function:invoke",({functionName:n,arguments:l})=>{p(`→ ${n}(${JSON.stringify(l??{})})`,"invoke")}),o.on("function:result",({result:n,error:l})=>{p(l?`✗ error: ${l}`:`← ${JSON.stringify(n)}`,l?"error":"result"),c()}),c()}var g="ago-dev-panel-styles";function b(){if(document.getElementById(g))return;const a=document.createElement("style");a.id=g,a.textContent=h,document.head.appendChild(a)}var h=`
14
+ `,c=t.querySelector("#ago-dev-state"),d=t.querySelector("#ago-dev-log"),t.querySelector(".dev-toggle")?.addEventListener("click",a=>{a.stopPropagation(),r(t,!t.classList.contains("collapsed"))}),t.addEventListener("click",()=>{t.classList.contains("collapsed")&&r(t,!1)});let p=!1;try{p=localStorage.getItem(x)==="1"}catch{}r(t,p),e.on("function:invoke",({functionName:a,arguments:n})=>{s(`→ ${a}(${JSON.stringify(n??{})})`,"invoke")}),e.on("function:result",({result:a,error:n})=>{s(n?`✗ error: ${n}`:`← ${JSON.stringify(a)}`,n?"error":"result"),i()}),e.on("context:changed",i),e.on("conversation:loaded",a=>{const n=(a.messages??[]).flatMap(f=>f.toolCalls??[]);s(`⟳ hydrated "${a.title||a.id}" — replayed ${n.length} tool call${n.length===1?"":"s"}`,"hydrate"),i()}),i()}var g="ago-dev-panel-styles";function b(){if(document.getElementById(g))return;const l=document.createElement("style");l.id=g,l.textContent=m,document.head.appendChild(l)}var m=`
15
15
  #ago-dev-panel {
16
16
  position: fixed;
17
17
  top: 16px;
@@ -105,4 +105,5 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var r,d,v=()=
105
105
  #ago-dev-panel .dev-log-invoke { color: #9ecbff; }
106
106
  #ago-dev-panel .dev-log-result { color: #86efac; }
107
107
  #ago-dev-panel .dev-log-error { color: #fca5a5; }
108
- `;exports.initDevPanel=f;
108
+ #ago-dev-panel .dev-log-hydrate { color: #d8b4fe; }
109
+ `;exports.initDevPanel=h;
@@ -147,6 +147,13 @@ declare class AgoClient {
147
147
  * Remove a dynamic context provider.
148
148
  */
149
149
  removeDynamicContext(key: string): boolean;
150
+ /**
151
+ * Broadcast that the client-side context changed by emitting `context:changed`
152
+ * with the fresh snapshot. The context-mutating methods call this automatically;
153
+ * stateful helpers whose context lives in a store (e.g. `createFormCollector`)
154
+ * call it when their store updates so observers like the dev panel stay live.
155
+ */
156
+ notifyContextChanged(): void;
150
157
  /**
151
158
  * Enable automatic capture of the current browser page (URL + title).
152
159
  * Injected as a dynamic context entry named `browser-page`.
@@ -192,6 +199,14 @@ declare class AgoClient {
192
199
  * SDK Events
193
200
  */
194
201
  declare interface AgoClientEvents {
202
+ /**
203
+ * The client-side context changed: a context entry or dynamic provider was
204
+ * added/removed, or a stateful helper (e.g. `createFormCollector`) updated its
205
+ * store. Carries the fresh snapshot so observers — notably the dev panel — can
206
+ * repaint without waiting for the next message. Fires for the form collector's
207
+ * initial install too, so its missing fields show from the start of a conversation.
208
+ */
209
+ "context:changed": ContextSnapshot | null;
195
210
  "message:start": {
196
211
  conversationId: string;
197
212
  messageId: string;
@@ -147,6 +147,13 @@ declare class AgoClient {
147
147
  * Remove a dynamic context provider.
148
148
  */
149
149
  removeDynamicContext(key: string): boolean;
150
+ /**
151
+ * Broadcast that the client-side context changed by emitting `context:changed`
152
+ * with the fresh snapshot. The context-mutating methods call this automatically;
153
+ * stateful helpers whose context lives in a store (e.g. `createFormCollector`)
154
+ * call it when their store updates so observers like the dev panel stay live.
155
+ */
156
+ notifyContextChanged(): void;
150
157
  /**
151
158
  * Enable automatic capture of the current browser page (URL + title).
152
159
  * Injected as a dynamic context entry named `browser-page`.
@@ -192,6 +199,14 @@ declare class AgoClient {
192
199
  * SDK Events
193
200
  */
194
201
  declare interface AgoClientEvents {
202
+ /**
203
+ * The client-side context changed: a context entry or dynamic provider was
204
+ * added/removed, or a stateful helper (e.g. `createFormCollector`) updated its
205
+ * store. Carries the fresh snapshot so observers — notably the dev panel — can
206
+ * repaint without waiting for the next message. Fires for the form collector's
207
+ * initial install too, so its missing fields show from the start of a conversation.
208
+ */
209
+ "context:changed": ContextSnapshot | null;
195
210
  "message:start": {
196
211
  conversationId: string;
197
212
  messageId: string;