@useago/sdk 1.4.2 → 1.4.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.
Files changed (38) hide show
  1. package/README.md +4 -1
  2. package/dist/AgoClient-CMDVqNaH.cjs +8 -0
  3. package/dist/{AgoClient-BdtuHX7k.js → AgoClient-S8oeNnAE.js} +273 -157
  4. package/dist/angular.cjs +1 -1
  5. package/dist/angular.d.cts +121 -4
  6. package/dist/angular.d.ts +121 -4
  7. package/dist/angular.js +1 -1
  8. package/dist/{createConversationSession-B8zfTL78.cjs → createConversationSession-CmBq7uGi.cjs} +1 -1
  9. package/dist/{createConversationSession-CWpf4u6I.js → createConversationSession-DoUHdVNR.js} +1 -1
  10. package/dist/{createFormCollector-BB_l0Sia.cjs → createFormCollector-Bz_0IJ0Q.cjs} +1 -1
  11. package/dist/{createFormCollector-B4n0_diV.js → createFormCollector-vy-QvFja.js} +1 -1
  12. package/dist/createMockClient-BSr-UV8R.cjs +1 -0
  13. package/dist/{createMockClient-d-arlmCq.js → createMockClient-bAZ9KBHC.js} +18 -15
  14. package/dist/devtools.d.cts +120 -3
  15. package/dist/devtools.d.ts +120 -3
  16. package/dist/index.cjs +1 -1
  17. package/dist/index.d.cts +132 -3
  18. package/dist/index.d.ts +132 -3
  19. package/dist/index.js +4 -4
  20. package/dist/react.cjs +3 -3
  21. package/dist/react.d.cts +134 -9
  22. package/dist/react.d.ts +134 -9
  23. package/dist/react.js +440 -429
  24. package/dist/testing.cjs +1 -1
  25. package/dist/testing.d.cts +120 -3
  26. package/dist/testing.d.ts +120 -3
  27. package/dist/testing.js +1 -1
  28. package/dist/vue.cjs +1 -1
  29. package/dist/vue.d.cts +127 -4
  30. package/dist/vue.d.ts +127 -4
  31. package/dist/vue.js +1 -1
  32. package/dist/widget.cjs +3 -3
  33. package/dist/widget.d.cts +120 -3
  34. package/dist/widget.d.ts +120 -3
  35. package/dist/widget.js +120 -120
  36. package/package.json +1 -1
  37. package/dist/AgoClient-CRAnT4qE.cjs +0 -8
  38. package/dist/createMockClient-ucPENDzz.cjs +0 -1
@@ -39,12 +39,45 @@ declare class AgoClient {
39
39
  private config;
40
40
  /** Conversations already warned about an empty reply (one warning each). */
41
41
  private warnedEmptyConversations;
42
+ /** Paused turns awaiting auto-resume, keyed by assistant message id. */
43
+ private pendingResumes;
44
+ /** App-provided gate deciding WHEN a paused turn resumes (see {@link registerResumeGate}). */
45
+ private resumeGate;
42
46
  constructor(config: AgoConfig);
43
47
  /**
44
48
  * Send a message and receive a streaming response
45
49
  */
46
50
  sendMessage(content: string, options?: SendMessageOptions): Promise<AgoMessage>;
47
51
  private processSSEResponse;
52
+ private resolveClientFunctionsMode;
53
+ /**
54
+ * Register a gate deciding WHEN a paused turn resumes. The SDK still decides
55
+ * *whether* (it resumes once every waiting result is submitted); the gate only
56
+ * delays the continue call — e.g. `useAgoAutoContinueAfterNavigation` waits for
57
+ * the destination page to register its page state. One gate at a time (last
58
+ * registration wins). Returns an unregister function.
59
+ */
60
+ registerResumeGate(gate: ResumeGate): () => void;
61
+ /**
62
+ * Resume a turn paused on client function results (`WAITING_CLIENT`).
63
+ *
64
+ * Sends the CURRENT page's registered functions and context — the page may
65
+ * have changed since the pause (that's the point of pausing on a navigation) —
66
+ * and streams the continuation through the same event pipeline as
67
+ * `sendMessage`, so `message:chunk` / `message:complete` (or another
68
+ * `message:waiting-client` for chained pauses) fire as usual.
69
+ *
70
+ * The SDK calls this automatically after submitting the waiting results; call
71
+ * it manually only for custom flows (e.g. after restoring a reloaded page via
72
+ * {@link resumePendingClientFunctions}).
73
+ */
74
+ continueMessage(messageId: string): Promise<AgoMessage>;
75
+ /**
76
+ * Record one of the two auto-resume preconditions for a paused turn and fire
77
+ * the resume when both are in (see {@link PendingResume}).
78
+ */
79
+ private markResumeSignal;
80
+ private runAutoResume;
48
81
  /**
49
82
  * Detect a reply that completed as DONE with no content and no activity —
50
83
  * today's backend answers an unknown `agent` slug with an empty 200, which
@@ -77,9 +110,25 @@ declare class AgoClient {
77
110
  */
78
111
  getMessages(conversationId: string): Promise<AgoMessage[]>;
79
112
  /**
80
- * Submit form data for a tool call
113
+ * Resume a turn left paused on client function results by a page reload.
114
+ *
115
+ * A paused turn (pause mode) survives a full reload: the backend keeps the
116
+ * assistant message in `WAITING_CLIENT` with its waiting tool calls. After
117
+ * restoring the conversation (`getConversation`) and re-registering the page's
118
+ * functions, call this: it re-executes each waiting client function through the
119
+ * registry, submits the results, and continues the turn.
120
+ *
121
+ * Opt-in on purpose — re-running functions on reload can be surprising (e.g. a
122
+ * navigation function would navigate again), so the app decides. Returns the
123
+ * resumed turn's final message, or `null` when there was nothing to resume or
124
+ * some waiting function is not registered on this page.
125
+ */
126
+ resumePendingClientFunctions(conversation: Conversation): Promise<AgoMessage | null>;
127
+ /**
128
+ * Submit form data for a tool call. The response's `resume` field (pause mode
129
+ * only) tells whether the paused turn is ready to be resumed.
81
130
  */
82
- submitToolCallForm(toolCallId: string, formData: Record<string, unknown>): Promise<void>;
131
+ submitToolCallForm(toolCallId: string, formData: Record<string, unknown>): Promise<SubmitToolCallResult>;
83
132
  /**
84
133
  * Confirm a tool call
85
134
  */
@@ -152,6 +201,12 @@ declare class AgoClient {
152
201
  * the agent know *where* it is after it navigates (e.g. so auto-continuation
153
202
  * can apply page state on the destination), not just how to navigate away.
154
203
  *
204
+ * Routes may contain `:param` placeholders (`/users/:id`). Each distinct
205
+ * placeholder becomes a top-level string argument of `navigateToPage`
206
+ * (`{ page: "userDetail", id: "42" }`), so one route covers every detail
207
+ * page of an entity. Flat arguments only: nested object parameters are not
208
+ * reliably rendered to the model, so placeholders must not be named `page`.
209
+ *
155
210
  * @param navigate - A callback that performs the navigation (e.g. react-router's navigate)
156
211
  * @param routes - Map of route names to paths, with descriptions for the LLM
157
212
  */
@@ -319,6 +374,19 @@ declare interface AgoClientEvents {
319
374
  */
320
375
  "message:answer-complete": AgoMessage;
321
376
  "message:complete": AgoMessage;
377
+ /**
378
+ * The turn paused on client function call(s) (pause mode): the stream closed
379
+ * with status `WAITING_CLIENT` instead of `DONE`. `message:complete` does NOT
380
+ * fire for this stream — it fires when the resumed turn concludes, so one
381
+ * logical turn still emits exactly one `message:complete`. The SDK submits the
382
+ * function results and resumes automatically; listen to this to know the agent
383
+ * is waiting on the page (e.g. to keep a "working…" indicator up).
384
+ */
385
+ "message:waiting-client": {
386
+ conversationId: string;
387
+ messageId: string;
388
+ waitingToolCallIds: string[];
389
+ };
322
390
  /**
323
391
  * A reply finished as `DONE` with empty content and no tool calls, client
324
392
  * functions, or follow-up replies — usually an unknown `agent` slug (the
@@ -406,6 +474,16 @@ declare interface AgoConfig {
406
474
  * event fires regardless of this setting.
407
475
  */
408
476
  warnOnEmptyReply?: boolean;
477
+ /**
478
+ * How the agent loop treats client function calls (requires backend support):
479
+ * - `"placeholder"` (default): the turn continues immediately on a placeholder
480
+ * result; the real result is only visible to the agent on later turns.
481
+ * - `"pause"`: the turn stops on client function call(s) with status
482
+ * `WAITING_CLIENT`; once every result is submitted, the SDK resumes the SAME
483
+ * turn via `POST /messages/{id}/continue`, so the agent sees the real results.
484
+ * Older backends ignore the flag, so `"pause"` degrades to legacy behavior.
485
+ */
486
+ clientFunctionsMode?: ClientFunctionsMode;
409
487
  }
410
488
 
411
489
  declare type AgoEventHandler<K extends AgoEventName> = (data: AgoClientEvents[K]) => void;
@@ -536,6 +614,9 @@ declare interface ClientFunctionSchema {
536
614
  };
537
615
  }
538
616
 
617
+ /** See {@link AgoConfig.clientFunctionsMode}. */
618
+ declare type ClientFunctionsMode = "placeholder" | "pause";
619
+
539
620
  /**
540
621
  * A single piece of context the client wants the LLM to know about.
541
622
  */
@@ -694,7 +775,24 @@ declare interface FormSchema {
694
775
 
695
776
  export declare function initDevPanel(options: DevPanelOptions): void;
696
777
 
697
- declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCELED";
778
+ declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCELED"
779
+ /**
780
+ * The turn paused on client function call(s) (pause mode): the agent waits for
781
+ * every waiting call to be submitted, then the turn resumes via
782
+ * `continueMessage`. Not a final state.
783
+ */
784
+ | "WAITING_CLIENT";
785
+
786
+ /**
787
+ * Hook run before a paused turn is resumed, so the app controls WHEN the
788
+ * continuation fires (e.g. wait for the destination page to mount after a
789
+ * navigation). It must resolve — throwing or hanging blocks the resume; on
790
+ * timeout-style situations resolve anyway and let the agent conclude.
791
+ */
792
+ declare type ResumeGate = (info: {
793
+ conversationId: string;
794
+ messageId: string;
795
+ }) => Promise<void> | void;
698
796
 
699
797
  /**
700
798
  * Options for sending a message
@@ -713,6 +811,8 @@ declare interface SendMessageOptions {
713
811
  * Requires backend support for the `hidden` flag; older backends ignore it.
714
812
  */
715
813
  hidden?: boolean;
814
+ /** Per-message override of {@link AgoConfig.clientFunctionsMode}. */
815
+ clientFunctionsMode?: ClientFunctionsMode;
716
816
  }
717
817
 
718
818
  /**
@@ -754,6 +854,8 @@ declare interface SSEChunkData {
754
854
  follow_up_replies?: string[];
755
855
  satisfaction_feedback?: unknown;
756
856
  ask_to_talk_to_human?: boolean;
857
+ /** Tool call ids still awaiting a client result, sent with the final `WAITING_CLIENT` event. */
858
+ waiting_tool_call_ids?: string[];
757
859
  }
758
860
 
759
861
  /**
@@ -778,6 +880,21 @@ declare type SubmitConfig<V = Record<string, unknown>> = string | {
778
880
  destination?: string;
779
881
  } | false;
780
882
 
883
+ /**
884
+ * Response of `POST /tool-calls/{id}/submit`. `resume` is only present when the
885
+ * tool call belongs to a turn paused on client functions (pause mode): `ready`
886
+ * flips to `true` once ALL waiting calls of that message are submitted, meaning
887
+ * the turn can be resumed via `continueMessage(resume.message_id)`.
888
+ */
889
+ declare interface SubmitToolCallResult {
890
+ status: string;
891
+ result?: unknown;
892
+ resume?: {
893
+ message_id: string;
894
+ ready: boolean;
895
+ };
896
+ }
897
+
781
898
  /**
782
899
  * Tool call data from SSE stream
783
900
  */
@@ -39,12 +39,45 @@ declare class AgoClient {
39
39
  private config;
40
40
  /** Conversations already warned about an empty reply (one warning each). */
41
41
  private warnedEmptyConversations;
42
+ /** Paused turns awaiting auto-resume, keyed by assistant message id. */
43
+ private pendingResumes;
44
+ /** App-provided gate deciding WHEN a paused turn resumes (see {@link registerResumeGate}). */
45
+ private resumeGate;
42
46
  constructor(config: AgoConfig);
43
47
  /**
44
48
  * Send a message and receive a streaming response
45
49
  */
46
50
  sendMessage(content: string, options?: SendMessageOptions): Promise<AgoMessage>;
47
51
  private processSSEResponse;
52
+ private resolveClientFunctionsMode;
53
+ /**
54
+ * Register a gate deciding WHEN a paused turn resumes. The SDK still decides
55
+ * *whether* (it resumes once every waiting result is submitted); the gate only
56
+ * delays the continue call — e.g. `useAgoAutoContinueAfterNavigation` waits for
57
+ * the destination page to register its page state. One gate at a time (last
58
+ * registration wins). Returns an unregister function.
59
+ */
60
+ registerResumeGate(gate: ResumeGate): () => void;
61
+ /**
62
+ * Resume a turn paused on client function results (`WAITING_CLIENT`).
63
+ *
64
+ * Sends the CURRENT page's registered functions and context — the page may
65
+ * have changed since the pause (that's the point of pausing on a navigation) —
66
+ * and streams the continuation through the same event pipeline as
67
+ * `sendMessage`, so `message:chunk` / `message:complete` (or another
68
+ * `message:waiting-client` for chained pauses) fire as usual.
69
+ *
70
+ * The SDK calls this automatically after submitting the waiting results; call
71
+ * it manually only for custom flows (e.g. after restoring a reloaded page via
72
+ * {@link resumePendingClientFunctions}).
73
+ */
74
+ continueMessage(messageId: string): Promise<AgoMessage>;
75
+ /**
76
+ * Record one of the two auto-resume preconditions for a paused turn and fire
77
+ * the resume when both are in (see {@link PendingResume}).
78
+ */
79
+ private markResumeSignal;
80
+ private runAutoResume;
48
81
  /**
49
82
  * Detect a reply that completed as DONE with no content and no activity —
50
83
  * today's backend answers an unknown `agent` slug with an empty 200, which
@@ -77,9 +110,25 @@ declare class AgoClient {
77
110
  */
78
111
  getMessages(conversationId: string): Promise<AgoMessage[]>;
79
112
  /**
80
- * Submit form data for a tool call
113
+ * Resume a turn left paused on client function results by a page reload.
114
+ *
115
+ * A paused turn (pause mode) survives a full reload: the backend keeps the
116
+ * assistant message in `WAITING_CLIENT` with its waiting tool calls. After
117
+ * restoring the conversation (`getConversation`) and re-registering the page's
118
+ * functions, call this: it re-executes each waiting client function through the
119
+ * registry, submits the results, and continues the turn.
120
+ *
121
+ * Opt-in on purpose — re-running functions on reload can be surprising (e.g. a
122
+ * navigation function would navigate again), so the app decides. Returns the
123
+ * resumed turn's final message, or `null` when there was nothing to resume or
124
+ * some waiting function is not registered on this page.
125
+ */
126
+ resumePendingClientFunctions(conversation: Conversation): Promise<AgoMessage | null>;
127
+ /**
128
+ * Submit form data for a tool call. The response's `resume` field (pause mode
129
+ * only) tells whether the paused turn is ready to be resumed.
81
130
  */
82
- submitToolCallForm(toolCallId: string, formData: Record<string, unknown>): Promise<void>;
131
+ submitToolCallForm(toolCallId: string, formData: Record<string, unknown>): Promise<SubmitToolCallResult>;
83
132
  /**
84
133
  * Confirm a tool call
85
134
  */
@@ -152,6 +201,12 @@ declare class AgoClient {
152
201
  * the agent know *where* it is after it navigates (e.g. so auto-continuation
153
202
  * can apply page state on the destination), not just how to navigate away.
154
203
  *
204
+ * Routes may contain `:param` placeholders (`/users/:id`). Each distinct
205
+ * placeholder becomes a top-level string argument of `navigateToPage`
206
+ * (`{ page: "userDetail", id: "42" }`), so one route covers every detail
207
+ * page of an entity. Flat arguments only: nested object parameters are not
208
+ * reliably rendered to the model, so placeholders must not be named `page`.
209
+ *
155
210
  * @param navigate - A callback that performs the navigation (e.g. react-router's navigate)
156
211
  * @param routes - Map of route names to paths, with descriptions for the LLM
157
212
  */
@@ -319,6 +374,19 @@ declare interface AgoClientEvents {
319
374
  */
320
375
  "message:answer-complete": AgoMessage;
321
376
  "message:complete": AgoMessage;
377
+ /**
378
+ * The turn paused on client function call(s) (pause mode): the stream closed
379
+ * with status `WAITING_CLIENT` instead of `DONE`. `message:complete` does NOT
380
+ * fire for this stream — it fires when the resumed turn concludes, so one
381
+ * logical turn still emits exactly one `message:complete`. The SDK submits the
382
+ * function results and resumes automatically; listen to this to know the agent
383
+ * is waiting on the page (e.g. to keep a "working…" indicator up).
384
+ */
385
+ "message:waiting-client": {
386
+ conversationId: string;
387
+ messageId: string;
388
+ waitingToolCallIds: string[];
389
+ };
322
390
  /**
323
391
  * A reply finished as `DONE` with empty content and no tool calls, client
324
392
  * functions, or follow-up replies — usually an unknown `agent` slug (the
@@ -406,6 +474,16 @@ declare interface AgoConfig {
406
474
  * event fires regardless of this setting.
407
475
  */
408
476
  warnOnEmptyReply?: boolean;
477
+ /**
478
+ * How the agent loop treats client function calls (requires backend support):
479
+ * - `"placeholder"` (default): the turn continues immediately on a placeholder
480
+ * result; the real result is only visible to the agent on later turns.
481
+ * - `"pause"`: the turn stops on client function call(s) with status
482
+ * `WAITING_CLIENT`; once every result is submitted, the SDK resumes the SAME
483
+ * turn via `POST /messages/{id}/continue`, so the agent sees the real results.
484
+ * Older backends ignore the flag, so `"pause"` degrades to legacy behavior.
485
+ */
486
+ clientFunctionsMode?: ClientFunctionsMode;
409
487
  }
410
488
 
411
489
  declare type AgoEventHandler<K extends AgoEventName> = (data: AgoClientEvents[K]) => void;
@@ -536,6 +614,9 @@ declare interface ClientFunctionSchema {
536
614
  };
537
615
  }
538
616
 
617
+ /** See {@link AgoConfig.clientFunctionsMode}. */
618
+ declare type ClientFunctionsMode = "placeholder" | "pause";
619
+
539
620
  /**
540
621
  * A single piece of context the client wants the LLM to know about.
541
622
  */
@@ -694,7 +775,24 @@ declare interface FormSchema {
694
775
 
695
776
  export declare function initDevPanel(options: DevPanelOptions): void;
696
777
 
697
- declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCELED";
778
+ declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCELED"
779
+ /**
780
+ * The turn paused on client function call(s) (pause mode): the agent waits for
781
+ * every waiting call to be submitted, then the turn resumes via
782
+ * `continueMessage`. Not a final state.
783
+ */
784
+ | "WAITING_CLIENT";
785
+
786
+ /**
787
+ * Hook run before a paused turn is resumed, so the app controls WHEN the
788
+ * continuation fires (e.g. wait for the destination page to mount after a
789
+ * navigation). It must resolve — throwing or hanging blocks the resume; on
790
+ * timeout-style situations resolve anyway and let the agent conclude.
791
+ */
792
+ declare type ResumeGate = (info: {
793
+ conversationId: string;
794
+ messageId: string;
795
+ }) => Promise<void> | void;
698
796
 
699
797
  /**
700
798
  * Options for sending a message
@@ -713,6 +811,8 @@ declare interface SendMessageOptions {
713
811
  * Requires backend support for the `hidden` flag; older backends ignore it.
714
812
  */
715
813
  hidden?: boolean;
814
+ /** Per-message override of {@link AgoConfig.clientFunctionsMode}. */
815
+ clientFunctionsMode?: ClientFunctionsMode;
716
816
  }
717
817
 
718
818
  /**
@@ -754,6 +854,8 @@ declare interface SSEChunkData {
754
854
  follow_up_replies?: string[];
755
855
  satisfaction_feedback?: unknown;
756
856
  ask_to_talk_to_human?: boolean;
857
+ /** Tool call ids still awaiting a client result, sent with the final `WAITING_CLIENT` event. */
858
+ waiting_tool_call_ids?: string[];
757
859
  }
758
860
 
759
861
  /**
@@ -778,6 +880,21 @@ declare type SubmitConfig<V = Record<string, unknown>> = string | {
778
880
  destination?: string;
779
881
  } | false;
780
882
 
883
+ /**
884
+ * Response of `POST /tool-calls/{id}/submit`. `resume` is only present when the
885
+ * tool call belongs to a turn paused on client functions (pause mode): `ready`
886
+ * flips to `true` once ALL waiting calls of that message are submitted, meaning
887
+ * the turn can be resumed via `continueMessage(resume.message_id)`.
888
+ */
889
+ declare interface SubmitToolCallResult {
890
+ status: string;
891
+ result?: unknown;
892
+ resume?: {
893
+ message_id: string;
894
+ ready: boolean;
895
+ };
896
+ }
897
+
781
898
  /**
782
899
  * Tool call data from SSE stream
783
900
  */
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("./AgoClient-CRAnT4qE.cjs"),f=require("./createFormCollector-BB_l0Sia.cjs"),h=require("./createConversationSession-B8zfTL78.cjs"),p=require("./createMockClient-ucPENDzz.cjs");require("./testing.cjs");const g=require("./functions-Djnq-JAo.cjs");function w(e){return e}function S(e,o){return e.on("message:complete",o),()=>e.off("message:complete",o)}function E(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 F(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 v(e,o){return e.on("form:submitted",o),()=>e.off("form:submitted",o)}function M(e,o){return e.on("form:error",o),()=>e.off("form:error",o)}function q(e,o){return e.on("function:invoke",o),()=>e.off("function:invoke",o)}async function*k(e,o,l){const a=[];let n=null,i=!1;const m=s=>{a.push(s),n?.()},c=s=>m({type:"start",data:s}),t=s=>m({type:"chunk",data:s}),u=s=>{m({type:"complete",data:s}),i=!0,n?.()},d=s=>{m({type:"error",data:s}),i=!0,n?.()},C=s=>m({type:"toolCall",data:s});e.on("message:start",c),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(()=>{i=!0,n?.()});try{for(;!i||a.length>0;)a.length>0?yield a.shift():(await new Promise(s=>{n=s}),n=null)}finally{e.off("message:start",c),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,n,i,m;if(typeof window<"u"&&window.AGO){const t=window.AGO;o=t.basepath,l=t.widgetId,a=t.agent||t.defaultAgent,n=t.permission,i=t.email,m=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"),n=n||t("ago-permission"),i=i||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,n=n||u.getAttribute("data-ago-permission")||void 0,i=i||u.getAttribute("data-ago-user-email")||void 0)}o=e?.baseUrl||o,l=e?.widgetId||l,a=e?.agent||e?.defaultAgentId||a,n=e?.permission||n,i=e?.userEmail||i,m=e?.userJwt||m;const c=e?.debug;return o?{baseUrl:o,widgetId:l,agent:a,permission:n,userEmail:i,userJwt:m,debug:c}:null}function T(e){const o=A(e);if(!o)throw new r.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 r.AgoClient(o)}function I(e,o){return{...e,handler:o}}exports.AgoApiError=r.AgoApiError;exports.AgoClient=r.AgoClient;exports.AgoError=r.AgoError;exports.AgoFunctionError=r.AgoFunctionError;exports.AgoNetworkError=r.AgoNetworkError;exports.AgoStreamError=r.AgoStreamError;exports.ClientContextRegistry=r.ClientContextRegistry;exports.EventEmitter=r.EventEmitter;exports.FunctionRegistry=r.FunctionRegistry;exports.SSEHandler=r.SSEHandler;exports.autoDetectConfig=A;exports.canInlineImage=r.canInlineImage;exports.copyToClipboard=g.copyToClipboard;exports.createAgo=T;exports.createConversationSession=h.createConversationSession;exports.createFormCollector=f.createFormCollector;exports.createMessageStream=k;exports.createMockClient=p.createMockClient;exports.createStore=f.createStore;exports.defineFunction=w;exports.deriveFormStatus=f.deriveFormStatus;exports.formatFileSize=r.formatFileSize;exports.getLocalStorage=g.getLocalStorage;exports.getUserLocation=g.getUserLocation;exports.highlightElement=g.highlightElement;exports.isStreamNetworkError=r.isStreamNetworkError;exports.loadFormCollector=f.loadFormCollector;exports.logger=r.logger;exports.onFormError=M;exports.onFormSubmitted=v;exports.onFunctionInvoke=q;exports.onMessage=S;exports.onMessageChunk=E;exports.onMessageError=F;exports.onMessageStart=y;exports.onToolCall=b;exports.openUrl=g.openUrl;exports.safeAttachmentUrl=r.safeAttachmentUrl;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=r.validateConfig;exports.withHandler=I;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("./AgoClient-CMDVqNaH.cjs"),f=require("./createFormCollector-Bz_0IJ0Q.cjs"),h=require("./createConversationSession-CmBq7uGi.cjs"),p=require("./createMockClient-BSr-UV8R.cjs");require("./testing.cjs");const g=require("./functions-Djnq-JAo.cjs");function w(e){return e}function S(e,o){return e.on("message:complete",o),()=>e.off("message:complete",o)}function E(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 F(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 v(e,o){return e.on("form:submitted",o),()=>e.off("form:submitted",o)}function M(e,o){return e.on("form:error",o),()=>e.off("form:error",o)}function q(e,o){return e.on("function:invoke",o),()=>e.off("function:invoke",o)}async function*k(e,o,l){const a=[];let n=null,i=!1;const m=s=>{a.push(s),n?.()},c=s=>m({type:"start",data:s}),t=s=>m({type:"chunk",data:s}),u=s=>{m({type:"complete",data:s}),i=!0,n?.()},d=s=>{m({type:"error",data:s}),i=!0,n?.()},C=s=>m({type:"toolCall",data:s});e.on("message:start",c),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(()=>{i=!0,n?.()});try{for(;!i||a.length>0;)a.length>0?yield a.shift():(await new Promise(s=>{n=s}),n=null)}finally{e.off("message:start",c),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,n,i,m;if(typeof window<"u"&&window.AGO){const t=window.AGO;o=t.basepath,l=t.widgetId,a=t.agent||t.defaultAgent,n=t.permission,i=t.email,m=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"),n=n||t("ago-permission"),i=i||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,n=n||u.getAttribute("data-ago-permission")||void 0,i=i||u.getAttribute("data-ago-user-email")||void 0)}o=e?.baseUrl||o,l=e?.widgetId||l,a=e?.agent||e?.defaultAgentId||a,n=e?.permission||n,i=e?.userEmail||i,m=e?.userJwt||m;const c=e?.debug;return o?{baseUrl:o,widgetId:l,agent:a,permission:n,userEmail:i,userJwt:m,debug:c}:null}function T(e){const o=A(e);if(!o)throw new r.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 r.AgoClient(o)}function I(e,o){return{...e,handler:o}}exports.AgoApiError=r.AgoApiError;exports.AgoClient=r.AgoClient;exports.AgoError=r.AgoError;exports.AgoFunctionError=r.AgoFunctionError;exports.AgoNetworkError=r.AgoNetworkError;exports.AgoStreamError=r.AgoStreamError;exports.ClientContextRegistry=r.ClientContextRegistry;exports.EventEmitter=r.EventEmitter;exports.FunctionRegistry=r.FunctionRegistry;exports.SSEHandler=r.SSEHandler;exports.autoDetectConfig=A;exports.canInlineImage=r.canInlineImage;exports.copyToClipboard=g.copyToClipboard;exports.createAgo=T;exports.createConversationSession=h.createConversationSession;exports.createFormCollector=f.createFormCollector;exports.createMessageStream=k;exports.createMockClient=p.createMockClient;exports.createStore=f.createStore;exports.defineFunction=w;exports.deriveFormStatus=f.deriveFormStatus;exports.formatFileSize=r.formatFileSize;exports.getLocalStorage=g.getLocalStorage;exports.getUserLocation=g.getUserLocation;exports.highlightElement=g.highlightElement;exports.isStreamNetworkError=r.isStreamNetworkError;exports.loadFormCollector=f.loadFormCollector;exports.logger=r.logger;exports.onFormError=M;exports.onFormSubmitted=v;exports.onFunctionInvoke=q;exports.onMessage=S;exports.onMessageChunk=E;exports.onMessageError=F;exports.onMessageStart=y;exports.onToolCall=b;exports.openUrl=g.openUrl;exports.safeAttachmentUrl=r.safeAttachmentUrl;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=r.validateConfig;exports.withHandler=I;
package/dist/index.d.cts CHANGED
@@ -50,12 +50,45 @@ export declare class AgoClient {
50
50
  private config;
51
51
  /** Conversations already warned about an empty reply (one warning each). */
52
52
  private warnedEmptyConversations;
53
+ /** Paused turns awaiting auto-resume, keyed by assistant message id. */
54
+ private pendingResumes;
55
+ /** App-provided gate deciding WHEN a paused turn resumes (see {@link registerResumeGate}). */
56
+ private resumeGate;
53
57
  constructor(config: AgoConfig);
54
58
  /**
55
59
  * Send a message and receive a streaming response
56
60
  */
57
61
  sendMessage(content: string, options?: SendMessageOptions): Promise<AgoMessage>;
58
62
  private processSSEResponse;
63
+ private resolveClientFunctionsMode;
64
+ /**
65
+ * Register a gate deciding WHEN a paused turn resumes. The SDK still decides
66
+ * *whether* (it resumes once every waiting result is submitted); the gate only
67
+ * delays the continue call — e.g. `useAgoAutoContinueAfterNavigation` waits for
68
+ * the destination page to register its page state. One gate at a time (last
69
+ * registration wins). Returns an unregister function.
70
+ */
71
+ registerResumeGate(gate: ResumeGate): () => void;
72
+ /**
73
+ * Resume a turn paused on client function results (`WAITING_CLIENT`).
74
+ *
75
+ * Sends the CURRENT page's registered functions and context — the page may
76
+ * have changed since the pause (that's the point of pausing on a navigation) —
77
+ * and streams the continuation through the same event pipeline as
78
+ * `sendMessage`, so `message:chunk` / `message:complete` (or another
79
+ * `message:waiting-client` for chained pauses) fire as usual.
80
+ *
81
+ * The SDK calls this automatically after submitting the waiting results; call
82
+ * it manually only for custom flows (e.g. after restoring a reloaded page via
83
+ * {@link resumePendingClientFunctions}).
84
+ */
85
+ continueMessage(messageId: string): Promise<AgoMessage>;
86
+ /**
87
+ * Record one of the two auto-resume preconditions for a paused turn and fire
88
+ * the resume when both are in (see {@link PendingResume}).
89
+ */
90
+ private markResumeSignal;
91
+ private runAutoResume;
59
92
  /**
60
93
  * Detect a reply that completed as DONE with no content and no activity —
61
94
  * today's backend answers an unknown `agent` slug with an empty 200, which
@@ -88,9 +121,25 @@ export declare class AgoClient {
88
121
  */
89
122
  getMessages(conversationId: string): Promise<AgoMessage[]>;
90
123
  /**
91
- * Submit form data for a tool call
124
+ * Resume a turn left paused on client function results by a page reload.
125
+ *
126
+ * A paused turn (pause mode) survives a full reload: the backend keeps the
127
+ * assistant message in `WAITING_CLIENT` with its waiting tool calls. After
128
+ * restoring the conversation (`getConversation`) and re-registering the page's
129
+ * functions, call this: it re-executes each waiting client function through the
130
+ * registry, submits the results, and continues the turn.
131
+ *
132
+ * Opt-in on purpose — re-running functions on reload can be surprising (e.g. a
133
+ * navigation function would navigate again), so the app decides. Returns the
134
+ * resumed turn's final message, or `null` when there was nothing to resume or
135
+ * some waiting function is not registered on this page.
92
136
  */
93
- submitToolCallForm(toolCallId: string, formData: Record<string, unknown>): Promise<void>;
137
+ resumePendingClientFunctions(conversation: Conversation): Promise<AgoMessage | null>;
138
+ /**
139
+ * Submit form data for a tool call. The response's `resume` field (pause mode
140
+ * only) tells whether the paused turn is ready to be resumed.
141
+ */
142
+ submitToolCallForm(toolCallId: string, formData: Record<string, unknown>): Promise<SubmitToolCallResult>;
94
143
  /**
95
144
  * Confirm a tool call
96
145
  */
@@ -163,6 +212,12 @@ export declare class AgoClient {
163
212
  * the agent know *where* it is after it navigates (e.g. so auto-continuation
164
213
  * can apply page state on the destination), not just how to navigate away.
165
214
  *
215
+ * Routes may contain `:param` placeholders (`/users/:id`). Each distinct
216
+ * placeholder becomes a top-level string argument of `navigateToPage`
217
+ * (`{ page: "userDetail", id: "42" }`), so one route covers every detail
218
+ * page of an entity. Flat arguments only: nested object parameters are not
219
+ * reliably rendered to the model, so placeholders must not be named `page`.
220
+ *
166
221
  * @param navigate - A callback that performs the navigation (e.g. react-router's navigate)
167
222
  * @param routes - Map of route names to paths, with descriptions for the LLM
168
223
  */
@@ -330,6 +385,19 @@ export declare interface AgoClientEvents {
330
385
  */
331
386
  "message:answer-complete": AgoMessage;
332
387
  "message:complete": AgoMessage;
388
+ /**
389
+ * The turn paused on client function call(s) (pause mode): the stream closed
390
+ * with status `WAITING_CLIENT` instead of `DONE`. `message:complete` does NOT
391
+ * fire for this stream — it fires when the resumed turn concludes, so one
392
+ * logical turn still emits exactly one `message:complete`. The SDK submits the
393
+ * function results and resumes automatically; listen to this to know the agent
394
+ * is waiting on the page (e.g. to keep a "working…" indicator up).
395
+ */
396
+ "message:waiting-client": {
397
+ conversationId: string;
398
+ messageId: string;
399
+ waitingToolCallIds: string[];
400
+ };
333
401
  /**
334
402
  * A reply finished as `DONE` with empty content and no tool calls, client
335
403
  * functions, or follow-up replies — usually an unknown `agent` slug (the
@@ -417,6 +485,16 @@ export declare interface AgoConfig {
417
485
  * event fires regardless of this setting.
418
486
  */
419
487
  warnOnEmptyReply?: boolean;
488
+ /**
489
+ * How the agent loop treats client function calls (requires backend support):
490
+ * - `"placeholder"` (default): the turn continues immediately on a placeholder
491
+ * result; the real result is only visible to the agent on later turns.
492
+ * - `"pause"`: the turn stops on client function call(s) with status
493
+ * `WAITING_CLIENT`; once every result is submitted, the SDK resumes the SAME
494
+ * turn via `POST /messages/{id}/continue`, so the agent sees the real results.
495
+ * Older backends ignore the flag, so `"pause"` degrades to legacy behavior.
496
+ */
497
+ clientFunctionsMode?: ClientFunctionsMode;
420
498
  }
421
499
 
422
500
  /**
@@ -694,6 +772,9 @@ export declare interface ClientFunctionSchema {
694
772
  };
695
773
  }
696
774
 
775
+ /** See {@link AgoConfig.clientFunctionsMode}. */
776
+ export declare type ClientFunctionsMode = "placeholder" | "pause";
777
+
697
778
  /**
698
779
  * A single piece of context the client wants the LLM to know about.
699
780
  */
@@ -1276,7 +1357,13 @@ declare class Logger {
1276
1357
 
1277
1358
  export declare const logger: Logger;
1278
1359
 
1279
- export declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCELED";
1360
+ export declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCELED"
1361
+ /**
1362
+ * The turn paused on client function call(s) (pause mode): the agent waits for
1363
+ * every waiting call to be submitted, then the turn resumes via
1364
+ * `continueMessage`. Not a final state.
1365
+ */
1366
+ | "WAITING_CLIENT";
1280
1367
 
1281
1368
  export declare interface MockAgoClient extends AgoClient {
1282
1369
  /**
@@ -1386,6 +1473,17 @@ export declare interface RegisteredFunction {
1386
1473
  handler: ClientFunctionHandler;
1387
1474
  }
1388
1475
 
1476
+ /**
1477
+ * Hook run before a paused turn is resumed, so the app controls WHEN the
1478
+ * continuation fires (e.g. wait for the destination page to mount after a
1479
+ * navigation). It must resolve — throwing or hanging blocks the resume; on
1480
+ * timeout-style situations resolve anyway and let the agent conclude.
1481
+ */
1482
+ export declare type ResumeGate = (info: {
1483
+ conversationId: string;
1484
+ messageId: string;
1485
+ }) => Promise<void> | void;
1486
+
1389
1487
  /**
1390
1488
  * Allow only URL schemes that are safe to put in an `<img src>` / `<a href>`.
1391
1489
  * Presigned attachment URLs are `https:` and optimistic previews are `blob:`;
@@ -1417,6 +1515,8 @@ export declare interface SendMessageOptions {
1417
1515
  * Requires backend support for the `hidden` flag; older backends ignore it.
1418
1516
  */
1419
1517
  hidden?: boolean;
1518
+ /** Per-message override of {@link AgoConfig.clientFunctionsMode}. */
1519
+ clientFunctionsMode?: ClientFunctionsMode;
1420
1520
  }
1421
1521
 
1422
1522
  /**
@@ -1491,6 +1591,8 @@ export declare interface SSEChunkData {
1491
1591
  follow_up_replies?: string[];
1492
1592
  satisfaction_feedback?: unknown;
1493
1593
  ask_to_talk_to_human?: boolean;
1594
+ /** Tool call ids still awaiting a client result, sent with the final `WAITING_CLIENT` event. */
1595
+ waiting_tool_call_ids?: string[];
1494
1596
  }
1495
1597
 
1496
1598
  /**
@@ -1505,6 +1607,7 @@ export declare class SSEHandler {
1505
1607
  private followUpReplies;
1506
1608
  private isFirstChunk;
1507
1609
  private answerCompleteEmitted;
1610
+ private waitingClientEmitted;
1508
1611
  private firedClientFunctions;
1509
1612
  constructor(callbacks: SSEHandlerCallbacks);
1510
1613
  /**
@@ -1547,6 +1650,17 @@ declare interface SSEHandlerCallbacks {
1547
1650
  * with the message as it stands at that moment (no `followUpReplies` yet).
1548
1651
  */
1549
1652
  onAnswerComplete?: (message: AgoMessage) => void;
1653
+ /**
1654
+ * The turn paused on client function call(s) (pause mode): the backend closed
1655
+ * the stream with `status: "WAITING_CLIENT"` and the tool call ids awaiting a
1656
+ * result. {@link onComplete} does NOT fire for this stream — the turn is not
1657
+ * over; it resumes in a separate request once every result is submitted.
1658
+ */
1659
+ onWaitingClient?: (data: {
1660
+ conversationId: string;
1661
+ messageId: string;
1662
+ waitingToolCallIds: string[];
1663
+ }) => void;
1550
1664
  onComplete?: (message: AgoMessage) => void;
1551
1665
  onError?: (error: Error) => void;
1552
1666
  }
@@ -1602,6 +1716,21 @@ export declare type SubmitConfig<V = Record<string, unknown>> = string | {
1602
1716
  */
1603
1717
  export declare const submitForm: ClientFunctionDefinition;
1604
1718
 
1719
+ /**
1720
+ * Response of `POST /tool-calls/{id}/submit`. `resume` is only present when the
1721
+ * tool call belongs to a turn paused on client functions (pause mode): `ready`
1722
+ * flips to `true` once ALL waiting calls of that message are submitted, meaning
1723
+ * the turn can be resumed via `continueMessage(resume.message_id)`.
1724
+ */
1725
+ export declare interface SubmitToolCallResult {
1726
+ status: string;
1727
+ result?: unknown;
1728
+ resume?: {
1729
+ message_id: string;
1730
+ ready: boolean;
1731
+ };
1732
+ }
1733
+
1605
1734
  /**
1606
1735
  * Tool call data from SSE stream
1607
1736
  */