@useago/sdk 1.12.0 → 1.13.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +71 -4
  2. package/README.md +73 -0
  3. package/dist/angular.cjs +1 -1
  4. package/dist/angular.d.cts +97 -28
  5. package/dist/angular.d.ts +97 -28
  6. package/dist/angular.js +4 -1
  7. package/dist/{createConversationSession-B1Qn-y0I.js → createConversationSession-BfJg0WyA.js} +1 -1
  8. package/dist/{createConversationSession-B3v_xOU7.cjs → createConversationSession-CiOXKWl0.cjs} +1 -1
  9. package/dist/{createFormCollector-m79zk_NA.js → createFormCollector-DN1xjAv5.js} +1 -1
  10. package/dist/{createFormCollector-FvwDOqnV.cjs → createFormCollector-DnQl77Ko.cjs} +1 -1
  11. package/dist/createMockClient-BPt1gSve.cjs +1 -0
  12. package/dist/{createMockClient-Beao82tu.js → createMockClient-YoYr3pQr.js} +1 -0
  13. package/dist/devtools.cjs +4 -4
  14. package/dist/devtools.d.cts +95 -28
  15. package/dist/devtools.d.ts +95 -28
  16. package/dist/devtools.js +87 -84
  17. package/dist/helpers.d.cts +42 -12
  18. package/dist/helpers.d.ts +42 -12
  19. package/dist/index.cjs +1 -1
  20. package/dist/index.d.cts +101 -35
  21. package/dist/index.d.ts +101 -35
  22. package/dist/index.js +44 -43
  23. package/dist/react.cjs +4 -4
  24. package/dist/react.d.cts +147 -28
  25. package/dist/react.d.ts +147 -28
  26. package/dist/react.js +814 -727
  27. package/dist/speechToText-BV7qxqPF.js +704 -0
  28. package/dist/speechToText-ZciRyyJE.cjs +1 -0
  29. package/dist/testing.cjs +1 -1
  30. package/dist/testing.d.cts +95 -28
  31. package/dist/testing.d.ts +95 -28
  32. package/dist/testing.js +1 -1
  33. package/dist/{types-Ct1hlKwg.js → types-Q7t1peH-.js} +595 -419
  34. package/dist/types-a7teDBnC.cjs +10 -0
  35. package/dist/vue.cjs +1 -1
  36. package/dist/vue.d.cts +105 -28
  37. package/dist/vue.d.ts +105 -28
  38. package/dist/vue.js +103 -101
  39. package/dist/widget.cjs +6 -6
  40. package/dist/widget.d.cts +127 -28
  41. package/dist/widget.d.ts +127 -28
  42. package/dist/widget.js +1717 -1772
  43. package/llms-full.txt +129 -1
  44. package/package.json +1 -1
  45. package/dist/createMockClient-BEOXI8yW.cjs +0 -1
  46. package/dist/sheetController-BThJRtOu.cjs +0 -1
  47. package/dist/sheetController-aEKXIvjk.js +0 -343
  48. package/dist/types-mcW8vB1U.cjs +0 -10
package/dist/angular.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as o, t as u } from "./types-Ct1hlKwg.js";
1
+ import { n as o, t as u } from "./types-Q7t1peH-.js";
2
2
  import { t as a } from "./autoContinue-CC8K9mBU.js";
3
3
  var s = class {
4
4
  constructor(t) {
@@ -16,6 +16,9 @@ var s = class {
16
16
  sendMessage(t, e) {
17
17
  return this.client.sendMessage(t, e);
18
18
  }
19
+ transcribeAudio(t, e) {
20
+ return this.client.transcribeAudio(t, e);
21
+ }
19
22
  stop() {
20
23
  return this.client.stop();
21
24
  }
@@ -1,4 +1,4 @@
1
- import { g as d } from "./types-Ct1hlKwg.js";
1
+ import { g as d } from "./types-Q7t1peH-.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("./types-mcW8vB1U.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}),s=o.get();s.value!==null&&c(s.lastMessageAt)&&o.set({value:null,lastMessageAt:null});function c(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||c(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("./types-a7teDBnC.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}),s=o.get();s.value!==null&&c(s.lastMessageAt)&&o.set({value:null,lastMessageAt:null});function c(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||c(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 w, g as R } from "./types-Ct1hlKwg.js";
1
+ import { S as w, g as R } from "./types-Q7t1peH-.js";
2
2
  var j = /^[a-zA-Z0-9_-]{1,40}$/, V = (s) => s == null || s === "";
3
3
  function S(s, e) {
4
4
  if ("anyOf" in s) return s.anyOf.some((c) => S(c, e));
@@ -1 +1 @@
1
- const C=require("./types-mcW8vB1U.cjs");var W=/^[a-zA-Z0-9_-]{1,40}$/,V=n=>n==null||n==="";function S(n,e){if("anyOf"in n)return n.anyOf.some(c=>S(c,e));if("allOf"in n)return n.allOf.every(c=>S(c,e));const l=e[n.property];if(V(l))return!1;if(Array.isArray(n.value))return n.value.some(c=>String(l)===String(c));if(!n.op)return String(l)===String(n.value);const i=Number(l),a=Number(n.value);if(Number.isNaN(i)||Number.isNaN(a))return!1;switch(n.op){case">=":return i>=a;case"<=":return i<=a;case">":return i>a;case"<":return i<a;default:return C.logger.warn(`Unknown requiredWhen op "${n.op}"; treating as not required.`),!1}}function h(n,e){const l=n.properties??{},i=new Set;for(const c of n.required??[]){const d=l[c]?.requiredWhen;(!d||S(d,e))&&i.add(c)}for(const[c,d]of Object.entries(l))d.requiredWhen&&S(d.requiredWhen,e)&&i.add(c);const a=[...i].filter(c=>V(e[c]));return{missing:a,complete:a.length===0}}function B(n){const e={};for(const[l,i]of Object.entries(n.properties??{}))e[l]={type:i.type,...i.description!=null&&{description:i.description},...i.enum&&{enum:i.enum},...i.default!==void 0&&{default:i.default}};return{type:"object",properties:e,required:[]}}function A(n){const{name:e,description:l,schema:i}=n;if(!W.test(e))throw new Error(`Invalid form collector name "${e}": must match ${W} (it becomes the update_/submit_ function names).`);const a=typeof n.submit=="string"?n.submit?{via:"client",url:n.submit}:!1:n.submit??!1;n.autoSubmit===!0&&!a&&C.logger.warn(`FormCollector "${e}": autoSubmit is ignored because no submit target is configured.`);const c=(n.autoSubmit??!0)&&!!a,d=i.properties??{},$=t=>{const r={};for(const[o,s]of Object.entries(t)){const u=d[o];if(u)if(s==null)r[o]=s;else if(u.type==="number"||u.type==="integer"){const f=typeof s=="number"?s:Number(s);r[o]=Number.isNaN(f)?s:f}else u.type==="boolean"?r[o]=typeof s=="boolean"?s:s==="true"?!0:s==="false"?!1:!!s:r[o]=s}return r},N=n.initialValues??{},m=C.createStore({values:N,submitted:!1}),w=t=>{const r=m.get(),o={...r,values:{...r.values,...t}};return m.set(o),o};let b=null;const k=(t,r)=>{b?.emitFormEvent("form:error",{name:e,values:t,error:r})};let p=null;const I=async()=>{const{values:t}=m.get(),{complete:r,missing:o}=h(i,t);if(!r)return{ok:!1,missing:o};if(!a)return{ok:!1,error:"No submit target configured for this form collector."};const s=t;try{let u;if(a.via==="client")if("handler"in a)u=await a.handler(s);else{const f=await fetch(a.url,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(s)});if(!f.ok){const j=`Submit failed: HTTP ${f.status}`;return k(s,j),{ok:!1,error:j}}u=await f.json().catch(()=>{})}else{if(!b)return{ok:!1,error:"Backend submit requires install(client) (or useFormCollector) first."};u=await b.submitFormCollector(e,s)}return m.set({...m.get(),submitted:!0,submitResult:u}),b?.emitFormEvent("form:submitted",{name:e,values:s,result:u}),{ok:!0,result:u}}catch(u){const f=u instanceof Error?u.message:"Submit failed";return C.logger.error(`FormCollector "${e}" submit failed:`,u),k(s,f),{ok:!1,error:f}}},F=()=>p||(p=(async()=>{try{return await I()}finally{p=null}})(),p),q=async()=>{if(!c||!a)return null;const{values:t,submitted:r}=m.get();return r||!h(i,t).complete?null:F()},O={name:`update_${e}`,description:`Fill or update fields of the "${e}" form. ${l} 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:B(i),handler:async t=>{const r=w($(t)),{missing:o}=h(i,r.values),s=await q();return s?s.ok?{ok:!0,values:r.values,missing:o,submitted:!0}:{ok:!0,values:r.values,missing:o,submitted:!1,submitError:s.error}:{ok:!0,values:r.values,missing:o}}},y=[O];a&&!c&&y.push({name:`submit_${e}`,description:`Submit the completed "${e}" form. Only call this once every required field is collected and the user has confirmed. If fields are missing it returns them instead of submitting.`,parameters:{type:"object",properties:{}},handler:()=>F()});const D="client__",_=a?`submit_${e}`:null,R=t=>{const r=t.functionName??t.toolName;if(r)return r.startsWith(D)?r.slice(8):r},x=t=>{let r={...N},o=!1;for(const s of t){const u=R(s);u===O.name?s.arguments&&(r={...r,...$(s.arguments)}):_&&u===_&&s.status?.toLowerCase()==="done"&&(o=!0)}m.set({values:r,submitted:o})},g=`form:${e}`,v=`${g}:definition`,P=()=>({name:`Form definition: ${e}`,description:`${l} Some fields are conditionally required; the requiredWhen field in the schema tells you when each becomes required. The form schema is the following: ${JSON.stringify(i)}.`,stable:!0}),T=()=>{const{values:t,submitted:r}=m.get(),{missing:o,complete:s}=h(i,t),u=a?c?" The form is submitted automatically as soon as every required field is filled, so there is no submit function to call.":` When nothing is missing and the user confirms, call submit_${e}.`:"",f=r?`The "${e}" form has been submitted.`:`You are currently collecting information from the user to fill the "${e}" form.`;return{name:`Form: ${e}`,description:`${f} The form's schema and field requirements are in the "${v}" client context. Call update_${e} with any fields the user provides; ask only for what is still missing.${u}`,data:{values:t,missing:o,complete:s,submitted:r}}},E=t=>{x((t.messages??[]).flatMap(r=>r.toolCalls??[]))};return{name:e,store:m,functions:y,contextKey:g,contextProvider:T,definitionContextKey:v,definitionContextProvider:P,install:t=>{b=t;for(const o of y)t.register(o);t.addDynamicContext(v,P),t.addDynamicContext(g,T);const r=m.subscribe(()=>t.notifyContextChanged());return t.on("conversation:loaded",E),()=>{r();for(const o of y)t.unregisterFunction(o.name);t.removeDynamicContext(g),t.removeDynamicContext(v),t.off("conversation:loaded",E),b===t&&(b=null)}},hydrate:x,submit:F,getValues:()=>m.get().values,setValues:t=>{w($(t)),q()},reset:()=>{m.set({values:N,submitted:!1})},getStatus:()=>h(i,m.get().values)}}async function L(n,e){const l=await n.getFormCollector(e.name);return A({name:l.name,description:e.description??l.description,schema:e.schema??l.schema,submit:e.submit??l.submit,initialValues:e.initialValues,autoSubmit:e.autoSubmit??l.autoSubmit})}Object.defineProperty(exports,"createFormCollector",{enumerable:!0,get:function(){return A}});Object.defineProperty(exports,"deriveFormStatus",{enumerable:!0,get:function(){return h}});Object.defineProperty(exports,"loadFormCollector",{enumerable:!0,get:function(){return L}});
1
+ const C=require("./types-a7teDBnC.cjs");var W=/^[a-zA-Z0-9_-]{1,40}$/,V=n=>n==null||n==="";function S(n,e){if("anyOf"in n)return n.anyOf.some(c=>S(c,e));if("allOf"in n)return n.allOf.every(c=>S(c,e));const l=e[n.property];if(V(l))return!1;if(Array.isArray(n.value))return n.value.some(c=>String(l)===String(c));if(!n.op)return String(l)===String(n.value);const i=Number(l),a=Number(n.value);if(Number.isNaN(i)||Number.isNaN(a))return!1;switch(n.op){case">=":return i>=a;case"<=":return i<=a;case">":return i>a;case"<":return i<a;default:return C.logger.warn(`Unknown requiredWhen op "${n.op}"; treating as not required.`),!1}}function h(n,e){const l=n.properties??{},i=new Set;for(const c of n.required??[]){const d=l[c]?.requiredWhen;(!d||S(d,e))&&i.add(c)}for(const[c,d]of Object.entries(l))d.requiredWhen&&S(d.requiredWhen,e)&&i.add(c);const a=[...i].filter(c=>V(e[c]));return{missing:a,complete:a.length===0}}function B(n){const e={};for(const[l,i]of Object.entries(n.properties??{}))e[l]={type:i.type,...i.description!=null&&{description:i.description},...i.enum&&{enum:i.enum},...i.default!==void 0&&{default:i.default}};return{type:"object",properties:e,required:[]}}function A(n){const{name:e,description:l,schema:i}=n;if(!W.test(e))throw new Error(`Invalid form collector name "${e}": must match ${W} (it becomes the update_/submit_ function names).`);const a=typeof n.submit=="string"?n.submit?{via:"client",url:n.submit}:!1:n.submit??!1;n.autoSubmit===!0&&!a&&C.logger.warn(`FormCollector "${e}": autoSubmit is ignored because no submit target is configured.`);const c=(n.autoSubmit??!0)&&!!a,d=i.properties??{},$=t=>{const r={};for(const[o,s]of Object.entries(t)){const u=d[o];if(u)if(s==null)r[o]=s;else if(u.type==="number"||u.type==="integer"){const f=typeof s=="number"?s:Number(s);r[o]=Number.isNaN(f)?s:f}else u.type==="boolean"?r[o]=typeof s=="boolean"?s:s==="true"?!0:s==="false"?!1:!!s:r[o]=s}return r},N=n.initialValues??{},m=C.createStore({values:N,submitted:!1}),w=t=>{const r=m.get(),o={...r,values:{...r.values,...t}};return m.set(o),o};let b=null;const k=(t,r)=>{b?.emitFormEvent("form:error",{name:e,values:t,error:r})};let p=null;const I=async()=>{const{values:t}=m.get(),{complete:r,missing:o}=h(i,t);if(!r)return{ok:!1,missing:o};if(!a)return{ok:!1,error:"No submit target configured for this form collector."};const s=t;try{let u;if(a.via==="client")if("handler"in a)u=await a.handler(s);else{const f=await fetch(a.url,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(s)});if(!f.ok){const j=`Submit failed: HTTP ${f.status}`;return k(s,j),{ok:!1,error:j}}u=await f.json().catch(()=>{})}else{if(!b)return{ok:!1,error:"Backend submit requires install(client) (or useFormCollector) first."};u=await b.submitFormCollector(e,s)}return m.set({...m.get(),submitted:!0,submitResult:u}),b?.emitFormEvent("form:submitted",{name:e,values:s,result:u}),{ok:!0,result:u}}catch(u){const f=u instanceof Error?u.message:"Submit failed";return C.logger.error(`FormCollector "${e}" submit failed:`,u),k(s,f),{ok:!1,error:f}}},F=()=>p||(p=(async()=>{try{return await I()}finally{p=null}})(),p),q=async()=>{if(!c||!a)return null;const{values:t,submitted:r}=m.get();return r||!h(i,t).complete?null:F()},O={name:`update_${e}`,description:`Fill or update fields of the "${e}" form. ${l} 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:B(i),handler:async t=>{const r=w($(t)),{missing:o}=h(i,r.values),s=await q();return s?s.ok?{ok:!0,values:r.values,missing:o,submitted:!0}:{ok:!0,values:r.values,missing:o,submitted:!1,submitError:s.error}:{ok:!0,values:r.values,missing:o}}},y=[O];a&&!c&&y.push({name:`submit_${e}`,description:`Submit the completed "${e}" form. Only call this once every required field is collected and the user has confirmed. If fields are missing it returns them instead of submitting.`,parameters:{type:"object",properties:{}},handler:()=>F()});const D="client__",_=a?`submit_${e}`:null,R=t=>{const r=t.functionName??t.toolName;if(r)return r.startsWith(D)?r.slice(8):r},x=t=>{let r={...N},o=!1;for(const s of t){const u=R(s);u===O.name?s.arguments&&(r={...r,...$(s.arguments)}):_&&u===_&&s.status?.toLowerCase()==="done"&&(o=!0)}m.set({values:r,submitted:o})},g=`form:${e}`,v=`${g}:definition`,P=()=>({name:`Form definition: ${e}`,description:`${l} Some fields are conditionally required; the requiredWhen field in the schema tells you when each becomes required. The form schema is the following: ${JSON.stringify(i)}.`,stable:!0}),T=()=>{const{values:t,submitted:r}=m.get(),{missing:o,complete:s}=h(i,t),u=a?c?" The form is submitted automatically as soon as every required field is filled, so there is no submit function to call.":` When nothing is missing and the user confirms, call submit_${e}.`:"",f=r?`The "${e}" form has been submitted.`:`You are currently collecting information from the user to fill the "${e}" form.`;return{name:`Form: ${e}`,description:`${f} The form's schema and field requirements are in the "${v}" client context. Call update_${e} with any fields the user provides; ask only for what is still missing.${u}`,data:{values:t,missing:o,complete:s,submitted:r}}},E=t=>{x((t.messages??[]).flatMap(r=>r.toolCalls??[]))};return{name:e,store:m,functions:y,contextKey:g,contextProvider:T,definitionContextKey:v,definitionContextProvider:P,install:t=>{b=t;for(const o of y)t.register(o);t.addDynamicContext(v,P),t.addDynamicContext(g,T);const r=m.subscribe(()=>t.notifyContextChanged());return t.on("conversation:loaded",E),()=>{r();for(const o of y)t.unregisterFunction(o.name);t.removeDynamicContext(g),t.removeDynamicContext(v),t.off("conversation:loaded",E),b===t&&(b=null)}},hydrate:x,submit:F,getValues:()=>m.get().values,setValues:t=>{w($(t)),q()},reset:()=>{m.set({values:N,submitted:!1})},getStatus:()=>h(i,m.get().values)}}async function L(n,e){const l=await n.getFormCollector(e.name);return A({name:l.name,description:e.description??l.description,schema:e.schema??l.schema,submit:e.submit??l.submit,initialValues:e.initialValues,autoSubmit:e.autoSubmit??l.autoSubmit})}Object.defineProperty(exports,"createFormCollector",{enumerable:!0,get:function(){return A}});Object.defineProperty(exports,"deriveFormStatus",{enumerable:!0,get:function(){return h}});Object.defineProperty(exports,"loadFormCollector",{enumerable:!0,get:function(){return L}});
@@ -0,0 +1 @@
1
+ function y(u={}){const{overrides:g={}}=u,a={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},n=new Map,c=[],m={sendMessage:async()=>a,transcribeAudio:async()=>({text:"Mock transcription"}),continueMessage:async()=>a,stop:async()=>null,stopMessage:async()=>({status:"not_running"}),isGenerating:()=>!1,resumePendingClientFunctions:async()=>null,registerResumeGate:()=>()=>{},getConversations:async()=>[l],getConversation:async()=>l,getMessages:async()=>[a],submitToolCallForm:async()=>({status:"completed"}),confirmToolCall:async()=>{},rejectToolCall:async()=>{},getConfig:async()=>({permissions:[],proactive:{enabled:!1}}),createTicket:async()=>({id:"mock-ticket-1",url:"https://example.test/tickets/mock-ticket-1"}),submitFeedback:async()=>{},submitConversationFeedback:async()=>a.id,registerFunction:()=>{},unregisterFunction:()=>!0,getRegisteredFunctions:()=>[],executeClientFunction:async()=>{},getContextSnapshot:()=>null,notifyContextChanged:()=>{},setContext:()=>{},removeContext:()=>!0,addDynamicContext:()=>{},removeDynamicContext:()=>!0,registerNavigationFunction:()=>{},unregisterNavigationFunction:()=>{},getConfiguredAgent:()=>{},getUserIdentity:()=>({email:void 0,hasJwt:!1}),getHttp:()=>({get:async()=>({}),post:async()=>({})}),emitProactiveEvent:(e,t)=>{const o=n.get(e);o&&[...o].forEach(s=>s(t))},on:(e,t)=>{n.has(e)||n.set(e,new Set),n.get(e).add(t)},off:(e,t)=>{n.get(e)?.delete(t)},once:(e,t)=>{const o=(...s)=>{n.get(e)?.delete(o),t(...s)};n.has(e)||n.set(e,new Set),n.get(e).add(o)},waitFor:(e,t)=>new Promise((o,s)=>{let r;const d=f=>{r&&clearTimeout(r),n.get(e)?.delete(d),o(f)};n.has(e)||n.set(e,new Set),n.get(e).add(d),t?.timeout&&(r=setTimeout(()=>{n.get(e)?.delete(d),s(new Error(`waitFor("${e}") timed out after ${t.timeout}ms`))},t.timeout))}),updateConfig:()=>{},destroy:()=>{n.clear()},...g},i={};for(const[e,t]of Object.entries(m))i[e]=(...o)=>(c.push({method:e,args:o}),t(...o));return i.proactive=null,i.__calls=c,i.__callsFor=e=>c.filter(t=>t.method===e),i.__emitEvent=(e,t)=>{const o=n.get(e);o&&[...o].forEach(s=>s(t))},i}Object.defineProperty(exports,"createMockClient",{enumerable:!0,get:function(){return y}});
@@ -12,6 +12,7 @@ function y(g = {}) {
12
12
  lastMessageDate: /* @__PURE__ */ new Date()
13
13
  }, n = /* @__PURE__ */ new Map(), c = [], m = {
14
14
  sendMessage: async () => a,
15
+ transcribeAudio: async () => ({ text: "Mock transcription" }),
15
16
  continueMessage: async () => a,
16
17
  stop: async () => null,
17
18
  stopMessage: async () => ({ status: "not_running" }),
package/dist/devtools.cjs CHANGED
@@ -1,4 +1,4 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const te=require("./errors-o1IB5fEu.cjs");function Q(n,e,i){if(!n)return;const r=document.createElement("div");r.className=`dev-log-line dev-log-${i}`,r.textContent=`${new Date().toLocaleTimeString()} ${e}`,n.appendChild(r),n.scrollTop=n.scrollHeight}function ne(n){let e;return n.type?e=n.type:n.content!==void 0?e="content":n.full_content!==void 0?e="full_content":n.status?e=`status:${n.status}`:e="event",`${e} ${JSON.stringify(n)}`}var oe="ago_dev_panel_collapsed",ae="ago_dev_events_collapsed";function _(n,e,i,r){n.classList.toggle("collapsed",e);const v=n.querySelector(".dev-toggle");v&&(v.textContent=e?"▢":"—",v.title=e?`Expand ${r}`:`Collapse ${r}`,v.setAttribute("aria-expanded",String(!e)));try{localStorage.setItem(i,e?"1":"0")}catch{}}function W(n,e,i){n.querySelector(".dev-toggle")?.addEventListener("click",v=>{v.stopPropagation(),_(n,!n.classList.contains("collapsed"),e,i)}),n.addEventListener("click",()=>{n.classList.contains("collapsed")&&_(n,!1,e,i)});let r=!1;try{r=localStorage.getItem(e)==="1"}catch{}_(n,r,e,i)}var re=0;function de(n){const{client:e,target:i,label:r,side:v="right",enableFunctionRunner:P=!1}=n;if(P&&typeof e.executeClientFunction!="function")throw new te.AgoError("initDevPanel: enableFunctionRunner requires client.executeClientFunction. Pass a real AgoClient, not a mock that omits it.","dev_panel_missing_capability");let u=!1;const F=re++,R=F===0?"":`-${F+1}`,q=document.querySelectorAll(`#ago-dev-panel[data-ago-dev-side="${v}"]`).length,N=q>0?`${16+q*376}px`:"";let w=null,A=null,J=null;const Z=()=>{const t=e.getContextSnapshot()?.entries??{};return Object.fromEntries(Object.entries(t).map(([o,{name:d,data:a}])=>[o,{name:d,data:a}]))},h=()=>{u||w&&(w.textContent=JSON.stringify(Z(),null,2))},k=(t,o)=>{u||Q(A,t,o)};se();const D=typeof i=="string"?document.querySelector(i):i instanceof Element?i:document.body,M=t=>{t.dataset.agoDevSide=v,v==="left"?(t.style.right="auto",t.style.left=N||"16px"):N&&(t.style.right=N)},p=document.createElement("aside");p.id="ago-dev-panel",p.className="ago-dev-card",M(p),(D??document.body).appendChild(p),p.innerHTML=`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ne=require("./errors-o1IB5fEu.cjs");function W(n,e,u){if(!n)return;const r=document.createElement("div");r.className=`dev-log-line dev-log-${u}`,r.textContent=`${new Date().toLocaleTimeString()} ${e}`,n.appendChild(r),n.scrollTop=n.scrollHeight}function oe(n){let e;return n.type?e=n.type:n.content!==void 0?e="content":n.full_content!==void 0?e="full_content":n.status?e=`status:${n.status}`:e="event",`${e} ${JSON.stringify(n)}`}var ae="ago_dev_panel_collapsed",re="ago_dev_events_collapsed";function _(n,e,u,r){n.classList.toggle("collapsed",e);const v=n.querySelector(".dev-toggle");v&&(v.textContent=e?"▢":"—",v.title=e?`Expand ${r}`:`Collapse ${r}`,v.setAttribute("aria-expanded",String(!e)));try{localStorage.setItem(u,e?"1":"0")}catch{}}function X(n,e,u){n.querySelector(".dev-toggle")?.addEventListener("click",v=>{v.stopPropagation(),_(n,!n.classList.contains("collapsed"),e,u)}),n.addEventListener("click",()=>{n.classList.contains("collapsed")&&_(n,!1,e,u)});let r=!1;try{r=localStorage.getItem(e)==="1"}catch{}_(n,r,e,u)}var de=0;function se(n){const{client:e,target:u,label:r,side:v="right",enableFunctionRunner:F=!1}=n;if(F&&typeof e.executeClientFunction!="function")throw new ne.AgoError("initDevPanel: enableFunctionRunner requires client.executeClientFunction. Pass a real AgoClient, not a mock that omits it.","dev_panel_missing_capability");let d=!1;const P=de++,R=P===0?"":`-${P+1}`,q=document.querySelectorAll(`#ago-dev-panel[data-ago-dev-side="${v}"]`).length,N=q>0?`${16+q*376}px`:"";let w=null,A=null,J=null;const ee=()=>{const t=e.getContextSnapshot()?.entries??{};return Object.fromEntries(Object.entries(t).map(([o,{name:s,data:a}])=>[o,{name:s,data:a}]))},h=()=>{d||w&&(w.textContent=JSON.stringify(ee(),null,2))},k=(t,o)=>{d||W(A,t,o)};le();const D=typeof u=="string"?document.querySelector(u):u instanceof Element?u:document.body,M=t=>{t.dataset.agoDevSide=v,v==="left"?(t.style.right="auto",t.style.left=N||"16px"):N&&(t.style.right=N)},p=document.createElement("aside");p.id="ago-dev-panel",p.className="ago-dev-card",M(p),(D??document.body).appendChild(p),p.innerHTML=`
2
2
  <div class="dev-head">
3
3
  <span class="dev-badge">DEV</span>
4
4
  <span class="dev-title">${r?`DEV TOOLS · ${r}`:"DEV TOOLS · client-side function state — not for production"}</span>
@@ -15,7 +15,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const te=requ
15
15
  <div class="dev-log" id="ago-dev-log"></div>
16
16
  </details>
17
17
  </div>
18
- `,w=p.querySelector(".dev-state"),A=p.querySelector(".dev-log");const j=p.querySelector(".dev-fns code");let b=null,L=null,O="";const m=()=>{if(u)return;const t=e.getRegisteredFunctions?.()??[],o=t.map(a=>a.name);if(j&&(j.textContent=o.join(", ")||"—"),!b)return;let d=O;if(o.includes(d)||(d=o.includes("setPageState")?"setPageState":o[0]??""),O=d,b.innerHTML="",o.length===0){const a=document.createElement("option");a.textContent="(no functions registered)",a.disabled=!0,b.appendChild(a)}for(const a of o){const s=document.createElement("option");s.value=a,s.textContent=a,s.selected=a===d,b.appendChild(s)}if(L){const a=t.find(s=>s.name===d);L.textContent=a?JSON.stringify(a.parameters??{},null,2):""}};W(p,oe+R,"dev tools");const g=document.createElement("aside");g.id="ago-dev-events",g.className="ago-dev-card",M(g),(D??document.body).appendChild(g),g.innerHTML=`
18
+ `,w=p.querySelector(".dev-state"),A=p.querySelector(".dev-log");const j=p.querySelector(".dev-fns code");let b=null,L=null,O="";const g=()=>{if(d)return;const t=e.getRegisteredFunctions?.()??[],o=t.map(a=>a.name);if(j&&(j.textContent=o.join(", ")||"—"),!b)return;let s=O;if(o.includes(s)||(s=o.includes("setPageState")?"setPageState":o[0]??""),O=s,b.innerHTML="",o.length===0){const a=document.createElement("option");a.textContent="(no functions registered)",a.disabled=!0,b.appendChild(a)}for(const a of o){const l=document.createElement("option");l.value=a,l.textContent=a,l.selected=a===s,b.appendChild(l)}if(L){const a=t.find(l=>l.name===s);L.textContent=a?JSON.stringify(a.parameters??{},null,2):""}};X(p,ae+R,"dev tools");const f=document.createElement("aside");f.id="ago-dev-events",f.className="ago-dev-card",M(f),(D??document.body).appendChild(f),f.innerHTML=`
19
19
  <div class="dev-head">
20
20
  <span class="dev-badge">SSE</span>
21
21
  <span class="dev-title">${r?`SSE EVENT LOG · ${r}`:"SSE EVENT LOG · raw stream messages"}</span>
@@ -24,7 +24,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const te=requ
24
24
  <div class="dev-body">
25
25
  <div class="dev-log" id="ago-dev-event-log"></div>
26
26
  </div>
27
- `,J=g.querySelector(".dev-log"),W(g,ae+R,"SSE event log");function I(t){u||Q(J,ne(t),"event")}function V({functionName:t,arguments:o}){u||(k(`→ ${t}(${JSON.stringify(o??{})})`,"invoke"),m())}function H({result:t,error:o}){u||(k(o?`✗ error: ${o}`:`← ${JSON.stringify(t)}`,o?"error":"result"),h(),m())}function U(){u||(h(),m())}function B(t){if(u)return;const o=(t.messages??[]).flatMap(d=>d.toolCalls??[]);k(`⟳ hydrated "${t.title||t.id}" — replayed ${o.length} tool call${o.length===1?"":"s"}`,"hydrate"),h()}if(e.on("stream:message",I),e.on("function:invoke",V),e.on("function:result",H),e.on("context:changed",U),e.on("conversation:loaded",B),P){const t=document.createElement("div");t.className="dev-runner";const o=document.createElement("div");o.className="dev-section-label",o.textContent="LOCAL FUNCTION RUNNER",t.appendChild(o);const d=document.createElement("div");d.className="dev-runner-warning",d.textContent="Executes locally. Does not contact the agent backend.",t.appendChild(d);const a=document.createElement("div");a.className="dev-runner-row";const s=document.createElement("select");s.className="dev-runner-select",a.appendChild(s);const y=document.createElement("button");y.type="button",y.className="dev-runner-btn dev-runner-btn-sm",y.textContent="Refresh",y.addEventListener("click",m),a.appendChild(y),t.appendChild(a),b=s;const $=document.createElement("div");$.className="dev-section-label",$.textContent="SCHEMA",t.appendChild($);const T=document.createElement("pre");T.className="dev-runner-schema",t.appendChild(T),L=T,s.addEventListener("change",()=>{O=s.value,m()});const z=document.createElement("div");z.className="dev-section-label",z.textContent="ARGUMENTS (JSON)",t.appendChild(z);const C=document.createElement("textarea");C.className="dev-runner-args",C.value="{}",C.spellcheck=!1,t.appendChild(C);const f=document.createElement("button");f.type="button",f.className="dev-runner-btn",f.textContent="Run",t.appendChild(f);const l=document.createElement("div");l.className="dev-runner-status",t.appendChild(l);const x=document.createElement("pre");x.className="dev-runner-result",t.appendChild(x);const E=document.createElement("div");E.className="dev-runner-bytes",t.appendChild(E);const ee=e.executeClientFunction.bind(e);f.addEventListener("click",async()=>{l.textContent="",x.textContent="",E.textContent="";let G;try{const c=JSON.parse(C.value);if(c===null||Array.isArray(c)||typeof c!="object"){l.textContent="Error: arguments must be a JSON object.",l.className="dev-runner-status dev-runner-error";return}G=c}catch(c){l.textContent=`Parse error: ${c instanceof Error?c.message:String(c)}`,l.className="dev-runner-status dev-runner-error";return}const Y=s.value;if(!Y)return;f.disabled=!0,l.textContent="Running…",l.className="dev-runner-status";let S,K=!1;try{S=await ee(Y,G),K=!0}catch(c){if(u)return;l.textContent="Execution error",l.className="dev-runner-status dev-runner-error",x.textContent=c instanceof Error?`${c.constructor.name}: ${c.message}`:String(c)}if(!u){if(K)if(l.textContent="OK",l.className="dev-runner-status dev-runner-ok",S===void 0)x.textContent="(undefined)";else try{x.textContent=JSON.stringify(S,null,2),E.textContent=`${new TextEncoder().encode(JSON.stringify(S)).length} bytes (UTF-8)`}catch{x.textContent="(result not serializable)"}f.disabled=!1,h(),m()}}),p.querySelector(".dev-body").appendChild(t)}return m(),h(),()=>{u||(u=!0,e.off("stream:message",I),e.off("function:invoke",V),e.off("function:result",H),e.off("context:changed",U),e.off("conversation:loaded",B),p.remove(),g.remove())}}var X="ago-dev-panel-styles";function se(){if(document.getElementById(X))return;const n=document.createElement("style");n.id=X,n.textContent=le,document.head.appendChild(n)}var le=`
27
+ `,J=f.querySelector(".dev-log"),X(f,re+R,"SSE event log");function I(t){d||W(J,oe(t),"event")}function V({functionName:t,arguments:o}){d||(k(`→ ${t}(${JSON.stringify(o??{})})`,"invoke"),g())}function H({result:t,error:o}){d||(k(o?`✗ error: ${o}`:`← ${JSON.stringify(t)}`,o?"error":"result"),h(),g())}function U(){d||(h(),g())}function B(){d||g()}function G(t){if(d)return;const o=(t.messages??[]).flatMap(s=>s.toolCalls??[]);k(`⟳ hydrated "${t.title||t.id}" — replayed ${o.length} tool call${o.length===1?"":"s"}`,"hydrate"),h()}if(e.on("stream:message",I),e.on("function:invoke",V),e.on("function:result",H),e.on("context:changed",U),e.on("conversation:loaded",G),e.on("functions:changed",B),F){const t=document.createElement("div");t.className="dev-runner";const o=document.createElement("div");o.className="dev-section-label",o.textContent="LOCAL FUNCTION RUNNER",t.appendChild(o);const s=document.createElement("div");s.className="dev-runner-warning",s.textContent="Executes locally. Does not contact the agent backend.",t.appendChild(s);const a=document.createElement("div");a.className="dev-runner-row";const l=document.createElement("select");l.className="dev-runner-select",a.appendChild(l);const y=document.createElement("button");y.type="button",y.className="dev-runner-btn dev-runner-btn-sm",y.textContent="Refresh",y.addEventListener("click",g),a.appendChild(y),t.appendChild(a),b=l;const $=document.createElement("div");$.className="dev-section-label",$.textContent="SCHEMA",t.appendChild($);const T=document.createElement("pre");T.className="dev-runner-schema",t.appendChild(T),L=T,l.addEventListener("change",()=>{O=l.value,g()});const z=document.createElement("div");z.className="dev-section-label",z.textContent="ARGUMENTS (JSON)",t.appendChild(z);const C=document.createElement("textarea");C.className="dev-runner-args",C.value="{}",C.spellcheck=!1,t.appendChild(C);const m=document.createElement("button");m.type="button",m.className="dev-runner-btn",m.textContent="Run",t.appendChild(m);const c=document.createElement("div");c.className="dev-runner-status",t.appendChild(c);const x=document.createElement("pre");x.className="dev-runner-result",t.appendChild(x);const E=document.createElement("div");E.className="dev-runner-bytes",t.appendChild(E);const te=e.executeClientFunction.bind(e);m.addEventListener("click",async()=>{c.textContent="",x.textContent="",E.textContent="";let Y;try{const i=JSON.parse(C.value);if(i===null||Array.isArray(i)||typeof i!="object"){c.textContent="Error: arguments must be a JSON object.",c.className="dev-runner-status dev-runner-error";return}Y=i}catch(i){c.textContent=`Parse error: ${i instanceof Error?i.message:String(i)}`,c.className="dev-runner-status dev-runner-error";return}const K=l.value;if(!K)return;m.disabled=!0,c.textContent="Running…",c.className="dev-runner-status";let S,Q=!1;try{S=await te(K,Y),Q=!0}catch(i){if(d)return;c.textContent="Execution error",c.className="dev-runner-status dev-runner-error",x.textContent=i instanceof Error?`${i.constructor.name}: ${i.message}`:String(i)}if(!d){if(Q)if(c.textContent="OK",c.className="dev-runner-status dev-runner-ok",S===void 0)x.textContent="(undefined)";else try{x.textContent=JSON.stringify(S,null,2),E.textContent=`${new TextEncoder().encode(JSON.stringify(S)).length} bytes (UTF-8)`}catch{x.textContent="(result not serializable)"}m.disabled=!1,h(),g()}}),p.querySelector(".dev-body").appendChild(t)}return g(),h(),()=>{d||(d=!0,e.off("stream:message",I),e.off("function:invoke",V),e.off("function:result",H),e.off("context:changed",U),e.off("conversation:loaded",G),e.off("functions:changed",B),p.remove(),f.remove())}}var Z="ago-dev-panel-styles";function le(){if(document.getElementById(Z))return;const n=document.createElement("style");n.id=Z,n.textContent=ce,document.head.appendChild(n)}var ce=`
28
28
  .ago-dev-card {
29
29
  position: fixed;
30
30
  right: 16px;
@@ -169,4 +169,4 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const te=requ
169
169
  .ago-dev-card .dev-runner-result:empty { display: none; }
170
170
  .ago-dev-card .dev-runner-bytes { color: #7c8a99; font-size: 10px; margin-top: 2px; }
171
171
  .ago-dev-card .dev-runner-bytes:empty { display: none; }
172
- `;exports.initDevPanel=de;
172
+ `;exports.initDevPanel=se;
@@ -92,7 +92,10 @@ declare class AgoClient {
92
92
  * `null` otherwise.
93
93
  */
94
94
  proactive: ProactiveController | null;
95
+ /** Removes the mirrored WebMCP tools; `null` when the bridge is off. */
96
+ private detachWebMCP;
95
97
  constructor(config: AgoConfig);
98
+ private attachWebMCPBridge;
96
99
  /**
97
100
  * Send a message and receive a streaming response
98
101
  */
@@ -204,6 +207,7 @@ declare class AgoClient {
204
207
  * (the agent decides what to do next). No-op if the invocation is unknown.
205
208
  */
206
209
  rejectFunction(invocationId: string): Promise<void>;
210
+ /* Excluded from this release type: runExternalFunction */
207
211
  /**
208
212
  * Get a page of conversations, newest-first. `pageSize` is capped at 100 by
209
213
  * the backend (default 50). Returns the `{ data, has_more, total }` envelope
@@ -223,11 +227,20 @@ declare class AgoClient {
223
227
  * `SSEHandler.parseToolCall` so persisted and streamed tool calls match.
224
228
  */
225
229
  private static mapPersistedToolCalls;
230
+ /**
231
+ * Transcribe an audio file into editable text (`POST /api/sdk/v1/audio/transcriptions`).
232
+ * Requires speech to text to be enabled for the tenant. Supports FLAC, MP3,
233
+ * MP4, MPEG, MPGA, M4A, OGG, WAV and WebM files up to 25 MB.
234
+ * The filename must include the matching extension. For a MediaRecorder blob,
235
+ * wrap it in a File with the recording's extension and MIME type.
236
+ * Show the returned text as a draft; call `sendMessage` when the user sends it.
237
+ */
238
+ transcribeAudio(file: File, options?: TranscribeAudioOptions): Promise<AudioTranscription>;
226
239
  /**
227
240
  * The tenant's SDK configuration (`GET /api/sdk/v1/config`): per-permission
228
241
  * agents, the ticket form the agent's `ago_ticketing` tool opens, and the
229
- * file-attachment flag. The vanilla widget fetches it once, when a ticket
230
- * form first appears in a conversation.
242
+ * file-attachment and speech-to-text flags. The vanilla widget fetches it
243
+ * once, when a ticket form first appears in a conversation.
231
244
  */
232
245
  getConfig(): Promise<SdkConfig>;
233
246
  /**
@@ -364,6 +377,9 @@ declare class AgoClient {
364
377
  * Get all registered function schemas
365
378
  */
366
379
  getRegisteredFunctions(): ClientFunctionSchema[];
380
+ /** The callback form of `functions:changed`. Returns an unsubscribe. */
381
+ onFunctionsChanged(listener: () => void): () => void;
382
+ /* Excluded from this release type: getFunctionRegistrations */
367
383
  /**
368
384
  * Execute a registered client function locally, through the same
369
385
  * FunctionRegistry path (result-size guard, error wrapping) as agent-invoked
@@ -696,6 +712,8 @@ declare interface AgoClientEvents {
696
712
  * call running immediately.
697
713
  */
698
714
  "function:awaiting-approval": ClientFunctionInvocation;
715
+ /** A function was registered or unregistered, or the registry cleared. */
716
+ "functions:changed": ClientFunctionSchema[];
699
717
  "function:result": {
700
718
  invocationId: string;
701
719
  result: unknown;
@@ -768,6 +786,8 @@ declare interface AgoConfig {
768
786
  defaultAgentId?: string;
769
787
  /** Permission name to apply to all requests (sent as `X-Widget-Permission`). Mirrors the widget's `window.AGO.permission`. */
770
788
  permission?: string;
789
+ /** Interface locale selected by the host app, sent as Accept-Language. Null clears the override. */
790
+ language?: string | null;
771
791
  /** User email for identification */
772
792
  userEmail?: string;
773
793
  /** JWT token for authenticated users */
@@ -845,6 +865,15 @@ declare interface AgoConfig {
845
865
  * mode's `jsErrors` signal. See `client.reportError()` for caught errors.
846
866
  */
847
867
  errorWatcher?: boolean | ErrorWatcherOptions;
868
+ /** Mirror every registered client function into the browser's WebMCP registry
869
+ * (`document.modelContext`), so an external agent can call the same functions
870
+ * the in-app agent calls. Off by default; no-ops without WebMCP.
871
+ *
872
+ * A mirrored function runs immediately: the approval gate
873
+ * ({@link approvalPolicy}, `requiresApproval`) covers the agent loop only.
874
+ * Use `webmcp: false` on a definition to keep it out.
875
+ */
876
+ webmcp?: boolean;
848
877
  }
849
878
 
850
879
  declare type AgoEventHandler<K extends AgoEventName> = (data: AgoClientEvents[K]) => void;
@@ -1029,6 +1058,11 @@ declare type AgoStateSetResult = {
1029
1058
  result: "unchanged";
1030
1059
  };
1031
1060
 
1061
+ /** Editable text returned by `AgoClient.transcribeAudio`. */
1062
+ declare interface AudioTranscription {
1063
+ text: string;
1064
+ }
1065
+
1032
1066
  /** One JavaScript error captured on the page (deduplicated, see `count`). */
1033
1067
  declare interface CapturedError {
1034
1068
  type: CapturedErrorType;
@@ -1068,22 +1102,11 @@ declare type CapturedErrorType = "error" | "unhandledrejection" | "console" | "m
1068
1102
  * client.registerFunction(fn);
1069
1103
  * ```
1070
1104
  */
1071
- declare interface ClientFunctionDefinition {
1105
+ declare interface ClientFunctionDefinition extends ClientFunctionSettings {
1072
1106
  name: string;
1073
1107
  description: string;
1074
1108
  parameters: ClientFunctionSchema["parameters"];
1075
1109
  handler: ClientFunctionHandler;
1076
- /**
1077
- * Max serialized result size in bytes before the SDK truncates it to a
1078
- * flagged preview (default: `AgoConfig.maxFunctionResultBytes`, 50 000).
1079
- * `Infinity` disables the guard for this function.
1080
- */
1081
- maxResultBytes?: number;
1082
- /**
1083
- * Require explicit user approval before this function runs. See
1084
- * {@link AgoConfig.approvalPolicy} — pause mode only. ORs with the policy.
1085
- */
1086
- requiresApproval?: boolean;
1087
1110
  }
1088
1111
 
1089
1112
  /**
@@ -1102,20 +1125,7 @@ declare interface ClientFunctionInvocation {
1102
1125
  * Schema-plus-settings object accepted when registering a function: the schema
1103
1126
  * (minus `name`) and SDK-side options that are NOT sent to the backend.
1104
1127
  */
1105
- declare type ClientFunctionRegisterOptions = Omit<ClientFunctionSchema, "name"> & {
1106
- /**
1107
- * Max serialized result size in bytes before the SDK truncates it to a
1108
- * flagged preview. Overrides the client-level default
1109
- * (`AgoConfig.maxFunctionResultBytes`, 50 000 by default). `Infinity`
1110
- * disables the guard for this function.
1111
- */
1112
- maxResultBytes?: number;
1113
- /**
1114
- * Require explicit user approval before this function runs. See
1115
- * {@link AgoConfig.approvalPolicy} — pause mode only. ORs with the policy.
1116
- */
1117
- requiresApproval?: boolean;
1118
- };
1128
+ declare type ClientFunctionRegisterOptions = Omit<ClientFunctionSchema, "name"> & ClientFunctionSettings;
1119
1129
 
1120
1130
  /**
1121
1131
  * Schema for a client-side function that AGO can call
@@ -1142,6 +1152,28 @@ declare interface ClientFunctionSchema {
1142
1152
  };
1143
1153
  }
1144
1154
 
1155
+ /** SDK-side function settings that are never sent to the backend. */
1156
+ declare interface ClientFunctionSettings {
1157
+ /**
1158
+ * Max serialized result size in bytes before the SDK truncates it to a
1159
+ * flagged preview. Overrides the client-level default
1160
+ * (`AgoConfig.maxFunctionResultBytes`, 50 000 by default). `Infinity`
1161
+ * disables the guard for this function.
1162
+ */
1163
+ maxResultBytes?: number;
1164
+ /**
1165
+ * Require explicit user approval before this function runs. See
1166
+ * {@link AgoConfig.approvalPolicy} — pause mode only. ORs with the policy.
1167
+ */
1168
+ requiresApproval?: boolean;
1169
+ /**
1170
+ * WebMCP metadata, read only when the bridge is on (`AgoConfig.webmcp`).
1171
+ * `false` keeps this function out of WebMCP while leaving it available to the
1172
+ * in-app agent.
1173
+ */
1174
+ webmcp?: WebMCPToolMeta | false;
1175
+ }
1176
+
1145
1177
  /** See {@link AgoConfig.clientFunctionsMode}. */
1146
1178
  declare type ClientFunctionsMode = "placeholder" | "pause";
1147
1179
 
@@ -1641,6 +1673,14 @@ declare interface ProactiveTriggerWhen {
1641
1673
  fieldErrors?: Record<string, number>;
1642
1674
  }
1643
1675
 
1676
+ /**
1677
+ * Registered function with handler
1678
+ */
1679
+ declare interface RegisteredFunction extends ClientFunctionSettings {
1680
+ schema: ClientFunctionSchema;
1681
+ handler: ClientFunctionHandler;
1682
+ }
1683
+
1644
1684
  /**
1645
1685
  * Hook run before a paused turn is resumed, so the app controls WHEN the
1646
1686
  * continuation fires (e.g. wait for the destination page to mount after a
@@ -1697,6 +1737,8 @@ declare interface SdkPermissionConfig {
1697
1737
  homePage?: SdkHomePageConfig;
1698
1738
  fileAttachmentsEnabled: boolean;
1699
1739
  voiceEnabled: boolean;
1740
+ /** Whether audio uploads can be transcribed. Defaults to false on older backends. */
1741
+ speechToTextEnabled: boolean;
1700
1742
  }
1701
1743
 
1702
1744
  /**
@@ -2009,4 +2051,29 @@ declare interface ToolCallTicketPrefill {
2009
2051
 
2010
2052
  declare type ToolCallType = "form" | "confirmation_input" | "status_message" | "progress_indicator" | "client_function" | "reasoning" | "mcp_ui_resource";
2011
2053
 
2054
+ /** Options for `AgoClient.transcribeAudio`. */
2055
+ declare interface TranscribeAudioOptions {
2056
+ /** Cancel the upload or stop waiting for its transcription. */
2057
+ signal?: AbortSignal;
2058
+ }
2059
+
2060
+ /** The MCP behavior hints AGO has no equivalent for. */
2061
+ declare interface WebMCPToolMeta {
2062
+ /**
2063
+ * Both default to `false`, so only set what is true: `readOnlyHint` marks a
2064
+ * function that changes nothing, `untrustedContentHint` one whose result may
2065
+ * carry third-party text.
2066
+ */
2067
+ annotations?: {
2068
+ readOnlyHint?: boolean;
2069
+ untrustedContentHint?: boolean;
2070
+ };
2071
+ /**
2072
+ * This function navigates. The WebMCP call is held open until the function
2073
+ * registry goes quiet, so the caller sees the destination page's tools rather
2074
+ * than the departing page's. Already set on the built-in `navigateToPage`.
2075
+ */
2076
+ navigates?: boolean;
2077
+ }
2078
+
2012
2079
  export { }
@@ -92,7 +92,10 @@ declare class AgoClient {
92
92
  * `null` otherwise.
93
93
  */
94
94
  proactive: ProactiveController | null;
95
+ /** Removes the mirrored WebMCP tools; `null` when the bridge is off. */
96
+ private detachWebMCP;
95
97
  constructor(config: AgoConfig);
98
+ private attachWebMCPBridge;
96
99
  /**
97
100
  * Send a message and receive a streaming response
98
101
  */
@@ -204,6 +207,7 @@ declare class AgoClient {
204
207
  * (the agent decides what to do next). No-op if the invocation is unknown.
205
208
  */
206
209
  rejectFunction(invocationId: string): Promise<void>;
210
+ /* Excluded from this release type: runExternalFunction */
207
211
  /**
208
212
  * Get a page of conversations, newest-first. `pageSize` is capped at 100 by
209
213
  * the backend (default 50). Returns the `{ data, has_more, total }` envelope
@@ -223,11 +227,20 @@ declare class AgoClient {
223
227
  * `SSEHandler.parseToolCall` so persisted and streamed tool calls match.
224
228
  */
225
229
  private static mapPersistedToolCalls;
230
+ /**
231
+ * Transcribe an audio file into editable text (`POST /api/sdk/v1/audio/transcriptions`).
232
+ * Requires speech to text to be enabled for the tenant. Supports FLAC, MP3,
233
+ * MP4, MPEG, MPGA, M4A, OGG, WAV and WebM files up to 25 MB.
234
+ * The filename must include the matching extension. For a MediaRecorder blob,
235
+ * wrap it in a File with the recording's extension and MIME type.
236
+ * Show the returned text as a draft; call `sendMessage` when the user sends it.
237
+ */
238
+ transcribeAudio(file: File, options?: TranscribeAudioOptions): Promise<AudioTranscription>;
226
239
  /**
227
240
  * The tenant's SDK configuration (`GET /api/sdk/v1/config`): per-permission
228
241
  * agents, the ticket form the agent's `ago_ticketing` tool opens, and the
229
- * file-attachment flag. The vanilla widget fetches it once, when a ticket
230
- * form first appears in a conversation.
242
+ * file-attachment and speech-to-text flags. The vanilla widget fetches it
243
+ * once, when a ticket form first appears in a conversation.
231
244
  */
232
245
  getConfig(): Promise<SdkConfig>;
233
246
  /**
@@ -364,6 +377,9 @@ declare class AgoClient {
364
377
  * Get all registered function schemas
365
378
  */
366
379
  getRegisteredFunctions(): ClientFunctionSchema[];
380
+ /** The callback form of `functions:changed`. Returns an unsubscribe. */
381
+ onFunctionsChanged(listener: () => void): () => void;
382
+ /* Excluded from this release type: getFunctionRegistrations */
367
383
  /**
368
384
  * Execute a registered client function locally, through the same
369
385
  * FunctionRegistry path (result-size guard, error wrapping) as agent-invoked
@@ -696,6 +712,8 @@ declare interface AgoClientEvents {
696
712
  * call running immediately.
697
713
  */
698
714
  "function:awaiting-approval": ClientFunctionInvocation;
715
+ /** A function was registered or unregistered, or the registry cleared. */
716
+ "functions:changed": ClientFunctionSchema[];
699
717
  "function:result": {
700
718
  invocationId: string;
701
719
  result: unknown;
@@ -768,6 +786,8 @@ declare interface AgoConfig {
768
786
  defaultAgentId?: string;
769
787
  /** Permission name to apply to all requests (sent as `X-Widget-Permission`). Mirrors the widget's `window.AGO.permission`. */
770
788
  permission?: string;
789
+ /** Interface locale selected by the host app, sent as Accept-Language. Null clears the override. */
790
+ language?: string | null;
771
791
  /** User email for identification */
772
792
  userEmail?: string;
773
793
  /** JWT token for authenticated users */
@@ -845,6 +865,15 @@ declare interface AgoConfig {
845
865
  * mode's `jsErrors` signal. See `client.reportError()` for caught errors.
846
866
  */
847
867
  errorWatcher?: boolean | ErrorWatcherOptions;
868
+ /** Mirror every registered client function into the browser's WebMCP registry
869
+ * (`document.modelContext`), so an external agent can call the same functions
870
+ * the in-app agent calls. Off by default; no-ops without WebMCP.
871
+ *
872
+ * A mirrored function runs immediately: the approval gate
873
+ * ({@link approvalPolicy}, `requiresApproval`) covers the agent loop only.
874
+ * Use `webmcp: false` on a definition to keep it out.
875
+ */
876
+ webmcp?: boolean;
848
877
  }
849
878
 
850
879
  declare type AgoEventHandler<K extends AgoEventName> = (data: AgoClientEvents[K]) => void;
@@ -1029,6 +1058,11 @@ declare type AgoStateSetResult = {
1029
1058
  result: "unchanged";
1030
1059
  };
1031
1060
 
1061
+ /** Editable text returned by `AgoClient.transcribeAudio`. */
1062
+ declare interface AudioTranscription {
1063
+ text: string;
1064
+ }
1065
+
1032
1066
  /** One JavaScript error captured on the page (deduplicated, see `count`). */
1033
1067
  declare interface CapturedError {
1034
1068
  type: CapturedErrorType;
@@ -1068,22 +1102,11 @@ declare type CapturedErrorType = "error" | "unhandledrejection" | "console" | "m
1068
1102
  * client.registerFunction(fn);
1069
1103
  * ```
1070
1104
  */
1071
- declare interface ClientFunctionDefinition {
1105
+ declare interface ClientFunctionDefinition extends ClientFunctionSettings {
1072
1106
  name: string;
1073
1107
  description: string;
1074
1108
  parameters: ClientFunctionSchema["parameters"];
1075
1109
  handler: ClientFunctionHandler;
1076
- /**
1077
- * Max serialized result size in bytes before the SDK truncates it to a
1078
- * flagged preview (default: `AgoConfig.maxFunctionResultBytes`, 50 000).
1079
- * `Infinity` disables the guard for this function.
1080
- */
1081
- maxResultBytes?: number;
1082
- /**
1083
- * Require explicit user approval before this function runs. See
1084
- * {@link AgoConfig.approvalPolicy} — pause mode only. ORs with the policy.
1085
- */
1086
- requiresApproval?: boolean;
1087
1110
  }
1088
1111
 
1089
1112
  /**
@@ -1102,20 +1125,7 @@ declare interface ClientFunctionInvocation {
1102
1125
  * Schema-plus-settings object accepted when registering a function: the schema
1103
1126
  * (minus `name`) and SDK-side options that are NOT sent to the backend.
1104
1127
  */
1105
- declare type ClientFunctionRegisterOptions = Omit<ClientFunctionSchema, "name"> & {
1106
- /**
1107
- * Max serialized result size in bytes before the SDK truncates it to a
1108
- * flagged preview. Overrides the client-level default
1109
- * (`AgoConfig.maxFunctionResultBytes`, 50 000 by default). `Infinity`
1110
- * disables the guard for this function.
1111
- */
1112
- maxResultBytes?: number;
1113
- /**
1114
- * Require explicit user approval before this function runs. See
1115
- * {@link AgoConfig.approvalPolicy} — pause mode only. ORs with the policy.
1116
- */
1117
- requiresApproval?: boolean;
1118
- };
1128
+ declare type ClientFunctionRegisterOptions = Omit<ClientFunctionSchema, "name"> & ClientFunctionSettings;
1119
1129
 
1120
1130
  /**
1121
1131
  * Schema for a client-side function that AGO can call
@@ -1142,6 +1152,28 @@ declare interface ClientFunctionSchema {
1142
1152
  };
1143
1153
  }
1144
1154
 
1155
+ /** SDK-side function settings that are never sent to the backend. */
1156
+ declare interface ClientFunctionSettings {
1157
+ /**
1158
+ * Max serialized result size in bytes before the SDK truncates it to a
1159
+ * flagged preview. Overrides the client-level default
1160
+ * (`AgoConfig.maxFunctionResultBytes`, 50 000 by default). `Infinity`
1161
+ * disables the guard for this function.
1162
+ */
1163
+ maxResultBytes?: number;
1164
+ /**
1165
+ * Require explicit user approval before this function runs. See
1166
+ * {@link AgoConfig.approvalPolicy} — pause mode only. ORs with the policy.
1167
+ */
1168
+ requiresApproval?: boolean;
1169
+ /**
1170
+ * WebMCP metadata, read only when the bridge is on (`AgoConfig.webmcp`).
1171
+ * `false` keeps this function out of WebMCP while leaving it available to the
1172
+ * in-app agent.
1173
+ */
1174
+ webmcp?: WebMCPToolMeta | false;
1175
+ }
1176
+
1145
1177
  /** See {@link AgoConfig.clientFunctionsMode}. */
1146
1178
  declare type ClientFunctionsMode = "placeholder" | "pause";
1147
1179
 
@@ -1641,6 +1673,14 @@ declare interface ProactiveTriggerWhen {
1641
1673
  fieldErrors?: Record<string, number>;
1642
1674
  }
1643
1675
 
1676
+ /**
1677
+ * Registered function with handler
1678
+ */
1679
+ declare interface RegisteredFunction extends ClientFunctionSettings {
1680
+ schema: ClientFunctionSchema;
1681
+ handler: ClientFunctionHandler;
1682
+ }
1683
+
1644
1684
  /**
1645
1685
  * Hook run before a paused turn is resumed, so the app controls WHEN the
1646
1686
  * continuation fires (e.g. wait for the destination page to mount after a
@@ -1697,6 +1737,8 @@ declare interface SdkPermissionConfig {
1697
1737
  homePage?: SdkHomePageConfig;
1698
1738
  fileAttachmentsEnabled: boolean;
1699
1739
  voiceEnabled: boolean;
1740
+ /** Whether audio uploads can be transcribed. Defaults to false on older backends. */
1741
+ speechToTextEnabled: boolean;
1700
1742
  }
1701
1743
 
1702
1744
  /**
@@ -2009,4 +2051,29 @@ declare interface ToolCallTicketPrefill {
2009
2051
 
2010
2052
  declare type ToolCallType = "form" | "confirmation_input" | "status_message" | "progress_indicator" | "client_function" | "reasoning" | "mcp_ui_resource";
2011
2053
 
2054
+ /** Options for `AgoClient.transcribeAudio`. */
2055
+ declare interface TranscribeAudioOptions {
2056
+ /** Cancel the upload or stop waiting for its transcription. */
2057
+ signal?: AbortSignal;
2058
+ }
2059
+
2060
+ /** The MCP behavior hints AGO has no equivalent for. */
2061
+ declare interface WebMCPToolMeta {
2062
+ /**
2063
+ * Both default to `false`, so only set what is true: `readOnlyHint` marks a
2064
+ * function that changes nothing, `untrustedContentHint` one whose result may
2065
+ * carry third-party text.
2066
+ */
2067
+ annotations?: {
2068
+ readOnlyHint?: boolean;
2069
+ untrustedContentHint?: boolean;
2070
+ };
2071
+ /**
2072
+ * This function navigates. The WebMCP call is held open until the function
2073
+ * registry goes quiet, so the caller sees the destination page's tools rather
2074
+ * than the departing page's. Already set on the built-in `navigateToPage`.
2075
+ */
2076
+ navigates?: boolean;
2077
+ }
2078
+
2012
2079
  export { }