@useago/sdk 1.3.2 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -92,6 +92,46 @@ guards, auth and layouts keep working exactly as they do today.
92
92
  `react-router-dom` here is *your* router, not an SDK dependency:
93
93
  `useAgoNavigation` accepts any `(path: string) => void` function.
94
94
 
95
+ ## Let the agent change the page
96
+
97
+ The mirror of navigation. Same idea, applied to the page the user is already on:
98
+ describe its editable state (filters, sort, view mode…) and *"show me only the
99
+ overdue ones, newest first"* actually updates the view. The agent also reads the
100
+ current state, so it knows what to change.
101
+
102
+ ```tsx
103
+ import { useAgoPageState } from "@useago/sdk/react";
104
+
105
+ function InvoiceList() {
106
+ const [status, setStatus] = useState("all");
107
+ const [sort, setSort] = useState("newest");
108
+
109
+ useAgoPageState([
110
+ {
111
+ name: "statusFilter",
112
+ description: "Filter invoices by status",
113
+ schema: { type: "string", enum: ["all", "paid", "overdue"] },
114
+ get: () => status, // current value → the agent sees it
115
+ set: setStatus, // the agent changes it
116
+ },
117
+ {
118
+ name: "sort",
119
+ description: "Sort order of the list",
120
+ schema: { type: "string", enum: ["newest", "oldest"] },
121
+ get: () => sort,
122
+ set: setSort,
123
+ },
124
+ ]);
125
+
126
+ return /* your existing list, driven by status + sort */;
127
+ }
128
+ ```
129
+
130
+ Each control becomes one optional property of a single `setPageState` function,
131
+ so the agent changes only what the user asked for. The current value from each
132
+ `get()` is sent with every message, so the agent knows the state before it
133
+ changes it. Vue and Angular have the same helper.
134
+
95
135
  ## Turn a JavaScript function into an agent tool
96
136
 
97
137
  Keep your application logic as a regular JavaScript function, then describe its
@@ -215,6 +255,7 @@ react-router navigation), Vue, Angular, plain TypeScript, and no-build HTML.
215
255
  - [**Events & streaming**](docs/general/events-and-streaming.md): low-level hooks into the message stream
216
256
  - [**Testing**](docs/general/testing.md): mock client for unit tests
217
257
  - [**Configuration & auth**](docs/general/configuration.md): every `AgoConfig` option, headers, errors
258
+ - [**Custom domain (reverse proxy)**](docs/general/custom-domain.md): serve AGO from your own domain, same-origin
218
259
 
219
260
  Full documentation: [ago.mintlify.app](https://ago.mintlify.app/)
220
261
 
@@ -0,0 +1,8 @@
1
+ var h=class extends Error{constructor(e,t,n){super(e),this.code=t,this.statusCode=n,this.name="AgoError"}},u=class E extends h{constructor(t,n,r,s,i,o){super(t,n,r),this.type=s,this.param=i,this.docUrl=o,this.name="AgoApiError"}static fromResponse(t,n){const r=t.error;return new E(r.doc_url?`${r.message} See ${r.doc_url}`:r.message,r.code,n,r.type,r.param,r.doc_url)}},m=class extends h{constructor(e,t){super(e,"network_error"),this.originalError=t,this.name="AgoNetworkError"}},f=class extends h{constructor(e,t="stream_error"){super(e,t),this.name="AgoStreamError"}},g=class extends h{constructor(e,t,n){super(e,"function_error"),this.functionName=t,this.originalError=n,this.name="AgoFunctionError"}},R=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)}},a=new R,v="ago_widget_id";function x(){if(typeof localStorage<"u"){const t=localStorage.getItem(v);if(t)return t}const e=typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`ago-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,12)}`;if(typeof localStorage<"u")try{localStorage.setItem(v,e)}catch{}return e}var I=class{constructor(e){this.baseUrl=e.baseUrl.replace(/\/$/,""),this.headers={"X-User-Anon-Id":e.widgetId||x()},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-User-Anon-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 n=`${this.baseUrl}${e}`;a.debug("POST (stream)",n,t);try{const r=await fetch(n,{method:"POST",headers:{...this.headers,"Content-Type":"application/json"},body:t?JSON.stringify(t):void 0});return r.ok||await this.handleErrorResponse(r),r}catch(r){throw r instanceof u?r:new m(`Network error: ${r instanceof Error?r.message:"Unknown error"}. Check that \`baseUrl\` is reachable and includes the protocol (https://).`,r instanceof Error?r:void 0)}}async postFormData(e,t){const n=`${this.baseUrl}${e}`;a.debug("POST (formData)",n);const r={...this.headers};try{const s=await fetch(n,{method:"POST",headers:r,body:t});return s.ok||await this.handleErrorResponse(s),s}catch(s){throw s instanceof u?s:new m(`Network error: ${s instanceof Error?s.message:"Unknown error"}. Check that \`baseUrl\` is reachable and includes the protocol (https://).`,s instanceof Error?s:void 0)}}async request(e,t,n){const r=`${this.baseUrl}${t}`;a.debug(e,r,n);try{const s=await fetch(r,{method:e,headers:{...this.headers,"Content-Type":"application/json"},body:n?JSON.stringify(n):void 0});return s.ok||await this.handleErrorResponse(s),s.status===204?void 0:s.json()}catch(s){throw s instanceof u?s:new m(`Network error: ${s instanceof Error?s.message:"Unknown error"}. Check that \`baseUrl\` is reachable and includes the protocol (https://).`,s instanceof Error?s:void 0)}}async handleErrorResponse(e){let t;try{t=await e.json()}catch{}if(t?.error)throw u.fromResponse(t,e.status);let n="";throw e.status===401||e.status===403?n=" Check `userJwt` (and that it has not expired).":e.status===404&&(n=" Check that `baseUrl` points at your AGO API root."),new u(`HTTP ${e.status}: ${e.statusText}.${n}`,"http_error",e.status,"api_error")}},_=class{constructor(){this.functions=new Map}register(e,t,n){if(typeof e=="object"){const{name:s,handler:i,description:o,parameters:l}=e;return this.register(s,i,{description:o,parameters:l})}const r=e;if(!t||!n)throw new h(`registerFunction("${r}"): both a handler and a schema are required. Pass them as arguments or use the single-object form: registerFunction({ name, parameters, handler }).`,"function_invalid_registration");this.functions.has(r)&&a.warn(`Function "${r}" is being overwritten`),this.functions.set(r,{schema:{...n,name:r},handler:t}),a.log(`Registered function: ${r}`)}unregister(e){const t=this.functions.delete(e);return t&&a.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 n=this.functions.get(e);if(!n)throw new g(`Function "${e}" is not registered`,e);a.log(`Executing function: ${e}`,t);try{const r=await n.handler(t);return a.log(`Function ${e} completed:`,r),r}catch(r){throw a.error(`Function ${e} failed:`,r),new g(`Function "${e}" execution failed: ${r instanceof Error?r.message:"Unknown error"}`,e,r instanceof Error?r:void 0)}}clear(){this.functions.clear(),a.log("Cleared all registered functions")}get size(){return this.functions.size}},S=class{constructor(){this.entries=new Map,this.dynamicProviders=new Map}set(e,t){this.entries.set(e,t),a.log(`ClientContext set: ${e}`)}remove(e){const t=this.entries.delete(e);return t&&a.log(`ClientContext removed: ${e}`),t}addDynamicProvider(e,t){this.dynamicProviders.set(e,t),a.log(`DynamicContext provider added: ${e}`)}removeDynamicProvider(e){const t=this.dynamicProviders.delete(e);return t&&a.log(`DynamicContext provider removed: ${e}`),t}getSnapshot(){if(this.entries.size===0&&this.dynamicProviders.size===0)return null;const e={};for(const[t,n]of this.entries)e[t]=n;for(const[t,n]of this.dynamicProviders)try{const r=n();r&&(e[t]=r)}catch(r){a.error(`DynamicContext provider "${t}" threw:`,r)}return Object.keys(e).length===0?null:{entries:e}}clear(){this.entries.clear(),this.dynamicProviders.clear(),a.log("ClientContext cleared")}};function p(e){return e===null||typeof e!="object"?JSON.stringify(e)??"null":Array.isArray(e)?`[${e.map(p).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${p(e[t])}`).join(",")}}`}var k=class{constructor(e){this.callbacks=e,this.buffer="",this.message={},this.toolCalls=[],this.sources=[],this.followUpReplies=[],this.isFirstChunk=!0,this.answerCompleteEmitted=!1,this.firedClientFunctions=new Set}async processStream(e){if(!e.body)throw new f("Response has no body. The endpoint did not return a stream: check that `baseUrl` points at an AGO API and nothing (proxy, mock) strips the SSE body.","stream_no_body");const t=e.body.getReader(),n=new TextDecoder;try{for(;;){const{done:r,value:s}=await t.read();if(r)break;const i=n.decode(s,{stream:!0});this.buffer+=i,this.processBuffer()}return this.buffer.trim()&&this.processBuffer(),this.buildFinalMessage()}catch(r){const s=r instanceof Error?r:new f("Stream processing failed mid-flight. The connection may have dropped; retry the message.");throw this.callbacks.onError?.(s),s}finally{t.releaseLock()}}processBuffer(){const e=this.buffer.split(`
2
+
3
+ `);this.buffer=e.pop()||"";for(const t of e){if(!t.trim())continue;const n=t.split(`
4
+ `);for(const r of n)if(!r.startsWith(": ")&&r.startsWith("data: ")){const s=r.slice(6);try{const i=JSON.parse(s);this.handleChunk(i)}catch(i){a.warn("Failed to parse SSE data:",s,i)}}}}handleChunk(e){if(this.callbacks.onRawChunk?.(e),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 n=t.knowledge_document;return{id:n.id,title:n.title,url:n.use_external_link?n.external_link_url:n.internal_link_url}})),e.type==="client_function"&&e.function_name){const t=`${e.function_name}::${p(e.arguments??{})}`;this.firedClientFunctions.has(t)||(this.firedClientFunctions.add(t),this.callbacks.onClientFunction?.({invocationId:e.id||"",functionName:e.function_name,arguments:e.arguments||{},conversationId:this.message.conversationId||""}))}if(e.tool_call_data&&e.type&&e.type!=="client_function"){const t=this.parseToolCall(e);this.callbacks.onToolCall?.(t);const n=this.toolCalls.findIndex(r=>r.id===t.id);n>=0?this.toolCalls[n]=t:this.toolCalls.push(t)}e.follow_up_replies&&(this.followUpReplies=e.follow_up_replies),this.message.status==="DONE"&&!this.answerCompleteEmitted&&this.message.id&&(this.answerCompleteEmitted=!0,this.callbacks.onAnswerComplete?.(this.buildMessage()))}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}}buildMessage(){return{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}}buildFinalMessage(){const e=this.buildMessage();return this.callbacks.onComplete?.(e),e}};function U(e){const t=e.message.toLowerCase();return t.includes("load failed")||t.includes("failed to fetch")||t.includes("network")||t.includes("abort")}var P=new Set(["image/jpeg","image/png","image/gif","image/webp","image/bmp","image/tiff"]);function A(e){if(!e)return;const t=typeof window<"u"&&window.location?window.location.href:"https://ago.local/";try{const n=new URL(e,t);if(n.protocol==="http:"||n.protocol==="https:"||n.protocol==="blob:")return e}catch{}}function O(e){return e.isSafeImage===!0&&typeof e.contentType=="string"&&e.contentType.startsWith("image/")&&A(e.url)!==void 0}function j(e){if(e==null||e<0)return"";if(e<1024)return`${e} B`;const t=e/1024;return t<1024?`${t.toFixed(1)} KB`:`${(t/1024).toFixed(1)} MB`}function N(e){return{id:String(e.id??""),name:typeof e.name=="string"&&e.name?e.name:"file",contentType:typeof e.content_type=="string"?e.content_type:void 0,fileSize:typeof e.file_size=="number"?e.file_size:void 0,url:typeof e.file_url=="string"?e.file_url:void 0,isSafeImage:e.is_safe_image===!0}}function T(e){return e.map((t,n)=>({id:`local-${n}-${t.name}`,name:t.name,contentType:t.type||void 0,fileSize:t.size,url:typeof URL<"u"&&URL.createObjectURL?URL.createObjectURL(t):void 0,isSafeImage:P.has(t.type)}))}var $=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 n=this.handlers.get(e);n&&n.delete(t)}emit(e,t){const n=this.handlers.get(e);n&&n.forEach(r=>{try{r(t)}catch(s){console.error(`Error in event handler for ${String(e)}:`,s)}})}once(e,t){const n=(r=>{this.off(e,n),t(r)});this.on(e,n)}waitFor(e,t){return new Promise((n,r)=>{let s;const i=(o=>{s&&clearTimeout(s),n(o)});this.once(e,i),t?.timeout&&(s=setTimeout(()=>{this.off(e,i),r(new Error(`waitFor("${String(e)}") timed out after ${t.timeout}ms`))},t.timeout))})}removeAllListeners(e){e?this.handlers.delete(e):this.handlers.clear()}},b='`baseUrl` is required, e.g. new AgoClient({ baseUrl: "https://YOUR-DOMAIN.api.useago.com" }). Try the live demo endpoint https://playground.api.useago.com. See docs/general/configuration.md#error-codes (config_missing_base_url).',D=/^[a-z][a-z0-9+.-]*:\/\//i,C=!1;function y(e,t="AgoClient"){if(typeof e!="object"||e===null)throw new h(`${t}: ${b}`,"config_missing_base_url");const n=e.baseUrl;if(typeof n!="string"||n.trim()==="")throw new h(`${t}: ${b}`,"config_missing_base_url");!n.startsWith("/")&&!D.test(n)&&(C||(C=!0,console.warn(`[AGO] ${t}: \`baseUrl\` has no protocol and is not a relative path (config_suspect_base_url). Requests will fail: Node throws a URL parse error, browsers fetch it as a relative path. Use "https://..." (or a "/path" for a same-origin proxy).`)))}var M=class F{constructor(t){this.warnedEmptyConversations=new Set,y(t,"AgoClient"),this.config=t,this.httpClient=new I(t),this.functionRegistry=new _,this.contextRegistry=new S,this.eventEmitter=new $,t.debug&&a.enable(),a.log("AgoClient initialized")}async sendMessage(t,n){const r=this.functionRegistry.getSchemas(),s=this.contextRegistry.getSnapshot(),i=this.config.agent||this.config.defaultAgentId,o={content:t,conversation_id:n?.conversationId,agent_id:n?.agentId||i};r.length>0&&(o.client_functions=r),s&&(o.client_context=s),n?.hidden&&(o.hidden=!0);let l;if(n?.files&&n.files.length>0){const c=new FormData;c.append("content",t),n.conversationId&&c.append("conversation_id",n.conversationId),(n.agentId||i)&&c.append("agent_id",n.agentId||i||""),r.length>0&&c.append("client_functions",JSON.stringify(r)),s&&c.append("client_context",JSON.stringify(s)),n.hidden&&c.append("hidden","true");for(const d of n.files)c.append("files",d);l=await this.httpClient.postFormData("/api/sdk/v1/messages",c)}else l=await this.httpClient.postStream("/api/sdk/v1/messages",o);return this.processSSEResponse(l)}async processSSEResponse(t){let n=!1;const r=await new k({onRawChunk:s=>{this.eventEmitter.emit("stream:message",s)},onStart:s=>{this.eventEmitter.emit("message:start",s)},onChunk:s=>{this.eventEmitter.emit("message:chunk",s)},onToolCall:s=>{this.eventEmitter.emit("toolCall:received",s),s.type==="form"&&this.eventEmitter.emit("toolCall:form",s)},onClientFunction:async s=>{n=!0,this.eventEmitter.emit("function:invoke",s),await this.handleClientFunctionInvocation(s)},onAnswerComplete:s=>{this.eventEmitter.emit("message:answer-complete",s)},onComplete:s=>{this.eventEmitter.emit("message:complete",s)},onError:s=>{this.eventEmitter.emit("message:error",{error:s.message,code:s instanceof h?s.code:void 0})}}).processStream(t);return this.maybeFlagEmptyReply(r,n),r}maybeFlagEmptyReply(t,n){t.status==="DONE"&&(t.content??"").trim()===""&&!n&&!(t.toolCalls&&t.toolCalls.length>0)&&!(t.followUpReplies&&t.followUpReplies.length>0)&&setTimeout(()=>{if(this.eventEmitter.emit("message:empty",{conversationId:t.conversationId??"",messageId:t.id??""}),this.config.warnOnEmptyReply===!1)return;const r=t.conversationId||"(no conversation)";if(this.warnedEmptyConversations.has(r))return;this.warnedEmptyConversations.add(r);const s=this.config.agent||this.config.defaultAgentId;t.id?console.warn("[AGO] Reply completed with empty content. Possible causes: "+(s?`the agent "${s}" may not exist for this tenant, `:"an unknown `agent` slug, ")+"or the agent replied with no text. Listen for the `message:empty` event to handle this in your app; silence this warning with `warnOnEmptyReply: false`."):console.warn("[AGO] The stream completed without any message data. Possible causes: "+(s?`the agent "${s}" may not exist for this tenant, or `:"")+"`baseUrl` does not point at an AGO endpoint that returns server-sent events. Listen for the `message:empty` event to handle this in your app; silence this warning with `warnOnEmptyReply: false`.")},0)}async handleClientFunctionInvocation(t){let n,r;try{n=await this.functionRegistry.execute(t.functionName,t.arguments)}catch(s){r=s instanceof Error?s.message:"Unknown error",a.error("Client function execution failed:",s)}if(t.invocationId)try{await this.submitToolCallForm(t.invocationId,{result:n,error:r,_type:"client_function_result"})}catch(s){a.error("Failed to submit function result:",s)}this.eventEmitter.emit("function:result",{invocationId:t.invocationId,result:n,error:r})}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 n=await this.httpClient.get(`/api/sdk/v1/conversations/${t}`),r={id:n.id,title:n.title,lastMessageDate:new Date(n.last_message_date),messages:n.messages.map(s=>({id:s.id,conversationId:n.id,content:s.content,role:s.role,status:s.status,createdAt:new Date(s.created_at),hidden:s.hidden,toolCalls:F.mapPersistedToolCalls(s.tool_call_data),attachments:s.attachments&&s.attachments.length>0?s.attachments.map(N):void 0}))};return this.eventEmitter.emit("conversation:loaded",r),r}static mapPersistedToolCalls(t){if(!(!t||t.length===0))return t.map(n=>({id:String(n.id??""),type:n.type??"status_message",status:String(n.status??"unknown"),toolName:n.tool_name??"",toolDisplayName:n.tool_display_name,message:n.message,formSchema:n.form_schema,data:n.data,functionName:n.function_name,arguments:n.arguments}))}async getMessages(t){return(await this.getConversation(t)).messages||[]}async submitToolCallForm(t,n){await this.httpClient.post(`/api/sdk/v1/tool-calls/${t}/submit`,{formData:n})}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 getFormCollector(t){const n=await this.httpClient.get(`/api/sdk/v1/forms/${encodeURIComponent(t)}`);return{name:n.name,description:n.description,schema:n.schema,submit:n.submit??void 0}}async submitFormCollector(t,n){return this.httpClient.post("/api/sdk/v1/forms/submit",{name:t,values:n})}async submitFeedback(t,n){await this.httpClient.post(`/api/sdk/v1/messages/${t}/feedback`,{rating:n})}registerFunction(t,n,r){typeof t=="object"?this.functionRegistry.register(t):this.functionRegistry.register(t,n,r)}register(t){if(Array.isArray(t))for(const n of t)this.functionRegistry.register(n);else this.functionRegistry.register(t)}unregisterFunction(t){return this.functionRegistry.unregister(t)}getRegisteredFunctions(){return this.functionRegistry.getSchemas()}registerNavigationFunction(t,n){const r=n.map(i=>i.name),s=n.map(i=>`- "${i.name}": ${i.description}`).join(`
5
+ `);this.registerFunction("navigateToPage",async i=>{const o=i.page,l=n.find(c=>c.name===o);return l?(t(l.path),{success:!0,navigatedTo:l.path}):{success:!1,error:`Unknown page: ${o}`}},{description:`Navigate the user to a page in the application. Available pages:
6
+ ${s}`,parameters:{type:"object",properties:{page:{type:"string",description:"The page to navigate to",enum:r}},required:["page"]}})}registerPageStateFunction(t,n){const r=n?.functionName??"setPageState",s=new Map(t.map(o=>[o.name,o])),i=t.map(o=>`- "${o.name}": ${o.description}`).join(`
7
+ `);this.registerFunction(r,async o=>{const l={};for(const[c,d]of Object.entries(o)){if(d===void 0)continue;const w=s.get(c);w&&(await w.set(d),l[c]=d)}return{success:!0,applied:l}},{description:`Change the state of the current page. Set ONLY the controls the user explicitly asked for; leave the others unset. Available controls:
8
+ ${i}`,parameters:{type:"object",properties:Object.fromEntries(t.map(o=>[o.name,{...o.schema,description:o.description}]))}}),this.addDynamicContext(`page-state:${r}`,()=>{const o=t.filter(c=>typeof c.get=="function");if(o.length===0)return null;const l={};for(const c of o)l[c.name]=c.get();return{name:"Page state",description:"Current, editable state of the page the user is viewing.",data:l}})}unregisterPageStateFunction(t){const n=t??"setPageState";this.unregisterFunction(n),this.removeDynamicContext(`page-state:${n}`)}setContext(t,n){this.contextRegistry.set(t,n),this.notifyContextChanged()}removeContext(t){const n=this.contextRegistry.remove(t);return n&&this.notifyContextChanged(),n}addDynamicContext(t,n){this.contextRegistry.addDynamicProvider(t,n),this.notifyContextChanged()}removeDynamicContext(t){const n=this.contextRegistry.removeDynamicProvider(t);return n&&this.notifyContextChanged(),n}notifyContextChanged(){this.eventEmitter.emit("context:changed",this.contextRegistry.getSnapshot())}emitFormEvent(t,n){this.eventEmitter.emit(t,n)}enableAutoPageContext(){this.addDynamicContext("browser-page",()=>{const t=typeof window<"u"?window.location.href:void 0,n=typeof document<"u"?document.title:void 0;return!t&&!n?null:{name:"Browser page",description:"Current page the user is viewing",data:{url:t,title:n}}})}getContextSnapshot(){return this.contextRegistry.getSnapshot()}on(t,n){this.eventEmitter.on(t,n)}off(t,n){this.eventEmitter.off(t,n)}once(t,n){this.eventEmitter.once(t,n)}waitFor(t,n){return this.eventEmitter.waitFor(t,n)}updateConfig(t){const n={};for(const[s,i]of Object.entries(t))i!==void 0&&(n[s]=i);const r={...this.config,...n};y(r,"AgoClient.updateConfig"),this.config=r,this.httpClient.updateConfig(n),n.debug!==void 0&&(n.debug?a.enable():a.disable())}destroy(){this.eventEmitter.removeAllListeners(),this.functionRegistry.clear(),this.contextRegistry.clear(),a.log("AgoClient destroyed")}};Object.defineProperty(exports,"AgoApiError",{enumerable:!0,get:function(){return u}});Object.defineProperty(exports,"AgoClient",{enumerable:!0,get:function(){return M}});Object.defineProperty(exports,"AgoError",{enumerable:!0,get:function(){return h}});Object.defineProperty(exports,"AgoFunctionError",{enumerable:!0,get:function(){return g}});Object.defineProperty(exports,"AgoNetworkError",{enumerable:!0,get:function(){return m}});Object.defineProperty(exports,"AgoStreamError",{enumerable:!0,get:function(){return f}});Object.defineProperty(exports,"ClientContextRegistry",{enumerable:!0,get:function(){return S}});Object.defineProperty(exports,"EventEmitter",{enumerable:!0,get:function(){return $}});Object.defineProperty(exports,"FunctionRegistry",{enumerable:!0,get:function(){return _}});Object.defineProperty(exports,"SSEHandler",{enumerable:!0,get:function(){return k}});Object.defineProperty(exports,"attachmentsFromFiles",{enumerable:!0,get:function(){return T}});Object.defineProperty(exports,"canInlineImage",{enumerable:!0,get:function(){return O}});Object.defineProperty(exports,"formatFileSize",{enumerable:!0,get:function(){return j}});Object.defineProperty(exports,"isStreamNetworkError",{enumerable:!0,get:function(){return U}});Object.defineProperty(exports,"logger",{enumerable:!0,get:function(){return a}});Object.defineProperty(exports,"safeAttachmentUrl",{enumerable:!0,get:function(){return A}});Object.defineProperty(exports,"validateConfig",{enumerable:!0,get:function(){return y}});
@@ -2,27 +2,27 @@ var h = class extends Error {
2
2
  constructor(e, t, s) {
3
3
  super(e), this.code = t, this.statusCode = s, this.name = "AgoError";
4
4
  }
5
- }, d = class C extends h {
6
- constructor(t, s, i, n, r, a) {
7
- super(t, s, i), this.type = n, this.param = r, this.docUrl = a, this.name = "AgoApiError";
5
+ }, u = class E extends h {
6
+ constructor(t, s, i, n, r, o) {
7
+ super(t, s, i), this.type = n, this.param = r, this.docUrl = o, this.name = "AgoApiError";
8
8
  }
9
9
  static fromResponse(t, s) {
10
10
  const i = t.error;
11
- return new C(i.doc_url ? `${i.message} See ${i.doc_url}` : i.message, i.code, s, i.type, i.param, i.doc_url);
11
+ return new E(i.doc_url ? `${i.message} See ${i.doc_url}` : i.message, i.code, s, i.type, i.param, i.doc_url);
12
12
  }
13
- }, u = class extends h {
13
+ }, m = class extends h {
14
14
  constructor(e, t) {
15
15
  super(e, "network_error"), this.originalError = t, this.name = "AgoNetworkError";
16
16
  }
17
- }, g = class extends h {
17
+ }, p = class extends h {
18
18
  constructor(e, t = "stream_error") {
19
19
  super(e, t), this.name = "AgoStreamError";
20
20
  }
21
- }, f = class extends h {
21
+ }, y = class extends h {
22
22
  constructor(e, t, s) {
23
23
  super(e, "function_error"), this.functionName = t, this.originalError = s, this.name = "AgoFunctionError";
24
24
  }
25
- }, E = class {
25
+ }, S = class {
26
26
  constructor(e = !1) {
27
27
  this.enabled = e;
28
28
  }
@@ -44,22 +44,22 @@ var h = class extends Error {
44
44
  debug(...e) {
45
45
  this.enabled && console.debug("[AGO SDK]", ...e);
46
46
  }
47
- }, o = new E(), p = "ago_widget_id";
48
- function S() {
47
+ }, a = new S(), w = "ago_widget_id";
48
+ function $() {
49
49
  if (typeof localStorage < "u") {
50
- const t = localStorage.getItem(p);
50
+ const t = localStorage.getItem(w);
51
51
  if (t) return t;
52
52
  }
53
53
  const e = typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID() : `ago-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
54
54
  if (typeof localStorage < "u") try {
55
- localStorage.setItem(p, e);
55
+ localStorage.setItem(w, e);
56
56
  } catch {
57
57
  }
58
58
  return e;
59
59
  }
60
60
  var k = class {
61
61
  constructor(e) {
62
- this.baseUrl = e.baseUrl.replace(/\/$/, ""), this.headers = { "X-User-Anon-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);
62
+ this.baseUrl = e.baseUrl.replace(/\/$/, ""), this.headers = { "X-User-Anon-Id": e.widgetId || $() }, 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);
63
63
  }
64
64
  updateConfig(e) {
65
65
  e.baseUrl && (this.baseUrl = e.baseUrl.replace(/\/$/, "")), e.widgetId && (this.headers["X-User-Anon-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"]);
@@ -72,7 +72,7 @@ var k = class {
72
72
  }
73
73
  async postStream(e, t) {
74
74
  const s = `${this.baseUrl}${e}`;
75
- o.debug("POST (stream)", s, t);
75
+ a.debug("POST (stream)", s, t);
76
76
  try {
77
77
  const i = await fetch(s, {
78
78
  method: "POST",
@@ -84,12 +84,12 @@ var k = class {
84
84
  });
85
85
  return i.ok || await this.handleErrorResponse(i), i;
86
86
  } catch (i) {
87
- throw i instanceof d ? i : new u(`Network error: ${i instanceof Error ? i.message : "Unknown error"}. Check that \`baseUrl\` is reachable and includes the protocol (https://).`, i instanceof Error ? i : void 0);
87
+ throw i instanceof u ? i : new m(`Network error: ${i instanceof Error ? i.message : "Unknown error"}. Check that \`baseUrl\` is reachable and includes the protocol (https://).`, i instanceof Error ? i : void 0);
88
88
  }
89
89
  }
90
90
  async postFormData(e, t) {
91
91
  const s = `${this.baseUrl}${e}`;
92
- o.debug("POST (formData)", s);
92
+ a.debug("POST (formData)", s);
93
93
  const i = { ...this.headers };
94
94
  try {
95
95
  const n = await fetch(s, {
@@ -99,12 +99,12 @@ var k = class {
99
99
  });
100
100
  return n.ok || await this.handleErrorResponse(n), n;
101
101
  } catch (n) {
102
- throw n instanceof d ? n : new u(`Network error: ${n instanceof Error ? n.message : "Unknown error"}. Check that \`baseUrl\` is reachable and includes the protocol (https://).`, n instanceof Error ? n : void 0);
102
+ throw n instanceof u ? n : new m(`Network error: ${n instanceof Error ? n.message : "Unknown error"}. Check that \`baseUrl\` is reachable and includes the protocol (https://).`, n instanceof Error ? n : void 0);
103
103
  }
104
104
  }
105
105
  async request(e, t, s) {
106
106
  const i = `${this.baseUrl}${t}`;
107
- o.debug(e, i, s);
107
+ a.debug(e, i, s);
108
108
  try {
109
109
  const n = await fetch(i, {
110
110
  method: e,
@@ -116,7 +116,7 @@ var k = class {
116
116
  });
117
117
  return n.ok || await this.handleErrorResponse(n), n.status === 204 ? void 0 : n.json();
118
118
  } catch (n) {
119
- throw n instanceof d ? n : new u(`Network error: ${n instanceof Error ? n.message : "Unknown error"}. Check that \`baseUrl\` is reachable and includes the protocol (https://).`, n instanceof Error ? n : void 0);
119
+ throw n instanceof u ? n : new m(`Network error: ${n instanceof Error ? n.message : "Unknown error"}. Check that \`baseUrl\` is reachable and includes the protocol (https://).`, n instanceof Error ? n : void 0);
120
120
  }
121
121
  }
122
122
  async handleErrorResponse(e) {
@@ -125,35 +125,35 @@ var k = class {
125
125
  t = await e.json();
126
126
  } catch {
127
127
  }
128
- if (t?.error) throw d.fromResponse(t, e.status);
128
+ if (t?.error) throw u.fromResponse(t, e.status);
129
129
  let s = "";
130
- throw e.status === 401 || e.status === 403 ? s = " Check `userJwt` (and that it has not expired)." : e.status === 404 && (s = " Check that `baseUrl` points at your AGO API root."), new d(`HTTP ${e.status}: ${e.statusText}.${s}`, "http_error", e.status, "api_error");
130
+ throw e.status === 401 || e.status === 403 ? s = " Check `userJwt` (and that it has not expired)." : e.status === 404 && (s = " Check that `baseUrl` points at your AGO API root."), new u(`HTTP ${e.status}: ${e.statusText}.${s}`, "http_error", e.status, "api_error");
131
131
  }
132
- }, $ = class {
132
+ }, A = class {
133
133
  constructor() {
134
134
  this.functions = /* @__PURE__ */ new Map();
135
135
  }
136
136
  register(e, t, s) {
137
137
  if (typeof e == "object") {
138
- const { name: n, handler: r, description: a, parameters: l } = e;
138
+ const { name: n, handler: r, description: o, parameters: l } = e;
139
139
  return this.register(n, r, {
140
- description: a,
140
+ description: o,
141
141
  parameters: l
142
142
  });
143
143
  }
144
144
  const i = e;
145
145
  if (!t || !s) throw new h(`registerFunction("${i}"): both a handler and a schema are required. Pass them as arguments or use the single-object form: registerFunction({ name, parameters, handler }).`, "function_invalid_registration");
146
- this.functions.has(i) && o.warn(`Function "${i}" is being overwritten`), this.functions.set(i, {
146
+ this.functions.has(i) && a.warn(`Function "${i}" is being overwritten`), this.functions.set(i, {
147
147
  schema: {
148
148
  ...s,
149
149
  name: i
150
150
  },
151
151
  handler: t
152
- }), o.log(`Registered function: ${i}`);
152
+ }), a.log(`Registered function: ${i}`);
153
153
  }
154
154
  unregister(e) {
155
155
  const t = this.functions.delete(e);
156
- return t && o.log(`Unregistered function: ${e}`), t;
156
+ return t && a.log(`Unregistered function: ${e}`), t;
157
157
  }
158
158
  get(e) {
159
159
  return this.functions.get(e);
@@ -166,38 +166,38 @@ var k = class {
166
166
  }
167
167
  async execute(e, t) {
168
168
  const s = this.functions.get(e);
169
- if (!s) throw new f(`Function "${e}" is not registered`, e);
170
- o.log(`Executing function: ${e}`, t);
169
+ if (!s) throw new y(`Function "${e}" is not registered`, e);
170
+ a.log(`Executing function: ${e}`, t);
171
171
  try {
172
172
  const i = await s.handler(t);
173
- return o.log(`Function ${e} completed:`, i), i;
173
+ return a.log(`Function ${e} completed:`, i), i;
174
174
  } catch (i) {
175
- throw o.error(`Function ${e} failed:`, i), new f(`Function "${e}" execution failed: ${i instanceof Error ? i.message : "Unknown error"}`, e, i instanceof Error ? i : void 0);
175
+ throw a.error(`Function ${e} failed:`, i), new y(`Function "${e}" execution failed: ${i instanceof Error ? i.message : "Unknown error"}`, e, i instanceof Error ? i : void 0);
176
176
  }
177
177
  }
178
178
  clear() {
179
- this.functions.clear(), o.log("Cleared all registered functions");
179
+ this.functions.clear(), a.log("Cleared all registered functions");
180
180
  }
181
181
  get size() {
182
182
  return this.functions.size;
183
183
  }
184
- }, A = class {
184
+ }, x = class {
185
185
  constructor() {
186
186
  this.entries = /* @__PURE__ */ new Map(), this.dynamicProviders = /* @__PURE__ */ new Map();
187
187
  }
188
188
  set(e, t) {
189
- this.entries.set(e, t), o.log(`ClientContext set: ${e}`);
189
+ this.entries.set(e, t), a.log(`ClientContext set: ${e}`);
190
190
  }
191
191
  remove(e) {
192
192
  const t = this.entries.delete(e);
193
- return t && o.log(`ClientContext removed: ${e}`), t;
193
+ return t && a.log(`ClientContext removed: ${e}`), t;
194
194
  }
195
195
  addDynamicProvider(e, t) {
196
- this.dynamicProviders.set(e, t), o.log(`DynamicContext provider added: ${e}`);
196
+ this.dynamicProviders.set(e, t), a.log(`DynamicContext provider added: ${e}`);
197
197
  }
198
198
  removeDynamicProvider(e) {
199
199
  const t = this.dynamicProviders.delete(e);
200
- return t && o.log(`DynamicContext provider removed: ${e}`), t;
200
+ return t && a.log(`DynamicContext provider removed: ${e}`), t;
201
201
  }
202
202
  getSnapshot() {
203
203
  if (this.entries.size === 0 && this.dynamicProviders.size === 0) return null;
@@ -207,23 +207,23 @@ var k = class {
207
207
  const i = s();
208
208
  i && (e[t] = i);
209
209
  } catch (i) {
210
- o.error(`DynamicContext provider "${t}" threw:`, i);
210
+ a.error(`DynamicContext provider "${t}" threw:`, i);
211
211
  }
212
212
  return Object.keys(e).length === 0 ? null : { entries: e };
213
213
  }
214
214
  clear() {
215
- this.entries.clear(), this.dynamicProviders.clear(), o.log("ClientContext cleared");
215
+ this.entries.clear(), this.dynamicProviders.clear(), a.log("ClientContext cleared");
216
216
  }
217
217
  };
218
- function m(e) {
219
- return e === null || typeof e != "object" ? JSON.stringify(e) ?? "null" : Array.isArray(e) ? `[${e.map(m).join(",")}]` : `{${Object.keys(e).sort().map((t) => `${JSON.stringify(t)}:${m(e[t])}`).join(",")}}`;
218
+ function g(e) {
219
+ return e === null || typeof e != "object" ? JSON.stringify(e) ?? "null" : Array.isArray(e) ? `[${e.map(g).join(",")}]` : `{${Object.keys(e).sort().map((t) => `${JSON.stringify(t)}:${g(e[t])}`).join(",")}}`;
220
220
  }
221
221
  var R = class {
222
222
  constructor(e) {
223
223
  this.callbacks = e, this.buffer = "", this.message = {}, this.toolCalls = [], this.sources = [], this.followUpReplies = [], this.isFirstChunk = !0, this.answerCompleteEmitted = !1, this.firedClientFunctions = /* @__PURE__ */ new Set();
224
224
  }
225
225
  async processStream(e) {
226
- if (!e.body) throw new g("Response has no body. The endpoint did not return a stream: check that `baseUrl` points at an AGO API and nothing (proxy, mock) strips the SSE body.", "stream_no_body");
226
+ if (!e.body) throw new p("Response has no body. The endpoint did not return a stream: check that `baseUrl` points at an AGO API and nothing (proxy, mock) strips the SSE body.", "stream_no_body");
227
227
  const t = e.body.getReader(), s = new TextDecoder();
228
228
  try {
229
229
  for (; ; ) {
@@ -234,7 +234,7 @@ var R = class {
234
234
  }
235
235
  return this.buffer.trim() && this.processBuffer(), this.buildFinalMessage();
236
236
  } catch (i) {
237
- const n = i instanceof Error ? i : new g("Stream processing failed mid-flight. The connection may have dropped; retry the message.");
237
+ const n = i instanceof Error ? i : new p("Stream processing failed mid-flight. The connection may have dropped; retry the message.");
238
238
  throw this.callbacks.onError?.(n), n;
239
239
  } finally {
240
240
  t.releaseLock();
@@ -256,7 +256,7 @@ var R = class {
256
256
  const r = JSON.parse(n);
257
257
  this.handleChunk(r);
258
258
  } catch (r) {
259
- o.warn("Failed to parse SSE data:", n, r);
259
+ a.warn("Failed to parse SSE data:", n, r);
260
260
  }
261
261
  }
262
262
  }
@@ -281,7 +281,7 @@ var R = class {
281
281
  url: s.use_external_link ? s.external_link_url : s.internal_link_url
282
282
  };
283
283
  })), e.type === "client_function" && e.function_name) {
284
- const t = `${e.function_name}::${m(e.arguments ?? {})}`;
284
+ const t = `${e.function_name}::${g(e.arguments ?? {})}`;
285
285
  this.firedClientFunctions.has(t) || (this.firedClientFunctions.add(t), this.callbacks.onClientFunction?.({
286
286
  invocationId: e.id || "",
287
287
  functionName: e.function_name,
@@ -330,11 +330,11 @@ var R = class {
330
330
  return this.callbacks.onComplete?.(e), e;
331
331
  }
332
332
  };
333
- function D(e) {
333
+ function N(e) {
334
334
  const t = e.message.toLowerCase();
335
335
  return t.includes("load failed") || t.includes("failed to fetch") || t.includes("network") || t.includes("abort");
336
336
  }
337
- var x = /* @__PURE__ */ new Set([
337
+ var I = /* @__PURE__ */ new Set([
338
338
  "image/jpeg",
339
339
  "image/png",
340
340
  "image/gif",
@@ -342,7 +342,7 @@ var x = /* @__PURE__ */ new Set([
342
342
  "image/bmp",
343
343
  "image/tiff"
344
344
  ]);
345
- function I(e) {
345
+ function F(e) {
346
346
  if (!e) return;
347
347
  const t = typeof window < "u" && window.location ? window.location.href : "https://ago.local/";
348
348
  try {
@@ -351,8 +351,8 @@ function I(e) {
351
351
  } catch {
352
352
  }
353
353
  }
354
- function N(e) {
355
- return e.isSafeImage === !0 && typeof e.contentType == "string" && e.contentType.startsWith("image/") && I(e.url) !== void 0;
354
+ function P(e) {
355
+ return e.isSafeImage === !0 && typeof e.contentType == "string" && e.contentType.startsWith("image/") && F(e.url) !== void 0;
356
356
  }
357
357
  function O(e) {
358
358
  if (e == null || e < 0) return "";
@@ -370,17 +370,17 @@ function U(e) {
370
370
  isSafeImage: e.is_safe_image === !0
371
371
  };
372
372
  }
373
- function P(e) {
373
+ function j(e) {
374
374
  return e.map((t, s) => ({
375
375
  id: `local-${s}-${t.name}`,
376
376
  name: t.name,
377
377
  contentType: t.type || void 0,
378
378
  fileSize: t.size,
379
379
  url: typeof URL < "u" && URL.createObjectURL ? URL.createObjectURL(t) : void 0,
380
- isSafeImage: x.has(t.type)
380
+ isSafeImage: I.has(t.type)
381
381
  }));
382
382
  }
383
- var F = class {
383
+ var T = class {
384
384
  constructor() {
385
385
  this.handlers = /* @__PURE__ */ new Map();
386
386
  }
@@ -410,8 +410,8 @@ var F = class {
410
410
  waitFor(e, t) {
411
411
  return new Promise((s, i) => {
412
412
  let n;
413
- const r = ((a) => {
414
- n && clearTimeout(n), s(a);
413
+ const r = ((o) => {
414
+ n && clearTimeout(n), s(o);
415
415
  });
416
416
  this.once(e, r), t?.timeout && (n = setTimeout(() => {
417
417
  this.off(e, r), i(/* @__PURE__ */ new Error(`waitFor("${String(e)}") timed out after ${t.timeout}ms`));
@@ -421,31 +421,31 @@ var F = class {
421
421
  removeAllListeners(e) {
422
422
  e ? this.handlers.delete(e) : this.handlers.clear();
423
423
  }
424
- }, y = '`baseUrl` is required, e.g. new AgoClient({ baseUrl: "https://YOUR-DOMAIN.api.useago.com" }). Try the live demo endpoint https://playground.api.useago.com. See docs/general/configuration.md#error-codes (config_missing_base_url).', T = /^[a-z][a-z0-9+.-]*:\/\//i, w = !1;
425
- function v(e, t = "AgoClient") {
426
- if (typeof e != "object" || e === null) throw new h(`${t}: ${y}`, "config_missing_base_url");
424
+ }, v = '`baseUrl` is required, e.g. new AgoClient({ baseUrl: "https://YOUR-DOMAIN.api.useago.com" }). Try the live demo endpoint https://playground.api.useago.com. See docs/general/configuration.md#error-codes (config_missing_base_url).', D = /^[a-z][a-z0-9+.-]*:\/\//i, C = !1;
425
+ function b(e, t = "AgoClient") {
426
+ if (typeof e != "object" || e === null) throw new h(`${t}: ${v}`, "config_missing_base_url");
427
427
  const s = e.baseUrl;
428
- if (typeof s != "string" || s.trim() === "") throw new h(`${t}: ${y}`, "config_missing_base_url");
429
- !s.startsWith("/") && !T.test(s) && (w || (w = !0, console.warn(`[AGO] ${t}: \`baseUrl\` has no protocol and is not a relative path (config_suspect_base_url). Requests will fail: Node throws a URL parse error, browsers fetch it as a relative path. Use "https://..." (or a "/path" for a same-origin proxy).`)));
428
+ if (typeof s != "string" || s.trim() === "") throw new h(`${t}: ${v}`, "config_missing_base_url");
429
+ !s.startsWith("/") && !D.test(s) && (C || (C = !0, console.warn(`[AGO] ${t}: \`baseUrl\` has no protocol and is not a relative path (config_suspect_base_url). Requests will fail: Node throws a URL parse error, browsers fetch it as a relative path. Use "https://..." (or a "/path" for a same-origin proxy).`)));
430
430
  }
431
- var j = class b {
431
+ var M = class _ {
432
432
  constructor(t) {
433
- this.warnedEmptyConversations = /* @__PURE__ */ new Set(), v(t, "AgoClient"), this.config = t, this.httpClient = new k(t), this.functionRegistry = new $(), this.contextRegistry = new A(), this.eventEmitter = new F(), t.debug && o.enable(), o.log("AgoClient initialized");
433
+ this.warnedEmptyConversations = /* @__PURE__ */ new Set(), b(t, "AgoClient"), this.config = t, this.httpClient = new k(t), this.functionRegistry = new A(), this.contextRegistry = new x(), this.eventEmitter = new T(), t.debug && a.enable(), a.log("AgoClient initialized");
434
434
  }
435
435
  async sendMessage(t, s) {
436
- const i = this.functionRegistry.getSchemas(), n = this.contextRegistry.getSnapshot(), r = this.config.agent || this.config.defaultAgentId, a = {
436
+ const i = this.functionRegistry.getSchemas(), n = this.contextRegistry.getSnapshot(), r = this.config.agent || this.config.defaultAgentId, o = {
437
437
  content: t,
438
438
  conversation_id: s?.conversationId,
439
439
  agent_id: s?.agentId || r
440
440
  };
441
- i.length > 0 && (a.client_functions = i), n && (a.client_context = n);
441
+ i.length > 0 && (o.client_functions = i), n && (o.client_context = n), s?.hidden && (o.hidden = !0);
442
442
  let l;
443
443
  if (s?.files && s.files.length > 0) {
444
444
  const c = new FormData();
445
- c.append("content", t), s.conversationId && c.append("conversation_id", s.conversationId), (s.agentId || r) && c.append("agent_id", s.agentId || r || ""), i.length > 0 && c.append("client_functions", JSON.stringify(i)), n && c.append("client_context", JSON.stringify(n));
446
- for (const _ of s.files) c.append("files", _);
445
+ c.append("content", t), s.conversationId && c.append("conversation_id", s.conversationId), (s.agentId || r) && c.append("agent_id", s.agentId || r || ""), i.length > 0 && c.append("client_functions", JSON.stringify(i)), n && c.append("client_context", JSON.stringify(n)), s.hidden && c.append("hidden", "true");
446
+ for (const d of s.files) c.append("files", d);
447
447
  l = await this.httpClient.postFormData("/api/sdk/v1/messages", c);
448
- } else l = await this.httpClient.postStream("/api/sdk/v1/messages", a);
448
+ } else l = await this.httpClient.postStream("/api/sdk/v1/messages", o);
449
449
  return this.processSSEResponse(l);
450
450
  }
451
451
  async processSSEResponse(t) {
@@ -499,7 +499,7 @@ var j = class b {
499
499
  try {
500
500
  s = await this.functionRegistry.execute(t.functionName, t.arguments);
501
501
  } catch (n) {
502
- i = n instanceof Error ? n.message : "Unknown error", o.error("Client function execution failed:", n);
502
+ i = n instanceof Error ? n.message : "Unknown error", a.error("Client function execution failed:", n);
503
503
  }
504
504
  if (t.invocationId) try {
505
505
  await this.submitToolCallForm(t.invocationId, {
@@ -508,7 +508,7 @@ var j = class b {
508
508
  _type: "client_function_result"
509
509
  });
510
510
  } catch (n) {
511
- o.error("Failed to submit function result:", n);
511
+ a.error("Failed to submit function result:", n);
512
512
  }
513
513
  this.eventEmitter.emit("function:result", {
514
514
  invocationId: t.invocationId,
@@ -535,7 +535,8 @@ var j = class b {
535
535
  role: n.role,
536
536
  status: n.status,
537
537
  createdAt: new Date(n.created_at),
538
- toolCalls: b.mapPersistedToolCalls(n.tool_call_data),
538
+ hidden: n.hidden,
539
+ toolCalls: _.mapPersistedToolCalls(n.tool_call_data),
539
540
  attachments: n.attachments && n.attachments.length > 0 ? n.attachments.map(U) : void 0
540
541
  }))
541
542
  };
@@ -603,13 +604,13 @@ var j = class b {
603
604
  const i = s.map((r) => r.name), n = s.map((r) => `- "${r.name}": ${r.description}`).join(`
604
605
  `);
605
606
  this.registerFunction("navigateToPage", async (r) => {
606
- const a = r.page, l = s.find((c) => c.name === a);
607
+ const o = r.page, l = s.find((c) => c.name === o);
607
608
  return l ? (t(l.path), {
608
609
  success: !0,
609
610
  navigatedTo: l.path
610
611
  }) : {
611
612
  success: !1,
612
- error: `Unknown page: ${a}`
613
+ error: `Unknown page: ${o}`
613
614
  };
614
615
  }, {
615
616
  description: `Navigate the user to a page in the application. Available pages:
@@ -625,6 +626,46 @@ ${n}`,
625
626
  }
626
627
  });
627
628
  }
629
+ registerPageStateFunction(t, s) {
630
+ const i = s?.functionName ?? "setPageState", n = new Map(t.map((o) => [o.name, o])), r = t.map((o) => `- "${o.name}": ${o.description}`).join(`
631
+ `);
632
+ this.registerFunction(i, async (o) => {
633
+ const l = {};
634
+ for (const [c, d] of Object.entries(o)) {
635
+ if (d === void 0) continue;
636
+ const f = n.get(c);
637
+ f && (await f.set(d), l[c] = d);
638
+ }
639
+ return {
640
+ success: !0,
641
+ applied: l
642
+ };
643
+ }, {
644
+ description: `Change the state of the current page. Set ONLY the controls the user explicitly asked for; leave the others unset. Available controls:
645
+ ${r}`,
646
+ parameters: {
647
+ type: "object",
648
+ properties: Object.fromEntries(t.map((o) => [o.name, {
649
+ ...o.schema,
650
+ description: o.description
651
+ }]))
652
+ }
653
+ }), this.addDynamicContext(`page-state:${i}`, () => {
654
+ const o = t.filter((c) => typeof c.get == "function");
655
+ if (o.length === 0) return null;
656
+ const l = {};
657
+ for (const c of o) l[c.name] = c.get();
658
+ return {
659
+ name: "Page state",
660
+ description: "Current, editable state of the page the user is viewing.",
661
+ data: l
662
+ };
663
+ });
664
+ }
665
+ unregisterPageStateFunction(t) {
666
+ const s = t ?? "setPageState";
667
+ this.unregisterFunction(s), this.removeDynamicContext(`page-state:${s}`);
668
+ }
628
669
  setContext(t, s) {
629
670
  this.contextRegistry.set(t, s), this.notifyContextChanged();
630
671
  }
@@ -680,28 +721,28 @@ ${n}`,
680
721
  ...this.config,
681
722
  ...s
682
723
  };
683
- v(i, "AgoClient.updateConfig"), this.config = i, this.httpClient.updateConfig(s), s.debug !== void 0 && (s.debug ? o.enable() : o.disable());
724
+ b(i, "AgoClient.updateConfig"), this.config = i, this.httpClient.updateConfig(s), s.debug !== void 0 && (s.debug ? a.enable() : a.disable());
684
725
  }
685
726
  destroy() {
686
- this.eventEmitter.removeAllListeners(), this.functionRegistry.clear(), this.contextRegistry.clear(), o.log("AgoClient destroyed");
727
+ this.eventEmitter.removeAllListeners(), this.functionRegistry.clear(), this.contextRegistry.clear(), a.log("AgoClient destroyed");
687
728
  }
688
729
  };
689
730
  export {
690
- g as _,
691
- N as a,
731
+ p as _,
732
+ P as a,
692
733
  R as c,
693
- $ as d,
694
- o as f,
695
- u as g,
696
- f as h,
697
- P as i,
698
- D as l,
734
+ A as d,
735
+ a as f,
736
+ m as g,
737
+ y as h,
738
+ j as i,
739
+ N as l,
699
740
  h as m,
700
- v as n,
741
+ b as n,
701
742
  O as o,
702
- d as p,
703
- F as r,
704
- I as s,
705
- j as t,
706
- A as u
743
+ u as p,
744
+ T as r,
745
+ F as s,
746
+ M as t,
747
+ x as u
707
748
  };
package/dist/angular.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./AgoClient-CzSmJQxl.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-B2BU8tfB.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)}registerPageStateFunction(e,t){this.client.registerPageStateFunction(e,t)}unregisterPageStateFunction(e){this.client.unregisterPageStateFunction(e)}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;