@useago/sdk 1.0.1 → 1.0.3

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/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
@@ -64,10 +78,11 @@ declare class AgoClient {
64
78
  * Relay a completed form collector's values to a server-configured destination.
65
79
  *
66
80
  * Used by `createFormCollector` / `useFormCollector` in `{ via: "backend" }` mode:
67
- * the browser never holds the destination URL or its secret — the backend resolves
68
- * `destination` (a named, opted-in tool) and forwards the values from the server.
81
+ * the browser never holds the destination name, URL, or its secret — the backend
82
+ * resolves the destination from the named form's stored definition and forwards
83
+ * the values from the server.
69
84
  */
70
- submitFormCollector(destination: string, values: Record<string, unknown>): Promise<unknown>;
85
+ submitFormCollector(name: string, values: Record<string, unknown>): Promise<unknown>;
71
86
  /**
72
87
  * Submit feedback for a message
73
88
  */
@@ -194,6 +209,11 @@ declare class AgoClient {
194
209
  }): Promise<AgoClientEvents[K]>;
195
210
  /**
196
211
  * Update client configuration
212
+ *
213
+ * Validates the MERGED config before committing: omitting a key (or passing
214
+ * it as `undefined`, common with spread-built partials) keeps the current
215
+ * value; an explicit empty/non-string `baseUrl` throws `config_missing_base_url`
216
+ * and leaves the client unchanged (no half-updated state).
197
217
  */
198
218
  updateConfig(config: Partial<AgoConfig>): void;
199
219
  /**
@@ -229,8 +249,23 @@ declare interface AgoClientEvents {
229
249
  */
230
250
  "message:answer-complete": AgoMessage;
231
251
  "message:complete": AgoMessage;
252
+ /**
253
+ * A reply finished as `DONE` with empty content and no tool calls, client
254
+ * functions, or follow-up replies — usually an unknown `agent` slug (the
255
+ * backend currently answers those with an empty 200). Fires after
256
+ * `message:complete` AND after `sendMessage` resolves, so subscribing right
257
+ * after `await sendMessage(...)` still catches it. `messageId` and
258
+ * `conversationId` are empty strings when the stream completed without any
259
+ * message data at all (e.g. a proxy stripped the SSE stream).
260
+ */
261
+ "message:empty": {
262
+ conversationId: string;
263
+ messageId: string;
264
+ };
232
265
  "message:error": {
233
266
  error: string;
267
+ /** Stable error code (see configuration.md#error-codes) when the failure was an AgoError. */
268
+ code?: string;
234
269
  conversationId?: string;
235
270
  messageId?: string;
236
271
  };
@@ -259,7 +294,7 @@ declare interface AgoClientEvents {
259
294
  declare interface AgoConfig {
260
295
  /** API base URL (e.g., https://YOUR-DOMAIN.useago.com) */
261
296
  baseUrl: string;
262
- /** Widget ID (X-Widget-Id header). Auto-generated if not provided. */
297
+ /** Per-visitor anonymous ID (X-User-Anon-Id header). Auto-generated if not provided. */
263
298
  widgetId?: string;
264
299
  /** Default agent (id or slug) for new conversations. Shorthand for `defaultAgentId`. */
265
300
  agent?: string;
@@ -273,6 +308,13 @@ declare interface AgoConfig {
273
308
  userJwt?: string;
274
309
  /** Enable debug logging */
275
310
  debug?: boolean;
311
+ /**
312
+ * Warn on the console when a reply completes with empty content and no tool
313
+ * calls (the usual cause is an unknown `agent` slug, which the backend
314
+ * currently answers with an empty 200). Default `true`. The `message:empty`
315
+ * event fires regardless of this setting.
316
+ */
317
+ warnOnEmptyReply?: boolean;
276
318
  }
277
319
 
278
320
  declare type AgoEventHandler<K extends AgoEventName> = (data: AgoClientEvents[K]) => void;
@@ -647,7 +689,7 @@ declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCEL
647
689
  * properties: { name: { type: "string" }, email: { type: "string" } },
648
690
  * required: ["name", "email"],
649
691
  * },
650
- * submit: { via: "backend", destination: "demo_webhook" },
692
+ * submit: { via: "backend" },
651
693
  * }],
652
694
  * });
653
695
  * // later: widget.destroy();
@@ -802,8 +844,9 @@ declare type StorageLike = Pick<Storage, "getItem" | "setItem">;
802
844
  * POSTs the values to that URL.
803
845
  * - `{ via: "client", url }` — same, written out.
804
846
  * - `{ via: "client", handler }` — the browser runs your own submit logic.
805
- * - `{ via: "backend", destination }` — the browser relays the values to the backend,
806
- * which forwards them to the server-configured destination (URL + secret stay server-side).
847
+ * - `{ via: "backend" }` — the browser relays the values to the backend, which resolves
848
+ * the destination from the form's backend-stored definition (name, URL and secret all
849
+ * stay server-side). `destination` is deprecated and ignored.
807
850
  * - `false` — collect only, no submit function.
808
851
  */
809
852
  declare type SubmitConfig<V = Record<string, unknown>> = string | {
@@ -814,7 +857,7 @@ declare type SubmitConfig<V = Record<string, unknown>> = string | {
814
857
  handler: (values: V) => Promise<unknown> | unknown;
815
858
  } | {
816
859
  via: "backend";
817
- destination: string;
860
+ destination?: string;
818
861
  } | false;
819
862
 
820
863
  /**
package/dist/widget.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
@@ -64,10 +78,11 @@ declare class AgoClient {
64
78
  * Relay a completed form collector's values to a server-configured destination.
65
79
  *
66
80
  * Used by `createFormCollector` / `useFormCollector` in `{ via: "backend" }` mode:
67
- * the browser never holds the destination URL or its secret — the backend resolves
68
- * `destination` (a named, opted-in tool) and forwards the values from the server.
81
+ * the browser never holds the destination name, URL, or its secret — the backend
82
+ * resolves the destination from the named form's stored definition and forwards
83
+ * the values from the server.
69
84
  */
70
- submitFormCollector(destination: string, values: Record<string, unknown>): Promise<unknown>;
85
+ submitFormCollector(name: string, values: Record<string, unknown>): Promise<unknown>;
71
86
  /**
72
87
  * Submit feedback for a message
73
88
  */
@@ -194,6 +209,11 @@ declare class AgoClient {
194
209
  }): Promise<AgoClientEvents[K]>;
195
210
  /**
196
211
  * Update client configuration
212
+ *
213
+ * Validates the MERGED config before committing: omitting a key (or passing
214
+ * it as `undefined`, common with spread-built partials) keeps the current
215
+ * value; an explicit empty/non-string `baseUrl` throws `config_missing_base_url`
216
+ * and leaves the client unchanged (no half-updated state).
197
217
  */
198
218
  updateConfig(config: Partial<AgoConfig>): void;
199
219
  /**
@@ -229,8 +249,23 @@ declare interface AgoClientEvents {
229
249
  */
230
250
  "message:answer-complete": AgoMessage;
231
251
  "message:complete": AgoMessage;
252
+ /**
253
+ * A reply finished as `DONE` with empty content and no tool calls, client
254
+ * functions, or follow-up replies — usually an unknown `agent` slug (the
255
+ * backend currently answers those with an empty 200). Fires after
256
+ * `message:complete` AND after `sendMessage` resolves, so subscribing right
257
+ * after `await sendMessage(...)` still catches it. `messageId` and
258
+ * `conversationId` are empty strings when the stream completed without any
259
+ * message data at all (e.g. a proxy stripped the SSE stream).
260
+ */
261
+ "message:empty": {
262
+ conversationId: string;
263
+ messageId: string;
264
+ };
232
265
  "message:error": {
233
266
  error: string;
267
+ /** Stable error code (see configuration.md#error-codes) when the failure was an AgoError. */
268
+ code?: string;
234
269
  conversationId?: string;
235
270
  messageId?: string;
236
271
  };
@@ -259,7 +294,7 @@ declare interface AgoClientEvents {
259
294
  declare interface AgoConfig {
260
295
  /** API base URL (e.g., https://YOUR-DOMAIN.useago.com) */
261
296
  baseUrl: string;
262
- /** Widget ID (X-Widget-Id header). Auto-generated if not provided. */
297
+ /** Per-visitor anonymous ID (X-User-Anon-Id header). Auto-generated if not provided. */
263
298
  widgetId?: string;
264
299
  /** Default agent (id or slug) for new conversations. Shorthand for `defaultAgentId`. */
265
300
  agent?: string;
@@ -273,6 +308,13 @@ declare interface AgoConfig {
273
308
  userJwt?: string;
274
309
  /** Enable debug logging */
275
310
  debug?: boolean;
311
+ /**
312
+ * Warn on the console when a reply completes with empty content and no tool
313
+ * calls (the usual cause is an unknown `agent` slug, which the backend
314
+ * currently answers with an empty 200). Default `true`. The `message:empty`
315
+ * event fires regardless of this setting.
316
+ */
317
+ warnOnEmptyReply?: boolean;
276
318
  }
277
319
 
278
320
  declare type AgoEventHandler<K extends AgoEventName> = (data: AgoClientEvents[K]) => void;
@@ -647,7 +689,7 @@ declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCEL
647
689
  * properties: { name: { type: "string" }, email: { type: "string" } },
648
690
  * required: ["name", "email"],
649
691
  * },
650
- * submit: { via: "backend", destination: "demo_webhook" },
692
+ * submit: { via: "backend" },
651
693
  * }],
652
694
  * });
653
695
  * // later: widget.destroy();
@@ -802,8 +844,9 @@ declare type StorageLike = Pick<Storage, "getItem" | "setItem">;
802
844
  * POSTs the values to that URL.
803
845
  * - `{ via: "client", url }` — same, written out.
804
846
  * - `{ via: "client", handler }` — the browser runs your own submit logic.
805
- * - `{ via: "backend", destination }` — the browser relays the values to the backend,
806
- * which forwards them to the server-configured destination (URL + secret stay server-side).
847
+ * - `{ via: "backend" }` — the browser relays the values to the backend, which resolves
848
+ * the destination from the form's backend-stored definition (name, URL and secret all
849
+ * stay server-side). `destination` is deprecated and ignored.
807
850
  * - `false` — collect only, no submit function.
808
851
  */
809
852
  declare type SubmitConfig<V = Record<string, unknown>> = string | {
@@ -814,7 +857,7 @@ declare type SubmitConfig<V = Record<string, unknown>> = string | {
814
857
  handler: (values: V) => Promise<unknown> | unknown;
815
858
  } | {
816
859
  via: "backend";
817
- destination: string;
860
+ destination?: string;
818
861
  } | false;
819
862
 
820
863
  /**