@useago/sdk 1.0.1 → 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 +1 -1
- package/dist/AgoClient-_fig8FoN.cjs +6 -0
- package/dist/{AgoClient-CZYNL25R.js → AgoClient-bQozE6-A.js} +172 -141
- package/dist/angular.cjs +1 -1
- package/dist/angular.d.cts +42 -1
- package/dist/angular.d.ts +42 -1
- package/dist/angular.js +1 -1
- package/dist/{createConversationSession-Bmqj2rSS.js → createConversationSession-BbK3ou1k.js} +1 -1
- package/dist/{createConversationSession-BLZvXMmM.cjs → createConversationSession-DJUFgOXy.cjs} +1 -1
- package/dist/{createFormCollector-Ca8wRrxc.cjs → createFormCollector-CdQjGAl_.cjs} +1 -1
- package/dist/{createFormCollector-Bk0DRhUf.js → createFormCollector-D-TpSd9x.js} +1 -1
- package/dist/devtools.d.cts +42 -1
- package/dist/devtools.d.ts +42 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +79 -4
- package/dist/index.d.ts +79 -4
- package/dist/index.js +60 -59
- package/dist/react.cjs +19 -19
- package/dist/react.d.cts +51 -7
- package/dist/react.d.ts +51 -7
- package/dist/react.js +1268 -1275
- package/dist/testing.d.cts +42 -1
- package/dist/testing.d.ts +42 -1
- package/dist/vue.cjs +1 -1
- package/dist/vue.d.cts +42 -1
- package/dist/vue.d.ts +42 -1
- package/dist/vue.js +1 -1
- package/dist/widget.cjs +4 -4
- package/dist/widget.d.cts +42 -1
- package/dist/widget.d.ts +42 -1
- package/dist/widget.js +194 -201
- package/package.json +2 -2
- package/dist/AgoClient-0x2Du_62.cjs +0 -6
package/dist/angular.d.cts
CHANGED
|
@@ -16,12 +16,26 @@ declare class AgoClient {
|
|
|
16
16
|
private contextRegistry;
|
|
17
17
|
private eventEmitter;
|
|
18
18
|
private config;
|
|
19
|
+
/** Conversations already warned about an empty reply (one warning each). */
|
|
20
|
+
private warnedEmptyConversations;
|
|
19
21
|
constructor(config: AgoConfig);
|
|
20
22
|
/**
|
|
21
23
|
* Send a message and receive a streaming response
|
|
22
24
|
*/
|
|
23
25
|
sendMessage(content: string, options?: SendMessageOptions): Promise<AgoMessage>;
|
|
24
26
|
private processSSEResponse;
|
|
27
|
+
/**
|
|
28
|
+
* Detect a reply that completed as DONE with no content and no activity —
|
|
29
|
+
* today's backend answers an unknown `agent` slug with an empty 200, which
|
|
30
|
+
* otherwise fails silently. Emits `message:empty` (always) and warns on the
|
|
31
|
+
* console once per conversation (unless `warnOnEmptyReply: false`).
|
|
32
|
+
*
|
|
33
|
+
* Deferred with setTimeout(0) so both land AFTER `sendMessage` resolves:
|
|
34
|
+
* `await client.sendMessage(...)` followed by `client.waitFor("message:empty")`
|
|
35
|
+
* must not race. TEMPORARY heuristic: remove once the backend returns an
|
|
36
|
+
* explicit error for unknown agents (see TODOS.md, backend issue).
|
|
37
|
+
*/
|
|
38
|
+
private maybeFlagEmptyReply;
|
|
25
39
|
private handleClientFunctionInvocation;
|
|
26
40
|
/**
|
|
27
41
|
* Get list of conversations
|
|
@@ -194,6 +208,11 @@ declare class AgoClient {
|
|
|
194
208
|
}): Promise<AgoClientEvents[K]>;
|
|
195
209
|
/**
|
|
196
210
|
* Update client configuration
|
|
211
|
+
*
|
|
212
|
+
* Validates the MERGED config before committing: omitting a key (or passing
|
|
213
|
+
* it as `undefined`, common with spread-built partials) keeps the current
|
|
214
|
+
* value; an explicit empty/non-string `baseUrl` throws `config_missing_base_url`
|
|
215
|
+
* and leaves the client unchanged (no half-updated state).
|
|
197
216
|
*/
|
|
198
217
|
updateConfig(config: Partial<AgoConfig>): void;
|
|
199
218
|
/**
|
|
@@ -229,8 +248,23 @@ export declare interface AgoClientEvents {
|
|
|
229
248
|
*/
|
|
230
249
|
"message:answer-complete": AgoMessage;
|
|
231
250
|
"message:complete": AgoMessage;
|
|
251
|
+
/**
|
|
252
|
+
* A reply finished as `DONE` with empty content and no tool calls, client
|
|
253
|
+
* functions, or follow-up replies — usually an unknown `agent` slug (the
|
|
254
|
+
* backend currently answers those with an empty 200). Fires after
|
|
255
|
+
* `message:complete` AND after `sendMessage` resolves, so subscribing right
|
|
256
|
+
* after `await sendMessage(...)` still catches it. `messageId` and
|
|
257
|
+
* `conversationId` are empty strings when the stream completed without any
|
|
258
|
+
* message data at all (e.g. a proxy stripped the SSE stream).
|
|
259
|
+
*/
|
|
260
|
+
"message:empty": {
|
|
261
|
+
conversationId: string;
|
|
262
|
+
messageId: string;
|
|
263
|
+
};
|
|
232
264
|
"message:error": {
|
|
233
265
|
error: string;
|
|
266
|
+
/** Stable error code (see configuration.md#error-codes) when the failure was an AgoError. */
|
|
267
|
+
code?: string;
|
|
234
268
|
conversationId?: string;
|
|
235
269
|
messageId?: string;
|
|
236
270
|
};
|
|
@@ -259,7 +293,7 @@ export declare interface AgoClientEvents {
|
|
|
259
293
|
export declare interface AgoConfig {
|
|
260
294
|
/** API base URL (e.g., https://YOUR-DOMAIN.useago.com) */
|
|
261
295
|
baseUrl: string;
|
|
262
|
-
/**
|
|
296
|
+
/** Per-visitor anonymous ID (X-User-Anon-Id header). Auto-generated if not provided. */
|
|
263
297
|
widgetId?: string;
|
|
264
298
|
/** Default agent (id or slug) for new conversations. Shorthand for `defaultAgentId`. */
|
|
265
299
|
agent?: string;
|
|
@@ -273,6 +307,13 @@ export declare interface AgoConfig {
|
|
|
273
307
|
userJwt?: string;
|
|
274
308
|
/** Enable debug logging */
|
|
275
309
|
debug?: boolean;
|
|
310
|
+
/**
|
|
311
|
+
* Warn on the console when a reply completes with empty content and no tool
|
|
312
|
+
* calls (the usual cause is an unknown `agent` slug, which the backend
|
|
313
|
+
* currently answers with an empty 200). Default `true`. The `message:empty`
|
|
314
|
+
* event fires regardless of this setting.
|
|
315
|
+
*/
|
|
316
|
+
warnOnEmptyReply?: boolean;
|
|
276
317
|
}
|
|
277
318
|
|
|
278
319
|
declare type AgoEventHandler<K extends AgoEventName> = (data: AgoClientEvents[K]) => void;
|
package/dist/angular.d.ts
CHANGED
|
@@ -16,12 +16,26 @@ declare class AgoClient {
|
|
|
16
16
|
private contextRegistry;
|
|
17
17
|
private eventEmitter;
|
|
18
18
|
private config;
|
|
19
|
+
/** Conversations already warned about an empty reply (one warning each). */
|
|
20
|
+
private warnedEmptyConversations;
|
|
19
21
|
constructor(config: AgoConfig);
|
|
20
22
|
/**
|
|
21
23
|
* Send a message and receive a streaming response
|
|
22
24
|
*/
|
|
23
25
|
sendMessage(content: string, options?: SendMessageOptions): Promise<AgoMessage>;
|
|
24
26
|
private processSSEResponse;
|
|
27
|
+
/**
|
|
28
|
+
* Detect a reply that completed as DONE with no content and no activity —
|
|
29
|
+
* today's backend answers an unknown `agent` slug with an empty 200, which
|
|
30
|
+
* otherwise fails silently. Emits `message:empty` (always) and warns on the
|
|
31
|
+
* console once per conversation (unless `warnOnEmptyReply: false`).
|
|
32
|
+
*
|
|
33
|
+
* Deferred with setTimeout(0) so both land AFTER `sendMessage` resolves:
|
|
34
|
+
* `await client.sendMessage(...)` followed by `client.waitFor("message:empty")`
|
|
35
|
+
* must not race. TEMPORARY heuristic: remove once the backend returns an
|
|
36
|
+
* explicit error for unknown agents (see TODOS.md, backend issue).
|
|
37
|
+
*/
|
|
38
|
+
private maybeFlagEmptyReply;
|
|
25
39
|
private handleClientFunctionInvocation;
|
|
26
40
|
/**
|
|
27
41
|
* Get list of conversations
|
|
@@ -194,6 +208,11 @@ declare class AgoClient {
|
|
|
194
208
|
}): Promise<AgoClientEvents[K]>;
|
|
195
209
|
/**
|
|
196
210
|
* Update client configuration
|
|
211
|
+
*
|
|
212
|
+
* Validates the MERGED config before committing: omitting a key (or passing
|
|
213
|
+
* it as `undefined`, common with spread-built partials) keeps the current
|
|
214
|
+
* value; an explicit empty/non-string `baseUrl` throws `config_missing_base_url`
|
|
215
|
+
* and leaves the client unchanged (no half-updated state).
|
|
197
216
|
*/
|
|
198
217
|
updateConfig(config: Partial<AgoConfig>): void;
|
|
199
218
|
/**
|
|
@@ -229,8 +248,23 @@ export declare interface AgoClientEvents {
|
|
|
229
248
|
*/
|
|
230
249
|
"message:answer-complete": AgoMessage;
|
|
231
250
|
"message:complete": AgoMessage;
|
|
251
|
+
/**
|
|
252
|
+
* A reply finished as `DONE` with empty content and no tool calls, client
|
|
253
|
+
* functions, or follow-up replies — usually an unknown `agent` slug (the
|
|
254
|
+
* backend currently answers those with an empty 200). Fires after
|
|
255
|
+
* `message:complete` AND after `sendMessage` resolves, so subscribing right
|
|
256
|
+
* after `await sendMessage(...)` still catches it. `messageId` and
|
|
257
|
+
* `conversationId` are empty strings when the stream completed without any
|
|
258
|
+
* message data at all (e.g. a proxy stripped the SSE stream).
|
|
259
|
+
*/
|
|
260
|
+
"message:empty": {
|
|
261
|
+
conversationId: string;
|
|
262
|
+
messageId: string;
|
|
263
|
+
};
|
|
232
264
|
"message:error": {
|
|
233
265
|
error: string;
|
|
266
|
+
/** Stable error code (see configuration.md#error-codes) when the failure was an AgoError. */
|
|
267
|
+
code?: string;
|
|
234
268
|
conversationId?: string;
|
|
235
269
|
messageId?: string;
|
|
236
270
|
};
|
|
@@ -259,7 +293,7 @@ export declare interface AgoClientEvents {
|
|
|
259
293
|
export declare interface AgoConfig {
|
|
260
294
|
/** API base URL (e.g., https://YOUR-DOMAIN.useago.com) */
|
|
261
295
|
baseUrl: string;
|
|
262
|
-
/**
|
|
296
|
+
/** Per-visitor anonymous ID (X-User-Anon-Id header). Auto-generated if not provided. */
|
|
263
297
|
widgetId?: string;
|
|
264
298
|
/** Default agent (id or slug) for new conversations. Shorthand for `defaultAgentId`. */
|
|
265
299
|
agent?: string;
|
|
@@ -273,6 +307,13 @@ export declare interface AgoConfig {
|
|
|
273
307
|
userJwt?: string;
|
|
274
308
|
/** Enable debug logging */
|
|
275
309
|
debug?: boolean;
|
|
310
|
+
/**
|
|
311
|
+
* Warn on the console when a reply completes with empty content and no tool
|
|
312
|
+
* calls (the usual cause is an unknown `agent` slug, which the backend
|
|
313
|
+
* currently answers with an empty 200). Default `true`. The `message:empty`
|
|
314
|
+
* event fires regardless of this setting.
|
|
315
|
+
*/
|
|
316
|
+
warnOnEmptyReply?: boolean;
|
|
276
317
|
}
|
|
277
318
|
|
|
278
319
|
declare type AgoEventHandler<K extends AgoEventName> = (data: AgoClientEvents[K]) => void;
|
package/dist/angular.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as o } from "./AgoClient-
|
|
1
|
+
import { t as o } from "./AgoClient-bQozE6-A.js";
|
|
2
2
|
var n = class {
|
|
3
3
|
constructor(t) {
|
|
4
4
|
this.client = new o(t), this.messages$ = this.fromEvent("message:complete"), this.chunks$ = this.fromEvent("message:chunk"), this.errors$ = this.fromEvent("message:error"), this.messageStart$ = this.fromEvent("message:start");
|
package/dist/{createConversationSession-Bmqj2rSS.js → createConversationSession-BbK3ou1k.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as d } from "./createFormCollector-
|
|
1
|
+
import { i as d } from "./createFormCollector-D-TpSd9x.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) => {
|
package/dist/{createConversationSession-BLZvXMmM.cjs → createConversationSession-DJUFgOXy.cjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
const d=require("./createFormCollector-
|
|
1
|
+
const d=require("./createFormCollector-CdQjGAl_.cjs");var f="ago_widget_id",g="ago_last_thread",y=7200*1e3;function v(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const r=Math.floor(Math.random()*16);return(e==="x"?r:r&3|8).toString(16)})}function _(e={}){const r=e.key??f,i=e.threadKey??g,u=e.ttlMs??y,l=e.storage??(typeof localStorage<"u"?localStorage:void 0);let n=e.widgetId??"";if(!n&&l)try{n=l.getItem(r)??""}catch{}if(n||(n=v()),l)try{l.setItem(r,n)}catch{}const o=d.createStore({value:null,lastMessageAt:null},{key:i,storage:l}),c=o.get();c.value!==null&&s(c.lastMessageAt)&&o.set({value:null,lastMessageAt:null});function s(t){return t===null?!0:Number.isFinite(u)?Date.now()-t>u:!1}return{widgetId:n,key:r,getLastActiveThread(){const{value:t,lastMessageAt:a}=o.get();return t===null||s(a)?null:t},setActiveThread(t,a){const x=a==null?null:a instanceof Date?a.getTime():a;o.set({value:t,lastMessageAt:x})},clear(){o.set({value:null,lastMessageAt:null})}}}Object.defineProperty(exports,"createConversationSession",{enumerable:!0,get:function(){return _}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const O=require("./AgoClient-
|
|
1
|
+
const O=require("./AgoClient-_fig8FoN.cjs");function _(o,e){const i=e?e.storage??(typeof localStorage<"u"?localStorage:void 0):void 0;let t=o;if(e&&i)try{const c=i.getItem(e.key);c!=null&&(t=JSON.parse(c))}catch{}const a=new Set,f=()=>a.forEach(c=>c(t));function d(){if(e&&i)try{i.setItem(e.key,JSON.stringify(t))}catch{}}return{get:()=>t,set:c=>{t=c,d(),f()},subscribe:c=>(a.add(c),()=>{a.delete(c)})}}var k=/^[a-zA-Z0-9_-]{1,40}$/,P=o=>o==null||o==="";function q(o,e){const i=e[o.property];if(P(i))return!1;if(Array.isArray(o.value))return o.value.some(f=>String(i)===String(f));if(!o.op)return String(i)===String(o.value);const t=Number(i),a=Number(o.value);if(Number.isNaN(t)||Number.isNaN(a))return!1;switch(o.op){case">=":return t>=a;case"<=":return t<=a;case">":return t>a;case"<":return t<a;default:return O.logger.warn(`Unknown requiredWhen op "${o.op}"; treating as not required.`),!1}}function p(o,e){const i=o.properties??{},t=new Set;for(const f of o.required??[]){const d=i[f]?.requiredWhen;(!d||q(d,e))&&t.add(f)}for(const[f,d]of Object.entries(i))d.requiredWhen&&q(d.requiredWhen,e)&&t.add(f);const a=[...t].filter(f=>P(e[f]));return{missing:a,complete:a.length===0}}function W(o){const e={};for(const[i,t]of Object.entries(o.properties??{}))e[i]={type:t.type,...t.description!=null&&{description:t.description},...t.enum&&{enum:t.enum},...t.default!==void 0&&{default:t.default}};return{type:"object",properties:e,required:[]}}function j(o){const{name:e,description:i,schema:t}=o;if(!k.test(e))throw new Error(`Invalid form collector name "${e}": must match ${k} (it becomes the update_/submit_ function names).`);const a=typeof o.submit=="string"?o.submit?{via:"client",url:o.submit}:!1:o.submit??!1,f=t.properties??{},d=r=>{const n={};for(const[u,s]of Object.entries(r)){const l=f[u];if(l)if(s==null)n[u]=s;else if(l.type==="number"||l.type==="integer"){const b=typeof s=="number"?s:Number(s);n[u]=Number.isNaN(b)?s:b}else l.type==="boolean"?n[u]=typeof s=="boolean"?s:s==="true"?!0:s==="false"?!1:!!s:n[u]=s}return n},c=o.initialValues??{},m=_({values:c,submitted:!1}),v=r=>{const n=m.get(),u={...n,values:{...n.values,...r}};return m.set(u),u};let h=null;const N=async()=>{const{values:r}=m.get(),{complete:n,missing:u}=p(t,r);if(!n)return{ok:!1,missing:u};if(!a)return{ok:!1,error:"No submit target configured for this form collector."};const s=r;try{let l;if(a.via==="client")if("handler"in a)l=await a.handler(s);else{const b=await fetch(a.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}`};l=await b.json().catch(()=>{})}else{if(!h)return{ok:!1,error:"Backend submit requires install(client) (or useFormCollector) first."};l=await h.submitFormCollector(a.destination,s)}return m.set({...m.get(),submitted:!0}),{ok:!0,result:l}}catch(l){const b=l instanceof Error?l.message:"Submit failed";return O.logger.error(`FormCollector "${e}" submit failed:`,l),{ok:!1,error:b}}},S={name:`update_${e}`,description:`Fill or update fields of the "${e}" form. ${i} 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:W(t),handler:r=>{const n=v(d(r)),{missing:u}=p(t,n.values);return{ok:!0,values:n.values,missing:u}}},g=[S];a&&g.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__",C=a?`submit_${e}`:null,E=r=>{const n=r.functionName??r.toolName;if(n)return n.startsWith(T)?n.slice(8):n},$=r=>{let n={...c},u=!1;for(const s of r){const l=E(s);l===S.name?s.arguments&&(n={...n,...d(s.arguments)}):C&&l===C&&s.status?.toLowerCase()==="done"&&(u=!0)}m.set({values:n,submitted:u})},y=`form:${e}`,w=()=>{const{values:r,submitted:n}=m.get(),{missing:u,complete:s}=p(t,r),l=a?` 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} ${i} 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(t)}. Data collected so far: ${JSON.stringify(r)}. Call update_${e} with any fields the user provides; ask only for what is still missing.${l}`,data:{values:r,missing:u,complete:s,submitted:n}}},F=r=>{$((r.messages??[]).flatMap(n=>n.toolCalls??[]))};return{name:e,store:m,functions:g,contextKey:y,contextProvider:w,install:r=>{h=r;for(const u of g)r.register(u);r.addDynamicContext(y,w);const n=m.subscribe(()=>r.notifyContextChanged());return r.on("conversation:loaded",F),()=>{n();for(const u of g)r.unregisterFunction(u.name);r.removeDynamicContext(y),r.off("conversation:loaded",F),h===r&&(h=null)}},hydrate:$,submit:N,getValues:()=>m.get().values,setValues:r=>{v(d(r))},reset:()=>{m.set({values:c,submitted:!1})},getStatus:()=>p(t,m.get().values)}}async function x(o,e){const i=await o.getFormCollector(e.name);return j({name:i.name,description:e.description??i.description,schema:e.schema??i.schema,submit:e.submit??i.submit,initialValues:e.initialValues})}Object.defineProperty(exports,"createFormCollector",{enumerable:!0,get:function(){return j}});Object.defineProperty(exports,"createStore",{enumerable:!0,get:function(){return _}});Object.defineProperty(exports,"deriveFormStatus",{enumerable:!0,get:function(){return p}});Object.defineProperty(exports,"loadFormCollector",{enumerable:!0,get:function(){return x}});
|
package/dist/devtools.d.cts
CHANGED
|
@@ -16,12 +16,26 @@ declare class AgoClient {
|
|
|
16
16
|
private contextRegistry;
|
|
17
17
|
private eventEmitter;
|
|
18
18
|
private config;
|
|
19
|
+
/** Conversations already warned about an empty reply (one warning each). */
|
|
20
|
+
private warnedEmptyConversations;
|
|
19
21
|
constructor(config: AgoConfig);
|
|
20
22
|
/**
|
|
21
23
|
* Send a message and receive a streaming response
|
|
22
24
|
*/
|
|
23
25
|
sendMessage(content: string, options?: SendMessageOptions): Promise<AgoMessage>;
|
|
24
26
|
private processSSEResponse;
|
|
27
|
+
/**
|
|
28
|
+
* Detect a reply that completed as DONE with no content and no activity —
|
|
29
|
+
* today's backend answers an unknown `agent` slug with an empty 200, which
|
|
30
|
+
* otherwise fails silently. Emits `message:empty` (always) and warns on the
|
|
31
|
+
* console once per conversation (unless `warnOnEmptyReply: false`).
|
|
32
|
+
*
|
|
33
|
+
* Deferred with setTimeout(0) so both land AFTER `sendMessage` resolves:
|
|
34
|
+
* `await client.sendMessage(...)` followed by `client.waitFor("message:empty")`
|
|
35
|
+
* must not race. TEMPORARY heuristic: remove once the backend returns an
|
|
36
|
+
* explicit error for unknown agents (see TODOS.md, backend issue).
|
|
37
|
+
*/
|
|
38
|
+
private maybeFlagEmptyReply;
|
|
25
39
|
private handleClientFunctionInvocation;
|
|
26
40
|
/**
|
|
27
41
|
* Get list of conversations
|
|
@@ -194,6 +208,11 @@ declare class AgoClient {
|
|
|
194
208
|
}): Promise<AgoClientEvents[K]>;
|
|
195
209
|
/**
|
|
196
210
|
* Update client configuration
|
|
211
|
+
*
|
|
212
|
+
* Validates the MERGED config before committing: omitting a key (or passing
|
|
213
|
+
* it as `undefined`, common with spread-built partials) keeps the current
|
|
214
|
+
* value; an explicit empty/non-string `baseUrl` throws `config_missing_base_url`
|
|
215
|
+
* and leaves the client unchanged (no half-updated state).
|
|
197
216
|
*/
|
|
198
217
|
updateConfig(config: Partial<AgoConfig>): void;
|
|
199
218
|
/**
|
|
@@ -229,8 +248,23 @@ declare interface AgoClientEvents {
|
|
|
229
248
|
*/
|
|
230
249
|
"message:answer-complete": AgoMessage;
|
|
231
250
|
"message:complete": AgoMessage;
|
|
251
|
+
/**
|
|
252
|
+
* A reply finished as `DONE` with empty content and no tool calls, client
|
|
253
|
+
* functions, or follow-up replies — usually an unknown `agent` slug (the
|
|
254
|
+
* backend currently answers those with an empty 200). Fires after
|
|
255
|
+
* `message:complete` AND after `sendMessage` resolves, so subscribing right
|
|
256
|
+
* after `await sendMessage(...)` still catches it. `messageId` and
|
|
257
|
+
* `conversationId` are empty strings when the stream completed without any
|
|
258
|
+
* message data at all (e.g. a proxy stripped the SSE stream).
|
|
259
|
+
*/
|
|
260
|
+
"message:empty": {
|
|
261
|
+
conversationId: string;
|
|
262
|
+
messageId: string;
|
|
263
|
+
};
|
|
232
264
|
"message:error": {
|
|
233
265
|
error: string;
|
|
266
|
+
/** Stable error code (see configuration.md#error-codes) when the failure was an AgoError. */
|
|
267
|
+
code?: string;
|
|
234
268
|
conversationId?: string;
|
|
235
269
|
messageId?: string;
|
|
236
270
|
};
|
|
@@ -259,7 +293,7 @@ declare interface AgoClientEvents {
|
|
|
259
293
|
declare interface AgoConfig {
|
|
260
294
|
/** API base URL (e.g., https://YOUR-DOMAIN.useago.com) */
|
|
261
295
|
baseUrl: string;
|
|
262
|
-
/**
|
|
296
|
+
/** Per-visitor anonymous ID (X-User-Anon-Id header). Auto-generated if not provided. */
|
|
263
297
|
widgetId?: string;
|
|
264
298
|
/** Default agent (id or slug) for new conversations. Shorthand for `defaultAgentId`. */
|
|
265
299
|
agent?: string;
|
|
@@ -273,6 +307,13 @@ declare interface AgoConfig {
|
|
|
273
307
|
userJwt?: string;
|
|
274
308
|
/** Enable debug logging */
|
|
275
309
|
debug?: boolean;
|
|
310
|
+
/**
|
|
311
|
+
* Warn on the console when a reply completes with empty content and no tool
|
|
312
|
+
* calls (the usual cause is an unknown `agent` slug, which the backend
|
|
313
|
+
* currently answers with an empty 200). Default `true`. The `message:empty`
|
|
314
|
+
* event fires regardless of this setting.
|
|
315
|
+
*/
|
|
316
|
+
warnOnEmptyReply?: boolean;
|
|
276
317
|
}
|
|
277
318
|
|
|
278
319
|
declare type AgoEventHandler<K extends AgoEventName> = (data: AgoClientEvents[K]) => void;
|
package/dist/devtools.d.ts
CHANGED
|
@@ -16,12 +16,26 @@ declare class AgoClient {
|
|
|
16
16
|
private contextRegistry;
|
|
17
17
|
private eventEmitter;
|
|
18
18
|
private config;
|
|
19
|
+
/** Conversations already warned about an empty reply (one warning each). */
|
|
20
|
+
private warnedEmptyConversations;
|
|
19
21
|
constructor(config: AgoConfig);
|
|
20
22
|
/**
|
|
21
23
|
* Send a message and receive a streaming response
|
|
22
24
|
*/
|
|
23
25
|
sendMessage(content: string, options?: SendMessageOptions): Promise<AgoMessage>;
|
|
24
26
|
private processSSEResponse;
|
|
27
|
+
/**
|
|
28
|
+
* Detect a reply that completed as DONE with no content and no activity —
|
|
29
|
+
* today's backend answers an unknown `agent` slug with an empty 200, which
|
|
30
|
+
* otherwise fails silently. Emits `message:empty` (always) and warns on the
|
|
31
|
+
* console once per conversation (unless `warnOnEmptyReply: false`).
|
|
32
|
+
*
|
|
33
|
+
* Deferred with setTimeout(0) so both land AFTER `sendMessage` resolves:
|
|
34
|
+
* `await client.sendMessage(...)` followed by `client.waitFor("message:empty")`
|
|
35
|
+
* must not race. TEMPORARY heuristic: remove once the backend returns an
|
|
36
|
+
* explicit error for unknown agents (see TODOS.md, backend issue).
|
|
37
|
+
*/
|
|
38
|
+
private maybeFlagEmptyReply;
|
|
25
39
|
private handleClientFunctionInvocation;
|
|
26
40
|
/**
|
|
27
41
|
* Get list of conversations
|
|
@@ -194,6 +208,11 @@ declare class AgoClient {
|
|
|
194
208
|
}): Promise<AgoClientEvents[K]>;
|
|
195
209
|
/**
|
|
196
210
|
* Update client configuration
|
|
211
|
+
*
|
|
212
|
+
* Validates the MERGED config before committing: omitting a key (or passing
|
|
213
|
+
* it as `undefined`, common with spread-built partials) keeps the current
|
|
214
|
+
* value; an explicit empty/non-string `baseUrl` throws `config_missing_base_url`
|
|
215
|
+
* and leaves the client unchanged (no half-updated state).
|
|
197
216
|
*/
|
|
198
217
|
updateConfig(config: Partial<AgoConfig>): void;
|
|
199
218
|
/**
|
|
@@ -229,8 +248,23 @@ declare interface AgoClientEvents {
|
|
|
229
248
|
*/
|
|
230
249
|
"message:answer-complete": AgoMessage;
|
|
231
250
|
"message:complete": AgoMessage;
|
|
251
|
+
/**
|
|
252
|
+
* A reply finished as `DONE` with empty content and no tool calls, client
|
|
253
|
+
* functions, or follow-up replies — usually an unknown `agent` slug (the
|
|
254
|
+
* backend currently answers those with an empty 200). Fires after
|
|
255
|
+
* `message:complete` AND after `sendMessage` resolves, so subscribing right
|
|
256
|
+
* after `await sendMessage(...)` still catches it. `messageId` and
|
|
257
|
+
* `conversationId` are empty strings when the stream completed without any
|
|
258
|
+
* message data at all (e.g. a proxy stripped the SSE stream).
|
|
259
|
+
*/
|
|
260
|
+
"message:empty": {
|
|
261
|
+
conversationId: string;
|
|
262
|
+
messageId: string;
|
|
263
|
+
};
|
|
232
264
|
"message:error": {
|
|
233
265
|
error: string;
|
|
266
|
+
/** Stable error code (see configuration.md#error-codes) when the failure was an AgoError. */
|
|
267
|
+
code?: string;
|
|
234
268
|
conversationId?: string;
|
|
235
269
|
messageId?: string;
|
|
236
270
|
};
|
|
@@ -259,7 +293,7 @@ declare interface AgoClientEvents {
|
|
|
259
293
|
declare interface AgoConfig {
|
|
260
294
|
/** API base URL (e.g., https://YOUR-DOMAIN.useago.com) */
|
|
261
295
|
baseUrl: string;
|
|
262
|
-
/**
|
|
296
|
+
/** Per-visitor anonymous ID (X-User-Anon-Id header). Auto-generated if not provided. */
|
|
263
297
|
widgetId?: string;
|
|
264
298
|
/** Default agent (id or slug) for new conversations. Shorthand for `defaultAgentId`. */
|
|
265
299
|
agent?: string;
|
|
@@ -273,6 +307,13 @@ declare interface AgoConfig {
|
|
|
273
307
|
userJwt?: string;
|
|
274
308
|
/** Enable debug logging */
|
|
275
309
|
debug?: boolean;
|
|
310
|
+
/**
|
|
311
|
+
* Warn on the console when a reply completes with empty content and no tool
|
|
312
|
+
* calls (the usual cause is an unknown `agent` slug, which the backend
|
|
313
|
+
* currently answers with an empty 200). Default `true`. The `message:empty`
|
|
314
|
+
* event fires regardless of this setting.
|
|
315
|
+
*/
|
|
316
|
+
warnOnEmptyReply?: boolean;
|
|
276
317
|
}
|
|
277
318
|
|
|
278
319
|
declare type AgoEventHandler<K extends AgoEventName> = (data: AgoClientEvents[K]) => void;
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./AgoClient-_fig8FoN.cjs"),m=require("./createFormCollector-CdQjGAl_.cjs"),p=require("./createConversationSession-DJUFgOXy.cjs"),w=require("./createMockClient-zHQ0cjUH.cjs");require("./testing.cjs");const g=require("./functions-DsmzgHjC.cjs");function h(e){return e}function E(e,o){return e.on("message:complete",o),()=>e.off("message:complete",o)}function S(e,o){return e.on("message:chunk",o),()=>e.off("message:chunk",o)}function y(e,o){return e.on("message:start",o),()=>e.off("message:start",o)}function v(e,o){return e.on("message:error",o),()=>e.off("message:error",o)}function b(e,o){return e.on("toolCall:received",o),()=>e.off("toolCall:received",o)}function F(e,o){return e.on("function:invoke",o),()=>e.off("function:invoke",o)}async function*M(e,o,l){const a=[];let r=null,s=!1;const c=i=>{a.push(i),r?.()},f=i=>c({type:"start",data:i}),t=i=>c({type:"chunk",data:i}),u=i=>{c({type:"complete",data:i}),s=!0,r?.()},d=i=>{c({type:"error",data:i}),s=!0,r?.()},C=i=>c({type:"toolCall",data:i});e.on("message:start",f),e.on("message:chunk",t),e.on("message:complete",u),e.on("message:error",d),e.on("toolCall:received",C),e.sendMessage(o,l).catch(()=>{s=!0,r?.()});try{for(;!s||a.length>0;)a.length>0?yield a.shift():(await new Promise(i=>{r=i}),r=null)}finally{e.off("message:start",f),e.off("message:chunk",t),e.off("message:complete",u),e.off("message:error",d),e.off("toolCall:received",C)}}function A(e){let o,l,a,r,s,c;if(typeof window<"u"&&window.AGO){const t=window.AGO;o=t.basepath,l=t.widgetId,a=t.agent||t.defaultAgent,r=t.permission,s=t.email,c=t.jwt}if(typeof document<"u"){const t=u=>document.querySelector(`meta[name="${u}"]`)?.getAttribute("content")||void 0;o=o||t("ago-base-url"),l=l||t("ago-widget-id"),a=a||t("ago-agent")||t("ago-agent-id"),r=r||t("ago-permission"),s=s||t("ago-user-email")}if(typeof document<"u"){const t=[document.body,...Array.from(document.querySelectorAll("script[data-ago-base-url]"))].filter(Boolean);for(const u of t)u&&(o=o||u.getAttribute("data-ago-base-url")||void 0,l=l||u.getAttribute("data-ago-widget-id")||void 0,a=a||u.getAttribute("data-ago-agent")||u.getAttribute("data-ago-agent-id")||void 0,r=r||u.getAttribute("data-ago-permission")||void 0,s=s||u.getAttribute("data-ago-user-email")||void 0)}o=e?.baseUrl||o,l=e?.widgetId||l,a=e?.agent||e?.defaultAgentId||a,r=e?.permission||r,s=e?.userEmail||s,c=e?.userJwt||c;const f=e?.debug;return o?{baseUrl:o,widgetId:l,agent:a,permission:r,userEmail:s,userJwt:c,debug:f}:null}function k(e){const o=A(e);if(!o)throw new n.AgoError('createAgo(): could not detect AGO configuration. Set window.AGO, add <meta name="ago-base-url">, or pass { baseUrl } explicitly.',"config_missing_base_url");return new n.AgoClient(o)}function q(e,o){return{...e,handler:o}}exports.AgoApiError=n.AgoApiError;exports.AgoClient=n.AgoClient;exports.AgoError=n.AgoError;exports.AgoFunctionError=n.AgoFunctionError;exports.AgoNetworkError=n.AgoNetworkError;exports.AgoStreamError=n.AgoStreamError;exports.ClientContextRegistry=n.ClientContextRegistry;exports.EventEmitter=n.EventEmitter;exports.FunctionRegistry=n.FunctionRegistry;exports.SSEHandler=n.SSEHandler;exports.autoDetectConfig=A;exports.copyToClipboard=g.copyToClipboard;exports.createAgo=k;exports.createConversationSession=p.createConversationSession;exports.createFormCollector=m.createFormCollector;exports.createMessageStream=M;exports.createMockClient=w.createMockClient;exports.createStore=m.createStore;exports.defineFunction=h;exports.deriveFormStatus=m.deriveFormStatus;exports.getLocalStorage=g.getLocalStorage;exports.getUserLocation=g.getUserLocation;exports.highlightElement=g.highlightElement;exports.isStreamNetworkError=n.isStreamNetworkError;exports.loadFormCollector=m.loadFormCollector;exports.logger=n.logger;exports.onFunctionInvoke=F;exports.onMessage=E;exports.onMessageChunk=S;exports.onMessageError=v;exports.onMessageStart=y;exports.onToolCall=b;exports.openUrl=g.openUrl;exports.scrollToElement=g.scrollToElement;exports.setLocalStorage=g.setLocalStorage;exports.setTheme=g.setTheme;exports.showConfirmDialog=g.showConfirmDialog;exports.showNotification=g.showNotification;exports.showToast=g.showToast;exports.submitForm=g.submitForm;exports.trackEvent=g.trackEvent;exports.validateConfig=n.validateConfig;exports.withHandler=q;
|
package/dist/index.d.cts
CHANGED
|
@@ -27,12 +27,26 @@ export declare class AgoClient {
|
|
|
27
27
|
private contextRegistry;
|
|
28
28
|
private eventEmitter;
|
|
29
29
|
private config;
|
|
30
|
+
/** Conversations already warned about an empty reply (one warning each). */
|
|
31
|
+
private warnedEmptyConversations;
|
|
30
32
|
constructor(config: AgoConfig);
|
|
31
33
|
/**
|
|
32
34
|
* Send a message and receive a streaming response
|
|
33
35
|
*/
|
|
34
36
|
sendMessage(content: string, options?: SendMessageOptions): Promise<AgoMessage>;
|
|
35
37
|
private processSSEResponse;
|
|
38
|
+
/**
|
|
39
|
+
* Detect a reply that completed as DONE with no content and no activity —
|
|
40
|
+
* today's backend answers an unknown `agent` slug with an empty 200, which
|
|
41
|
+
* otherwise fails silently. Emits `message:empty` (always) and warns on the
|
|
42
|
+
* console once per conversation (unless `warnOnEmptyReply: false`).
|
|
43
|
+
*
|
|
44
|
+
* Deferred with setTimeout(0) so both land AFTER `sendMessage` resolves:
|
|
45
|
+
* `await client.sendMessage(...)` followed by `client.waitFor("message:empty")`
|
|
46
|
+
* must not race. TEMPORARY heuristic: remove once the backend returns an
|
|
47
|
+
* explicit error for unknown agents (see TODOS.md, backend issue).
|
|
48
|
+
*/
|
|
49
|
+
private maybeFlagEmptyReply;
|
|
36
50
|
private handleClientFunctionInvocation;
|
|
37
51
|
/**
|
|
38
52
|
* Get list of conversations
|
|
@@ -205,6 +219,11 @@ export declare class AgoClient {
|
|
|
205
219
|
}): Promise<AgoClientEvents[K]>;
|
|
206
220
|
/**
|
|
207
221
|
* Update client configuration
|
|
222
|
+
*
|
|
223
|
+
* Validates the MERGED config before committing: omitting a key (or passing
|
|
224
|
+
* it as `undefined`, common with spread-built partials) keeps the current
|
|
225
|
+
* value; an explicit empty/non-string `baseUrl` throws `config_missing_base_url`
|
|
226
|
+
* and leaves the client unchanged (no half-updated state).
|
|
208
227
|
*/
|
|
209
228
|
updateConfig(config: Partial<AgoConfig>): void;
|
|
210
229
|
/**
|
|
@@ -240,8 +259,23 @@ export declare interface AgoClientEvents {
|
|
|
240
259
|
*/
|
|
241
260
|
"message:answer-complete": AgoMessage;
|
|
242
261
|
"message:complete": AgoMessage;
|
|
262
|
+
/**
|
|
263
|
+
* A reply finished as `DONE` with empty content and no tool calls, client
|
|
264
|
+
* functions, or follow-up replies — usually an unknown `agent` slug (the
|
|
265
|
+
* backend currently answers those with an empty 200). Fires after
|
|
266
|
+
* `message:complete` AND after `sendMessage` resolves, so subscribing right
|
|
267
|
+
* after `await sendMessage(...)` still catches it. `messageId` and
|
|
268
|
+
* `conversationId` are empty strings when the stream completed without any
|
|
269
|
+
* message data at all (e.g. a proxy stripped the SSE stream).
|
|
270
|
+
*/
|
|
271
|
+
"message:empty": {
|
|
272
|
+
conversationId: string;
|
|
273
|
+
messageId: string;
|
|
274
|
+
};
|
|
243
275
|
"message:error": {
|
|
244
276
|
error: string;
|
|
277
|
+
/** Stable error code (see configuration.md#error-codes) when the failure was an AgoError. */
|
|
278
|
+
code?: string;
|
|
245
279
|
conversationId?: string;
|
|
246
280
|
messageId?: string;
|
|
247
281
|
};
|
|
@@ -270,7 +304,7 @@ export declare interface AgoClientEvents {
|
|
|
270
304
|
export declare interface AgoConfig {
|
|
271
305
|
/** API base URL (e.g., https://YOUR-DOMAIN.useago.com) */
|
|
272
306
|
baseUrl: string;
|
|
273
|
-
/**
|
|
307
|
+
/** Per-visitor anonymous ID (X-User-Anon-Id header). Auto-generated if not provided. */
|
|
274
308
|
widgetId?: string;
|
|
275
309
|
/** Default agent (id or slug) for new conversations. Shorthand for `defaultAgentId`. */
|
|
276
310
|
agent?: string;
|
|
@@ -284,10 +318,23 @@ export declare interface AgoConfig {
|
|
|
284
318
|
userJwt?: string;
|
|
285
319
|
/** Enable debug logging */
|
|
286
320
|
debug?: boolean;
|
|
321
|
+
/**
|
|
322
|
+
* Warn on the console when a reply completes with empty content and no tool
|
|
323
|
+
* calls (the usual cause is an unknown `agent` slug, which the backend
|
|
324
|
+
* currently answers with an empty 200). Default `true`. The `message:empty`
|
|
325
|
+
* event fires regardless of this setting.
|
|
326
|
+
*/
|
|
327
|
+
warnOnEmptyReply?: boolean;
|
|
287
328
|
}
|
|
288
329
|
|
|
289
330
|
/**
|
|
290
331
|
* Base error class for AGO SDK
|
|
332
|
+
*
|
|
333
|
+
* Error convention: every throw carries a stable `code` (snake_case), a
|
|
334
|
+
* one-line fix hint in the message, and a doc URL/anchor when one exists.
|
|
335
|
+
* `code` is the compatibility surface — match on it, never on message text,
|
|
336
|
+
* which may be reworded in any release. The code registry lives in
|
|
337
|
+
* docs/general/configuration.md#error-codes.
|
|
291
338
|
*/
|
|
292
339
|
export declare class AgoError extends Error {
|
|
293
340
|
code: string;
|
|
@@ -343,9 +390,14 @@ export declare interface AgoSource {
|
|
|
343
390
|
|
|
344
391
|
/**
|
|
345
392
|
* SSE stream error
|
|
393
|
+
*
|
|
394
|
+
* `code` distinguishes failure classes without message parsing:
|
|
395
|
+
* - `stream_no_body`: the response had no streamable body (usually a
|
|
396
|
+
* misconfigured endpoint or a proxy stripping the SSE stream)
|
|
397
|
+
* - `stream_error` (default): the stream failed mid-flight
|
|
346
398
|
*/
|
|
347
399
|
export declare class AgoStreamError extends AgoError {
|
|
348
|
-
constructor(message: string);
|
|
400
|
+
constructor(message: string, code?: string);
|
|
349
401
|
}
|
|
350
402
|
|
|
351
403
|
/**
|
|
@@ -623,8 +675,8 @@ export declare const copyToClipboard: ClientFunctionDefinition;
|
|
|
623
675
|
export declare function createAgo(overrides?: Partial<AgoConfig>): AgoClient;
|
|
624
676
|
|
|
625
677
|
/**
|
|
626
|
-
* Identify a returning visitor with a single, stable
|
|
627
|
-
*
|
|
678
|
+
* Identify a returning visitor with a single, stable anon id (one id, generated
|
|
679
|
+
* once and reused forever) and resume their last active thread.
|
|
628
680
|
*
|
|
629
681
|
* There is no per-agent conversation id: the widget id is the identity, and the last
|
|
630
682
|
* active thread (its id + the time of its last message) is cached locally so resuming
|
|
@@ -1361,6 +1413,29 @@ export declare type ToolCallType = "form" | "confirmation_input" | "status_messa
|
|
|
1361
1413
|
*/
|
|
1362
1414
|
export declare const trackEvent: ClientFunctionDefinition;
|
|
1363
1415
|
|
|
1416
|
+
/**
|
|
1417
|
+
* Validate an AgoConfig at the public API boundary.
|
|
1418
|
+
*
|
|
1419
|
+
* Rules:
|
|
1420
|
+
* - nullish / non-object config, or a missing/empty/non-string `baseUrl`,
|
|
1421
|
+
* throws `AgoError` with the stable code `config_missing_base_url`.
|
|
1422
|
+
* - Values starting with `/` are allowed (same-origin proxy paths like
|
|
1423
|
+
* `/ago-proxy` are a supported embed pattern).
|
|
1424
|
+
* - Values with any `scheme://` are allowed.
|
|
1425
|
+
* - Anything else (no scheme, no leading slash, e.g. "ago.api.useago.com")
|
|
1426
|
+
* warns once per process — it usually means a forgotten protocol. It does
|
|
1427
|
+
* not throw: the request fails at send time with a runtime-specific error
|
|
1428
|
+
* (Node: URL parse error; browser: relative fetch), and a hard throw here
|
|
1429
|
+
* could break embeds we cannot foresee.
|
|
1430
|
+
*
|
|
1431
|
+
* The warning never echoes the configured value: misconfigured baseUrls
|
|
1432
|
+
* sometimes carry credentials (e.g. `https://user:token@host`).
|
|
1433
|
+
*
|
|
1434
|
+
* @param context Prefix for the error message, naming the API the developer
|
|
1435
|
+
* actually called (e.g. "AgoClient", "createAgo()").
|
|
1436
|
+
*/
|
|
1437
|
+
export declare function validateConfig(config: unknown, context?: string): asserts config is AgoConfig;
|
|
1438
|
+
|
|
1364
1439
|
/**
|
|
1365
1440
|
* Attach a handler to a pre-built function definition.
|
|
1366
1441
|
*
|