@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.
@@ -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
- /** Widget ID (X-Widget-Id header). Auto-generated if not provided. */
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/testing.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
- /** Widget ID (X-Widget-Id header). Auto-generated if not provided. */
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/vue.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P=require("./rolldown-runtime-CaekUdDJ.cjs"),p=require("./AgoClient-0x2Du_62.cjs");let t=require("vue");var I=Symbol("ago-client"),y={install(o,n){const e=new p.AgoClient(n);o.provide(I,e)}};function g(o){if(o)return new p.AgoClient(o);const n=(0,t.inject)(I);if(!n)throw new Error("useAgo(): no AgoClient found. Either pass config or install AgoPlugin.");return n}function E(o={}){const n=o.client??g(),e=(0,t.ref)([]),s=(0,t.ref)(o.conversationId),i=(0,t.ref)(!1),r=(0,t.ref)(null),c=a=>{s.value||(s.value=a.conversationId)},f=a=>{const u=e.value.findIndex(v=>v.id===a.messageId);u>=0&&(e.value[u]={...e.value[u],content:e.value[u].content+a.content})},m=a=>{const u=e.value.findIndex(v=>v.id===a.id);u>=0?e.value[u]=a:e.value.push(a),i.value=!1},C=a=>{r.value=new Error(a.error),i.value=!1};(0,t.onMounted)(()=>{n.on("message:start",c),n.on("message:chunk",f),n.on("message:complete",m),n.on("message:error",C)}),(0,t.onUnmounted)(()=>{n.off("message:start",c),n.off("message:chunk",f),n.off("message:complete",m),n.off("message:error",C)});async function d(a,u){i.value=!0,r.value=null;const v={id:`temp-${Date.now()}`,conversationId:s.value||"",content:a,role:"user",status:"DONE",createdAt:new Date},L={id:`temp-assistant-${Date.now()}`,conversationId:s.value||"",content:"",role:"assistant",status:"IN_PROGRESS",createdAt:new Date};e.value.push(v,L);try{const l=await n.sendMessage(a,{conversationId:s.value,files:u});l.conversationId&&!s.value&&(s.value=l.conversationId),e.value=e.value.filter(w=>!w.id.startsWith("temp-"));const A={...v,id:v.id.replace("temp-","user-"),conversationId:l.conversationId};return e.value.some(w=>w.id===l.id)?e.value.push(A):e.value.push(A,l),l}catch(l){return r.value=l instanceof Error?l:new Error("Failed to send"),i.value=!1,e.value=e.value.filter(A=>!A.id.startsWith("temp-")),null}}function h(){e.value=[],s.value=void 0,r.value=null}return{messages:e,isLoading:i,error:r,conversationId:s,sendMessage:d,clearMessages:h}}function M(o={}){const n=o.client??g(),e=o.autoLoad??!0,s=(0,t.ref)([]),i=(0,t.ref)(null),r=(0,t.ref)(!1),c=(0,t.ref)(null);async function f(){r.value=!0,c.value=null;try{s.value=await n.getConversations()}catch(d){c.value=d instanceof Error?d:new Error("Failed to load conversations")}finally{r.value=!1}}async function m(d){r.value=!0,c.value=null;try{i.value=await n.getConversation(d)}catch(h){c.value=h instanceof Error?h:new Error("Failed to load conversation")}finally{r.value=!1}}function C(){i.value=null}return(0,t.onMounted)(()=>{e&&f()}),{conversations:s,currentConversation:i,isLoading:r,error:c,selectConversation:m,startNewConversation:C,refreshConversations:f}}function N(o={}){const n=E({client:o.client,conversationId:o.conversationId}),e=M({client:o.client,autoLoad:o.autoLoad}),s=(0,t.computed)(()=>n.error.value||e.error.value);return{messages:n.messages,isLoading:n.isLoading,error:s,sendMessage:n.sendMessage,clearMessages:n.clearMessages,conversationId:n.conversationId,conversations:e.conversations,currentConversation:e.currentConversation,isConversationsLoading:e.isLoading,selectConversation:e.selectConversation,startNewConversation:e.startNewConversation,refreshConversations:e.refreshConversations}}function F(o,n){const e=g();(0,t.onMounted)(()=>{e.registerFunction(o,n.handler,{description:n.description,parameters:n.parameters})}),(0,t.onUnmounted)(()=>{e.unregisterFunction(o)})}function S(o,n){const e=g();(0,t.onMounted)(()=>{e.registerNavigationFunction(o,n)}),(0,t.onUnmounted)(()=>{e.unregisterFunction("navigateToPage")})}function _(o,n){const e=g();(0,t.onMounted)(()=>{e.on(o,n)}),(0,t.onUnmounted)(()=>{e.off(o,n)})}function D(o){const n=(0,t.shallowRef)(o.get());return(0,t.onScopeDispose)(o.subscribe(e=>{n.value=e})),n}exports.AGO_CLIENT_KEY=I;exports.AgoPlugin=y;exports.useAgo=g;exports.useAgoEvents=_;exports.useAgoFunction=F;exports.useAgoNavigation=S;exports.useAgoStore=D;exports.useChat=N;exports.useConversation=M;exports.useMessages=E;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P=require("./rolldown-runtime-CaekUdDJ.cjs"),p=require("./AgoClient-_fig8FoN.cjs");let t=require("vue");var I=Symbol("ago-client"),y={install(o,n){const e=new p.AgoClient(n);o.provide(I,e)}};function g(o){if(o)return new p.AgoClient(o);const n=(0,t.inject)(I);if(!n)throw new Error("useAgo(): no AgoClient found. Either pass config or install AgoPlugin.");return n}function E(o={}){const n=o.client??g(),e=(0,t.ref)([]),s=(0,t.ref)(o.conversationId),i=(0,t.ref)(!1),r=(0,t.ref)(null),c=a=>{s.value||(s.value=a.conversationId)},f=a=>{const u=e.value.findIndex(v=>v.id===a.messageId);u>=0&&(e.value[u]={...e.value[u],content:e.value[u].content+a.content})},m=a=>{const u=e.value.findIndex(v=>v.id===a.id);u>=0?e.value[u]=a:e.value.push(a),i.value=!1},C=a=>{r.value=new Error(a.error),i.value=!1};(0,t.onMounted)(()=>{n.on("message:start",c),n.on("message:chunk",f),n.on("message:complete",m),n.on("message:error",C)}),(0,t.onUnmounted)(()=>{n.off("message:start",c),n.off("message:chunk",f),n.off("message:complete",m),n.off("message:error",C)});async function d(a,u){i.value=!0,r.value=null;const v={id:`temp-${Date.now()}`,conversationId:s.value||"",content:a,role:"user",status:"DONE",createdAt:new Date},L={id:`temp-assistant-${Date.now()}`,conversationId:s.value||"",content:"",role:"assistant",status:"IN_PROGRESS",createdAt:new Date};e.value.push(v,L);try{const l=await n.sendMessage(a,{conversationId:s.value,files:u});l.conversationId&&!s.value&&(s.value=l.conversationId),e.value=e.value.filter(w=>!w.id.startsWith("temp-"));const A={...v,id:v.id.replace("temp-","user-"),conversationId:l.conversationId};return e.value.some(w=>w.id===l.id)?e.value.push(A):e.value.push(A,l),l}catch(l){return r.value=l instanceof Error?l:new Error("Failed to send"),i.value=!1,e.value=e.value.filter(A=>!A.id.startsWith("temp-")),null}}function h(){e.value=[],s.value=void 0,r.value=null}return{messages:e,isLoading:i,error:r,conversationId:s,sendMessage:d,clearMessages:h}}function M(o={}){const n=o.client??g(),e=o.autoLoad??!0,s=(0,t.ref)([]),i=(0,t.ref)(null),r=(0,t.ref)(!1),c=(0,t.ref)(null);async function f(){r.value=!0,c.value=null;try{s.value=await n.getConversations()}catch(d){c.value=d instanceof Error?d:new Error("Failed to load conversations")}finally{r.value=!1}}async function m(d){r.value=!0,c.value=null;try{i.value=await n.getConversation(d)}catch(h){c.value=h instanceof Error?h:new Error("Failed to load conversation")}finally{r.value=!1}}function C(){i.value=null}return(0,t.onMounted)(()=>{e&&f()}),{conversations:s,currentConversation:i,isLoading:r,error:c,selectConversation:m,startNewConversation:C,refreshConversations:f}}function N(o={}){const n=E({client:o.client,conversationId:o.conversationId}),e=M({client:o.client,autoLoad:o.autoLoad}),s=(0,t.computed)(()=>n.error.value||e.error.value);return{messages:n.messages,isLoading:n.isLoading,error:s,sendMessage:n.sendMessage,clearMessages:n.clearMessages,conversationId:n.conversationId,conversations:e.conversations,currentConversation:e.currentConversation,isConversationsLoading:e.isLoading,selectConversation:e.selectConversation,startNewConversation:e.startNewConversation,refreshConversations:e.refreshConversations}}function F(o,n){const e=g();(0,t.onMounted)(()=>{e.registerFunction(o,n.handler,{description:n.description,parameters:n.parameters})}),(0,t.onUnmounted)(()=>{e.unregisterFunction(o)})}function S(o,n){const e=g();(0,t.onMounted)(()=>{e.registerNavigationFunction(o,n)}),(0,t.onUnmounted)(()=>{e.unregisterFunction("navigateToPage")})}function _(o,n){const e=g();(0,t.onMounted)(()=>{e.on(o,n)}),(0,t.onUnmounted)(()=>{e.off(o,n)})}function D(o){const n=(0,t.shallowRef)(o.get());return(0,t.onScopeDispose)(o.subscribe(e=>{n.value=e})),n}exports.AGO_CLIENT_KEY=I;exports.AgoPlugin=y;exports.useAgo=g;exports.useAgoEvents=_;exports.useAgoFunction=F;exports.useAgoNavigation=S;exports.useAgoStore=D;exports.useChat=N;exports.useConversation=M;exports.useMessages=E;
package/dist/vue.d.cts CHANGED
@@ -24,12 +24,26 @@ declare class AgoClient {
24
24
  private contextRegistry;
25
25
  private eventEmitter;
26
26
  private config;
27
+ /** Conversations already warned about an empty reply (one warning each). */
28
+ private warnedEmptyConversations;
27
29
  constructor(config: AgoConfig);
28
30
  /**
29
31
  * Send a message and receive a streaming response
30
32
  */
31
33
  sendMessage(content: string, options?: SendMessageOptions): Promise<AgoMessage>;
32
34
  private processSSEResponse;
35
+ /**
36
+ * Detect a reply that completed as DONE with no content and no activity —
37
+ * today's backend answers an unknown `agent` slug with an empty 200, which
38
+ * otherwise fails silently. Emits `message:empty` (always) and warns on the
39
+ * console once per conversation (unless `warnOnEmptyReply: false`).
40
+ *
41
+ * Deferred with setTimeout(0) so both land AFTER `sendMessage` resolves:
42
+ * `await client.sendMessage(...)` followed by `client.waitFor("message:empty")`
43
+ * must not race. TEMPORARY heuristic: remove once the backend returns an
44
+ * explicit error for unknown agents (see TODOS.md, backend issue).
45
+ */
46
+ private maybeFlagEmptyReply;
33
47
  private handleClientFunctionInvocation;
34
48
  /**
35
49
  * Get list of conversations
@@ -202,6 +216,11 @@ declare class AgoClient {
202
216
  }): Promise<AgoClientEvents[K]>;
203
217
  /**
204
218
  * Update client configuration
219
+ *
220
+ * Validates the MERGED config before committing: omitting a key (or passing
221
+ * it as `undefined`, common with spread-built partials) keeps the current
222
+ * value; an explicit empty/non-string `baseUrl` throws `config_missing_base_url`
223
+ * and leaves the client unchanged (no half-updated state).
205
224
  */
206
225
  updateConfig(config: Partial<AgoConfig>): void;
207
226
  /**
@@ -237,8 +256,23 @@ declare interface AgoClientEvents {
237
256
  */
238
257
  "message:answer-complete": AgoMessage;
239
258
  "message:complete": AgoMessage;
259
+ /**
260
+ * A reply finished as `DONE` with empty content and no tool calls, client
261
+ * functions, or follow-up replies — usually an unknown `agent` slug (the
262
+ * backend currently answers those with an empty 200). Fires after
263
+ * `message:complete` AND after `sendMessage` resolves, so subscribing right
264
+ * after `await sendMessage(...)` still catches it. `messageId` and
265
+ * `conversationId` are empty strings when the stream completed without any
266
+ * message data at all (e.g. a proxy stripped the SSE stream).
267
+ */
268
+ "message:empty": {
269
+ conversationId: string;
270
+ messageId: string;
271
+ };
240
272
  "message:error": {
241
273
  error: string;
274
+ /** Stable error code (see configuration.md#error-codes) when the failure was an AgoError. */
275
+ code?: string;
242
276
  conversationId?: string;
243
277
  messageId?: string;
244
278
  };
@@ -267,7 +301,7 @@ declare interface AgoClientEvents {
267
301
  export declare interface AgoConfig {
268
302
  /** API base URL (e.g., https://YOUR-DOMAIN.useago.com) */
269
303
  baseUrl: string;
270
- /** Widget ID (X-Widget-Id header). Auto-generated if not provided. */
304
+ /** Per-visitor anonymous ID (X-User-Anon-Id header). Auto-generated if not provided. */
271
305
  widgetId?: string;
272
306
  /** Default agent (id or slug) for new conversations. Shorthand for `defaultAgentId`. */
273
307
  agent?: string;
@@ -281,6 +315,13 @@ export declare interface AgoConfig {
281
315
  userJwt?: string;
282
316
  /** Enable debug logging */
283
317
  debug?: boolean;
318
+ /**
319
+ * Warn on the console when a reply completes with empty content and no tool
320
+ * calls (the usual cause is an unknown `agent` slug, which the backend
321
+ * currently answers with an empty 200). Default `true`. The `message:empty`
322
+ * event fires regardless of this setting.
323
+ */
324
+ warnOnEmptyReply?: boolean;
284
325
  }
285
326
 
286
327
  declare type AgoEventHandler<K extends AgoEventName> = (data: AgoClientEvents[K]) => void;
package/dist/vue.d.ts CHANGED
@@ -24,12 +24,26 @@ declare class AgoClient {
24
24
  private contextRegistry;
25
25
  private eventEmitter;
26
26
  private config;
27
+ /** Conversations already warned about an empty reply (one warning each). */
28
+ private warnedEmptyConversations;
27
29
  constructor(config: AgoConfig);
28
30
  /**
29
31
  * Send a message and receive a streaming response
30
32
  */
31
33
  sendMessage(content: string, options?: SendMessageOptions): Promise<AgoMessage>;
32
34
  private processSSEResponse;
35
+ /**
36
+ * Detect a reply that completed as DONE with no content and no activity —
37
+ * today's backend answers an unknown `agent` slug with an empty 200, which
38
+ * otherwise fails silently. Emits `message:empty` (always) and warns on the
39
+ * console once per conversation (unless `warnOnEmptyReply: false`).
40
+ *
41
+ * Deferred with setTimeout(0) so both land AFTER `sendMessage` resolves:
42
+ * `await client.sendMessage(...)` followed by `client.waitFor("message:empty")`
43
+ * must not race. TEMPORARY heuristic: remove once the backend returns an
44
+ * explicit error for unknown agents (see TODOS.md, backend issue).
45
+ */
46
+ private maybeFlagEmptyReply;
33
47
  private handleClientFunctionInvocation;
34
48
  /**
35
49
  * Get list of conversations
@@ -202,6 +216,11 @@ declare class AgoClient {
202
216
  }): Promise<AgoClientEvents[K]>;
203
217
  /**
204
218
  * Update client configuration
219
+ *
220
+ * Validates the MERGED config before committing: omitting a key (or passing
221
+ * it as `undefined`, common with spread-built partials) keeps the current
222
+ * value; an explicit empty/non-string `baseUrl` throws `config_missing_base_url`
223
+ * and leaves the client unchanged (no half-updated state).
205
224
  */
206
225
  updateConfig(config: Partial<AgoConfig>): void;
207
226
  /**
@@ -237,8 +256,23 @@ declare interface AgoClientEvents {
237
256
  */
238
257
  "message:answer-complete": AgoMessage;
239
258
  "message:complete": AgoMessage;
259
+ /**
260
+ * A reply finished as `DONE` with empty content and no tool calls, client
261
+ * functions, or follow-up replies — usually an unknown `agent` slug (the
262
+ * backend currently answers those with an empty 200). Fires after
263
+ * `message:complete` AND after `sendMessage` resolves, so subscribing right
264
+ * after `await sendMessage(...)` still catches it. `messageId` and
265
+ * `conversationId` are empty strings when the stream completed without any
266
+ * message data at all (e.g. a proxy stripped the SSE stream).
267
+ */
268
+ "message:empty": {
269
+ conversationId: string;
270
+ messageId: string;
271
+ };
240
272
  "message:error": {
241
273
  error: string;
274
+ /** Stable error code (see configuration.md#error-codes) when the failure was an AgoError. */
275
+ code?: string;
242
276
  conversationId?: string;
243
277
  messageId?: string;
244
278
  };
@@ -267,7 +301,7 @@ declare interface AgoClientEvents {
267
301
  export declare interface AgoConfig {
268
302
  /** API base URL (e.g., https://YOUR-DOMAIN.useago.com) */
269
303
  baseUrl: string;
270
- /** Widget ID (X-Widget-Id header). Auto-generated if not provided. */
304
+ /** Per-visitor anonymous ID (X-User-Anon-Id header). Auto-generated if not provided. */
271
305
  widgetId?: string;
272
306
  /** Default agent (id or slug) for new conversations. Shorthand for `defaultAgentId`. */
273
307
  agent?: string;
@@ -281,6 +315,13 @@ export declare interface AgoConfig {
281
315
  userJwt?: string;
282
316
  /** Enable debug logging */
283
317
  debug?: boolean;
318
+ /**
319
+ * Warn on the console when a reply completes with empty content and no tool
320
+ * calls (the usual cause is an unknown `agent` slug, which the backend
321
+ * currently answers with an empty 200). Default `true`. The `message:empty`
322
+ * event fires regardless of this setting.
323
+ */
324
+ warnOnEmptyReply?: boolean;
284
325
  }
285
326
 
286
327
  declare type AgoEventHandler<K extends AgoEventName> = (data: AgoClientEvents[K]) => void;
package/dist/vue.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as A } from "./AgoClient-CZYNL25R.js";
1
+ import { t as A } from "./AgoClient-bQozE6-A.js";
2
2
  import { computed as y, inject as F, onMounted as g, onScopeDispose as N, onUnmounted as I, ref as c, shallowRef as D } from "vue";
3
3
  var L = /* @__PURE__ */ Symbol("ago-client"), b = { install(t, n) {
4
4
  const e = new A(n);
package/dist/widget.cjs CHANGED
@@ -1,5 +1,5 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Xe=require("./AgoClient-0x2Du_62.cjs"),$e=require("./createFormCollector-Ca8wRrxc.cjs"),Ke=require("./createConversationSession-BLZvXMmM.cjs");var Ve={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};function F(o){return o.replace(/[&<>"']/g,n=>Ve[n])}function Ie(o){const n=o.trim();return/^(https?:|mailto:|tel:|#|\/|\.\/|\.\.\/)/i.test(n)||!/^[a-z][a-z0-9+.-]*:/i.test(n)?n:null}var Te='"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace',Q="";function M(o){const n=[],r=u=>(n.push(u),`${Q}${n.length-1}${Q}`);let t=o;return t=t.replace(/`([^`]+)`/g,(u,i)=>r(`<code style="background:#f0f2f5;padding:2px 5px;border-radius:4px;font-size:13px;font-family:${Te}">${F(i)}</code>`)),t=t.replace(/!\[([^\]]*)\]\(([^)\s]+)\)/g,(u,i,f)=>{const s=Ie(f);return s?r(`<img alt="${F(i)}" src="${F(s)}" style="max-width:100%;border-radius:8px;margin:4px 0" />`):u}),t=t.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g,(u,i,f)=>{const s=Ie(f);return s?r(`<a href="${F(s)}" target="_blank" rel="noopener noreferrer" style="color:#1b5fc4;text-decoration:underline">${M(i)}</a>`):u}),t=F(t),t=t.replace(/\*\*([^*]+?)\*\*/g,"<strong>$1</strong>").replace(/__([^_]+?)__/g,"<strong>$1</strong>").replace(/~~([^~]+?)~~/g,"<del>$1</del>").replace(/(^|[^*])\*(?!\s)([^*]+?)\*/g,"$1<em>$2</em>").replace(/(^|[^\w_])_(?!\s)([^_]+?)_/g,"$1<em>$2</em>"),t=t.replace(new RegExp(`${Q}(\\d+)${Q}`,"g"),(u,i)=>n[Number(i)]),t}function R(o,n,r){const t=document.createElement(o);return Object.assign(t.style,n),r!==void 0&&(t.innerHTML=r),t}var De=/^ {0,3}([-*_])( *\1){2,} *$/,Me=/^ {0,3}(#{1,6})\s+(.*?)\s*#*\s*$/,Be=/^ {0,3}(```+|~~~+)/,Z=/^ {0,3}>\s?/,P=/^(\s*)([-*+]|\d+[.)])\s+(.*)$/,Qe=["20px","18px","16px","15px","14px","13px"],ce=o=>o.match(/^\s*/)?.[0].length??0;function Ye(o){return o.trim()===""||De.test(o)||Me.test(o)||Be.test(o)||Z.test(o)||P.test(o)}function ze(o){const n=o[0].match(P),r=n[1].length,t=/\d/.test(n[2]),u=R(t?"ol":"ul",{margin:"0 0 8px 0",paddingLeft:"20px",listStyleType:t?"decimal":"disc",listStylePosition:"outside"});let i=0;for(;i<o.length;){const f=o[i].match(P),s=[];for(i++;i<o.length&&ce(o[i])>r;)s.push(o[i]),i++;const p=R("li",{display:"list-item",margin:"2px 0",lineHeight:"1.6"}),c=f[3].match(/^\[([ xX])\]\s+(.*)$/);c?(p.style.listStyleType="none",p.style.marginLeft="-20px",p.innerHTML=`<span style="margin-right:6px">${c[1].toLowerCase()==="x"?"☑":"☐"}</span>${M(c[2])}`):p.innerHTML=M(f[3]),s.filter(m=>P.test(m)).length>0&&p.appendChild(ze(s.filter(m=>m.trim()!==""))),u.appendChild(p)}return u}function Ze(o){const n=s=>s.replace(/^\s*\|?/,"").replace(/\|?\s*$/,"").split("|").map(p=>p.trim()),r=R("div",{overflowX:"auto",margin:"0 0 8px 0"}),t=R("table",{borderCollapse:"collapse",width:"100%",fontSize:"13px"}),u=document.createElement("thead"),i=document.createElement("tr");for(const s of n(o[0]))i.appendChild(R("th",{border:"1px solid #dee3e8",padding:"6px 10px",textAlign:"left",backgroundColor:"#f5f7fa",fontWeight:"600"},M(s)));u.appendChild(i),t.appendChild(u);const f=document.createElement("tbody");for(const s of o.slice(2)){const p=document.createElement("tr");for(const c of n(s))p.appendChild(R("td",{border:"1px solid #dee3e8",padding:"6px 10px"},M(c)));f.appendChild(p)}return t.appendChild(f),r.appendChild(t),r}var Je=o=>!!o&&/^\s*\|?\s*:?-{1,}:?\s*(\|\s*:?-{1,}:?\s*)*\|?\s*$/.test(o);function ge(o){const n=document.createDocumentFragment(),r=o.replace(/\r\n?/g,`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ke=require("./AgoClient-_fig8FoN.cjs"),$e=require("./createFormCollector-CdQjGAl_.cjs"),Ke=require("./createConversationSession-DJUFgOXy.cjs");var Ve={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};function U(o){return o.replace(/[&<>"']/g,n=>Ve[n])}function Ae(o){const n=o.trim();return/^(https?:|mailto:|tel:|#|\/|\.\/|\.\.\/)/i.test(n)||!/^[a-z][a-z0-9+.-]*:/i.test(n)?n:null}var Te='"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace',Q="";function M(o){const n=[],r=u=>(n.push(u),`${Q}${n.length-1}${Q}`);let t=o;return t=t.replace(/`([^`]+)`/g,(u,i)=>r(`<code style="background:#f0f2f5;padding:2px 5px;border-radius:4px;font-size:13px;font-family:${Te}">${U(i)}</code>`)),t=t.replace(/!\[([^\]]*)\]\(([^)\s]+)\)/g,(u,i,f)=>{const s=Ae(f);return s?r(`<img alt="${U(i)}" src="${U(s)}" style="max-width:100%;border-radius:8px;margin:4px 0" />`):u}),t=t.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g,(u,i,f)=>{const s=Ae(f);return s?r(`<a href="${U(s)}" target="_blank" rel="noopener noreferrer" style="color:#1b5fc4;text-decoration:underline">${M(i)}</a>`):u}),t=U(t),t=t.replace(/\*\*([^*]+?)\*\*/g,"<strong>$1</strong>").replace(/__([^_]+?)__/g,"<strong>$1</strong>").replace(/~~([^~]+?)~~/g,"<del>$1</del>").replace(/(^|[^*])\*(?!\s)([^*]+?)\*/g,"$1<em>$2</em>").replace(/(^|[^\w_])_(?!\s)([^_]+?)_/g,"$1<em>$2</em>"),t=t.replace(new RegExp(`${Q}(\\d+)${Q}`,"g"),(u,i)=>n[Number(i)]),t}function _(o,n,r){const t=document.createElement(o);return Object.assign(t.style,n),r!==void 0&&(t.innerHTML=r),t}var De=/^ {0,3}([-*_])( *\1){2,} *$/,Me=/^ {0,3}(#{1,6})\s+(.*?)\s*#*\s*$/,Be=/^ {0,3}(```+|~~~+)/,Z=/^ {0,3}>\s?/,P=/^(\s*)([-*+]|\d+[.)])\s+(.*)$/,Qe=["20px","18px","16px","15px","14px","13px"],fe=o=>o.match(/^\s*/)?.[0].length??0;function Ye(o){return o.trim()===""||De.test(o)||Me.test(o)||Be.test(o)||Z.test(o)||P.test(o)}function ze(o){const n=o[0].match(P),r=n[1].length,t=/\d/.test(n[2]),u=_(t?"ol":"ul",{margin:"0 0 8px 0",paddingLeft:"20px",listStyleType:t?"decimal":"disc",listStylePosition:"outside"});let i=0;for(;i<o.length;){const f=o[i].match(P),s=[];for(i++;i<o.length&&fe(o[i])>r;)s.push(o[i]),i++;const p=_("li",{display:"list-item",margin:"2px 0",lineHeight:"1.6"}),c=f[3].match(/^\[([ xX])\]\s+(.*)$/);c?(p.style.listStyleType="none",p.style.marginLeft="-20px",p.innerHTML=`<span style="margin-right:6px">${c[1].toLowerCase()==="x"?"☑":"☐"}</span>${M(c[2])}`):p.innerHTML=M(f[3]),s.filter(h=>P.test(h)).length>0&&p.appendChild(ze(s.filter(h=>h.trim()!==""))),u.appendChild(p)}return u}function Ze(o){const n=s=>s.replace(/^\s*\|?/,"").replace(/\|?\s*$/,"").split("|").map(p=>p.trim()),r=_("div",{overflowX:"auto",margin:"0 0 8px 0"}),t=_("table",{borderCollapse:"collapse",width:"100%",fontSize:"13px"}),u=document.createElement("thead"),i=document.createElement("tr");for(const s of n(o[0]))i.appendChild(_("th",{border:"1px solid #dee3e8",padding:"6px 10px",textAlign:"left",backgroundColor:"#f5f7fa",fontWeight:"600"},M(s)));u.appendChild(i),t.appendChild(u);const f=document.createElement("tbody");for(const s of o.slice(2)){const p=document.createElement("tr");for(const c of n(s))p.appendChild(_("td",{border:"1px solid #dee3e8",padding:"6px 10px"},M(c)));f.appendChild(p)}return t.appendChild(f),r.appendChild(t),r}var Je=o=>!!o&&/^\s*\|?\s*:?-{1,}:?\s*(\|\s*:?-{1,}:?\s*)*\|?\s*$/.test(o);function J(o){const n=document.createDocumentFragment(),r=o.replace(/\r\n?/g,`
2
2
  `).split(`
3
- `);let t=0;for(;t<r.length;){const i=r[t];if(i.trim()===""){t++;continue}const f=i.match(Be);if(f){const c=f[1][0],m=[];for(t++;t<r.length&&!new RegExp(`^ {0,3}${c==="`"?"`{3,}":"~{3,}"}\\s*$`).test(r[t]);)m.push(r[t]),t++;t++;const L=R("pre",{margin:"0 0 8px 0"});L.appendChild(R("code",{display:"block",background:"#f5f5f5",padding:"8px 12px",borderRadius:"6px",fontSize:"13px",overflowX:"auto",fontFamily:Te,whiteSpace:"pre"},F(m.join(`
4
- `)))),n.appendChild(L);continue}if(De.test(i)){n.appendChild(R("hr",{border:"none",borderTop:"1px solid #dee3e8",margin:"12px 0"})),t++;continue}const s=i.match(Me);if(s){const c=s[1].length;n.appendChild(R(`h${c}`,{margin:"16px 0 8px 0",fontSize:Qe[c-1],fontWeight:"600",lineHeight:"1.3"},M(s[2]))),t++;continue}if(Z.test(i)){const c=[];for(;t<r.length&&Z.test(r[t]);)c.push(r[t].replace(Z,"")),t++;const m=R("blockquote",{borderLeft:"4px solid #dee3e8",paddingLeft:"12px",margin:"0 0 8px 0",fontStyle:"italic",color:"#6b6d6f"});m.appendChild(ge(c.join(`
5
- `))),n.appendChild(m);continue}if(i.includes("|")&&Je(r[t+1])){const c=[i,r[t+1]];for(t+=2;t<r.length&&r[t].includes("|")&&r[t].trim();)c.push(r[t]),t++;n.appendChild(Ze(c));continue}if(P.test(i)){const c=[],m=ce(i);for(;t<r.length&&r[t].trim()!=="";)if(P.test(r[t])||ce(r[t])>m)c.push(r[t]),t++;else break;n.appendChild(ze(c));continue}const p=[i];for(t++;t<r.length&&!Ye(r[t]);)p.push(r[t]),t++;n.appendChild(R("p",{margin:"0 0 8px 0",lineHeight:"1.6"},p.map(c=>M(c)).join("<br>")))}const u=n.lastElementChild;return u&&(u.style.marginBottom="0"),n}var pe='var(--ago-font, "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif)',Ae={font:"--ago-font",radius:"--ago-radius",messageRadius:"--ago-message-radius",brand:"--ago-brand-color",brandText:"--ago-brand-text-color",headerBg:"--ago-header-background",headerText:"--ago-header-text-color",panelBg:"--ago-panel-background",messagesBg:"--ago-messages-background",text:"--ago-text-color",mutedText:"--ago-muted-text-color",border:"--ago-border-color",accent:"--ago-accent-color"},fe="var(--ago-brand-color, #03182f)",ue="var(--ago-brand-text-color, #fff)",et="var(--ago-header-background, var(--ago-brand-color, #03182f))",Ne="var(--ago-header-text-color, #e8f0fe)",j="var(--ago-panel-background, #fff)",tt="var(--ago-messages-background, #fbfbfb)",Y="var(--ago-text-color, #30373e)",nt="var(--ago-muted-text-color, #6b6d6f)",$="var(--ago-border-color, #dee3e8)",de="var(--ago-accent-color, #1b5fc4)",ot="var(--ago-radius, 16px)",Le="var(--ago-message-radius, 16px)";function rt(o,n){if(n)for(const r of Object.keys(Ae)){const t=n[r];t!=null&&o.style.setProperty(Ae[r],t)}}function y(o,n){Object.assign(o.style,n)}function b(o={}){const n=document.createElement("div");return y(n,o),n}var Oe="ago-chat-widget-keyframes";function at(){if(typeof document>"u"||document.getElementById(Oe))return;const o=document.createElement("style");o.id=Oe,o.textContent="@keyframes ago-pulse { 0%, 80%, 100% { opacity: 0.3; transform: scale(0.8); } 40% { opacity: 1; transform: scale(1); } }",document.head.appendChild(o)}function it(o){const n=typeof o=="string"?document.querySelector(o):o;if(!n)throw new Error(`mountChatWidget: target "${String(o)}" not found.`);return n}function st(o,n){const{title:r="Chat",welcomeMessage:t="Hello! How can I help you today?",placeholder:u="Type a message...",allowFiles:i=!1,height:f=500,placement:s="inline",width:p=400,defaultOpen:c=!1,logoUrl:m,showAgentName:L=!1,theme:x,loadThreads:_=!1,forms:q,onFollowUpClick:B,onMessageSent:O,onMessageReceived:he}=n;if(!n.client&&!n.config?.baseUrl)throw new Error("mountChatWidget requires either `client` or `config` (with a baseUrl).");const h=n.client??new Xe.AgoClient(n.config),me=it(o),z=s==="left"||s==="right",He=z&&(n.launcher??!0);let H=z?c:!0;const J=n.persistConversation,X=J?Ke.createConversationSession(J===!0?{}:J):void 0;let k=n.conversationId??X?.getLastActiveThread()??void 0,d=[],A=!1,W=null;const K=[],U=b({display:"flex",flexDirection:"column",height:z?"100%":typeof f=="number"?`${f}px`:f,border:`1px solid ${$}`,borderRadius:ot,overflow:"hidden",backgroundColor:j,fontFamily:pe,textAlign:"left",boxShadow:"rgba(15, 15, 15, 0.08) 0px 2px 16px 0px"});U.className="ago-chat-widget",rt(U,x);const G=b({padding:"14px 16px",borderBottom:`1px solid ${$}`,backgroundColor:et,color:Ne,display:"flex",alignItems:"center",gap:"10px"});if(G.className="ago-chat-widget__header",m){const e=document.createElement("img");e.src=m,e.alt="Logo",y(e,{height:"24px",width:"auto"}),G.appendChild(e)}const ee=document.createElement("h3");if(ee.textContent=r,y(ee,{margin:"0",fontSize:"15px",fontWeight:"600"}),G.appendChild(ee),z){const e=document.createElement("button");e.type="button",e.className="ago-chat-widget__close",e.setAttribute("aria-label","Close"),e.textContent="×",y(e,{marginLeft:"auto",background:"transparent",border:"none",color:Ne,fontSize:"22px",lineHeight:"1",cursor:"pointer",padding:"0 2px"}),e.addEventListener("click",()=>se()),G.appendChild(e)}const N=b({flex:"1",overflow:"auto",padding:"16px",backgroundColor:tt});N.className="ago-chat-widget__messages";const{inputRow:Ue,setDisabled:Fe,focus:xe}=lt({placeholder:u,allowFiles:i,onSend:(e,a)=>{oe(e,a)}});at(),U.append(G,N,Ue);let V=U,T,E;const te=s==="left"?"left":"right";if(z&&(T=b({position:"fixed",top:"0",bottom:"0",[te]:"0",width:typeof p=="number"?`${p}px`:p,maxWidth:"100vw",display:"flex",zIndex:"2147483000",transition:"transform 0.3s ease",boxShadow:"rgba(15, 15, 15, 0.18) 0px 0px 24px 0px"}),T.className="ago-chat-widget-panel",y(U,{height:"100%",width:"100%",borderRadius:"0",border:"none",boxShadow:"none",[te==="left"?"borderRight":"borderLeft"]:`1px solid ${$}`}),T.appendChild(U),V=T),He){if(E=document.createElement("button"),E.type="button",E.className="ago-chat-widget-launcher",E.setAttribute("aria-label",`Open ${r}`),y(E,{position:"fixed",bottom:"20px",[te]:"20px",width:"56px",height:"56px",borderRadius:"50%",border:"none",backgroundColor:fe,color:ue,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",zIndex:"2147483000",boxShadow:"rgba(15, 15, 15, 0.2) 0px 4px 14px 0px",fontFamily:pe}),m){const e=document.createElement("img");e.src=m,e.alt="",y(e,{width:"26px",height:"26px",objectFit:"contain"}),E.appendChild(e)}else E.appendChild(qe());E.addEventListener("click",()=>ie())}me.appendChild(V),E&&me.appendChild(E),ae();const be=B!==!1,Ce=B===!1?void 0:B??(e=>{oe(e)});function Pe(e,a){const l=e.role==="user",S=b({display:"flex",flexDirection:"column",alignItems:l?"flex-end":"flex-start",marginBottom:"16px"});if(S.className=`ago-message ago-message--${e.role}`,!l&&L&&e.agent){const g=b({fontSize:"13px",fontWeight:"500",color:Y,marginBottom:"6px",padding:"0 4px"});g.className="ago-message__agent",g.textContent=e.agent.displayName||e.agent.name,S.appendChild(g)}if(!l&&e.sources&&e.sources.length>0){const g=b({display:"grid",gridTemplateColumns:"1fr 1fr",gap:"6px",marginBottom:"10px",width:"100%",maxWidth:"85%"});g.className="ago-message__sources",e.sources.forEach((C,w)=>{const D=C.url?document.createElement("a"):document.createElement("div");C.url&&D instanceof HTMLAnchorElement&&(D.href=C.url,D.target="_blank",D.rel="noopener noreferrer"),y(D,{display:"flex",alignItems:"center",gap:"8px",padding:"8px 10px",border:`1px solid ${$}`,borderRadius:"8px",backgroundColor:j,textDecoration:"none",color:Y,fontSize:"12px",overflow:"hidden"});const ke=b({flexShrink:"0",width:"18px",height:"18px",borderRadius:"3px",border:`1px solid ${de}`,color:de,fontSize:"11px",fontWeight:"500",display:"flex",alignItems:"center",justifyContent:"center",backgroundColor:"#f0f4ff"});ke.textContent=String(w+1);const le=b({overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"});le.textContent=C.title,le.title=C.title,D.append(ke,le),g.appendChild(D)}),S.appendChild(g)}const v=b({maxWidth:l?"75%":"100%",padding:l?"10px 14px":"2px 8px",borderRadius:l?Le:"0",backgroundColor:l?fe:"transparent",color:l?ue:Y,wordBreak:"break-word",fontSize:"14px",lineHeight:"1.6"});if(v.className="ago-message__content",e.content?v.appendChild(ge(e.content)):e.status==="IN_PROGRESS"&&v.appendChild(_e()),S.appendChild(v),a&&A&&e.role==="assistant"&&e.status==="DONE"&&!(e.followUpReplies&&e.followUpReplies.length>0)){const g=b({marginTop:"10px",paddingLeft:"8px"});g.className="ago-message__followups-loading",g.appendChild(_e()),S.appendChild(g)}if(a&&e.followUpReplies&&e.followUpReplies.length>0){const g=b({display:"flex",flexWrap:"wrap",gap:"8px",marginTop:"10px"});g.className="ago-message__followups";for(const C of e.followUpReplies){const w=document.createElement("button");w.type="button",w.className="ago-message__followup-btn",w.textContent=C,w.disabled=!be,y(w,{padding:"6px 14px",fontSize:"13px",borderRadius:Le,border:`1px solid ${$}`,backgroundColor:j,color:Y,cursor:be?"pointer":"default",transition:"border-color 0.15s"}),Ce&&w.addEventListener("click",()=>Ce(C)),w.addEventListener("mouseenter",()=>{w.style.borderColor=de}),w.addEventListener("mouseleave",()=>{w.style.borderColor=$}),g.appendChild(w)}S.appendChild(g)}return S}function I(){if(N.replaceChildren(),d.length===0){const a=b({textAlign:"center",color:nt,padding:"24px 16px",fontSize:"14px",lineHeight:"1.5"});a.textContent=t,N.appendChild(a)}else d.forEach((a,l)=>{N.appendChild(Pe(a,l===d.length-1))});if(W){const a=b({padding:"10px 14px",backgroundColor:"#fef2f2",color:"#dc2626",borderRadius:"12px",marginTop:"8px",fontSize:"13px",border:"1px solid #fecaca"});a.textContent=W,N.appendChild(a)}N.scrollTop=N.scrollHeight;const e=d[d.length-1];Fe(A&&e?.role==="assistant"&&e.status==="IN_PROGRESS")}function We(){for(let e=d.length-1;e>=0;e--){const a=d[e];if(a.role==="assistant"&&a.status==="IN_PROGRESS")return a}}const ve=e=>{k||(k=e.conversationId)},we=e=>{const a=We();a&&(a.content+=e.content,I())},ye=e=>{const a=d.findIndex(l=>l.id===e.id||l.role==="assistant"&&l.status==="IN_PROGRESS");a>=0?d[a]=e:d.push(e),I()},Ee=e=>{const a=d.findIndex(l=>l.id===e.id||l.role==="assistant"&&l.status==="IN_PROGRESS");a>=0?d[a]=e:d.push(e),A=!1,I(),e.status==="DONE"&&he?.({id:e.id,content:e.content})},Se=e=>{W=e.error,A=!1,d=d.filter(a=>!a.id.startsWith("temp-")),I()};h.on("message:start",ve),h.on("message:chunk",we),h.on("message:answer-complete",ye),h.on("message:complete",Ee),h.on("message:error",Se);const ne=[];let Re=!1;for(const e of q??[])e.schema!=null?ne.push($e.createFormCollector(e).install(h)):$e.loadFormCollector(h,e).then(a=>{Re||ne.push(a.install(h))}).catch(()=>{});async function oe(e,a){const l=e.trim();if(!l&&!a?.length||A)return;O?.(l),A=!0,W=null;const S=Date.now();d.push({id:`temp-user-${S}`,conversationId:k||"",content:l,role:"user",status:"DONE",createdAt:new Date}),d.push({id:`temp-assistant-${S}`,conversationId:k||"",content:"",role:"assistant",status:"IN_PROGRESS",createdAt:new Date}),I();try{const v=await h.sendMessage(l,{conversationId:k,files:a});v.conversationId&&(k||(k=v.conversationId),X?.setActiveThread(v.conversationId,v.createdAt));const g=d.find(C=>C.id===`temp-user-${S}`);if(g&&(g.id=`user-${S}`,g.conversationId=v.conversationId),!d.some(C=>C.id===v.id)){const C=d.findIndex(w=>w.id===`temp-assistant-${S}`);C>=0?d[C]=v:d.push(v)}d=d.filter(C=>!C.id.startsWith("temp-")),A=!1,I(),_&&re()}catch(v){W=v instanceof Error?v.message:"Failed to send message",A=!1,d=d.filter(g=>!g.id.startsWith("temp-")),I()}}async function re(){try{const e=await h.getConversations();K.splice(0,K.length,...e)}catch{}return K}async function Ge(e){try{const a=(await h.getConversation(e))?.messages??[];a.length>0&&d.length===0&&(d=a,I())}catch{d.length===0&&(X?.clear(),k=void 0)}}return I(),xe(),k&&Ge(k),_&&re(),{client:h,element:V,sendMessage:oe,...z?{open:ie,close:se,toggle:je}:{},session:X,threads:K,refreshThreads:re,destroy(){h.off("message:start",ve),h.off("message:chunk",we),h.off("message:answer-complete",ye),h.off("message:complete",Ee),h.off("message:error",Se),Re=!0,ne.forEach(e=>e()),V.remove(),E?.remove(),n.client||h.destroy()}};function ae(){if(!T)return;const e=s==="left"?"translateX(-100%)":"translateX(100%)";T.style.transform=H?"translateX(0)":e,T.setAttribute("aria-hidden",H?"false":"true"),E&&(E.style.display=H?"none":"flex")}function ie(){H=!0,ae(),xe()}function se(){H=!1,ae()}function je(){H?se():ie()}function qe(){const e="http://www.w3.org/2000/svg",a=document.createElementNS(e,"svg");a.setAttribute("width","26"),a.setAttribute("height","26"),a.setAttribute("viewBox","0 0 24 24"),a.setAttribute("fill","none");const l=document.createElementNS(e,"path");return l.setAttribute("d","M21 11.5a8.38 8.38 0 0 1-8.5 8.5 8.5 8.5 0 0 1-3.8-.9L3 21l1.9-5.7a8.5 8.5 0 0 1-.9-3.8 8.38 8.38 0 0 1 8.5-8.5 8.38 8.38 0 0 1 8.5 8.5z"),l.setAttribute("stroke","currentColor"),l.setAttribute("stroke-width","2"),l.setAttribute("stroke-linecap","round"),l.setAttribute("stroke-linejoin","round"),a.appendChild(l),a}function _e(){const e=b({display:"flex",gap:"4px",padding:"4px 0"});for(let a=0;a<3;a++){const l=b({width:"6px",height:"6px",borderRadius:"50%",backgroundColor:"#b5bfc8",animation:"ago-pulse 1.2s ease-in-out infinite",animationDelay:`${a*.2}s`});e.appendChild(l)}return e}}function lt(o){let n=[];const r=document.createElement("form");y(r,{display:"flex",flexDirection:"column",gap:"8px",padding:"12px",borderTop:`1px solid ${$}`,backgroundColor:j}),r.className="ago-chat-input";const t=b({display:"flex",flexWrap:"wrap",gap:"6px"}),u=b({display:"flex",gap:"8px",alignItems:"flex-end"}),i=document.createElement("textarea");i.placeholder=o.placeholder,i.rows=1,y(i,{flex:"1",resize:"none",padding:"10px 12px",border:`1px solid ${$}`,borderRadius:"12px",fontSize:"14px",fontFamily:pe,lineHeight:"1.4",maxHeight:"120px",outline:"none"});const f=document.createElement("button");f.type="submit",f.textContent="Send",y(f,{padding:"10px 16px",border:"none",borderRadius:"12px",backgroundColor:fe,color:ue,fontSize:"14px",fontWeight:"500",cursor:"pointer"});let s=null,p=null;o.allowFiles&&(s=document.createElement("input"),s.type="file",s.multiple=!0,y(s,{display:"none"}),p=document.createElement("button"),p.type="button",p.textContent="📎",y(p,{padding:"10px 12px",border:`1px solid ${$}`,borderRadius:"12px",backgroundColor:j,cursor:"pointer",fontSize:"14px"}),p.addEventListener("click",()=>s?.click()),s.addEventListener("change",()=>{n=[...n,...Array.from(s?.files??[])],c()}));function c(){t.replaceChildren(),n.forEach((x,_)=>{const q=b({display:"flex",alignItems:"center",gap:"4px",padding:"4px 8px",backgroundColor:"#f0f4ff",border:`1px solid ${$}`,borderRadius:"8px",fontSize:"12px"}),B=document.createElement("span");B.textContent=x.name;const O=document.createElement("button");O.type="button",O.textContent="×",y(O,{border:"none",background:"transparent",cursor:"pointer",fontSize:"14px",lineHeight:"1"}),O.addEventListener("click",()=>{n=n.filter((he,h)=>h!==_),c()}),q.append(B,O),t.appendChild(q)})}const m=()=>{const x=i.value,_=n;return i.value="",n=[],c(),{content:x,files:_}},L=()=>{const{content:x,files:_}=m();(x.trim()||_.length>0)&&o.onSend(x.trim(),_.length>0?_:void 0)};return r.addEventListener("submit",x=>{x.preventDefault(),L()}),i.addEventListener("keydown",x=>{x.key==="Enter"&&!x.shiftKey&&(x.preventDefault(),L())}),p&&u.appendChild(p),u.append(i,f),s&&r.appendChild(s),r.append(t,u),{inputRow:r,getValueAndClear:m,setDisabled:x=>{i.disabled=x,f.disabled=x,f.style.opacity=x?"0.6":"1",f.style.cursor=x?"not-allowed":"pointer"},focus:()=>i.focus()}}exports.mountChatWidget=st;exports.renderMarkdown=ge;
3
+ `);let t=0;for(;t<r.length;){const i=r[t];if(i.trim()===""){t++;continue}const f=i.match(Be);if(f){const c=f[1][0],h=[];for(t++;t<r.length&&!new RegExp(`^ {0,3}${c==="`"?"`{3,}":"~{3,}"}\\s*$`).test(r[t]);)h.push(r[t]),t++;t++;const L=_("pre",{margin:"0 0 8px 0"});L.appendChild(_("code",{display:"block",background:"#f5f5f5",padding:"8px 12px",borderRadius:"6px",fontSize:"13px",overflowX:"auto",fontFamily:Te,whiteSpace:"pre"},U(h.join(`
4
+ `)))),n.appendChild(L);continue}if(De.test(i)){n.appendChild(_("hr",{border:"none",borderTop:"1px solid #dee3e8",margin:"12px 0"})),t++;continue}const s=i.match(Me);if(s){const c=s[1].length;n.appendChild(_(`h${c}`,{margin:"16px 0 8px 0",fontSize:Qe[c-1],fontWeight:"600",lineHeight:"1.3"},M(s[2]))),t++;continue}if(Z.test(i)){const c=[];for(;t<r.length&&Z.test(r[t]);)c.push(r[t].replace(Z,"")),t++;const h=_("blockquote",{borderLeft:"4px solid #dee3e8",paddingLeft:"12px",margin:"0 0 8px 0",fontStyle:"italic",color:"#6b6d6f"});h.appendChild(J(c.join(`
5
+ `))),n.appendChild(h);continue}if(i.includes("|")&&Je(r[t+1])){const c=[i,r[t+1]];for(t+=2;t<r.length&&r[t].includes("|")&&r[t].trim();)c.push(r[t]),t++;n.appendChild(Ze(c));continue}if(P.test(i)){const c=[],h=fe(i);for(;t<r.length&&r[t].trim()!=="";)if(P.test(r[t])||fe(r[t])>h)c.push(r[t]),t++;else break;n.appendChild(ze(c));continue}const p=[i];for(t++;t<r.length&&!Ye(r[t]);)p.push(r[t]),t++;n.appendChild(_("p",{margin:"0 0 8px 0",lineHeight:"1.6"},p.map(c=>M(c)).join("<br>")))}const u=n.lastElementChild;return u&&(u.style.marginBottom="0"),n}var ue='var(--ago-font, "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif)',Ie={font:"--ago-font",radius:"--ago-radius",messageRadius:"--ago-message-radius",brand:"--ago-brand-color",brandText:"--ago-brand-text-color",headerBg:"--ago-header-background",headerText:"--ago-header-text-color",panelBg:"--ago-panel-background",messagesBg:"--ago-messages-background",text:"--ago-text-color",mutedText:"--ago-muted-text-color",border:"--ago-border-color",accent:"--ago-accent-color"},ge="var(--ago-brand-color, #03182f)",he="var(--ago-brand-text-color, #fff)",et="var(--ago-header-background, var(--ago-brand-color, #03182f))",Le="var(--ago-header-text-color, #e8f0fe)",j="var(--ago-panel-background, #fff)",tt="var(--ago-messages-background, #fbfbfb)",Y="var(--ago-text-color, #30373e)",nt="var(--ago-muted-text-color, #6b6d6f)",$="var(--ago-border-color, #dee3e8)",pe="var(--ago-accent-color, #1b5fc4)",ot="var(--ago-radius, 16px)",Ne="var(--ago-message-radius, 16px)";function rt(o,n){if(n)for(const r of Object.keys(Ie)){const t=n[r];t!=null&&o.style.setProperty(Ie[r],t)}}function y(o,n){Object.assign(o.style,n)}function x(o={}){const n=document.createElement("div");return y(n,o),n}var Oe="ago-chat-widget-keyframes";function at(){if(typeof document>"u"||document.getElementById(Oe))return;const o=document.createElement("style");o.id=Oe,o.textContent="@keyframes ago-pulse { 0%, 80%, 100% { opacity: 0.3; transform: scale(0.8); } 40% { opacity: 1; transform: scale(1); } }",document.head.appendChild(o)}function it(o){const n=typeof o=="string"?document.querySelector(o):o;if(!n)throw new Error(`mountChatWidget: target "${String(o)}" not found.`);return n}function st(o,n){const{title:r="Chat",welcomeMessage:t="Hello! How can I help you today?",placeholder:u="Type a message...",allowFiles:i=!1,height:f=500,placement:s="inline",width:p=400,defaultOpen:c=!1,logoUrl:h,showAgentName:L=!1,theme:m,loadThreads:R=!1,forms:q,onFollowUpClick:B,onMessageSent:N,onMessageReceived:me}=n;if(!n.client&&!n.config?.baseUrl)throw new ke.AgoError("mountChatWidget requires either `client` or `config` (with a baseUrl).","config_missing_base_url");const g=n.client??new ke.AgoClient(n.config),xe=it(o),z=s==="left"||s==="right",He=z&&(n.launcher??!0);let H=z?c:!0;const ee=n.persistConversation,X=ee?Ke.createConversationSession(ee===!0?{}:ee):void 0;let k=n.conversationId??X?.getLastActiveThread()??void 0,d=[],O=!1,W=null;const K=[],F=x({display:"flex",flexDirection:"column",height:z?"100%":typeof f=="number"?`${f}px`:f,border:`1px solid ${$}`,borderRadius:ot,overflow:"hidden",backgroundColor:j,fontFamily:ue,textAlign:"left",boxShadow:"rgba(15, 15, 15, 0.08) 0px 2px 16px 0px"});F.className="ago-chat-widget",rt(F,m);const G=x({padding:"14px 16px",borderBottom:`1px solid ${$}`,backgroundColor:et,color:Le,display:"flex",alignItems:"center",gap:"10px"});if(G.className="ago-chat-widget__header",h){const e=document.createElement("img");e.src=h,e.alt="Logo",y(e,{height:"24px",width:"auto"}),G.appendChild(e)}const te=document.createElement("h3");if(te.textContent=r,y(te,{margin:"0",fontSize:"15px",fontWeight:"600"}),G.appendChild(te),z){const e=document.createElement("button");e.type="button",e.className="ago-chat-widget__close",e.setAttribute("aria-label","Close"),e.textContent="×",y(e,{marginLeft:"auto",background:"transparent",border:"none",color:Le,fontSize:"22px",lineHeight:"1",cursor:"pointer",padding:"0 2px"}),e.addEventListener("click",()=>de()),G.appendChild(e)}const I=x({flex:"1",overflow:"auto",padding:"16px",backgroundColor:tt});I.className="ago-chat-widget__messages";const{inputRow:Fe,setDisabled:Ue,focus:ne}=lt({placeholder:u,allowFiles:i,onSend:(e,a)=>{ae(e,a)}});at(),F.append(G,I,Fe);let V=F,T,E;const oe=s==="left"?"left":"right";if(z&&(T=x({position:"fixed",top:"0",bottom:"0",[oe]:"0",width:typeof p=="number"?`${p}px`:p,maxWidth:"100vw",display:"flex",zIndex:"2147483000",transition:"transform 0.3s ease",boxShadow:"rgba(15, 15, 15, 0.18) 0px 0px 24px 0px"}),T.className="ago-chat-widget-panel",y(F,{height:"100%",width:"100%",borderRadius:"0",border:"none",boxShadow:"none",[oe==="left"?"borderRight":"borderLeft"]:`1px solid ${$}`}),T.appendChild(F),V=T),He){if(E=document.createElement("button"),E.type="button",E.className="ago-chat-widget-launcher",E.setAttribute("aria-label",`Open ${r}`),y(E,{position:"fixed",bottom:"20px",[oe]:"20px",width:"56px",height:"56px",borderRadius:"50%",border:"none",backgroundColor:ge,color:he,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",zIndex:"2147483000",boxShadow:"rgba(15, 15, 15, 0.2) 0px 4px 14px 0px",fontFamily:ue}),h){const e=document.createElement("img");e.src=h,e.alt="",y(e,{width:"26px",height:"26px",objectFit:"contain"}),E.appendChild(e)}else E.appendChild(qe());E.addEventListener("click",()=>le())}xe.appendChild(V),E&&xe.appendChild(E),se();const be=B!==!1,Ce=B===!1?void 0:B??(e=>{ae(e)});function Pe(e,a){const l=e.role==="user",S=x({display:"flex",flexDirection:"column",alignItems:l?"flex-end":"flex-start",marginBottom:"16px"});if(S.className=`ago-message ago-message--${e.role}`,!l&&L&&e.agent){const b=x({fontSize:"13px",fontWeight:"500",color:Y,marginBottom:"6px",padding:"0 4px"});b.className="ago-message__agent",b.textContent=e.agent.displayName||e.agent.name,S.appendChild(b)}if(!l&&e.sources&&e.sources.length>0){const b=x({display:"grid",gridTemplateColumns:"1fr 1fr",gap:"6px",marginBottom:"10px",width:"100%",maxWidth:"85%"});b.className="ago-message__sources",e.sources.forEach((C,w)=>{const D=C.url?document.createElement("a"):document.createElement("div");C.url&&D instanceof HTMLAnchorElement&&(D.href=C.url,D.target="_blank",D.rel="noopener noreferrer"),y(D,{display:"flex",alignItems:"center",gap:"8px",padding:"8px 10px",border:`1px solid ${$}`,borderRadius:"8px",backgroundColor:j,textDecoration:"none",color:Y,fontSize:"12px",overflow:"hidden"});const Re=x({flexShrink:"0",width:"18px",height:"18px",borderRadius:"3px",border:`1px solid ${pe}`,color:pe,fontSize:"11px",fontWeight:"500",display:"flex",alignItems:"center",justifyContent:"center",backgroundColor:"#f0f4ff"});Re.textContent=String(w+1);const ce=x({overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"});ce.textContent=C.title,ce.title=C.title,D.append(Re,ce),b.appendChild(D)}),S.appendChild(b)}const v=x({maxWidth:l?"75%":"100%",padding:l?"10px 14px":"2px 8px",borderRadius:l?Ne:"0",backgroundColor:l?ge:"transparent",color:l?he:Y,wordBreak:"break-word",fontSize:"14px",lineHeight:"1.6"});if(v.className="ago-message__content",e.content?v.appendChild(J(e.content)):e.status==="IN_PROGRESS"&&v.appendChild(Xe()),S.appendChild(v),a&&e.followUpReplies&&e.followUpReplies.length>0){const b=x({display:"flex",flexWrap:"wrap",gap:"8px",marginTop:"10px"});b.className="ago-message__followups";for(const C of e.followUpReplies){const w=document.createElement("button");w.type="button",w.className="ago-message__followup-btn",w.textContent=C,w.disabled=!be,y(w,{padding:"6px 14px",fontSize:"14px",borderRadius:Ne,border:`1px solid ${$}`,backgroundColor:j,color:Y,cursor:be?"pointer":"default",transition:"border-color 0.15s"}),Ce&&w.addEventListener("click",()=>Ce(C)),w.addEventListener("mouseenter",()=>{w.style.borderColor=pe}),w.addEventListener("mouseleave",()=>{w.style.borderColor=$}),b.appendChild(w)}S.appendChild(b)}return S}function A(){if(I.replaceChildren(),d.length===0){const a=x({textAlign:"center",color:nt,padding:"24px 16px",fontSize:"14px",lineHeight:"1.5"});a.appendChild(J(t)),I.appendChild(a)}else d.forEach((a,l)=>{I.appendChild(Pe(a,l===d.length-1))});if(W){const a=x({padding:"10px 14px",backgroundColor:"#fef2f2",color:"#dc2626",borderRadius:"12px",marginTop:"8px",fontSize:"13px",border:"1px solid #fecaca"});a.textContent=W,I.appendChild(a)}I.scrollTop=I.scrollHeight;const e=d[d.length-1];Ue(O&&e?.role==="assistant"&&e.status==="IN_PROGRESS")}function We(){for(let e=d.length-1;e>=0;e--){const a=d[e];if(a.role==="assistant"&&a.status==="IN_PROGRESS")return a}}const ve=e=>{k||(k=e.conversationId)},we=e=>{const a=We();a&&(a.content+=e.content,A())},ye=e=>{const a=d.findIndex(l=>l.id===e.id||l.role==="assistant"&&l.status==="IN_PROGRESS");a>=0?d[a]=e:d.push(e),A(),ne()},Ee=e=>{const a=d.findIndex(l=>l.id===e.id||l.role==="assistant"&&l.status==="IN_PROGRESS");a>=0?d[a]=e:d.push(e),O=!1,A(),e.status==="DONE"&&me?.({id:e.id,content:e.content})},Se=e=>{W=e.error,O=!1,d=d.filter(a=>!a.id.startsWith("temp-")),A()};g.on("message:start",ve),g.on("message:chunk",we),g.on("message:answer-complete",ye),g.on("message:complete",Ee),g.on("message:error",Se);const re=[];let _e=!1;for(const e of q??[])e.schema!=null?re.push($e.createFormCollector(e).install(g)):$e.loadFormCollector(g,e).then(a=>{_e||re.push(a.install(g))}).catch(()=>{});async function ae(e,a){const l=e.trim();if(!l&&!a?.length||O)return;N?.(l),O=!0,W=null;const S=Date.now();d.push({id:`temp-user-${S}`,conversationId:k||"",content:l,role:"user",status:"DONE",createdAt:new Date}),d.push({id:`temp-assistant-${S}`,conversationId:k||"",content:"",role:"assistant",status:"IN_PROGRESS",createdAt:new Date}),A();try{const v=await g.sendMessage(l,{conversationId:k,files:a});v.conversationId&&(k||(k=v.conversationId),X?.setActiveThread(v.conversationId,v.createdAt));const b=d.find(C=>C.id===`temp-user-${S}`);if(b&&(b.id=`user-${S}`,b.conversationId=v.conversationId),!d.some(C=>C.id===v.id)){const C=d.findIndex(w=>w.id===`temp-assistant-${S}`);C>=0?d[C]=v:d.push(v)}d=d.filter(C=>!C.id.startsWith("temp-")),O=!1,A(),R&&ie()}catch(v){W=v instanceof Error?v.message:"Failed to send message",O=!1,d=d.filter(b=>!b.id.startsWith("temp-")),A()}}async function ie(){try{const e=await g.getConversations();K.splice(0,K.length,...e)}catch{}return K}async function Ge(e){try{const a=(await g.getConversation(e))?.messages??[];a.length>0&&d.length===0&&(d=a,A())}catch{d.length===0&&(X?.clear(),k=void 0)}}return A(),ne(),k&&Ge(k),R&&ie(),{client:g,element:V,sendMessage:ae,...z?{open:le,close:de,toggle:je}:{},session:X,threads:K,refreshThreads:ie,destroy(){g.off("message:start",ve),g.off("message:chunk",we),g.off("message:answer-complete",ye),g.off("message:complete",Ee),g.off("message:error",Se),_e=!0,re.forEach(e=>e()),V.remove(),E?.remove(),n.client||g.destroy()}};function se(){if(!T)return;const e=s==="left"?"translateX(-100%)":"translateX(100%)";T.style.transform=H?"translateX(0)":e,T.setAttribute("aria-hidden",H?"false":"true"),E&&(E.style.display=H?"none":"flex")}function le(){H=!0,se(),ne()}function de(){H=!1,se()}function je(){H?de():le()}function qe(){const e="http://www.w3.org/2000/svg",a=document.createElementNS(e,"svg");a.setAttribute("width","26"),a.setAttribute("height","26"),a.setAttribute("viewBox","0 0 24 24"),a.setAttribute("fill","none");const l=document.createElementNS(e,"path");return l.setAttribute("d","M21 11.5a8.38 8.38 0 0 1-8.5 8.5 8.5 8.5 0 0 1-3.8-.9L3 21l1.9-5.7a8.5 8.5 0 0 1-.9-3.8 8.38 8.38 0 0 1 8.5-8.5 8.38 8.38 0 0 1 8.5 8.5z"),l.setAttribute("stroke","currentColor"),l.setAttribute("stroke-width","2"),l.setAttribute("stroke-linecap","round"),l.setAttribute("stroke-linejoin","round"),a.appendChild(l),a}function Xe(){const e=x({display:"flex",gap:"4px",padding:"4px 0"});for(let a=0;a<3;a++){const l=x({width:"6px",height:"6px",borderRadius:"50%",backgroundColor:"#b5bfc8",animation:"ago-pulse 1.2s ease-in-out infinite",animationDelay:`${a*.2}s`});e.appendChild(l)}return e}}function lt(o){let n=[];const r=document.createElement("form");y(r,{display:"flex",flexDirection:"column",gap:"8px",padding:"12px",borderTop:`1px solid ${$}`,backgroundColor:j}),r.className="ago-chat-input";const t=x({display:"flex",flexWrap:"wrap",gap:"6px"}),u=x({display:"flex",gap:"8px",alignItems:"flex-end"}),i=document.createElement("textarea");i.placeholder=o.placeholder,i.rows=1,y(i,{flex:"1",resize:"none",padding:"10px 12px",border:`1px solid ${$}`,borderRadius:"12px",fontSize:"14px",fontFamily:ue,lineHeight:"1.4",maxHeight:"120px",outline:"none"});const f=document.createElement("button");f.type="submit",f.textContent="Send",y(f,{padding:"10px 16px",border:"none",borderRadius:"12px",backgroundColor:ge,color:he,fontSize:"14px",fontWeight:"500",cursor:"pointer"});let s=null,p=null;o.allowFiles&&(s=document.createElement("input"),s.type="file",s.multiple=!0,y(s,{display:"none"}),p=document.createElement("button"),p.type="button",p.textContent="📎",y(p,{padding:"10px 12px",border:`1px solid ${$}`,borderRadius:"12px",backgroundColor:j,cursor:"pointer",fontSize:"14px"}),p.addEventListener("click",()=>s?.click()),s.addEventListener("change",()=>{n=[...n,...Array.from(s?.files??[])],c()}));function c(){t.replaceChildren(),n.forEach((m,R)=>{const q=x({display:"flex",alignItems:"center",gap:"4px",padding:"4px 8px",backgroundColor:"#f0f4ff",border:`1px solid ${$}`,borderRadius:"8px",fontSize:"12px"}),B=document.createElement("span");B.textContent=m.name;const N=document.createElement("button");N.type="button",N.textContent="×",y(N,{border:"none",background:"transparent",cursor:"pointer",fontSize:"14px",lineHeight:"1"}),N.addEventListener("click",()=>{n=n.filter((me,g)=>g!==R),c()}),q.append(B,N),t.appendChild(q)})}const h=()=>{const m=i.value,R=n;return i.value="",n=[],c(),{content:m,files:R}},L=()=>{const{content:m,files:R}=h();(m.trim()||R.length>0)&&o.onSend(m.trim(),R.length>0?R:void 0)};return r.addEventListener("submit",m=>{m.preventDefault(),L()}),i.addEventListener("keydown",m=>{m.key==="Enter"&&!m.shiftKey&&(m.preventDefault(),L())}),p&&u.appendChild(p),u.append(i,f),s&&r.appendChild(s),r.append(t,u),{inputRow:r,getValueAndClear:h,setDisabled:m=>{i.disabled=m,f.disabled=m,f.style.opacity=m?"0.6":"1",f.style.cursor=m?"not-allowed":"pointer"},focus:()=>i.focus()}}exports.mountChatWidget=st;exports.renderMarkdown=J;
package/dist/widget.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
- /** Widget ID (X-Widget-Id header). Auto-generated if not provided. */
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;