@useago/sdk 1.0.0 → 1.0.2
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/CHANGELOG.md +44 -0
- package/README.md +103 -74
- package/dist/AgoClient-_fig8FoN.cjs +6 -0
- package/dist/{AgoClient-BrYhSO5M.js → AgoClient-bQozE6-A.js} +174 -134
- package/dist/angular.cjs +1 -1
- package/dist/angular.d.cts +131 -1
- package/dist/angular.d.ts +131 -1
- package/dist/angular.js +1 -1
- package/dist/{createConversationSession-Dmqd80DX.js → createConversationSession-BbK3ou1k.js} +1 -1
- package/dist/{createConversationSession-CGRO0bs2.cjs → createConversationSession-DJUFgOXy.cjs} +1 -1
- package/dist/createFormCollector-CdQjGAl_.cjs +1 -0
- package/dist/createFormCollector-D-TpSd9x.js +257 -0
- package/dist/devtools.d.cts +131 -1
- package/dist/devtools.d.ts +131 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +126 -4
- package/dist/index.d.ts +126 -4
- package/dist/index.js +94 -92
- package/dist/react.cjs +20 -20
- package/dist/react.d.cts +125 -30
- package/dist/react.d.ts +125 -30
- package/dist/react.js +2207 -2135
- package/dist/testing.d.cts +131 -1
- package/dist/testing.d.ts +131 -1
- package/dist/vue.cjs +1 -1
- package/dist/vue.d.cts +131 -1
- package/dist/vue.d.ts +131 -1
- package/dist/vue.js +1 -1
- package/dist/widget.cjs +4 -4
- package/dist/widget.d.cts +115 -5
- package/dist/widget.d.ts +115 -5
- package/dist/widget.js +408 -322
- package/package.json +2 -2
- package/dist/AgoClient-CPqPT5s6.cjs +0 -6
- package/dist/createFormCollector-CPS2phYq.js +0 -245
- package/dist/createFormCollector-DaWZsBsI.cjs +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useago/sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Create In-APP AI agents that answers question and performs actions. Works with React, Vue, Angular and vanilla JS/TS.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
"dev": "vite build --watch",
|
|
119
119
|
"test": "vitest run",
|
|
120
120
|
"test:watch": "vitest",
|
|
121
|
-
"lint": "eslint \"src/**/*.{ts,tsx}\"",
|
|
121
|
+
"lint": "eslint \"src/**/*.{ts,tsx}\" --max-warnings 0",
|
|
122
122
|
"typecheck": "tsc --noEmit"
|
|
123
123
|
},
|
|
124
124
|
"dependencies": {
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
var u=class extends Error{constructor(e,t,s){super(e),this.code=t,this.statusCode=s,this.name="AgoError"}},h=class p extends u{constructor(t,s,r,n,o,a){super(t,s,r),this.type=n,this.param=o,this.docUrl=a,this.name="AgoApiError"}static fromResponse(t,s){const r=t.error;return new p(r.message,r.code,s,r.type,r.param,r.doc_url)}},d=class extends u{constructor(e,t){super(e,"network_error"),this.originalError=t,this.name="AgoNetworkError"}},g=class extends u{constructor(e){super(e,"stream_error"),this.name="AgoStreamError"}},m=class extends u{constructor(e,t,s){super(e,"function_error"),this.functionName=t,this.originalError=s,this.name="AgoFunctionError"}},_=class{constructor(e=!1){this.enabled=e}enable(){this.enabled=!0}disable(){this.enabled=!1}log(...e){this.enabled&&console.log("[AGO SDK]",...e)}warn(...e){this.enabled&&console.warn("[AGO SDK]",...e)}error(...e){console.error("[AGO SDK]",...e)}debug(...e){this.enabled&&console.debug("[AGO SDK]",...e)}},i=new _,f="ago_widget_id";function S(){if(typeof localStorage<"u"){const t=localStorage.getItem(f);if(t)return t}const e=crypto.randomUUID();if(typeof localStorage<"u")try{localStorage.setItem(f,e)}catch{}return e}var k=class{constructor(e){this.baseUrl=e.baseUrl.replace(/\/$/,""),this.headers={"X-Widget-Id":e.widgetId||S()},e.userEmail&&(this.headers["X-User-Email"]=e.userEmail),e.userJwt&&(this.headers.Authorization=`Bearer ${e.userJwt}`),e.permission&&(this.headers["X-Widget-Permission"]=e.permission)}updateConfig(e){e.baseUrl&&(this.baseUrl=e.baseUrl.replace(/\/$/,"")),e.widgetId&&(this.headers["X-Widget-Id"]=e.widgetId),e.userEmail&&(this.headers["X-User-Email"]=e.userEmail),e.userJwt&&(this.headers.Authorization=`Bearer ${e.userJwt}`),e.permission!==void 0&&(e.permission?this.headers["X-Widget-Permission"]=e.permission:delete this.headers["X-Widget-Permission"])}async get(e){return this.request("GET",e)}async post(e,t){return this.request("POST",e,t)}async postStream(e,t){const s=`${this.baseUrl}${e}`;i.debug("POST (stream)",s,t);try{const r=await fetch(s,{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 h?r:new d(`Network error: ${r instanceof Error?r.message:"Unknown error"}`,r instanceof Error?r:void 0)}}async postFormData(e,t){const s=`${this.baseUrl}${e}`;i.debug("POST (formData)",s);const r={...this.headers};try{const n=await fetch(s,{method:"POST",headers:r,body:t});return n.ok||await this.handleErrorResponse(n),n}catch(n){throw n instanceof h?n:new d(`Network error: ${n instanceof Error?n.message:"Unknown error"}`,n instanceof Error?n:void 0)}}async request(e,t,s){const r=`${this.baseUrl}${t}`;i.debug(e,r,s);try{const n=await fetch(r,{method:e,headers:{...this.headers,"Content-Type":"application/json"},body:s?JSON.stringify(s):void 0});return n.ok||await this.handleErrorResponse(n),n.status===204?void 0:n.json()}catch(n){throw n instanceof h?n:new d(`Network error: ${n instanceof Error?n.message:"Unknown error"}`,n instanceof Error?n:void 0)}}async handleErrorResponse(e){let t;try{t=await e.json()}catch{}throw t?.error?h.fromResponse(t,e.status):new h(`HTTP ${e.status}: ${e.statusText}`,"http_error",e.status,"api_error")}},y=class{constructor(){this.functions=new Map}register(e,t,s){if(typeof e=="object"){const{name:n,handler:o,description:a,parameters:c}=e;return this.register(n,o,{description:a,parameters:c})}const r=e;if(!t||!s)throw new Error("handler and schema are required");this.functions.has(r)&&i.warn(`Function "${r}" is being overwritten`),this.functions.set(r,{schema:{...s,name:r},handler:t}),i.log(`Registered function: ${r}`)}unregister(e){const t=this.functions.delete(e);return t&&i.log(`Unregistered function: ${e}`),t}get(e){return this.functions.get(e)}has(e){return this.functions.has(e)}getSchemas(){return Array.from(this.functions.values()).map(e=>e.schema)}async execute(e,t){const s=this.functions.get(e);if(!s)throw new m(`Function "${e}" is not registered`,e);i.log(`Executing function: ${e}`,t);try{const r=await s.handler(t);return i.log(`Function ${e} completed:`,r),r}catch(r){throw i.error(`Function ${e} failed:`,r),new m(`Function "${e}" execution failed: ${r instanceof Error?r.message:"Unknown error"}`,e,r instanceof Error?r:void 0)}}clear(){this.functions.clear(),i.log("Cleared all registered functions")}get size(){return this.functions.size}},w=class{constructor(){this.entries=new Map,this.dynamicProviders=new Map}set(e,t){this.entries.set(e,t),i.log(`ClientContext set: ${e}`)}remove(e){const t=this.entries.delete(e);return t&&i.log(`ClientContext removed: ${e}`),t}addDynamicProvider(e,t){this.dynamicProviders.set(e,t),i.log(`DynamicContext provider added: ${e}`)}removeDynamicProvider(e){const t=this.dynamicProviders.delete(e);return t&&i.log(`DynamicContext provider removed: ${e}`),t}getSnapshot(){if(this.entries.size===0&&this.dynamicProviders.size===0)return null;const e={};for(const[t,s]of this.entries)e[t]=s;for(const[t,s]of this.dynamicProviders)try{const r=s();r&&(e[t]=r)}catch(r){i.error(`DynamicContext provider "${t}" threw:`,r)}return Object.keys(e).length===0?null:{entries:e}}clear(){this.entries.clear(),this.dynamicProviders.clear(),i.log("ClientContext cleared")}},v=class{constructor(e){this.callbacks=e,this.buffer="",this.message={},this.toolCalls=[],this.sources=[],this.followUpReplies=[],this.isFirstChunk=!0,this.answerCompleteEmitted=!1}async processStream(e){if(!e.body)throw new g("Response has no body");const t=e.body.getReader(),s=new TextDecoder;try{for(;;){const{done:r,value:n}=await t.read();if(r)break;const o=s.decode(n,{stream:!0});this.buffer+=o,this.processBuffer()}return this.buffer.trim()&&this.processBuffer(),this.buildFinalMessage()}catch(r){const n=r instanceof Error?r:new g("Stream processing failed");throw this.callbacks.onError?.(n),n}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 s=t.split(`
|
|
4
|
-
`);for(const r of s)if(!r.startsWith(": ")&&r.startsWith("data: ")){const n=r.slice(6);try{const o=JSON.parse(n);this.handleChunk(o)}catch(o){i.warn("Failed to parse SSE data:",n,o)}}}}handleChunk(e){if(e.message_id&&!this.message.id&&(this.message.id=e.message_id),e.thread?.id&&(this.message.conversationId=e.thread.id,this.isFirstChunk&&this.message.id&&(this.isFirstChunk=!1,this.callbacks.onStart?.({conversationId:this.message.conversationId,messageId:this.message.id}))),e.content!==void 0&&(this.message.content=(this.message.content||"")+e.content,this.message.conversationId&&this.message.id&&this.callbacks.onChunk?.({content:e.content,conversationId:this.message.conversationId,messageId:this.message.id})),e.full_content!==void 0&&(this.message.content=e.full_content),e.status&&(this.message.status=e.status),e.agent&&(this.message.agent={id:e.agent.id,name:e.agent.name,displayName:e.agent.display_name}),e.knowledge_sources&&(this.sources=e.knowledge_sources.map(t=>{const s=t.knowledge_document;return{id:s.id,title:s.title,url:s.use_external_link?s.external_link_url:s.internal_link_url}})),e.type==="client_function"&&e.function_name&&this.callbacks.onClientFunction?.({invocationId:e.id||"",functionName:e.function_name,arguments:e.arguments||{},conversationId:this.message.conversationId||""}),e.tool_call_data&&e.type&&e.type!=="client_function"){const t=this.parseToolCall(e);this.callbacks.onToolCall?.(t);const s=this.toolCalls.findIndex(r=>r.id===t.id);s>=0?this.toolCalls[s]=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 x(e){const t=e.message.toLowerCase();return t.includes("load failed")||t.includes("failed to fetch")||t.includes("network")||t.includes("abort")}var C=class{constructor(){this.handlers=new Map}on(e,t){this.handlers.has(e)||this.handlers.set(e,new Set),this.handlers.get(e).add(t)}off(e,t){const s=this.handlers.get(e);s&&s.delete(t)}emit(e,t){const s=this.handlers.get(e);s&&s.forEach(r=>{try{r(t)}catch(n){console.error(`Error in event handler for ${String(e)}:`,n)}})}once(e,t){const s=(r=>{this.off(e,s),t(r)});this.on(e,s)}waitFor(e,t){return new Promise((s,r)=>{let n;const o=(a=>{n&&clearTimeout(n),s(a)});this.once(e,o),t?.timeout&&(n=setTimeout(()=>{this.off(e,o),r(new Error(`waitFor("${String(e)}") timed out after ${t.timeout}ms`))},t.timeout))})}removeAllListeners(e){e?this.handlers.delete(e):this.handlers.clear()}},A=class b{constructor(t){this.config=t,this.httpClient=new k(t),this.functionRegistry=new y,this.contextRegistry=new w,this.eventEmitter=new C,t.debug&&i.enable(),i.log("AgoClient initialized")}async sendMessage(t,s){const r=this.functionRegistry.getSchemas(),n=this.contextRegistry.getSnapshot(),o=this.config.agent||this.config.defaultAgentId,a={content:t,conversation_id:s?.conversationId,agent_id:s?.agentId||o};r.length>0&&(a.client_functions=r),n&&(a.client_context=n);let c;if(s?.files&&s.files.length>0){const l=new FormData;l.append("content",t),s.conversationId&&l.append("conversation_id",s.conversationId),(s.agentId||o)&&l.append("agent_id",s.agentId||o||""),r.length>0&&l.append("client_functions",JSON.stringify(r)),n&&l.append("client_context",JSON.stringify(n));for(const E of s.files)l.append("files",E);c=await this.httpClient.postFormData("/api/sdk/v1/messages",l)}else c=await this.httpClient.postStream("/api/sdk/v1/messages",a);return this.processSSEResponse(c)}async processSSEResponse(t){return new v({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=>{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})}}).processStream(t)}async handleClientFunctionInvocation(t){let s,r;try{s=await this.functionRegistry.execute(t.functionName,t.arguments)}catch(n){r=n instanceof Error?n.message:"Unknown error",i.error("Client function execution failed:",n)}if(t.invocationId)try{await this.submitToolCallForm(t.invocationId,{result:s,error:r,_type:"client_function_result"})}catch(n){i.error("Failed to submit function result:",n)}this.eventEmitter.emit("function:result",{invocationId:t.invocationId,result:s,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 s=await this.httpClient.get(`/api/sdk/v1/conversations/${t}`),r={id:s.id,title:s.title,lastMessageDate:new Date(s.last_message_date),messages:s.messages.map(n=>({id:n.id,conversationId:s.id,content:n.content,role:n.role,status:n.status,createdAt:new Date(n.created_at),toolCalls:b.mapPersistedToolCalls(n.tool_call_data)}))};return this.eventEmitter.emit("conversation:loaded",r),r}static mapPersistedToolCalls(t){if(!(!t||t.length===0))return t.map(s=>({id:String(s.id??""),type:s.type??"status_message",status:String(s.status??"unknown"),toolName:s.tool_name??"",toolDisplayName:s.tool_display_name,message:s.message,formSchema:s.form_schema,data:s.data,functionName:s.function_name,arguments:s.arguments}))}async getMessages(t){return(await this.getConversation(t)).messages||[]}async submitToolCallForm(t,s){await this.httpClient.post(`/api/sdk/v1/tool-calls/${t}/submit`,{formData:s})}async confirmToolCall(t){await this.httpClient.post(`/api/tool-calls/${t}/confirm/`)}async rejectToolCall(t){await this.httpClient.post(`/api/tool-calls/${t}/reject/`)}async submitFormCollector(t,s){return this.httpClient.post("/api/sdk/v1/forms/submit",{destination:t,values:s})}async submitFeedback(t,s){await this.httpClient.post(`/api/sdk/v1/messages/${t}/feedback`,{rating:s})}registerFunction(t,s,r){typeof t=="object"?this.functionRegistry.register(t):this.functionRegistry.register(t,s,r)}register(t){if(Array.isArray(t))for(const s of t)this.functionRegistry.register(s);else this.functionRegistry.register(t)}unregisterFunction(t){return this.functionRegistry.unregister(t)}getRegisteredFunctions(){return this.functionRegistry.getSchemas()}registerNavigationFunction(t,s){const r=s.map(o=>o.name),n=s.map(o=>`- "${o.name}": ${o.description}`).join(`
|
|
5
|
-
`);this.registerFunction("navigateToPage",async o=>{const a=o.page,c=s.find(l=>l.name===a);return c?(t(c.path),{success:!0,navigatedTo:c.path}):{success:!1,error:`Unknown page: ${a}`}},{description:`Navigate the user to a page in the application. Available pages:
|
|
6
|
-
${n}`,parameters:{type:"object",properties:{page:{type:"string",description:"The page to navigate to",enum:r}},required:["page"]}})}setContext(t,s){this.contextRegistry.set(t,s),this.notifyContextChanged()}removeContext(t){const s=this.contextRegistry.remove(t);return s&&this.notifyContextChanged(),s}addDynamicContext(t,s){this.contextRegistry.addDynamicProvider(t,s),this.notifyContextChanged()}removeDynamicContext(t){const s=this.contextRegistry.removeDynamicProvider(t);return s&&this.notifyContextChanged(),s}notifyContextChanged(){this.eventEmitter.emit("context:changed",this.contextRegistry.getSnapshot())}enableAutoPageContext(){this.addDynamicContext("browser-page",()=>{const t=typeof window<"u"?window.location.href:void 0,s=typeof document<"u"?document.title:void 0;return!t&&!s?null:{name:"Browser page",description:"Current page the user is viewing",data:{url:t,title:s}}})}getContextSnapshot(){return this.contextRegistry.getSnapshot()}on(t,s){this.eventEmitter.on(t,s)}off(t,s){this.eventEmitter.off(t,s)}once(t,s){this.eventEmitter.once(t,s)}waitFor(t,s){return this.eventEmitter.waitFor(t,s)}updateConfig(t){this.config={...this.config,...t},this.httpClient.updateConfig(t),t.debug!==void 0&&(t.debug?i.enable():i.disable())}destroy(){this.eventEmitter.removeAllListeners(),this.functionRegistry.clear(),this.contextRegistry.clear(),i.log("AgoClient destroyed")}};Object.defineProperty(exports,"AgoApiError",{enumerable:!0,get:function(){return h}});Object.defineProperty(exports,"AgoClient",{enumerable:!0,get:function(){return A}});Object.defineProperty(exports,"AgoError",{enumerable:!0,get:function(){return u}});Object.defineProperty(exports,"AgoFunctionError",{enumerable:!0,get:function(){return m}});Object.defineProperty(exports,"AgoNetworkError",{enumerable:!0,get:function(){return d}});Object.defineProperty(exports,"AgoStreamError",{enumerable:!0,get:function(){return g}});Object.defineProperty(exports,"ClientContextRegistry",{enumerable:!0,get:function(){return w}});Object.defineProperty(exports,"EventEmitter",{enumerable:!0,get:function(){return C}});Object.defineProperty(exports,"FunctionRegistry",{enumerable:!0,get:function(){return y}});Object.defineProperty(exports,"SSEHandler",{enumerable:!0,get:function(){return v}});Object.defineProperty(exports,"isStreamNetworkError",{enumerable:!0,get:function(){return x}});Object.defineProperty(exports,"logger",{enumerable:!0,get:function(){return i}});
|
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
import { s as _ } from "./AgoClient-BrYhSO5M.js";
|
|
2
|
-
function E(n, e) {
|
|
3
|
-
const l = e ? e.storage ?? (typeof localStorage < "u" ? localStorage : void 0) : void 0;
|
|
4
|
-
let r = n;
|
|
5
|
-
if (e && l) try {
|
|
6
|
-
const c = l.getItem(e.key);
|
|
7
|
-
c != null && (r = JSON.parse(c));
|
|
8
|
-
} catch {
|
|
9
|
-
}
|
|
10
|
-
const i = /* @__PURE__ */ new Set(), f = () => i.forEach((c) => c(r));
|
|
11
|
-
function m() {
|
|
12
|
-
if (e && l) try {
|
|
13
|
-
l.setItem(e.key, JSON.stringify(r));
|
|
14
|
-
} catch {
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
return {
|
|
18
|
-
get: () => r,
|
|
19
|
-
set: (c) => {
|
|
20
|
-
r = c, m(), f();
|
|
21
|
-
},
|
|
22
|
-
subscribe: (c) => (i.add(c), () => {
|
|
23
|
-
i.delete(c);
|
|
24
|
-
})
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
var q = /^[a-zA-Z0-9_-]{1,40}$/, O = (n) => n == null || n === "";
|
|
28
|
-
function F(n, e) {
|
|
29
|
-
const l = e[n.property];
|
|
30
|
-
if (O(l)) return !1;
|
|
31
|
-
if (Array.isArray(n.value)) return n.value.some((f) => String(l) === String(f));
|
|
32
|
-
if (!n.op) return String(l) === String(n.value);
|
|
33
|
-
const r = Number(l), i = Number(n.value);
|
|
34
|
-
if (Number.isNaN(r) || Number.isNaN(i)) return !1;
|
|
35
|
-
switch (n.op) {
|
|
36
|
-
case ">=":
|
|
37
|
-
return r >= i;
|
|
38
|
-
case "<=":
|
|
39
|
-
return r <= i;
|
|
40
|
-
case ">":
|
|
41
|
-
return r > i;
|
|
42
|
-
case "<":
|
|
43
|
-
return r < i;
|
|
44
|
-
default:
|
|
45
|
-
return _.warn(`Unknown requiredWhen op "${n.op}"; treating as not required.`), !1;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
function y(n, e) {
|
|
49
|
-
const l = n.properties ?? {}, r = /* @__PURE__ */ new Set();
|
|
50
|
-
for (const f of n.required ?? []) {
|
|
51
|
-
const m = l[f]?.requiredWhen;
|
|
52
|
-
(!m || F(m, e)) && r.add(f);
|
|
53
|
-
}
|
|
54
|
-
for (const [f, m] of Object.entries(l)) m.requiredWhen && F(m.requiredWhen, e) && r.add(f);
|
|
55
|
-
const i = [...r].filter((f) => O(e[f]));
|
|
56
|
-
return {
|
|
57
|
-
missing: i,
|
|
58
|
-
complete: i.length === 0
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
function P(n) {
|
|
62
|
-
const e = {};
|
|
63
|
-
for (const [l, r] of Object.entries(n.properties ?? {})) e[l] = {
|
|
64
|
-
type: r.type,
|
|
65
|
-
...r.description != null && { description: r.description },
|
|
66
|
-
...r.enum && { enum: r.enum },
|
|
67
|
-
...r.default !== void 0 && { default: r.default }
|
|
68
|
-
};
|
|
69
|
-
return {
|
|
70
|
-
type: "object",
|
|
71
|
-
properties: e,
|
|
72
|
-
required: []
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
function I(n) {
|
|
76
|
-
const { name: e, description: l, schema: r } = n;
|
|
77
|
-
if (!q.test(e)) throw new Error(`Invalid form collector name "${e}": must match ${q} (it becomes the update_/submit_ function names).`);
|
|
78
|
-
const i = typeof n.submit == "string" ? n.submit ? {
|
|
79
|
-
via: "client",
|
|
80
|
-
url: n.submit
|
|
81
|
-
} : !1 : n.submit ?? !1, f = r.properties ?? {}, m = (t) => {
|
|
82
|
-
const s = {};
|
|
83
|
-
for (const [a, o] of Object.entries(t)) {
|
|
84
|
-
const u = f[a];
|
|
85
|
-
if (u)
|
|
86
|
-
if (o == null) s[a] = o;
|
|
87
|
-
else if (u.type === "number" || u.type === "integer") {
|
|
88
|
-
const p = typeof o == "number" ? o : Number(o);
|
|
89
|
-
s[a] = Number.isNaN(p) ? o : p;
|
|
90
|
-
} else u.type === "boolean" ? s[a] = typeof o == "boolean" ? o : o === "true" ? !0 : o === "false" ? !1 : !!o : s[a] = o;
|
|
91
|
-
}
|
|
92
|
-
return s;
|
|
93
|
-
}, c = n.initialValues ?? {}, d = E({
|
|
94
|
-
values: c,
|
|
95
|
-
submitted: !1
|
|
96
|
-
}), v = (t) => {
|
|
97
|
-
const s = d.get(), a = {
|
|
98
|
-
...s,
|
|
99
|
-
values: {
|
|
100
|
-
...s.values,
|
|
101
|
-
...t
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
return d.set(a), a;
|
|
105
|
-
};
|
|
106
|
-
let h = null;
|
|
107
|
-
const N = async () => {
|
|
108
|
-
const { values: t } = d.get(), { complete: s, missing: a } = y(r, t);
|
|
109
|
-
if (!s) return {
|
|
110
|
-
ok: !1,
|
|
111
|
-
missing: a
|
|
112
|
-
};
|
|
113
|
-
if (!i) return {
|
|
114
|
-
ok: !1,
|
|
115
|
-
error: "No submit target configured for this form collector."
|
|
116
|
-
};
|
|
117
|
-
const o = t;
|
|
118
|
-
try {
|
|
119
|
-
let u;
|
|
120
|
-
if (i.via === "client") if ("handler" in i) u = await i.handler(o);
|
|
121
|
-
else {
|
|
122
|
-
const p = await fetch(i.url, {
|
|
123
|
-
method: "POST",
|
|
124
|
-
headers: { "Content-Type": "application/json" },
|
|
125
|
-
credentials: "include",
|
|
126
|
-
body: JSON.stringify(o)
|
|
127
|
-
});
|
|
128
|
-
if (!p.ok) return {
|
|
129
|
-
ok: !1,
|
|
130
|
-
error: `Submit failed: HTTP ${p.status}`
|
|
131
|
-
};
|
|
132
|
-
u = await p.json().catch(() => {
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
if (!h) return {
|
|
137
|
-
ok: !1,
|
|
138
|
-
error: "Backend submit requires install(client) (or useFormCollector) first."
|
|
139
|
-
};
|
|
140
|
-
u = await h.submitFormCollector(i.destination, o);
|
|
141
|
-
}
|
|
142
|
-
return d.set({
|
|
143
|
-
...d.get(),
|
|
144
|
-
submitted: !0
|
|
145
|
-
}), {
|
|
146
|
-
ok: !0,
|
|
147
|
-
result: u
|
|
148
|
-
};
|
|
149
|
-
} catch (u) {
|
|
150
|
-
const p = u instanceof Error ? u.message : "Submit failed";
|
|
151
|
-
return _.error(`FormCollector "${e}" submit failed:`, u), {
|
|
152
|
-
ok: !1,
|
|
153
|
-
error: p
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
}, $ = {
|
|
157
|
-
name: `update_${e}`,
|
|
158
|
-
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.`,
|
|
159
|
-
parameters: P(r),
|
|
160
|
-
handler: (t) => {
|
|
161
|
-
const s = v(m(t)), { missing: a } = y(r, s.values);
|
|
162
|
-
return {
|
|
163
|
-
ok: !0,
|
|
164
|
-
values: s.values,
|
|
165
|
-
missing: a
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
}, b = [$];
|
|
169
|
-
i && b.push({
|
|
170
|
-
name: `submit_${e}`,
|
|
171
|
-
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.`,
|
|
172
|
-
parameters: {
|
|
173
|
-
type: "object",
|
|
174
|
-
properties: {}
|
|
175
|
-
},
|
|
176
|
-
handler: () => N()
|
|
177
|
-
});
|
|
178
|
-
const T = "client__", S = i ? `submit_${e}` : null, x = (t) => {
|
|
179
|
-
const s = t.functionName ?? t.toolName;
|
|
180
|
-
if (s)
|
|
181
|
-
return s.startsWith(T) ? s.slice(8) : s;
|
|
182
|
-
}, w = (t) => {
|
|
183
|
-
let s = { ...c }, a = !1;
|
|
184
|
-
for (const o of t) {
|
|
185
|
-
const u = x(o);
|
|
186
|
-
u === $.name ? o.arguments && (s = {
|
|
187
|
-
...s,
|
|
188
|
-
...m(o.arguments)
|
|
189
|
-
}) : S && u === S && o.status?.toLowerCase() === "done" && (a = !0);
|
|
190
|
-
}
|
|
191
|
-
d.set({
|
|
192
|
-
values: s,
|
|
193
|
-
submitted: a
|
|
194
|
-
});
|
|
195
|
-
}, g = `form:${e}`, C = () => {
|
|
196
|
-
const { values: t, submitted: s } = d.get(), { missing: a, complete: o } = y(r, t), u = i ? ` When nothing is missing and the user confirms, call submit_${e}.` : "", p = s ? `The "${e}" form has been submitted.` : `You are currently collecting information from the user to fill the "${e}" form.`;
|
|
197
|
-
return {
|
|
198
|
-
name: `Form: ${e}`,
|
|
199
|
-
description: `${p} ${l} There are conditionnals questions/values to collected, you can find this information with the requiredWhen field in the form. The form schema is the following: ${JSON.stringify(r)}. Data collected so far: ${JSON.stringify(t)}. Call update_${e} with any fields the user provides; ask only for what is still missing.${u}`,
|
|
200
|
-
data: {
|
|
201
|
-
values: t,
|
|
202
|
-
missing: a,
|
|
203
|
-
complete: o,
|
|
204
|
-
submitted: s
|
|
205
|
-
}
|
|
206
|
-
};
|
|
207
|
-
}, k = (t) => {
|
|
208
|
-
w((t.messages ?? []).flatMap((s) => s.toolCalls ?? []));
|
|
209
|
-
};
|
|
210
|
-
return {
|
|
211
|
-
name: e,
|
|
212
|
-
store: d,
|
|
213
|
-
functions: b,
|
|
214
|
-
contextKey: g,
|
|
215
|
-
contextProvider: C,
|
|
216
|
-
install: (t) => {
|
|
217
|
-
h = t;
|
|
218
|
-
for (const a of b) t.register(a);
|
|
219
|
-
t.addDynamicContext(g, C);
|
|
220
|
-
const s = d.subscribe(() => t.notifyContextChanged());
|
|
221
|
-
return t.on("conversation:loaded", k), () => {
|
|
222
|
-
s();
|
|
223
|
-
for (const a of b) t.unregisterFunction(a.name);
|
|
224
|
-
t.removeDynamicContext(g), t.off("conversation:loaded", k), h === t && (h = null);
|
|
225
|
-
};
|
|
226
|
-
},
|
|
227
|
-
hydrate: w,
|
|
228
|
-
submit: N,
|
|
229
|
-
getValues: () => d.get().values,
|
|
230
|
-
setValues: (t) => {
|
|
231
|
-
v(m(t));
|
|
232
|
-
},
|
|
233
|
-
reset: () => {
|
|
234
|
-
d.set({
|
|
235
|
-
values: c,
|
|
236
|
-
submitted: !1
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
export {
|
|
242
|
-
y as n,
|
|
243
|
-
E as r,
|
|
244
|
-
I as t
|
|
245
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const O=require("./AgoClient-CPqPT5s6.cjs");function _(o,e){const l=e?e.storage??(typeof localStorage<"u"?localStorage:void 0):void 0;let r=o;if(e&&l)try{const c=l.getItem(e.key);c!=null&&(r=JSON.parse(c))}catch{}const i=new Set,f=()=>i.forEach(c=>c(r));function m(){if(e&&l)try{l.setItem(e.key,JSON.stringify(r))}catch{}}return{get:()=>r,set:c=>{r=c,m(),f()},subscribe:c=>(i.add(c),()=>{i.delete(c)})}}var q=/^[a-zA-Z0-9_-]{1,40}$/,P=o=>o==null||o==="";function F(o,e){const l=e[o.property];if(P(l))return!1;if(Array.isArray(o.value))return o.value.some(f=>String(l)===String(f));if(!o.op)return String(l)===String(o.value);const r=Number(l),i=Number(o.value);if(Number.isNaN(r)||Number.isNaN(i))return!1;switch(o.op){case">=":return r>=i;case"<=":return r<=i;case">":return r>i;case"<":return r<i;default:return O.logger.warn(`Unknown requiredWhen op "${o.op}"; treating as not required.`),!1}}function g(o,e){const l=o.properties??{},r=new Set;for(const f of o.required??[]){const m=l[f]?.requiredWhen;(!m||F(m,e))&&r.add(f)}for(const[f,m]of Object.entries(l))m.requiredWhen&&F(m.requiredWhen,e)&&r.add(f);const i=[...r].filter(f=>P(e[f]));return{missing:i,complete:i.length===0}}function E(o){const e={};for(const[l,r]of Object.entries(o.properties??{}))e[l]={type:r.type,...r.description!=null&&{description:r.description},...r.enum&&{enum:r.enum},...r.default!==void 0&&{default:r.default}};return{type:"object",properties:e,required:[]}}function W(o){const{name:e,description:l,schema:r}=o;if(!q.test(e))throw new Error(`Invalid form collector name "${e}": must match ${q} (it becomes the update_/submit_ function names).`);const i=typeof o.submit=="string"?o.submit?{via:"client",url:o.submit}:!1:o.submit??!1,f=r.properties??{},m=t=>{const n={};for(const[a,s]of Object.entries(t)){const u=f[a];if(u)if(s==null)n[a]=s;else if(u.type==="number"||u.type==="integer"){const b=typeof s=="number"?s:Number(s);n[a]=Number.isNaN(b)?s:b}else u.type==="boolean"?n[a]=typeof s=="boolean"?s:s==="true"?!0:s==="false"?!1:!!s:n[a]=s}return n},c=o.initialValues??{},d=_({values:c,submitted:!1}),v=t=>{const n=d.get(),a={...n,values:{...n.values,...t}};return d.set(a),a};let p=null;const N=async()=>{const{values:t}=d.get(),{complete:n,missing:a}=g(r,t);if(!n)return{ok:!1,missing:a};if(!i)return{ok:!1,error:"No submit target configured for this form collector."};const s=t;try{let u;if(i.via==="client")if("handler"in i)u=await i.handler(s);else{const b=await fetch(i.url,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(s)});if(!b.ok)return{ok:!1,error:`Submit failed: HTTP ${b.status}`};u=await b.json().catch(()=>{})}else{if(!p)return{ok:!1,error:"Backend submit requires install(client) (or useFormCollector) first."};u=await p.submitFormCollector(i.destination,s)}return d.set({...d.get(),submitted:!0}),{ok:!0,result:u}}catch(u){const b=u instanceof Error?u.message:"Submit failed";return O.logger.error(`FormCollector "${e}" submit failed:`,u),{ok:!1,error:b}}},S={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:E(r),handler:t=>{const n=v(m(t)),{missing:a}=g(r,n.values);return{ok:!0,values:n.values,missing:a}}},h=[S];i&&h.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:()=>N()});const T="client__",$=i?`submit_${e}`:null,j=t=>{const n=t.functionName??t.toolName;if(n)return n.startsWith(T)?n.slice(8):n},w=t=>{let n={...c},a=!1;for(const s of t){const u=j(s);u===S.name?s.arguments&&(n={...n,...m(s.arguments)}):$&&u===$&&s.status?.toLowerCase()==="done"&&(a=!0)}d.set({values:n,submitted:a})},y=`form:${e}`,C=()=>{const{values:t,submitted:n}=d.get(),{missing:a,complete:s}=g(r,t),u=i?` When nothing is missing and the user confirms, call submit_${e}.`:"",b=n?`The "${e}" form has been submitted.`:`You are currently collecting information from the user to fill the "${e}" form.`;return{name:`Form: ${e}`,description:`${b} ${l} There are conditionnals questions/values to collected, you can find this information with the requiredWhen field in the form. The form schema is the following: ${JSON.stringify(r)}. Data collected so far: ${JSON.stringify(t)}. Call update_${e} with any fields the user provides; ask only for what is still missing.${u}`,data:{values:t,missing:a,complete:s,submitted:n}}},k=t=>{w((t.messages??[]).flatMap(n=>n.toolCalls??[]))};return{name:e,store:d,functions:h,contextKey:y,contextProvider:C,install:t=>{p=t;for(const a of h)t.register(a);t.addDynamicContext(y,C);const n=d.subscribe(()=>t.notifyContextChanged());return t.on("conversation:loaded",k),()=>{n();for(const a of h)t.unregisterFunction(a.name);t.removeDynamicContext(y),t.off("conversation:loaded",k),p===t&&(p=null)}},hydrate:w,submit:N,getValues:()=>d.get().values,setValues:t=>{v(m(t))},reset:()=>{d.set({values:c,submitted:!1})}}}Object.defineProperty(exports,"createFormCollector",{enumerable:!0,get:function(){return W}});Object.defineProperty(exports,"createStore",{enumerable:!0,get:function(){return _}});Object.defineProperty(exports,"deriveFormStatus",{enumerable:!0,get:function(){return g}});
|