@useago/sdk 1.13.0 → 1.13.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/angular.cjs +1 -1
  3. package/dist/angular.d.cts +43 -10
  4. package/dist/angular.d.ts +43 -10
  5. package/dist/angular.js +4 -4
  6. package/dist/autoContinue-C3UsCvT5.cjs +1 -0
  7. package/dist/{autoContinue-CC8K9mBU.js → autoContinue-Cb4_iEbO.js} +1 -1
  8. package/dist/{createConversationSession-CiOXKWl0.cjs → createConversationSession-Digvn0GQ.cjs} +1 -1
  9. package/dist/{createConversationSession-BfJg0WyA.js → createConversationSession-DrmOaZdO.js} +1 -1
  10. package/dist/{createFormCollector-DnQl77Ko.cjs → createFormCollector-Cq7HWjtU.cjs} +1 -1
  11. package/dist/{createFormCollector-DN1xjAv5.js → createFormCollector-ki_GTlp9.js} +1 -1
  12. package/dist/devtools.d.cts +34 -5
  13. package/dist/devtools.d.ts +34 -5
  14. package/dist/index.cjs +1 -1
  15. package/dist/index.d.cts +34 -5
  16. package/dist/index.d.ts +34 -5
  17. package/dist/index.js +4 -4
  18. package/dist/react.cjs +3 -3
  19. package/dist/react.d.cts +40 -6
  20. package/dist/react.d.ts +40 -6
  21. package/dist/react.js +290 -284
  22. package/dist/testing.d.cts +34 -5
  23. package/dist/testing.d.ts +34 -5
  24. package/dist/{types-Q7t1peH-.js → types-D1ZrqVhr.js} +884 -776
  25. package/dist/types-DNr6XEwI.cjs +10 -0
  26. package/dist/vue.cjs +1 -1
  27. package/dist/vue.d.cts +38 -7
  28. package/dist/vue.d.ts +38 -7
  29. package/dist/vue.js +57 -57
  30. package/dist/widget.cjs +6 -6
  31. package/dist/widget.d.cts +34 -5
  32. package/dist/widget.d.ts +34 -5
  33. package/dist/widget.js +136 -136
  34. package/llms-full.txt +56 -3
  35. package/package.json +1 -1
  36. package/dist/autoContinue-CP9pJR-V.cjs +0 -1
  37. package/dist/types-a7teDBnC.cjs +0 -10
package/CHANGELOG.md CHANGED
@@ -5,6 +5,46 @@ All notable changes to `@useago/sdk` are documented here.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+
12
+ - **`catalogue: "onDemand"` for navigation.** Route descriptions ride in the
13
+ prompt on every message, so a large table costs on every turn. Pass
14
+ `registerNavigationFunction(navigate, routes, { catalogue: "onDemand" })`, or
15
+ the same third argument to `useAgoNavigation`, and they move into a read-only
16
+ `listPages` companion instead. `navigateToPage` keeps the page names as its
17
+ `page` enum, and an unknown page answers with the valid names. On a large
18
+ table this can cut the tool's schema by around 70%.
19
+ - **`section` on a route.** Makes `section` a required argument of `listPages`,
20
+ so the agent asks for one group at a time and no single answer has to carry
21
+ the whole catalogue. Only read under `catalogue: "onDemand"`.
22
+
23
+ Without `catalogue` the generated schema is unchanged.
24
+
25
+ - **WebMCP calls are reported to AGO for analytics.** With `webmcp` on, each call
26
+ an external agent makes through the bridge is sent to AGO, so it shows up in
27
+ the dashboard alongside the calls your AGO agent makes. One request per call,
28
+ carrying the function name, arguments, the handler's result or its failure,
29
+ the duration, and a per-tab id that groups one external agent's run of calls.
30
+ The result is the same value your AGO agent's calls already store, under the
31
+ same `maxResultBytes`. Best-effort: nothing blocks the call, and a failed
32
+ report is not retried. There is no separate switch: turning `webmcp` on also
33
+ turns reporting on.
34
+
35
+ ### Fixed
36
+
37
+ - **`useAgoFunction` no longer re-registers on every render.** `parameters` was
38
+ compared by identity, so a component that re-renders on navigation (anything
39
+ calling react-router's `useNavigate`) unregistered and re-registered its
40
+ function on every route change. Now compared by value, like `webmcp` already
41
+ was.
42
+ - **A WebMCP navigation no longer triggers a continuation on the next turn.**
43
+ `autoContinue` watched `function:invoke` without checking where the call came
44
+ from, and the flag it sets is sticky. An external `navigateToPage` would sit on
45
+ that flag until the user's next message completed, which then fired a hidden
46
+ continuation prompt for something the agent never did.
47
+
8
48
  ## [1.13.0] - 2026-09-10
9
49
 
10
50
  ### Added
package/dist/angular.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("./types-a7teDBnC.cjs"),c=require("./autoContinue-CP9pJR-V.cjs");var n=class{constructor(t){this.client=new s.AgoClient(t),this.messages$=this.fromEvent("message:complete"),this.chunks$=this.fromEvent("message:chunk"),this.errors$=this.fromEvent("message:error"),this.messageStart$=this.fromEvent("message:start")}fromEvent(t){const e=this.client;return{subscribe(i){const r=o=>{i.next?.(o)};return e.on(t,r),{unsubscribe:()=>e.off(t,r)}}}}sendMessage(t,e){return this.client.sendMessage(t,e)}transcribeAudio(t,e){return this.client.transcribeAudio(t,e)}stop(){return this.client.stop()}stopMessage(t){return this.client.stopMessage(t)}isGenerating(){return this.client.isGenerating()}getConversations(){return this.client.getConversations().then(t=>t.data)}getConversation(t){return this.client.getConversation(t)}getMessages(t){return this.client.getMessages(t)}submitToolCallForm(t,e){return this.client.submitToolCallForm(t,e)}confirmToolCall(t){return this.client.confirmToolCall(t)}rejectToolCall(t){return this.client.rejectToolCall(t)}submitFeedback(t,e,i){return this.client.submitFeedback(t,e,i)}submitConversationFeedback(t,e,i){return this.client.submitConversationFeedback(t,e,i)}registerFunction(t,e,i){typeof t=="object"?this.client.registerFunction(t):this.client.registerFunction(t,e,i)}unregisterFunction(t){return this.client.unregisterFunction(t)}registerNavigationFunction(t,e){this.client.registerNavigationFunction(t,e)}unregisterNavigationFunction(){this.client.unregisterNavigationFunction()}enableAutoContinueAfterNavigation(t){return c.attachAutoContinueAfterNavigation(this.client,t)}registerPageStateFunction(t,e){this.client.registerPageStateFunction(t,e)}unregisterPageStateFunction(t){this.client.unregisterPageStateFunction(t)}on(t,e){this.client.on(t,e)}off(t,e){this.client.off(t,e)}updateConfig(t){this.client.updateConfig(t)}getClient(){return this.client}destroy(){this.client.destroy()}};function u(t){return{provide:n,useValue:new n(t)}}exports.AgoService=n;exports.FEEDBACK_REASONS=s.FEEDBACK_REASONS;exports.provideAgo=u;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("./types-DNr6XEwI.cjs"),a=require("./autoContinue-C3UsCvT5.cjs");var n=class{constructor(t){this.client=new s.AgoClient(t),this.messages$=this.fromEvent("message:complete"),this.chunks$=this.fromEvent("message:chunk"),this.errors$=this.fromEvent("message:error"),this.messageStart$=this.fromEvent("message:start")}fromEvent(t){const e=this.client;return{subscribe(i){const r=o=>{i.next?.(o)};return e.on(t,r),{unsubscribe:()=>e.off(t,r)}}}}sendMessage(t,e){return this.client.sendMessage(t,e)}transcribeAudio(t,e){return this.client.transcribeAudio(t,e)}stop(){return this.client.stop()}stopMessage(t){return this.client.stopMessage(t)}isGenerating(){return this.client.isGenerating()}getConversations(){return this.client.getConversations().then(t=>t.data)}getConversation(t){return this.client.getConversation(t)}getMessages(t){return this.client.getMessages(t)}submitToolCallForm(t,e){return this.client.submitToolCallForm(t,e)}confirmToolCall(t){return this.client.confirmToolCall(t)}rejectToolCall(t){return this.client.rejectToolCall(t)}submitFeedback(t,e,i){return this.client.submitFeedback(t,e,i)}submitConversationFeedback(t,e,i){return this.client.submitConversationFeedback(t,e,i)}registerFunction(t,e,i){typeof t=="object"?this.client.registerFunction(t):this.client.registerFunction(t,e,i)}unregisterFunction(t){return this.client.unregisterFunction(t)}registerNavigationFunction(t,e,i){this.client.registerNavigationFunction(t,e,{catalogue:i?.catalogue==="onDemand"?"onDemand":"inline"})}unregisterNavigationFunction(){this.client.unregisterNavigationFunction()}enableAutoContinueAfterNavigation(t){return a.attachAutoContinueAfterNavigation(this.client,t)}registerPageStateFunction(t,e){this.client.registerPageStateFunction(t,e)}unregisterPageStateFunction(t){this.client.unregisterPageStateFunction(t)}on(t,e){this.client.on(t,e)}off(t,e){this.client.off(t,e)}updateConfig(t){this.client.updateConfig(t)}getClient(){return this.client}destroy(){this.client.destroy()}};function c(t){return{provide:n,useValue:new n(t)}}exports.AgoService=n;exports.FEEDBACK_REASONS=s.FEEDBACK_REASONS;exports.provideAgo=c;
@@ -75,6 +75,8 @@ declare class AgoClient {
75
75
  private config;
76
76
  /** Conversations already warned about an empty reply (one warning each). */
77
77
  private warnedEmptyConversations;
78
+ /** Client functions the backend has accepted from a WebMCP call report. */
79
+ private declaredExternally;
78
80
  /** Whether the placeholder-mode page-data warning has already been logged. */
79
81
  private warnedPageDataPlaceholder;
80
82
  /** `readPageData` companions this SDK registered, so cleanup only removes its own. */
@@ -111,6 +113,8 @@ declare class AgoClient {
111
113
  proactive: ProactiveController | null;
112
114
  /** Removes the mirrored WebMCP tools; `null` when the bridge is off. */
113
115
  private detachWebMCP;
116
+ /** The `listPages` companion is live. */
117
+ private listPagesRegistered;
114
118
  constructor(config: AgoConfig);
115
119
  private attachWebMCPBridge;
116
120
  /**
@@ -225,6 +229,11 @@ declare class AgoClient {
225
229
  */
226
230
  rejectFunction(invocationId: string): Promise<void>;
227
231
  /* Excluded from this release type: runExternalFunction */
232
+ /**
233
+ * Best-effort analytics for one WebMCP call. No agent: the caller is someone
234
+ * else's agent and cannot be known from `execute`.
235
+ */
236
+ private reportExternalCall;
228
237
  /**
229
238
  * Get a page of conversations, newest-first. `pageSize` is capped at 100 by
230
239
  * the backend (default 50). Returns the `{ data, has_more, total }` envelope
@@ -419,14 +428,15 @@ declare class AgoClient {
419
428
  * page of an entity. Flat arguments only: nested object parameters are not
420
429
  * reliably rendered to the model, so placeholders must not be named `page`.
421
430
  *
431
+ * For a large table, `{ catalogue: "onDemand" }` moves the route descriptions
432
+ * into a read-only `listPages` companion, leaving only the page names in the
433
+ * per-message schema. Routes may carry a `section` to group that companion.
434
+ *
422
435
  * @param navigate - A callback that performs the navigation (e.g. react-router's navigate)
423
436
  * @param routes - Map of route names to paths, with descriptions for the LLM
437
+ * @param opts - Where the catalogue lives; `"inline"` by default
424
438
  */
425
- registerNavigationFunction(navigate: (path: string) => void, routes: Array<{
426
- name: string;
427
- path: string;
428
- description: string;
429
- }>): void;
439
+ registerNavigationFunction(navigate: (path: string) => void, routes: NavRoute[], opts?: AgoNavigationOptions): void;
430
440
  /**
431
441
  * Unregister the navigation function and its `current-page` context provider.
432
442
  */
@@ -921,6 +931,16 @@ export declare interface AgoMessage {
921
931
  createdAt: Date;
922
932
  }
923
933
 
934
+ /**
935
+ * Where the route catalogue lives: `"inline"` (default) in `navigateToPage`'s
936
+ * description, or `"onDemand"` in a `listPages` companion's result.
937
+ */
938
+ declare type AgoNavigationOptions = {
939
+ catalogue?: "inline";
940
+ } | {
941
+ catalogue: "onDemand";
942
+ };
943
+
924
944
  /**
925
945
  * What the page currently displays, returned to the agent as the *result* of
926
946
  * `setPageState` instead of only as context on the next message.
@@ -1027,6 +1047,14 @@ export declare interface AgoPageStateOptions {
1027
1047
 
1028
1048
  export declare type AgoProvideOptions = AgoConfig;
1029
1049
 
1050
+ declare interface AgoRoute {
1051
+ name: string;
1052
+ path: string;
1053
+ description: string;
1054
+ /** Groups this route for `catalogue: "onDemand"`. Unused otherwise. */
1055
+ section?: string;
1056
+ }
1057
+
1030
1058
  /**
1031
1059
  * Angular-style service wrapping AgoClient.
1032
1060
  * Provides RxJS-like Observables for streaming events and standard Promise-based methods.
@@ -1113,11 +1141,7 @@ export declare class AgoService {
1113
1141
  /** Unregister a client-side function */
1114
1142
  unregisterFunction(name: string): boolean;
1115
1143
  /** Register navigation routes */
1116
- registerNavigationFunction(navigate: (path: string) => void, routes: Array<{
1117
- name: string;
1118
- path: string;
1119
- description: string;
1120
- }>): void;
1144
+ registerNavigationFunction(navigate: (path: string) => void, routes: AgoRoute[], opts?: AgoNavigationOptions): void;
1121
1145
  /** Unregister navigation (function + current-page context) */
1122
1146
  unregisterNavigationFunction(): void;
1123
1147
  /**
@@ -1604,6 +1628,15 @@ declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCEL
1604
1628
  */
1605
1629
  | "WAITING_CLIENT";
1606
1630
 
1631
+ /** A navigable page. `path` may carry `:param` placeholders. */
1632
+ declare interface NavRoute {
1633
+ name: string;
1634
+ path: string;
1635
+ description: string;
1636
+ /** Only read under `catalogue: "onDemand"`. */
1637
+ section?: string;
1638
+ }
1639
+
1607
1640
  /**
1608
1641
  * Optional action attached to a nudge. Accepting a `functionName` action
1609
1642
  * executes the registered client function (same `FunctionRegistry` path as
package/dist/angular.d.ts CHANGED
@@ -75,6 +75,8 @@ declare class AgoClient {
75
75
  private config;
76
76
  /** Conversations already warned about an empty reply (one warning each). */
77
77
  private warnedEmptyConversations;
78
+ /** Client functions the backend has accepted from a WebMCP call report. */
79
+ private declaredExternally;
78
80
  /** Whether the placeholder-mode page-data warning has already been logged. */
79
81
  private warnedPageDataPlaceholder;
80
82
  /** `readPageData` companions this SDK registered, so cleanup only removes its own. */
@@ -111,6 +113,8 @@ declare class AgoClient {
111
113
  proactive: ProactiveController | null;
112
114
  /** Removes the mirrored WebMCP tools; `null` when the bridge is off. */
113
115
  private detachWebMCP;
116
+ /** The `listPages` companion is live. */
117
+ private listPagesRegistered;
114
118
  constructor(config: AgoConfig);
115
119
  private attachWebMCPBridge;
116
120
  /**
@@ -225,6 +229,11 @@ declare class AgoClient {
225
229
  */
226
230
  rejectFunction(invocationId: string): Promise<void>;
227
231
  /* Excluded from this release type: runExternalFunction */
232
+ /**
233
+ * Best-effort analytics for one WebMCP call. No agent: the caller is someone
234
+ * else's agent and cannot be known from `execute`.
235
+ */
236
+ private reportExternalCall;
228
237
  /**
229
238
  * Get a page of conversations, newest-first. `pageSize` is capped at 100 by
230
239
  * the backend (default 50). Returns the `{ data, has_more, total }` envelope
@@ -419,14 +428,15 @@ declare class AgoClient {
419
428
  * page of an entity. Flat arguments only: nested object parameters are not
420
429
  * reliably rendered to the model, so placeholders must not be named `page`.
421
430
  *
431
+ * For a large table, `{ catalogue: "onDemand" }` moves the route descriptions
432
+ * into a read-only `listPages` companion, leaving only the page names in the
433
+ * per-message schema. Routes may carry a `section` to group that companion.
434
+ *
422
435
  * @param navigate - A callback that performs the navigation (e.g. react-router's navigate)
423
436
  * @param routes - Map of route names to paths, with descriptions for the LLM
437
+ * @param opts - Where the catalogue lives; `"inline"` by default
424
438
  */
425
- registerNavigationFunction(navigate: (path: string) => void, routes: Array<{
426
- name: string;
427
- path: string;
428
- description: string;
429
- }>): void;
439
+ registerNavigationFunction(navigate: (path: string) => void, routes: NavRoute[], opts?: AgoNavigationOptions): void;
430
440
  /**
431
441
  * Unregister the navigation function and its `current-page` context provider.
432
442
  */
@@ -921,6 +931,16 @@ export declare interface AgoMessage {
921
931
  createdAt: Date;
922
932
  }
923
933
 
934
+ /**
935
+ * Where the route catalogue lives: `"inline"` (default) in `navigateToPage`'s
936
+ * description, or `"onDemand"` in a `listPages` companion's result.
937
+ */
938
+ declare type AgoNavigationOptions = {
939
+ catalogue?: "inline";
940
+ } | {
941
+ catalogue: "onDemand";
942
+ };
943
+
924
944
  /**
925
945
  * What the page currently displays, returned to the agent as the *result* of
926
946
  * `setPageState` instead of only as context on the next message.
@@ -1027,6 +1047,14 @@ export declare interface AgoPageStateOptions {
1027
1047
 
1028
1048
  export declare type AgoProvideOptions = AgoConfig;
1029
1049
 
1050
+ declare interface AgoRoute {
1051
+ name: string;
1052
+ path: string;
1053
+ description: string;
1054
+ /** Groups this route for `catalogue: "onDemand"`. Unused otherwise. */
1055
+ section?: string;
1056
+ }
1057
+
1030
1058
  /**
1031
1059
  * Angular-style service wrapping AgoClient.
1032
1060
  * Provides RxJS-like Observables for streaming events and standard Promise-based methods.
@@ -1113,11 +1141,7 @@ export declare class AgoService {
1113
1141
  /** Unregister a client-side function */
1114
1142
  unregisterFunction(name: string): boolean;
1115
1143
  /** Register navigation routes */
1116
- registerNavigationFunction(navigate: (path: string) => void, routes: Array<{
1117
- name: string;
1118
- path: string;
1119
- description: string;
1120
- }>): void;
1144
+ registerNavigationFunction(navigate: (path: string) => void, routes: AgoRoute[], opts?: AgoNavigationOptions): void;
1121
1145
  /** Unregister navigation (function + current-page context) */
1122
1146
  unregisterNavigationFunction(): void;
1123
1147
  /**
@@ -1604,6 +1628,15 @@ declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCEL
1604
1628
  */
1605
1629
  | "WAITING_CLIENT";
1606
1630
 
1631
+ /** A navigable page. `path` may carry `:param` placeholders. */
1632
+ declare interface NavRoute {
1633
+ name: string;
1634
+ path: string;
1635
+ description: string;
1636
+ /** Only read under `catalogue: "onDemand"`. */
1637
+ section?: string;
1638
+ }
1639
+
1607
1640
  /**
1608
1641
  * Optional action attached to a nudge. Accepting a `functionName` action
1609
1642
  * executes the registered client function (same `FunctionRegistry` path as
package/dist/angular.js CHANGED
@@ -1,5 +1,5 @@
1
- import { n as o, t as u } from "./types-Q7t1peH-.js";
2
- import { t as a } from "./autoContinue-CC8K9mBU.js";
1
+ import { n as o, t as u } from "./types-D1ZrqVhr.js";
2
+ import { t as a } from "./autoContinue-Cb4_iEbO.js";
3
3
  var s = class {
4
4
  constructor(t) {
5
5
  this.client = new o(t), this.messages$ = this.fromEvent("message:complete"), this.chunks$ = this.fromEvent("message:chunk"), this.errors$ = this.fromEvent("message:error"), this.messageStart$ = this.fromEvent("message:start");
@@ -58,8 +58,8 @@ var s = class {
58
58
  unregisterFunction(t) {
59
59
  return this.client.unregisterFunction(t);
60
60
  }
61
- registerNavigationFunction(t, e) {
62
- this.client.registerNavigationFunction(t, e);
61
+ registerNavigationFunction(t, e, i) {
62
+ this.client.registerNavigationFunction(t, e, { catalogue: i?.catalogue === "onDemand" ? "onDemand" : "inline" });
63
63
  }
64
64
  unregisterNavigationFunction() {
65
65
  this.client.unregisterNavigationFunction();
@@ -0,0 +1 @@
1
+ var N="You have navigated the user to a new page. That page now exposes its editable state through the available setPageState function, and its current values in the page context. If the user's latest request also asked to change something on this page, call setPageState now to apply exactly those changes and nothing else. Otherwise, reply with a short confirmation only.";function p(e){return{navigationFunctions:e?.navigationFunctions??["navigateToPage"],pageStateFunctionName:e?.pageStateFunctionName??"setPageState",continuationPrompt:e?.continuationPrompt??N,maxDepth:e?.maxDepth??1,readinessTimeoutMs:e?.readinessTimeoutMs??4e3,settleMs:e?.settleMs??150,enabled:e?.enabled??!0}}function w(e,s){const a=typeof s=="function"?()=>p(s()):()=>p(s),t={navigated:!1,pausedTurnNavigated:!1,depth:0,runId:0,ourSendPending:!1},r=()=>e.getRegisteredFunctions().some(n=>n.name===a().pageStateFunctionName),g=n=>new Promise(o=>{let l=!1;const i=I=>{l||(l=!0,clearTimeout(S),e.off("context:changed",u),o(I))},v=()=>setTimeout(()=>i(n===t.runId&&r()),a().settleMs),u=()=>{if(n!==t.runId)return i(!1);r()&&(e.off("context:changed",u),v())},S=setTimeout(()=>i(!1),a().readinessTimeoutMs);r()?v():e.on("context:changed",u)}),P=async n=>{const o=++t.runId;if(!(!await g(o)||o!==t.runId)){t.depth+=1,t.ourSendPending=!0;try{await e.sendMessage(a().continuationPrompt,{conversationId:n,hidden:!0})}catch{t.ourSendPending=!1}}},d=n=>{n.conversationId&&a().navigationFunctions.includes(n.functionName)&&(t.navigated=!0)},T=e.registerResumeGate(async()=>{a().enabled&&t.pausedTurnNavigated&&(t.pausedTurnNavigated=!1,await g(++t.runId))}),f=()=>{t.pausedTurnNavigated=t.navigated,t.navigated=!1},c=()=>{t.ourSendPending||(t.depth=0,t.runId+=1)},h=n=>{t.ourSendPending=!1;const o=t.navigated;t.navigated=!1,a().enabled&&o&&(t.depth>=a().maxDepth||P(n.conversationId))},m=()=>{t.ourSendPending=!1};return e.on("function:invoke",d),e.on("message:start",c),e.on("message:waiting-client",f),e.on("message:complete",h),e.on("message:error",m),()=>{t.runId+=1,T(),e.off("function:invoke",d),e.off("message:start",c),e.off("message:waiting-client",f),e.off("message:complete",h),e.off("message:error",m)}}Object.defineProperty(exports,"attachAutoContinueAfterNavigation",{enumerable:!0,get:function(){return w}});
@@ -40,7 +40,7 @@ function w(e, o) {
40
40
  }
41
41
  }
42
42
  }, d = (n) => {
43
- a().navigationFunctions.includes(n.functionName) && (t.navigated = !0);
43
+ n.conversationId && a().navigationFunctions.includes(n.functionName) && (t.navigated = !0);
44
44
  }, T = e.registerResumeGate(async () => {
45
45
  a().enabled && t.pausedTurnNavigated && (t.pausedTurnNavigated = !1, await g(++t.runId));
46
46
  }), f = () => {
@@ -1 +1 @@
1
- const d=require("./types-a7teDBnC.cjs");var f="ago_widget_id",g="ago_last_thread",y=7200*1e3;function v(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const r=Math.floor(Math.random()*16);return(e==="x"?r:r&3|8).toString(16)})}function _(e={}){const r=e.key??f,i=e.threadKey??g,u=e.ttlMs??y,l=e.storage??(typeof localStorage<"u"?localStorage:void 0);let n=e.widgetId??"";if(!n&&l)try{n=l.getItem(r)??""}catch{}if(n||(n=v()),l)try{l.setItem(r,n)}catch{}const o=d.createStore({value:null,lastMessageAt:null},{key:i,storage:l}),s=o.get();s.value!==null&&c(s.lastMessageAt)&&o.set({value:null,lastMessageAt:null});function c(t){return t===null?!0:Number.isFinite(u)?Date.now()-t>u:!1}return{widgetId:n,key:r,getLastActiveThread(){const{value:t,lastMessageAt:a}=o.get();return t===null||c(a)?null:t},setActiveThread(t,a){const x=a==null?null:a instanceof Date?a.getTime():a;o.set({value:t,lastMessageAt:x})},clear(){o.set({value:null,lastMessageAt:null})}}}Object.defineProperty(exports,"createConversationSession",{enumerable:!0,get:function(){return _}});
1
+ const d=require("./types-DNr6XEwI.cjs");var f="ago_widget_id",g="ago_last_thread",y=7200*1e3;function v(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const r=Math.floor(Math.random()*16);return(e==="x"?r:r&3|8).toString(16)})}function _(e={}){const r=e.key??f,i=e.threadKey??g,u=e.ttlMs??y,l=e.storage??(typeof localStorage<"u"?localStorage:void 0);let n=e.widgetId??"";if(!n&&l)try{n=l.getItem(r)??""}catch{}if(n||(n=v()),l)try{l.setItem(r,n)}catch{}const o=d.createStore({value:null,lastMessageAt:null},{key:i,storage:l}),s=o.get();s.value!==null&&c(s.lastMessageAt)&&o.set({value:null,lastMessageAt:null});function c(t){return t===null?!0:Number.isFinite(u)?Date.now()-t>u:!1}return{widgetId:n,key:r,getLastActiveThread(){const{value:t,lastMessageAt:a}=o.get();return t===null||c(a)?null:t},setActiveThread(t,a){const x=a==null?null:a instanceof Date?a.getTime():a;o.set({value:t,lastMessageAt:x})},clear(){o.set({value:null,lastMessageAt:null})}}}Object.defineProperty(exports,"createConversationSession",{enumerable:!0,get:function(){return _}});
@@ -1,4 +1,4 @@
1
- import { g as d } from "./types-Q7t1peH-.js";
1
+ import { g as d } from "./types-D1ZrqVhr.js";
2
2
  var f = "ago_widget_id", g = "ago_last_thread", y = 7200 * 1e3;
3
3
  function v() {
4
4
  return typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (e) => {
@@ -1 +1 @@
1
- const C=require("./types-a7teDBnC.cjs");var W=/^[a-zA-Z0-9_-]{1,40}$/,V=n=>n==null||n==="";function S(n,e){if("anyOf"in n)return n.anyOf.some(c=>S(c,e));if("allOf"in n)return n.allOf.every(c=>S(c,e));const l=e[n.property];if(V(l))return!1;if(Array.isArray(n.value))return n.value.some(c=>String(l)===String(c));if(!n.op)return String(l)===String(n.value);const i=Number(l),a=Number(n.value);if(Number.isNaN(i)||Number.isNaN(a))return!1;switch(n.op){case">=":return i>=a;case"<=":return i<=a;case">":return i>a;case"<":return i<a;default:return C.logger.warn(`Unknown requiredWhen op "${n.op}"; treating as not required.`),!1}}function h(n,e){const l=n.properties??{},i=new Set;for(const c of n.required??[]){const d=l[c]?.requiredWhen;(!d||S(d,e))&&i.add(c)}for(const[c,d]of Object.entries(l))d.requiredWhen&&S(d.requiredWhen,e)&&i.add(c);const a=[...i].filter(c=>V(e[c]));return{missing:a,complete:a.length===0}}function B(n){const e={};for(const[l,i]of Object.entries(n.properties??{}))e[l]={type:i.type,...i.description!=null&&{description:i.description},...i.enum&&{enum:i.enum},...i.default!==void 0&&{default:i.default}};return{type:"object",properties:e,required:[]}}function A(n){const{name:e,description:l,schema:i}=n;if(!W.test(e))throw new Error(`Invalid form collector name "${e}": must match ${W} (it becomes the update_/submit_ function names).`);const a=typeof n.submit=="string"?n.submit?{via:"client",url:n.submit}:!1:n.submit??!1;n.autoSubmit===!0&&!a&&C.logger.warn(`FormCollector "${e}": autoSubmit is ignored because no submit target is configured.`);const c=(n.autoSubmit??!0)&&!!a,d=i.properties??{},$=t=>{const r={};for(const[o,s]of Object.entries(t)){const u=d[o];if(u)if(s==null)r[o]=s;else if(u.type==="number"||u.type==="integer"){const f=typeof s=="number"?s:Number(s);r[o]=Number.isNaN(f)?s:f}else u.type==="boolean"?r[o]=typeof s=="boolean"?s:s==="true"?!0:s==="false"?!1:!!s:r[o]=s}return r},N=n.initialValues??{},m=C.createStore({values:N,submitted:!1}),w=t=>{const r=m.get(),o={...r,values:{...r.values,...t}};return m.set(o),o};let b=null;const k=(t,r)=>{b?.emitFormEvent("form:error",{name:e,values:t,error:r})};let p=null;const I=async()=>{const{values:t}=m.get(),{complete:r,missing:o}=h(i,t);if(!r)return{ok:!1,missing:o};if(!a)return{ok:!1,error:"No submit target configured for this form collector."};const s=t;try{let u;if(a.via==="client")if("handler"in a)u=await a.handler(s);else{const f=await fetch(a.url,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(s)});if(!f.ok){const j=`Submit failed: HTTP ${f.status}`;return k(s,j),{ok:!1,error:j}}u=await f.json().catch(()=>{})}else{if(!b)return{ok:!1,error:"Backend submit requires install(client) (or useFormCollector) first."};u=await b.submitFormCollector(e,s)}return m.set({...m.get(),submitted:!0,submitResult:u}),b?.emitFormEvent("form:submitted",{name:e,values:s,result:u}),{ok:!0,result:u}}catch(u){const f=u instanceof Error?u.message:"Submit failed";return C.logger.error(`FormCollector "${e}" submit failed:`,u),k(s,f),{ok:!1,error:f}}},F=()=>p||(p=(async()=>{try{return await I()}finally{p=null}})(),p),q=async()=>{if(!c||!a)return null;const{values:t,submitted:r}=m.get();return r||!h(i,t).complete?null:F()},O={name:`update_${e}`,description:`Fill or update fields of the "${e}" form. ${l} Pass any subset of fields; call it repeatedly to fill the form as the user provides information. Returns the current values and which required fields are still missing.`,parameters:B(i),handler:async t=>{const r=w($(t)),{missing:o}=h(i,r.values),s=await q();return s?s.ok?{ok:!0,values:r.values,missing:o,submitted:!0}:{ok:!0,values:r.values,missing:o,submitted:!1,submitError:s.error}:{ok:!0,values:r.values,missing:o}}},y=[O];a&&!c&&y.push({name:`submit_${e}`,description:`Submit the completed "${e}" form. Only call this once every required field is collected and the user has confirmed. If fields are missing it returns them instead of submitting.`,parameters:{type:"object",properties:{}},handler:()=>F()});const D="client__",_=a?`submit_${e}`:null,R=t=>{const r=t.functionName??t.toolName;if(r)return r.startsWith(D)?r.slice(8):r},x=t=>{let r={...N},o=!1;for(const s of t){const u=R(s);u===O.name?s.arguments&&(r={...r,...$(s.arguments)}):_&&u===_&&s.status?.toLowerCase()==="done"&&(o=!0)}m.set({values:r,submitted:o})},g=`form:${e}`,v=`${g}:definition`,P=()=>({name:`Form definition: ${e}`,description:`${l} Some fields are conditionally required; the requiredWhen field in the schema tells you when each becomes required. The form schema is the following: ${JSON.stringify(i)}.`,stable:!0}),T=()=>{const{values:t,submitted:r}=m.get(),{missing:o,complete:s}=h(i,t),u=a?c?" The form is submitted automatically as soon as every required field is filled, so there is no submit function to call.":` When nothing is missing and the user confirms, call submit_${e}.`:"",f=r?`The "${e}" form has been submitted.`:`You are currently collecting information from the user to fill the "${e}" form.`;return{name:`Form: ${e}`,description:`${f} The form's schema and field requirements are in the "${v}" client context. Call update_${e} with any fields the user provides; ask only for what is still missing.${u}`,data:{values:t,missing:o,complete:s,submitted:r}}},E=t=>{x((t.messages??[]).flatMap(r=>r.toolCalls??[]))};return{name:e,store:m,functions:y,contextKey:g,contextProvider:T,definitionContextKey:v,definitionContextProvider:P,install:t=>{b=t;for(const o of y)t.register(o);t.addDynamicContext(v,P),t.addDynamicContext(g,T);const r=m.subscribe(()=>t.notifyContextChanged());return t.on("conversation:loaded",E),()=>{r();for(const o of y)t.unregisterFunction(o.name);t.removeDynamicContext(g),t.removeDynamicContext(v),t.off("conversation:loaded",E),b===t&&(b=null)}},hydrate:x,submit:F,getValues:()=>m.get().values,setValues:t=>{w($(t)),q()},reset:()=>{m.set({values:N,submitted:!1})},getStatus:()=>h(i,m.get().values)}}async function L(n,e){const l=await n.getFormCollector(e.name);return A({name:l.name,description:e.description??l.description,schema:e.schema??l.schema,submit:e.submit??l.submit,initialValues:e.initialValues,autoSubmit:e.autoSubmit??l.autoSubmit})}Object.defineProperty(exports,"createFormCollector",{enumerable:!0,get:function(){return A}});Object.defineProperty(exports,"deriveFormStatus",{enumerable:!0,get:function(){return h}});Object.defineProperty(exports,"loadFormCollector",{enumerable:!0,get:function(){return L}});
1
+ const C=require("./types-DNr6XEwI.cjs");var W=/^[a-zA-Z0-9_-]{1,40}$/,V=n=>n==null||n==="";function S(n,e){if("anyOf"in n)return n.anyOf.some(c=>S(c,e));if("allOf"in n)return n.allOf.every(c=>S(c,e));const l=e[n.property];if(V(l))return!1;if(Array.isArray(n.value))return n.value.some(c=>String(l)===String(c));if(!n.op)return String(l)===String(n.value);const i=Number(l),a=Number(n.value);if(Number.isNaN(i)||Number.isNaN(a))return!1;switch(n.op){case">=":return i>=a;case"<=":return i<=a;case">":return i>a;case"<":return i<a;default:return C.logger.warn(`Unknown requiredWhen op "${n.op}"; treating as not required.`),!1}}function h(n,e){const l=n.properties??{},i=new Set;for(const c of n.required??[]){const d=l[c]?.requiredWhen;(!d||S(d,e))&&i.add(c)}for(const[c,d]of Object.entries(l))d.requiredWhen&&S(d.requiredWhen,e)&&i.add(c);const a=[...i].filter(c=>V(e[c]));return{missing:a,complete:a.length===0}}function B(n){const e={};for(const[l,i]of Object.entries(n.properties??{}))e[l]={type:i.type,...i.description!=null&&{description:i.description},...i.enum&&{enum:i.enum},...i.default!==void 0&&{default:i.default}};return{type:"object",properties:e,required:[]}}function A(n){const{name:e,description:l,schema:i}=n;if(!W.test(e))throw new Error(`Invalid form collector name "${e}": must match ${W} (it becomes the update_/submit_ function names).`);const a=typeof n.submit=="string"?n.submit?{via:"client",url:n.submit}:!1:n.submit??!1;n.autoSubmit===!0&&!a&&C.logger.warn(`FormCollector "${e}": autoSubmit is ignored because no submit target is configured.`);const c=(n.autoSubmit??!0)&&!!a,d=i.properties??{},$=t=>{const r={};for(const[o,s]of Object.entries(t)){const u=d[o];if(u)if(s==null)r[o]=s;else if(u.type==="number"||u.type==="integer"){const f=typeof s=="number"?s:Number(s);r[o]=Number.isNaN(f)?s:f}else u.type==="boolean"?r[o]=typeof s=="boolean"?s:s==="true"?!0:s==="false"?!1:!!s:r[o]=s}return r},N=n.initialValues??{},m=C.createStore({values:N,submitted:!1}),w=t=>{const r=m.get(),o={...r,values:{...r.values,...t}};return m.set(o),o};let b=null;const k=(t,r)=>{b?.emitFormEvent("form:error",{name:e,values:t,error:r})};let p=null;const I=async()=>{const{values:t}=m.get(),{complete:r,missing:o}=h(i,t);if(!r)return{ok:!1,missing:o};if(!a)return{ok:!1,error:"No submit target configured for this form collector."};const s=t;try{let u;if(a.via==="client")if("handler"in a)u=await a.handler(s);else{const f=await fetch(a.url,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(s)});if(!f.ok){const j=`Submit failed: HTTP ${f.status}`;return k(s,j),{ok:!1,error:j}}u=await f.json().catch(()=>{})}else{if(!b)return{ok:!1,error:"Backend submit requires install(client) (or useFormCollector) first."};u=await b.submitFormCollector(e,s)}return m.set({...m.get(),submitted:!0,submitResult:u}),b?.emitFormEvent("form:submitted",{name:e,values:s,result:u}),{ok:!0,result:u}}catch(u){const f=u instanceof Error?u.message:"Submit failed";return C.logger.error(`FormCollector "${e}" submit failed:`,u),k(s,f),{ok:!1,error:f}}},F=()=>p||(p=(async()=>{try{return await I()}finally{p=null}})(),p),q=async()=>{if(!c||!a)return null;const{values:t,submitted:r}=m.get();return r||!h(i,t).complete?null:F()},O={name:`update_${e}`,description:`Fill or update fields of the "${e}" form. ${l} Pass any subset of fields; call it repeatedly to fill the form as the user provides information. Returns the current values and which required fields are still missing.`,parameters:B(i),handler:async t=>{const r=w($(t)),{missing:o}=h(i,r.values),s=await q();return s?s.ok?{ok:!0,values:r.values,missing:o,submitted:!0}:{ok:!0,values:r.values,missing:o,submitted:!1,submitError:s.error}:{ok:!0,values:r.values,missing:o}}},y=[O];a&&!c&&y.push({name:`submit_${e}`,description:`Submit the completed "${e}" form. Only call this once every required field is collected and the user has confirmed. If fields are missing it returns them instead of submitting.`,parameters:{type:"object",properties:{}},handler:()=>F()});const D="client__",_=a?`submit_${e}`:null,R=t=>{const r=t.functionName??t.toolName;if(r)return r.startsWith(D)?r.slice(8):r},x=t=>{let r={...N},o=!1;for(const s of t){const u=R(s);u===O.name?s.arguments&&(r={...r,...$(s.arguments)}):_&&u===_&&s.status?.toLowerCase()==="done"&&(o=!0)}m.set({values:r,submitted:o})},g=`form:${e}`,v=`${g}:definition`,P=()=>({name:`Form definition: ${e}`,description:`${l} Some fields are conditionally required; the requiredWhen field in the schema tells you when each becomes required. The form schema is the following: ${JSON.stringify(i)}.`,stable:!0}),T=()=>{const{values:t,submitted:r}=m.get(),{missing:o,complete:s}=h(i,t),u=a?c?" The form is submitted automatically as soon as every required field is filled, so there is no submit function to call.":` When nothing is missing and the user confirms, call submit_${e}.`:"",f=r?`The "${e}" form has been submitted.`:`You are currently collecting information from the user to fill the "${e}" form.`;return{name:`Form: ${e}`,description:`${f} The form's schema and field requirements are in the "${v}" client context. Call update_${e} with any fields the user provides; ask only for what is still missing.${u}`,data:{values:t,missing:o,complete:s,submitted:r}}},E=t=>{x((t.messages??[]).flatMap(r=>r.toolCalls??[]))};return{name:e,store:m,functions:y,contextKey:g,contextProvider:T,definitionContextKey:v,definitionContextProvider:P,install:t=>{b=t;for(const o of y)t.register(o);t.addDynamicContext(v,P),t.addDynamicContext(g,T);const r=m.subscribe(()=>t.notifyContextChanged());return t.on("conversation:loaded",E),()=>{r();for(const o of y)t.unregisterFunction(o.name);t.removeDynamicContext(g),t.removeDynamicContext(v),t.off("conversation:loaded",E),b===t&&(b=null)}},hydrate:x,submit:F,getValues:()=>m.get().values,setValues:t=>{w($(t)),q()},reset:()=>{m.set({values:N,submitted:!1})},getStatus:()=>h(i,m.get().values)}}async function L(n,e){const l=await n.getFormCollector(e.name);return A({name:l.name,description:e.description??l.description,schema:e.schema??l.schema,submit:e.submit??l.submit,initialValues:e.initialValues,autoSubmit:e.autoSubmit??l.autoSubmit})}Object.defineProperty(exports,"createFormCollector",{enumerable:!0,get:function(){return A}});Object.defineProperty(exports,"deriveFormStatus",{enumerable:!0,get:function(){return h}});Object.defineProperty(exports,"loadFormCollector",{enumerable:!0,get:function(){return L}});
@@ -1,4 +1,4 @@
1
- import { S as w, g as R } from "./types-Q7t1peH-.js";
1
+ import { S as w, g as R } from "./types-D1ZrqVhr.js";
2
2
  var j = /^[a-zA-Z0-9_-]{1,40}$/, V = (s) => s == null || s === "";
3
3
  function S(s, e) {
4
4
  if ("anyOf" in s) return s.anyOf.some((c) => S(c, e));
@@ -58,6 +58,8 @@ declare class AgoClient {
58
58
  private config;
59
59
  /** Conversations already warned about an empty reply (one warning each). */
60
60
  private warnedEmptyConversations;
61
+ /** Client functions the backend has accepted from a WebMCP call report. */
62
+ private declaredExternally;
61
63
  /** Whether the placeholder-mode page-data warning has already been logged. */
62
64
  private warnedPageDataPlaceholder;
63
65
  /** `readPageData` companions this SDK registered, so cleanup only removes its own. */
@@ -94,6 +96,8 @@ declare class AgoClient {
94
96
  proactive: ProactiveController | null;
95
97
  /** Removes the mirrored WebMCP tools; `null` when the bridge is off. */
96
98
  private detachWebMCP;
99
+ /** The `listPages` companion is live. */
100
+ private listPagesRegistered;
97
101
  constructor(config: AgoConfig);
98
102
  private attachWebMCPBridge;
99
103
  /**
@@ -208,6 +212,11 @@ declare class AgoClient {
208
212
  */
209
213
  rejectFunction(invocationId: string): Promise<void>;
210
214
  /* Excluded from this release type: runExternalFunction */
215
+ /**
216
+ * Best-effort analytics for one WebMCP call. No agent: the caller is someone
217
+ * else's agent and cannot be known from `execute`.
218
+ */
219
+ private reportExternalCall;
211
220
  /**
212
221
  * Get a page of conversations, newest-first. `pageSize` is capped at 100 by
213
222
  * the backend (default 50). Returns the `{ data, has_more, total }` envelope
@@ -402,14 +411,15 @@ declare class AgoClient {
402
411
  * page of an entity. Flat arguments only: nested object parameters are not
403
412
  * reliably rendered to the model, so placeholders must not be named `page`.
404
413
  *
414
+ * For a large table, `{ catalogue: "onDemand" }` moves the route descriptions
415
+ * into a read-only `listPages` companion, leaving only the page names in the
416
+ * per-message schema. Routes may carry a `section` to group that companion.
417
+ *
405
418
  * @param navigate - A callback that performs the navigation (e.g. react-router's navigate)
406
419
  * @param routes - Map of route names to paths, with descriptions for the LLM
420
+ * @param opts - Where the catalogue lives; `"inline"` by default
407
421
  */
408
- registerNavigationFunction(navigate: (path: string) => void, routes: Array<{
409
- name: string;
410
- path: string;
411
- description: string;
412
- }>): void;
422
+ registerNavigationFunction(navigate: (path: string) => void, routes: NavRoute[], opts?: AgoNavigationOptions): void;
413
423
  /**
414
424
  * Unregister the navigation function and its `current-page` context provider.
415
425
  */
@@ -904,6 +914,16 @@ declare interface AgoMessage {
904
914
  createdAt: Date;
905
915
  }
906
916
 
917
+ /**
918
+ * Where the route catalogue lives: `"inline"` (default) in `navigateToPage`'s
919
+ * description, or `"onDemand"` in a `listPages` companion's result.
920
+ */
921
+ declare type AgoNavigationOptions = {
922
+ catalogue?: "inline";
923
+ } | {
924
+ catalogue: "onDemand";
925
+ };
926
+
907
927
  /**
908
928
  * What the page currently displays, returned to the agent as the *result* of
909
929
  * `setPageState` instead of only as context on the next message.
@@ -1481,6 +1501,15 @@ declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCEL
1481
1501
  */
1482
1502
  | "WAITING_CLIENT";
1483
1503
 
1504
+ /** A navigable page. `path` may carry `:param` placeholders. */
1505
+ declare interface NavRoute {
1506
+ name: string;
1507
+ path: string;
1508
+ description: string;
1509
+ /** Only read under `catalogue: "onDemand"`. */
1510
+ section?: string;
1511
+ }
1512
+
1484
1513
  /**
1485
1514
  * Optional action attached to a nudge. Accepting a `functionName` action
1486
1515
  * executes the registered client function (same `FunctionRegistry` path as
@@ -58,6 +58,8 @@ declare class AgoClient {
58
58
  private config;
59
59
  /** Conversations already warned about an empty reply (one warning each). */
60
60
  private warnedEmptyConversations;
61
+ /** Client functions the backend has accepted from a WebMCP call report. */
62
+ private declaredExternally;
61
63
  /** Whether the placeholder-mode page-data warning has already been logged. */
62
64
  private warnedPageDataPlaceholder;
63
65
  /** `readPageData` companions this SDK registered, so cleanup only removes its own. */
@@ -94,6 +96,8 @@ declare class AgoClient {
94
96
  proactive: ProactiveController | null;
95
97
  /** Removes the mirrored WebMCP tools; `null` when the bridge is off. */
96
98
  private detachWebMCP;
99
+ /** The `listPages` companion is live. */
100
+ private listPagesRegistered;
97
101
  constructor(config: AgoConfig);
98
102
  private attachWebMCPBridge;
99
103
  /**
@@ -208,6 +212,11 @@ declare class AgoClient {
208
212
  */
209
213
  rejectFunction(invocationId: string): Promise<void>;
210
214
  /* Excluded from this release type: runExternalFunction */
215
+ /**
216
+ * Best-effort analytics for one WebMCP call. No agent: the caller is someone
217
+ * else's agent and cannot be known from `execute`.
218
+ */
219
+ private reportExternalCall;
211
220
  /**
212
221
  * Get a page of conversations, newest-first. `pageSize` is capped at 100 by
213
222
  * the backend (default 50). Returns the `{ data, has_more, total }` envelope
@@ -402,14 +411,15 @@ declare class AgoClient {
402
411
  * page of an entity. Flat arguments only: nested object parameters are not
403
412
  * reliably rendered to the model, so placeholders must not be named `page`.
404
413
  *
414
+ * For a large table, `{ catalogue: "onDemand" }` moves the route descriptions
415
+ * into a read-only `listPages` companion, leaving only the page names in the
416
+ * per-message schema. Routes may carry a `section` to group that companion.
417
+ *
405
418
  * @param navigate - A callback that performs the navigation (e.g. react-router's navigate)
406
419
  * @param routes - Map of route names to paths, with descriptions for the LLM
420
+ * @param opts - Where the catalogue lives; `"inline"` by default
407
421
  */
408
- registerNavigationFunction(navigate: (path: string) => void, routes: Array<{
409
- name: string;
410
- path: string;
411
- description: string;
412
- }>): void;
422
+ registerNavigationFunction(navigate: (path: string) => void, routes: NavRoute[], opts?: AgoNavigationOptions): void;
413
423
  /**
414
424
  * Unregister the navigation function and its `current-page` context provider.
415
425
  */
@@ -904,6 +914,16 @@ declare interface AgoMessage {
904
914
  createdAt: Date;
905
915
  }
906
916
 
917
+ /**
918
+ * Where the route catalogue lives: `"inline"` (default) in `navigateToPage`'s
919
+ * description, or `"onDemand"` in a `listPages` companion's result.
920
+ */
921
+ declare type AgoNavigationOptions = {
922
+ catalogue?: "inline";
923
+ } | {
924
+ catalogue: "onDemand";
925
+ };
926
+
907
927
  /**
908
928
  * What the page currently displays, returned to the agent as the *result* of
909
929
  * `setPageState` instead of only as context on the next message.
@@ -1481,6 +1501,15 @@ declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCEL
1481
1501
  */
1482
1502
  | "WAITING_CLIENT";
1483
1503
 
1504
+ /** A navigable page. `path` may carry `:param` placeholders. */
1505
+ declare interface NavRoute {
1506
+ name: string;
1507
+ path: string;
1508
+ description: string;
1509
+ /** Only read under `catalogue: "onDemand"`. */
1510
+ section?: string;
1511
+ }
1512
+
1484
1513
  /**
1485
1514
  * Optional action attached to a nudge. Accepting a `functionName` action
1486
1515
  * executes the registered client function (same `FunctionRegistry` path as
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./types-a7teDBnC.cjs"),f=require("./errors-o1IB5fEu.cjs"),S=require("./autoContinue-CP9pJR-V.cjs"),p=require("./createConversationSession-CiOXKWl0.cjs"),A=require("./createFormCollector-DnQl77Ko.cjs"),w=require("./createMockClient-BPt1gSve.cjs");require("./testing.cjs");const g=require("./functions-CPs7omgM.cjs");function F(e){return e}function _(e,t){return e.on("message:complete",t),()=>e.off("message:complete",t)}function y(e,t){return e.on("message:chunk",t),()=>e.off("message:chunk",t)}function M(e,t){return e.on("message:start",t),()=>e.off("message:start",t)}function v(e,t){return e.on("message:error",t),()=>e.off("message:error",t)}function T(e,t){return e.on("toolCall:received",t),()=>e.off("toolCall:received",t)}function R(e,t){return e.on("form:submitted",t),()=>e.off("form:submitted",t)}function b(e,t){return e.on("form:error",t),()=>e.off("form:error",t)}function q(e,t){return e.on("function:invoke",t),()=>e.off("function:invoke",t)}async function*I(e,t,l){const i=[];let n=null,a=!1;const c=s=>{i.push(s),n?.()},m=s=>c({type:"start",data:s}),d=s=>c({type:"chunk",data:s}),r=s=>{c({type:"complete",data:s}),a=!0,n?.()},u=s=>{c({type:"error",data:s}),a=!0,n?.()},E=s=>c({type:"toolCall",data:s}),h=()=>{a=!0,n?.()};e.on("message:start",m),e.on("message:chunk",d),e.on("message:complete",r),e.on("message:error",u),e.on("message:stopped",h),e.on("toolCall:received",E),e.sendMessage(t,l).catch(()=>{a=!0,n?.()});try{for(;!a||i.length>0;)i.length>0?yield i.shift():(await new Promise(s=>{n=s}),n=null)}finally{e.off("message:start",m),e.off("message:chunk",d),e.off("message:complete",r),e.off("message:error",u),e.off("message:stopped",h),e.off("toolCall:received",E)}}function C(e){let t,l,i,n,a,c,m;if(typeof window<"u"&&window.AGO){const r=window.AGO;t=r.basepath,l=r.widgetId,i=r.agent||r.defaultAgent,n=r.permission,a=r.email,c=r.jwt,m=r.metadata}if(typeof document<"u"){const r=u=>document.querySelector(`meta[name="${u}"]`)?.getAttribute("content")||void 0;t=t||r("ago-base-url"),l=l||r("ago-widget-id"),i=i||r("ago-agent")||r("ago-agent-id"),n=n||r("ago-permission"),a=a||r("ago-user-email")}if(typeof document<"u"){const r=[document.body,...Array.from(document.querySelectorAll("script[data-ago-base-url]"))].filter(Boolean);for(const u of r)u&&(t=t||u.getAttribute("data-ago-base-url")||void 0,l=l||u.getAttribute("data-ago-widget-id")||void 0,i=i||u.getAttribute("data-ago-agent")||u.getAttribute("data-ago-agent-id")||void 0,n=n||u.getAttribute("data-ago-permission")||void 0,a=a||u.getAttribute("data-ago-user-email")||void 0)}t=e?.baseUrl||t,l=e?.widgetId||l,i=e?.agent||e?.defaultAgentId||i,n=e?.permission||n,a=e?.userEmail||a,c=e?.userJwt||c,e?.metadata!==void 0&&(m=e.metadata);const d=e?.debug;return t?{baseUrl:t,widgetId:l,agent:i,permission:n,language:e?.language,userEmail:a,userJwt:c,metadata:m,debug:d}:null}function U(e){const t=C(e);if(!t)throw new f.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 o.AgoClient(t)}function D(e,t){return{...e,handler:t}}exports.ActivityLedger=o.ActivityLedger;exports.AgoApiError=f.AgoApiError;exports.AgoClient=o.AgoClient;exports.AgoError=f.AgoError;exports.AgoFunctionError=f.AgoFunctionError;exports.AgoNetworkError=f.AgoNetworkError;exports.AgoStreamError=f.AgoStreamError;exports.ClientContextRegistry=o.ClientContextRegistry;exports.DEFAULT_MAX_ACTIVITY_ENTRIES=o.DEFAULT_MAX_ACTIVITY_ENTRIES;exports.DEFAULT_MAX_ERRORS=o.DEFAULT_MAX_ERRORS;exports.DEFAULT_MAX_ERROR_AGE_MS=o.DEFAULT_MAX_ERROR_AGE_MS;exports.ErrorWatcher=o.ErrorWatcher;exports.EventEmitter=o.EventEmitter;exports.FEEDBACK_REASONS=o.FEEDBACK_REASONS;exports.FunctionRegistry=o.FunctionRegistry;exports.SSEHandler=o.SSEHandler;exports.SignalCollector=o.SignalCollector;exports.attachAutoContinueAfterNavigation=S.attachAutoContinueAfterNavigation;exports.autoDetectConfig=C;exports.canInlineImage=o.canInlineImage;exports.copyToClipboard=g.copyToClipboard;exports.createAgo=U;exports.createAgoProactive=o.createAgoProactive;exports.createConversationSession=p.createConversationSession;exports.createFormCollector=A.createFormCollector;exports.createMessageStream=I;exports.createMockClient=w.createMockClient;exports.createStore=o.createStore;exports.defineFunction=F;exports.deriveFormStatus=A.deriveFormStatus;exports.formatFileSize=o.formatFileSize;exports.getLocalStorage=g.getLocalStorage;exports.getUserLocation=g.getUserLocation;exports.highlightElement=g.highlightElement;exports.isStreamNetworkError=o.isStreamNetworkError;exports.loadFormCollector=A.loadFormCollector;exports.logger=o.logger;exports.matchesRoutePattern=o.matchesRoutePattern;exports.matchesWhen=o.matchesWhen;exports.onFormError=b;exports.onFormSubmitted=R;exports.onFunctionInvoke=q;exports.onMessage=_;exports.onMessageChunk=y;exports.onMessageError=v;exports.onMessageStart=M;exports.onToolCall=T;exports.openUrl=g.openUrl;exports.partialDeepMatch=o.partialDeepMatch;exports.safeAttachmentUrl=o.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=o.validateConfig;exports.withHandler=D;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./types-DNr6XEwI.cjs"),f=require("./errors-o1IB5fEu.cjs"),S=require("./autoContinue-C3UsCvT5.cjs"),p=require("./createConversationSession-Digvn0GQ.cjs"),A=require("./createFormCollector-Cq7HWjtU.cjs"),w=require("./createMockClient-BPt1gSve.cjs");require("./testing.cjs");const g=require("./functions-CPs7omgM.cjs");function F(e){return e}function _(e,t){return e.on("message:complete",t),()=>e.off("message:complete",t)}function y(e,t){return e.on("message:chunk",t),()=>e.off("message:chunk",t)}function M(e,t){return e.on("message:start",t),()=>e.off("message:start",t)}function v(e,t){return e.on("message:error",t),()=>e.off("message:error",t)}function T(e,t){return e.on("toolCall:received",t),()=>e.off("toolCall:received",t)}function R(e,t){return e.on("form:submitted",t),()=>e.off("form:submitted",t)}function b(e,t){return e.on("form:error",t),()=>e.off("form:error",t)}function q(e,t){return e.on("function:invoke",t),()=>e.off("function:invoke",t)}async function*I(e,t,l){const i=[];let n=null,a=!1;const c=s=>{i.push(s),n?.()},m=s=>c({type:"start",data:s}),d=s=>c({type:"chunk",data:s}),r=s=>{c({type:"complete",data:s}),a=!0,n?.()},u=s=>{c({type:"error",data:s}),a=!0,n?.()},E=s=>c({type:"toolCall",data:s}),h=()=>{a=!0,n?.()};e.on("message:start",m),e.on("message:chunk",d),e.on("message:complete",r),e.on("message:error",u),e.on("message:stopped",h),e.on("toolCall:received",E),e.sendMessage(t,l).catch(()=>{a=!0,n?.()});try{for(;!a||i.length>0;)i.length>0?yield i.shift():(await new Promise(s=>{n=s}),n=null)}finally{e.off("message:start",m),e.off("message:chunk",d),e.off("message:complete",r),e.off("message:error",u),e.off("message:stopped",h),e.off("toolCall:received",E)}}function C(e){let t,l,i,n,a,c,m;if(typeof window<"u"&&window.AGO){const r=window.AGO;t=r.basepath,l=r.widgetId,i=r.agent||r.defaultAgent,n=r.permission,a=r.email,c=r.jwt,m=r.metadata}if(typeof document<"u"){const r=u=>document.querySelector(`meta[name="${u}"]`)?.getAttribute("content")||void 0;t=t||r("ago-base-url"),l=l||r("ago-widget-id"),i=i||r("ago-agent")||r("ago-agent-id"),n=n||r("ago-permission"),a=a||r("ago-user-email")}if(typeof document<"u"){const r=[document.body,...Array.from(document.querySelectorAll("script[data-ago-base-url]"))].filter(Boolean);for(const u of r)u&&(t=t||u.getAttribute("data-ago-base-url")||void 0,l=l||u.getAttribute("data-ago-widget-id")||void 0,i=i||u.getAttribute("data-ago-agent")||u.getAttribute("data-ago-agent-id")||void 0,n=n||u.getAttribute("data-ago-permission")||void 0,a=a||u.getAttribute("data-ago-user-email")||void 0)}t=e?.baseUrl||t,l=e?.widgetId||l,i=e?.agent||e?.defaultAgentId||i,n=e?.permission||n,a=e?.userEmail||a,c=e?.userJwt||c,e?.metadata!==void 0&&(m=e.metadata);const d=e?.debug;return t?{baseUrl:t,widgetId:l,agent:i,permission:n,language:e?.language,userEmail:a,userJwt:c,metadata:m,debug:d}:null}function U(e){const t=C(e);if(!t)throw new f.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 o.AgoClient(t)}function D(e,t){return{...e,handler:t}}exports.ActivityLedger=o.ActivityLedger;exports.AgoApiError=f.AgoApiError;exports.AgoClient=o.AgoClient;exports.AgoError=f.AgoError;exports.AgoFunctionError=f.AgoFunctionError;exports.AgoNetworkError=f.AgoNetworkError;exports.AgoStreamError=f.AgoStreamError;exports.ClientContextRegistry=o.ClientContextRegistry;exports.DEFAULT_MAX_ACTIVITY_ENTRIES=o.DEFAULT_MAX_ACTIVITY_ENTRIES;exports.DEFAULT_MAX_ERRORS=o.DEFAULT_MAX_ERRORS;exports.DEFAULT_MAX_ERROR_AGE_MS=o.DEFAULT_MAX_ERROR_AGE_MS;exports.ErrorWatcher=o.ErrorWatcher;exports.EventEmitter=o.EventEmitter;exports.FEEDBACK_REASONS=o.FEEDBACK_REASONS;exports.FunctionRegistry=o.FunctionRegistry;exports.SSEHandler=o.SSEHandler;exports.SignalCollector=o.SignalCollector;exports.attachAutoContinueAfterNavigation=S.attachAutoContinueAfterNavigation;exports.autoDetectConfig=C;exports.canInlineImage=o.canInlineImage;exports.copyToClipboard=g.copyToClipboard;exports.createAgo=U;exports.createAgoProactive=o.createAgoProactive;exports.createConversationSession=p.createConversationSession;exports.createFormCollector=A.createFormCollector;exports.createMessageStream=I;exports.createMockClient=w.createMockClient;exports.createStore=o.createStore;exports.defineFunction=F;exports.deriveFormStatus=A.deriveFormStatus;exports.formatFileSize=o.formatFileSize;exports.getLocalStorage=g.getLocalStorage;exports.getUserLocation=g.getUserLocation;exports.highlightElement=g.highlightElement;exports.isStreamNetworkError=o.isStreamNetworkError;exports.loadFormCollector=A.loadFormCollector;exports.logger=o.logger;exports.matchesRoutePattern=o.matchesRoutePattern;exports.matchesWhen=o.matchesWhen;exports.onFormError=b;exports.onFormSubmitted=R;exports.onFunctionInvoke=q;exports.onMessage=_;exports.onMessageChunk=y;exports.onMessageError=v;exports.onMessageStart=M;exports.onToolCall=T;exports.openUrl=g.openUrl;exports.partialDeepMatch=o.partialDeepMatch;exports.safeAttachmentUrl=o.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=o.validateConfig;exports.withHandler=D;