@useago/sdk 1.12.0 → 1.13.1

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 (51) hide show
  1. package/CHANGELOG.md +111 -4
  2. package/README.md +73 -0
  3. package/dist/angular.cjs +1 -1
  4. package/dist/angular.d.cts +140 -38
  5. package/dist/angular.d.ts +140 -38
  6. package/dist/angular.js +7 -4
  7. package/dist/autoContinue-C3UsCvT5.cjs +1 -0
  8. package/dist/{autoContinue-CC8K9mBU.js → autoContinue-Cb4_iEbO.js} +1 -1
  9. package/dist/{createConversationSession-B1Qn-y0I.js → createConversationSession-D0vks-8C.js} +1 -1
  10. package/dist/{createConversationSession-B3v_xOU7.cjs → createConversationSession-Ri3EKIJU.cjs} +1 -1
  11. package/dist/{createFormCollector-m79zk_NA.js → createFormCollector-BMN-blXs.js} +1 -1
  12. package/dist/{createFormCollector-FvwDOqnV.cjs → createFormCollector-BNCMIUw2.cjs} +1 -1
  13. package/dist/createMockClient-BPt1gSve.cjs +1 -0
  14. package/dist/{createMockClient-Beao82tu.js → createMockClient-YoYr3pQr.js} +1 -0
  15. package/dist/devtools.cjs +4 -4
  16. package/dist/devtools.d.cts +129 -33
  17. package/dist/devtools.d.ts +129 -33
  18. package/dist/devtools.js +87 -84
  19. package/dist/helpers.d.cts +42 -12
  20. package/dist/helpers.d.ts +42 -12
  21. package/dist/index.cjs +1 -1
  22. package/dist/index.d.cts +135 -40
  23. package/dist/index.d.ts +135 -40
  24. package/dist/index.js +44 -43
  25. package/dist/react.cjs +4 -4
  26. package/dist/react.d.cts +187 -34
  27. package/dist/react.d.ts +187 -34
  28. package/dist/react.js +822 -729
  29. package/dist/speechToText-BV7qxqPF.js +704 -0
  30. package/dist/speechToText-ZciRyyJE.cjs +1 -0
  31. package/dist/testing.cjs +1 -1
  32. package/dist/testing.d.cts +129 -33
  33. package/dist/testing.d.ts +129 -33
  34. package/dist/testing.js +1 -1
  35. package/dist/types-Ck3iZG0K.cjs +10 -0
  36. package/dist/{types-Ct1hlKwg.js → types-fX-VoHfa.js} +1042 -759
  37. package/dist/vue.cjs +1 -1
  38. package/dist/vue.d.cts +143 -35
  39. package/dist/vue.d.ts +143 -35
  40. package/dist/vue.js +133 -131
  41. package/dist/widget.cjs +6 -6
  42. package/dist/widget.d.cts +161 -33
  43. package/dist/widget.d.ts +161 -33
  44. package/dist/widget.js +1702 -1757
  45. package/llms-full.txt +166 -1
  46. package/package.json +1 -1
  47. package/dist/autoContinue-CP9pJR-V.cjs +0 -1
  48. package/dist/createMockClient-BEOXI8yW.cjs +0 -1
  49. package/dist/sheetController-BThJRtOu.cjs +0 -1
  50. package/dist/sheetController-aEKXIvjk.js +0 -343
  51. package/dist/types-mcW8vB1U.cjs +0 -10
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. */
@@ -109,7 +111,12 @@ declare class AgoClient {
109
111
  * `null` otherwise.
110
112
  */
111
113
  proactive: ProactiveController | null;
114
+ /** Removes the mirrored WebMCP tools; `null` when the bridge is off. */
115
+ private detachWebMCP;
116
+ /** The `listPages` companion is live. */
117
+ private listPagesRegistered;
112
118
  constructor(config: AgoConfig);
119
+ private attachWebMCPBridge;
113
120
  /**
114
121
  * Send a message and receive a streaming response
115
122
  */
@@ -221,6 +228,12 @@ declare class AgoClient {
221
228
  * (the agent decides what to do next). No-op if the invocation is unknown.
222
229
  */
223
230
  rejectFunction(invocationId: string): Promise<void>;
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;
224
237
  /**
225
238
  * Get a page of conversations, newest-first. `pageSize` is capped at 100 by
226
239
  * the backend (default 50). Returns the `{ data, has_more, total }` envelope
@@ -240,11 +253,20 @@ declare class AgoClient {
240
253
  * `SSEHandler.parseToolCall` so persisted and streamed tool calls match.
241
254
  */
242
255
  private static mapPersistedToolCalls;
256
+ /**
257
+ * Transcribe an audio file into editable text (`POST /api/sdk/v1/audio/transcriptions`).
258
+ * Requires speech to text to be enabled for the tenant. Supports FLAC, MP3,
259
+ * MP4, MPEG, MPGA, M4A, OGG, WAV and WebM files up to 25 MB.
260
+ * The filename must include the matching extension. For a MediaRecorder blob,
261
+ * wrap it in a File with the recording's extension and MIME type.
262
+ * Show the returned text as a draft; call `sendMessage` when the user sends it.
263
+ */
264
+ transcribeAudio(file: File, options?: TranscribeAudioOptions): Promise<AudioTranscription>;
243
265
  /**
244
266
  * The tenant's SDK configuration (`GET /api/sdk/v1/config`): per-permission
245
267
  * agents, the ticket form the agent's `ago_ticketing` tool opens, and the
246
- * file-attachment flag. The vanilla widget fetches it once, when a ticket
247
- * form first appears in a conversation.
268
+ * file-attachment and speech-to-text flags. The vanilla widget fetches it
269
+ * once, when a ticket form first appears in a conversation.
248
270
  */
249
271
  getConfig(): Promise<SdkConfig>;
250
272
  /**
@@ -381,6 +403,9 @@ declare class AgoClient {
381
403
  * Get all registered function schemas
382
404
  */
383
405
  getRegisteredFunctions(): ClientFunctionSchema[];
406
+ /** The callback form of `functions:changed`. Returns an unsubscribe. */
407
+ onFunctionsChanged(listener: () => void): () => void;
408
+ /* Excluded from this release type: getFunctionRegistrations */
384
409
  /**
385
410
  * Execute a registered client function locally, through the same
386
411
  * FunctionRegistry path (result-size guard, error wrapping) as agent-invoked
@@ -403,14 +428,15 @@ declare class AgoClient {
403
428
  * page of an entity. Flat arguments only: nested object parameters are not
404
429
  * reliably rendered to the model, so placeholders must not be named `page`.
405
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
+ *
406
435
  * @param navigate - A callback that performs the navigation (e.g. react-router's navigate)
407
436
  * @param routes - Map of route names to paths, with descriptions for the LLM
437
+ * @param opts - Where the catalogue lives; `"inline"` by default
408
438
  */
409
- registerNavigationFunction(navigate: (path: string) => void, routes: Array<{
410
- name: string;
411
- path: string;
412
- description: string;
413
- }>): void;
439
+ registerNavigationFunction(navigate: (path: string) => void, routes: NavRoute[], opts?: AgoNavigationOptions): void;
414
440
  /**
415
441
  * Unregister the navigation function and its `current-page` context provider.
416
442
  */
@@ -713,6 +739,8 @@ export declare interface AgoClientEvents {
713
739
  * call running immediately.
714
740
  */
715
741
  "function:awaiting-approval": ClientFunctionInvocation;
742
+ /** A function was registered or unregistered, or the registry cleared. */
743
+ "functions:changed": ClientFunctionSchema[];
716
744
  "function:result": {
717
745
  invocationId: string;
718
746
  result: unknown;
@@ -785,6 +813,8 @@ export declare interface AgoConfig {
785
813
  defaultAgentId?: string;
786
814
  /** Permission name to apply to all requests (sent as `X-Widget-Permission`). Mirrors the widget's `window.AGO.permission`. */
787
815
  permission?: string;
816
+ /** Interface locale selected by the host app, sent as Accept-Language. Null clears the override. */
817
+ language?: string | null;
788
818
  /** User email for identification */
789
819
  userEmail?: string;
790
820
  /** JWT token for authenticated users */
@@ -862,6 +892,15 @@ export declare interface AgoConfig {
862
892
  * mode's `jsErrors` signal. See `client.reportError()` for caught errors.
863
893
  */
864
894
  errorWatcher?: boolean | ErrorWatcherOptions;
895
+ /** Mirror every registered client function into the browser's WebMCP registry
896
+ * (`document.modelContext`), so an external agent can call the same functions
897
+ * the in-app agent calls. Off by default; no-ops without WebMCP.
898
+ *
899
+ * A mirrored function runs immediately: the approval gate
900
+ * ({@link approvalPolicy}, `requiresApproval`) covers the agent loop only.
901
+ * Use `webmcp: false` on a definition to keep it out.
902
+ */
903
+ webmcp?: boolean;
865
904
  }
866
905
 
867
906
  declare type AgoEventHandler<K extends AgoEventName> = (data: AgoClientEvents[K]) => void;
@@ -892,6 +931,16 @@ export declare interface AgoMessage {
892
931
  createdAt: Date;
893
932
  }
894
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
+
895
944
  /**
896
945
  * What the page currently displays, returned to the agent as the *result* of
897
946
  * `setPageState` instead of only as context on the next message.
@@ -998,6 +1047,14 @@ export declare interface AgoPageStateOptions {
998
1047
 
999
1048
  export declare type AgoProvideOptions = AgoConfig;
1000
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
+
1001
1058
  /**
1002
1059
  * Angular-style service wrapping AgoClient.
1003
1060
  * Provides RxJS-like Observables for streaming events and standard Promise-based methods.
@@ -1048,6 +1105,8 @@ export declare class AgoService {
1048
1105
  private fromEvent;
1049
1106
  /** Send a message and get a streaming response */
1050
1107
  sendMessage(content: string, options?: SendMessageOptions): Promise<AgoMessage>;
1108
+ /** Transcribe an audio file into an editable draft. */
1109
+ transcribeAudio(file: File, options?: TranscribeAudioOptions): Promise<AudioTranscription>;
1051
1110
  /**
1052
1111
  * Stop the turn that is generating: closes the stream and tells the backend to
1053
1112
  * stop generating. The partial answer is kept and the message ends as
@@ -1082,11 +1141,7 @@ export declare class AgoService {
1082
1141
  /** Unregister a client-side function */
1083
1142
  unregisterFunction(name: string): boolean;
1084
1143
  /** Register navigation routes */
1085
- registerNavigationFunction(navigate: (path: string) => void, routes: Array<{
1086
- name: string;
1087
- path: string;
1088
- description: string;
1089
- }>): void;
1144
+ registerNavigationFunction(navigate: (path: string) => void, routes: AgoRoute[], opts?: AgoNavigationOptions): void;
1090
1145
  /** Unregister navigation (function + current-page context) */
1091
1146
  unregisterNavigationFunction(): void;
1092
1147
  /**
@@ -1180,6 +1235,11 @@ declare type AgoStateSetResult = {
1180
1235
  result: "unchanged";
1181
1236
  };
1182
1237
 
1238
+ /** Editable text returned by `AgoClient.transcribeAudio`. */
1239
+ export declare interface AudioTranscription {
1240
+ text: string;
1241
+ }
1242
+
1183
1243
  /** One JavaScript error captured on the page (deduplicated, see `count`). */
1184
1244
  declare interface CapturedError {
1185
1245
  type: CapturedErrorType;
@@ -1219,22 +1279,11 @@ declare type CapturedErrorType = "error" | "unhandledrejection" | "console" | "m
1219
1279
  * client.registerFunction(fn);
1220
1280
  * ```
1221
1281
  */
1222
- declare interface ClientFunctionDefinition {
1282
+ declare interface ClientFunctionDefinition extends ClientFunctionSettings {
1223
1283
  name: string;
1224
1284
  description: string;
1225
1285
  parameters: ClientFunctionSchema["parameters"];
1226
1286
  handler: ClientFunctionHandler;
1227
- /**
1228
- * Max serialized result size in bytes before the SDK truncates it to a
1229
- * flagged preview (default: `AgoConfig.maxFunctionResultBytes`, 50 000).
1230
- * `Infinity` disables the guard for this function.
1231
- */
1232
- maxResultBytes?: number;
1233
- /**
1234
- * Require explicit user approval before this function runs. See
1235
- * {@link AgoConfig.approvalPolicy} — pause mode only. ORs with the policy.
1236
- */
1237
- requiresApproval?: boolean;
1238
1287
  }
1239
1288
 
1240
1289
  /**
@@ -1253,20 +1302,7 @@ declare interface ClientFunctionInvocation {
1253
1302
  * Schema-plus-settings object accepted when registering a function: the schema
1254
1303
  * (minus `name`) and SDK-side options that are NOT sent to the backend.
1255
1304
  */
1256
- declare type ClientFunctionRegisterOptions = Omit<ClientFunctionSchema, "name"> & {
1257
- /**
1258
- * Max serialized result size in bytes before the SDK truncates it to a
1259
- * flagged preview. Overrides the client-level default
1260
- * (`AgoConfig.maxFunctionResultBytes`, 50 000 by default). `Infinity`
1261
- * disables the guard for this function.
1262
- */
1263
- maxResultBytes?: number;
1264
- /**
1265
- * Require explicit user approval before this function runs. See
1266
- * {@link AgoConfig.approvalPolicy} — pause mode only. ORs with the policy.
1267
- */
1268
- requiresApproval?: boolean;
1269
- };
1305
+ declare type ClientFunctionRegisterOptions = Omit<ClientFunctionSchema, "name"> & ClientFunctionSettings;
1270
1306
 
1271
1307
  /**
1272
1308
  * Schema for a client-side function that AGO can call
@@ -1293,6 +1329,28 @@ declare interface ClientFunctionSchema {
1293
1329
  };
1294
1330
  }
1295
1331
 
1332
+ /** SDK-side function settings that are never sent to the backend. */
1333
+ declare interface ClientFunctionSettings {
1334
+ /**
1335
+ * Max serialized result size in bytes before the SDK truncates it to a
1336
+ * flagged preview. Overrides the client-level default
1337
+ * (`AgoConfig.maxFunctionResultBytes`, 50 000 by default). `Infinity`
1338
+ * disables the guard for this function.
1339
+ */
1340
+ maxResultBytes?: number;
1341
+ /**
1342
+ * Require explicit user approval before this function runs. See
1343
+ * {@link AgoConfig.approvalPolicy} — pause mode only. ORs with the policy.
1344
+ */
1345
+ requiresApproval?: boolean;
1346
+ /**
1347
+ * WebMCP metadata, read only when the bridge is on (`AgoConfig.webmcp`).
1348
+ * `false` keeps this function out of WebMCP while leaving it available to the
1349
+ * in-app agent.
1350
+ */
1351
+ webmcp?: WebMCPToolMeta | false;
1352
+ }
1353
+
1296
1354
  /** See {@link AgoConfig.clientFunctionsMode}. */
1297
1355
  declare type ClientFunctionsMode = "placeholder" | "pause";
1298
1356
 
@@ -1570,6 +1628,15 @@ declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCEL
1570
1628
  */
1571
1629
  | "WAITING_CLIENT";
1572
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
+
1573
1640
  /**
1574
1641
  * Optional action attached to a nudge. Accepting a `functionName` action
1575
1642
  * executes the registered client function (same `FunctionRegistry` path as
@@ -1795,6 +1862,14 @@ export declare function provideAgo(options: AgoProvideOptions): {
1795
1862
  useValue: AgoService;
1796
1863
  };
1797
1864
 
1865
+ /**
1866
+ * Registered function with handler
1867
+ */
1868
+ declare interface RegisteredFunction extends ClientFunctionSettings {
1869
+ schema: ClientFunctionSchema;
1870
+ handler: ClientFunctionHandler;
1871
+ }
1872
+
1798
1873
  /**
1799
1874
  * Hook run before a paused turn is resumed, so the app controls WHEN the
1800
1875
  * continuation fires (e.g. wait for the destination page to mount after a
@@ -1851,6 +1926,8 @@ declare interface SdkPermissionConfig {
1851
1926
  homePage?: SdkHomePageConfig;
1852
1927
  fileAttachmentsEnabled: boolean;
1853
1928
  voiceEnabled: boolean;
1929
+ /** Whether audio uploads can be transcribed. Defaults to false on older backends. */
1930
+ speechToTextEnabled: boolean;
1854
1931
  }
1855
1932
 
1856
1933
  /**
@@ -2163,4 +2240,29 @@ declare interface ToolCallTicketPrefill {
2163
2240
 
2164
2241
  declare type ToolCallType = "form" | "confirmation_input" | "status_message" | "progress_indicator" | "client_function" | "reasoning" | "mcp_ui_resource";
2165
2242
 
2243
+ /** Options for `AgoClient.transcribeAudio`. */
2244
+ export declare interface TranscribeAudioOptions {
2245
+ /** Cancel the upload or stop waiting for its transcription. */
2246
+ signal?: AbortSignal;
2247
+ }
2248
+
2249
+ /** The MCP behavior hints AGO has no equivalent for. */
2250
+ declare interface WebMCPToolMeta {
2251
+ /**
2252
+ * Both default to `false`, so only set what is true: `readOnlyHint` marks a
2253
+ * function that changes nothing, `untrustedContentHint` one whose result may
2254
+ * carry third-party text.
2255
+ */
2256
+ annotations?: {
2257
+ readOnlyHint?: boolean;
2258
+ untrustedContentHint?: boolean;
2259
+ };
2260
+ /**
2261
+ * This function navigates. The WebMCP call is held open until the function
2262
+ * registry goes quiet, so the caller sees the destination page's tools rather
2263
+ * than the departing page's. Already set on the built-in `navigateToPage`.
2264
+ */
2265
+ navigates?: boolean;
2266
+ }
2267
+
2166
2268
  export { }
package/dist/angular.js CHANGED
@@ -1,5 +1,5 @@
1
- import { n as o, t as u } from "./types-Ct1hlKwg.js";
2
- import { t as a } from "./autoContinue-CC8K9mBU.js";
1
+ import { n as o, t as u } from "./types-fX-VoHfa.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");
@@ -16,6 +16,9 @@ var s = class {
16
16
  sendMessage(t, e) {
17
17
  return this.client.sendMessage(t, e);
18
18
  }
19
+ transcribeAudio(t, e) {
20
+ return this.client.transcribeAudio(t, e);
21
+ }
19
22
  stop() {
20
23
  return this.client.stop();
21
24
  }
@@ -55,8 +58,8 @@ var s = class {
55
58
  unregisterFunction(t) {
56
59
  return this.client.unregisterFunction(t);
57
60
  }
58
- registerNavigationFunction(t, e) {
59
- this.client.registerNavigationFunction(t, e);
61
+ registerNavigationFunction(t, e, i) {
62
+ this.client.registerNavigationFunction(t, e, { catalogue: i?.catalogue === "onDemand" ? "onDemand" : "inline" });
60
63
  }
61
64
  unregisterNavigationFunction() {
62
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,4 +1,4 @@
1
- import { g as d } from "./types-Ct1hlKwg.js";
1
+ import { g as d } from "./types-fX-VoHfa.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 d=require("./types-mcW8vB1U.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-Ck3iZG0K.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 { S as w, g as R } from "./types-Ct1hlKwg.js";
1
+ import { S as w, g as R } from "./types-fX-VoHfa.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));
@@ -1 +1 @@
1
- const C=require("./types-mcW8vB1U.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-Ck3iZG0K.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}});
@@ -0,0 +1 @@
1
+ function y(u={}){const{overrides:g={}}=u,a={id:"mock-msg-1",conversationId:"mock-conv-1",content:"Mock response",role:"assistant",status:"DONE",createdAt:new Date},l={id:"mock-conv-1",title:"Mock Conversation",lastMessageDate:new Date},n=new Map,c=[],m={sendMessage:async()=>a,transcribeAudio:async()=>({text:"Mock transcription"}),continueMessage:async()=>a,stop:async()=>null,stopMessage:async()=>({status:"not_running"}),isGenerating:()=>!1,resumePendingClientFunctions:async()=>null,registerResumeGate:()=>()=>{},getConversations:async()=>[l],getConversation:async()=>l,getMessages:async()=>[a],submitToolCallForm:async()=>({status:"completed"}),confirmToolCall:async()=>{},rejectToolCall:async()=>{},getConfig:async()=>({permissions:[],proactive:{enabled:!1}}),createTicket:async()=>({id:"mock-ticket-1",url:"https://example.test/tickets/mock-ticket-1"}),submitFeedback:async()=>{},submitConversationFeedback:async()=>a.id,registerFunction:()=>{},unregisterFunction:()=>!0,getRegisteredFunctions:()=>[],executeClientFunction:async()=>{},getContextSnapshot:()=>null,notifyContextChanged:()=>{},setContext:()=>{},removeContext:()=>!0,addDynamicContext:()=>{},removeDynamicContext:()=>!0,registerNavigationFunction:()=>{},unregisterNavigationFunction:()=>{},getConfiguredAgent:()=>{},getUserIdentity:()=>({email:void 0,hasJwt:!1}),getHttp:()=>({get:async()=>({}),post:async()=>({})}),emitProactiveEvent:(e,t)=>{const o=n.get(e);o&&[...o].forEach(s=>s(t))},on:(e,t)=>{n.has(e)||n.set(e,new Set),n.get(e).add(t)},off:(e,t)=>{n.get(e)?.delete(t)},once:(e,t)=>{const o=(...s)=>{n.get(e)?.delete(o),t(...s)};n.has(e)||n.set(e,new Set),n.get(e).add(o)},waitFor:(e,t)=>new Promise((o,s)=>{let r;const d=f=>{r&&clearTimeout(r),n.get(e)?.delete(d),o(f)};n.has(e)||n.set(e,new Set),n.get(e).add(d),t?.timeout&&(r=setTimeout(()=>{n.get(e)?.delete(d),s(new Error(`waitFor("${e}") timed out after ${t.timeout}ms`))},t.timeout))}),updateConfig:()=>{},destroy:()=>{n.clear()},...g},i={};for(const[e,t]of Object.entries(m))i[e]=(...o)=>(c.push({method:e,args:o}),t(...o));return i.proactive=null,i.__calls=c,i.__callsFor=e=>c.filter(t=>t.method===e),i.__emitEvent=(e,t)=>{const o=n.get(e);o&&[...o].forEach(s=>s(t))},i}Object.defineProperty(exports,"createMockClient",{enumerable:!0,get:function(){return y}});
@@ -12,6 +12,7 @@ function y(g = {}) {
12
12
  lastMessageDate: /* @__PURE__ */ new Date()
13
13
  }, n = /* @__PURE__ */ new Map(), c = [], m = {
14
14
  sendMessage: async () => a,
15
+ transcribeAudio: async () => ({ text: "Mock transcription" }),
15
16
  continueMessage: async () => a,
16
17
  stop: async () => null,
17
18
  stopMessage: async () => ({ status: "not_running" }),
package/dist/devtools.cjs CHANGED
@@ -1,4 +1,4 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const te=require("./errors-o1IB5fEu.cjs");function Q(n,e,i){if(!n)return;const r=document.createElement("div");r.className=`dev-log-line dev-log-${i}`,r.textContent=`${new Date().toLocaleTimeString()} ${e}`,n.appendChild(r),n.scrollTop=n.scrollHeight}function ne(n){let e;return n.type?e=n.type:n.content!==void 0?e="content":n.full_content!==void 0?e="full_content":n.status?e=`status:${n.status}`:e="event",`${e} ${JSON.stringify(n)}`}var oe="ago_dev_panel_collapsed",ae="ago_dev_events_collapsed";function _(n,e,i,r){n.classList.toggle("collapsed",e);const v=n.querySelector(".dev-toggle");v&&(v.textContent=e?"▢":"—",v.title=e?`Expand ${r}`:`Collapse ${r}`,v.setAttribute("aria-expanded",String(!e)));try{localStorage.setItem(i,e?"1":"0")}catch{}}function W(n,e,i){n.querySelector(".dev-toggle")?.addEventListener("click",v=>{v.stopPropagation(),_(n,!n.classList.contains("collapsed"),e,i)}),n.addEventListener("click",()=>{n.classList.contains("collapsed")&&_(n,!1,e,i)});let r=!1;try{r=localStorage.getItem(e)==="1"}catch{}_(n,r,e,i)}var re=0;function de(n){const{client:e,target:i,label:r,side:v="right",enableFunctionRunner:P=!1}=n;if(P&&typeof e.executeClientFunction!="function")throw new te.AgoError("initDevPanel: enableFunctionRunner requires client.executeClientFunction. Pass a real AgoClient, not a mock that omits it.","dev_panel_missing_capability");let u=!1;const F=re++,R=F===0?"":`-${F+1}`,q=document.querySelectorAll(`#ago-dev-panel[data-ago-dev-side="${v}"]`).length,N=q>0?`${16+q*376}px`:"";let w=null,A=null,J=null;const Z=()=>{const t=e.getContextSnapshot()?.entries??{};return Object.fromEntries(Object.entries(t).map(([o,{name:d,data:a}])=>[o,{name:d,data:a}]))},h=()=>{u||w&&(w.textContent=JSON.stringify(Z(),null,2))},k=(t,o)=>{u||Q(A,t,o)};se();const D=typeof i=="string"?document.querySelector(i):i instanceof Element?i:document.body,M=t=>{t.dataset.agoDevSide=v,v==="left"?(t.style.right="auto",t.style.left=N||"16px"):N&&(t.style.right=N)},p=document.createElement("aside");p.id="ago-dev-panel",p.className="ago-dev-card",M(p),(D??document.body).appendChild(p),p.innerHTML=`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ne=require("./errors-o1IB5fEu.cjs");function W(n,e,u){if(!n)return;const r=document.createElement("div");r.className=`dev-log-line dev-log-${u}`,r.textContent=`${new Date().toLocaleTimeString()} ${e}`,n.appendChild(r),n.scrollTop=n.scrollHeight}function oe(n){let e;return n.type?e=n.type:n.content!==void 0?e="content":n.full_content!==void 0?e="full_content":n.status?e=`status:${n.status}`:e="event",`${e} ${JSON.stringify(n)}`}var ae="ago_dev_panel_collapsed",re="ago_dev_events_collapsed";function _(n,e,u,r){n.classList.toggle("collapsed",e);const v=n.querySelector(".dev-toggle");v&&(v.textContent=e?"▢":"—",v.title=e?`Expand ${r}`:`Collapse ${r}`,v.setAttribute("aria-expanded",String(!e)));try{localStorage.setItem(u,e?"1":"0")}catch{}}function X(n,e,u){n.querySelector(".dev-toggle")?.addEventListener("click",v=>{v.stopPropagation(),_(n,!n.classList.contains("collapsed"),e,u)}),n.addEventListener("click",()=>{n.classList.contains("collapsed")&&_(n,!1,e,u)});let r=!1;try{r=localStorage.getItem(e)==="1"}catch{}_(n,r,e,u)}var de=0;function se(n){const{client:e,target:u,label:r,side:v="right",enableFunctionRunner:F=!1}=n;if(F&&typeof e.executeClientFunction!="function")throw new ne.AgoError("initDevPanel: enableFunctionRunner requires client.executeClientFunction. Pass a real AgoClient, not a mock that omits it.","dev_panel_missing_capability");let d=!1;const P=de++,R=P===0?"":`-${P+1}`,q=document.querySelectorAll(`#ago-dev-panel[data-ago-dev-side="${v}"]`).length,N=q>0?`${16+q*376}px`:"";let w=null,A=null,J=null;const ee=()=>{const t=e.getContextSnapshot()?.entries??{};return Object.fromEntries(Object.entries(t).map(([o,{name:s,data:a}])=>[o,{name:s,data:a}]))},h=()=>{d||w&&(w.textContent=JSON.stringify(ee(),null,2))},k=(t,o)=>{d||W(A,t,o)};le();const D=typeof u=="string"?document.querySelector(u):u instanceof Element?u:document.body,M=t=>{t.dataset.agoDevSide=v,v==="left"?(t.style.right="auto",t.style.left=N||"16px"):N&&(t.style.right=N)},p=document.createElement("aside");p.id="ago-dev-panel",p.className="ago-dev-card",M(p),(D??document.body).appendChild(p),p.innerHTML=`
2
2
  <div class="dev-head">
3
3
  <span class="dev-badge">DEV</span>
4
4
  <span class="dev-title">${r?`DEV TOOLS · ${r}`:"DEV TOOLS · client-side function state — not for production"}</span>
@@ -15,7 +15,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const te=requ
15
15
  <div class="dev-log" id="ago-dev-log"></div>
16
16
  </details>
17
17
  </div>
18
- `,w=p.querySelector(".dev-state"),A=p.querySelector(".dev-log");const j=p.querySelector(".dev-fns code");let b=null,L=null,O="";const m=()=>{if(u)return;const t=e.getRegisteredFunctions?.()??[],o=t.map(a=>a.name);if(j&&(j.textContent=o.join(", ")||"—"),!b)return;let d=O;if(o.includes(d)||(d=o.includes("setPageState")?"setPageState":o[0]??""),O=d,b.innerHTML="",o.length===0){const a=document.createElement("option");a.textContent="(no functions registered)",a.disabled=!0,b.appendChild(a)}for(const a of o){const s=document.createElement("option");s.value=a,s.textContent=a,s.selected=a===d,b.appendChild(s)}if(L){const a=t.find(s=>s.name===d);L.textContent=a?JSON.stringify(a.parameters??{},null,2):""}};W(p,oe+R,"dev tools");const g=document.createElement("aside");g.id="ago-dev-events",g.className="ago-dev-card",M(g),(D??document.body).appendChild(g),g.innerHTML=`
18
+ `,w=p.querySelector(".dev-state"),A=p.querySelector(".dev-log");const j=p.querySelector(".dev-fns code");let b=null,L=null,O="";const g=()=>{if(d)return;const t=e.getRegisteredFunctions?.()??[],o=t.map(a=>a.name);if(j&&(j.textContent=o.join(", ")||"—"),!b)return;let s=O;if(o.includes(s)||(s=o.includes("setPageState")?"setPageState":o[0]??""),O=s,b.innerHTML="",o.length===0){const a=document.createElement("option");a.textContent="(no functions registered)",a.disabled=!0,b.appendChild(a)}for(const a of o){const l=document.createElement("option");l.value=a,l.textContent=a,l.selected=a===s,b.appendChild(l)}if(L){const a=t.find(l=>l.name===s);L.textContent=a?JSON.stringify(a.parameters??{},null,2):""}};X(p,ae+R,"dev tools");const f=document.createElement("aside");f.id="ago-dev-events",f.className="ago-dev-card",M(f),(D??document.body).appendChild(f),f.innerHTML=`
19
19
  <div class="dev-head">
20
20
  <span class="dev-badge">SSE</span>
21
21
  <span class="dev-title">${r?`SSE EVENT LOG · ${r}`:"SSE EVENT LOG · raw stream messages"}</span>
@@ -24,7 +24,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const te=requ
24
24
  <div class="dev-body">
25
25
  <div class="dev-log" id="ago-dev-event-log"></div>
26
26
  </div>
27
- `,J=g.querySelector(".dev-log"),W(g,ae+R,"SSE event log");function I(t){u||Q(J,ne(t),"event")}function V({functionName:t,arguments:o}){u||(k(`→ ${t}(${JSON.stringify(o??{})})`,"invoke"),m())}function H({result:t,error:o}){u||(k(o?`✗ error: ${o}`:`← ${JSON.stringify(t)}`,o?"error":"result"),h(),m())}function U(){u||(h(),m())}function B(t){if(u)return;const o=(t.messages??[]).flatMap(d=>d.toolCalls??[]);k(`⟳ hydrated "${t.title||t.id}" — replayed ${o.length} tool call${o.length===1?"":"s"}`,"hydrate"),h()}if(e.on("stream:message",I),e.on("function:invoke",V),e.on("function:result",H),e.on("context:changed",U),e.on("conversation:loaded",B),P){const t=document.createElement("div");t.className="dev-runner";const o=document.createElement("div");o.className="dev-section-label",o.textContent="LOCAL FUNCTION RUNNER",t.appendChild(o);const d=document.createElement("div");d.className="dev-runner-warning",d.textContent="Executes locally. Does not contact the agent backend.",t.appendChild(d);const a=document.createElement("div");a.className="dev-runner-row";const s=document.createElement("select");s.className="dev-runner-select",a.appendChild(s);const y=document.createElement("button");y.type="button",y.className="dev-runner-btn dev-runner-btn-sm",y.textContent="Refresh",y.addEventListener("click",m),a.appendChild(y),t.appendChild(a),b=s;const $=document.createElement("div");$.className="dev-section-label",$.textContent="SCHEMA",t.appendChild($);const T=document.createElement("pre");T.className="dev-runner-schema",t.appendChild(T),L=T,s.addEventListener("change",()=>{O=s.value,m()});const z=document.createElement("div");z.className="dev-section-label",z.textContent="ARGUMENTS (JSON)",t.appendChild(z);const C=document.createElement("textarea");C.className="dev-runner-args",C.value="{}",C.spellcheck=!1,t.appendChild(C);const f=document.createElement("button");f.type="button",f.className="dev-runner-btn",f.textContent="Run",t.appendChild(f);const l=document.createElement("div");l.className="dev-runner-status",t.appendChild(l);const x=document.createElement("pre");x.className="dev-runner-result",t.appendChild(x);const E=document.createElement("div");E.className="dev-runner-bytes",t.appendChild(E);const ee=e.executeClientFunction.bind(e);f.addEventListener("click",async()=>{l.textContent="",x.textContent="",E.textContent="";let G;try{const c=JSON.parse(C.value);if(c===null||Array.isArray(c)||typeof c!="object"){l.textContent="Error: arguments must be a JSON object.",l.className="dev-runner-status dev-runner-error";return}G=c}catch(c){l.textContent=`Parse error: ${c instanceof Error?c.message:String(c)}`,l.className="dev-runner-status dev-runner-error";return}const Y=s.value;if(!Y)return;f.disabled=!0,l.textContent="Running…",l.className="dev-runner-status";let S,K=!1;try{S=await ee(Y,G),K=!0}catch(c){if(u)return;l.textContent="Execution error",l.className="dev-runner-status dev-runner-error",x.textContent=c instanceof Error?`${c.constructor.name}: ${c.message}`:String(c)}if(!u){if(K)if(l.textContent="OK",l.className="dev-runner-status dev-runner-ok",S===void 0)x.textContent="(undefined)";else try{x.textContent=JSON.stringify(S,null,2),E.textContent=`${new TextEncoder().encode(JSON.stringify(S)).length} bytes (UTF-8)`}catch{x.textContent="(result not serializable)"}f.disabled=!1,h(),m()}}),p.querySelector(".dev-body").appendChild(t)}return m(),h(),()=>{u||(u=!0,e.off("stream:message",I),e.off("function:invoke",V),e.off("function:result",H),e.off("context:changed",U),e.off("conversation:loaded",B),p.remove(),g.remove())}}var X="ago-dev-panel-styles";function se(){if(document.getElementById(X))return;const n=document.createElement("style");n.id=X,n.textContent=le,document.head.appendChild(n)}var le=`
27
+ `,J=f.querySelector(".dev-log"),X(f,re+R,"SSE event log");function I(t){d||W(J,oe(t),"event")}function V({functionName:t,arguments:o}){d||(k(`→ ${t}(${JSON.stringify(o??{})})`,"invoke"),g())}function H({result:t,error:o}){d||(k(o?`✗ error: ${o}`:`← ${JSON.stringify(t)}`,o?"error":"result"),h(),g())}function U(){d||(h(),g())}function B(){d||g()}function G(t){if(d)return;const o=(t.messages??[]).flatMap(s=>s.toolCalls??[]);k(`⟳ hydrated "${t.title||t.id}" — replayed ${o.length} tool call${o.length===1?"":"s"}`,"hydrate"),h()}if(e.on("stream:message",I),e.on("function:invoke",V),e.on("function:result",H),e.on("context:changed",U),e.on("conversation:loaded",G),e.on("functions:changed",B),F){const t=document.createElement("div");t.className="dev-runner";const o=document.createElement("div");o.className="dev-section-label",o.textContent="LOCAL FUNCTION RUNNER",t.appendChild(o);const s=document.createElement("div");s.className="dev-runner-warning",s.textContent="Executes locally. Does not contact the agent backend.",t.appendChild(s);const a=document.createElement("div");a.className="dev-runner-row";const l=document.createElement("select");l.className="dev-runner-select",a.appendChild(l);const y=document.createElement("button");y.type="button",y.className="dev-runner-btn dev-runner-btn-sm",y.textContent="Refresh",y.addEventListener("click",g),a.appendChild(y),t.appendChild(a),b=l;const $=document.createElement("div");$.className="dev-section-label",$.textContent="SCHEMA",t.appendChild($);const T=document.createElement("pre");T.className="dev-runner-schema",t.appendChild(T),L=T,l.addEventListener("change",()=>{O=l.value,g()});const z=document.createElement("div");z.className="dev-section-label",z.textContent="ARGUMENTS (JSON)",t.appendChild(z);const C=document.createElement("textarea");C.className="dev-runner-args",C.value="{}",C.spellcheck=!1,t.appendChild(C);const m=document.createElement("button");m.type="button",m.className="dev-runner-btn",m.textContent="Run",t.appendChild(m);const c=document.createElement("div");c.className="dev-runner-status",t.appendChild(c);const x=document.createElement("pre");x.className="dev-runner-result",t.appendChild(x);const E=document.createElement("div");E.className="dev-runner-bytes",t.appendChild(E);const te=e.executeClientFunction.bind(e);m.addEventListener("click",async()=>{c.textContent="",x.textContent="",E.textContent="";let Y;try{const i=JSON.parse(C.value);if(i===null||Array.isArray(i)||typeof i!="object"){c.textContent="Error: arguments must be a JSON object.",c.className="dev-runner-status dev-runner-error";return}Y=i}catch(i){c.textContent=`Parse error: ${i instanceof Error?i.message:String(i)}`,c.className="dev-runner-status dev-runner-error";return}const K=l.value;if(!K)return;m.disabled=!0,c.textContent="Running…",c.className="dev-runner-status";let S,Q=!1;try{S=await te(K,Y),Q=!0}catch(i){if(d)return;c.textContent="Execution error",c.className="dev-runner-status dev-runner-error",x.textContent=i instanceof Error?`${i.constructor.name}: ${i.message}`:String(i)}if(!d){if(Q)if(c.textContent="OK",c.className="dev-runner-status dev-runner-ok",S===void 0)x.textContent="(undefined)";else try{x.textContent=JSON.stringify(S,null,2),E.textContent=`${new TextEncoder().encode(JSON.stringify(S)).length} bytes (UTF-8)`}catch{x.textContent="(result not serializable)"}m.disabled=!1,h(),g()}}),p.querySelector(".dev-body").appendChild(t)}return g(),h(),()=>{d||(d=!0,e.off("stream:message",I),e.off("function:invoke",V),e.off("function:result",H),e.off("context:changed",U),e.off("conversation:loaded",G),e.off("functions:changed",B),p.remove(),f.remove())}}var Z="ago-dev-panel-styles";function le(){if(document.getElementById(Z))return;const n=document.createElement("style");n.id=Z,n.textContent=ce,document.head.appendChild(n)}var ce=`
28
28
  .ago-dev-card {
29
29
  position: fixed;
30
30
  right: 16px;
@@ -169,4 +169,4 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const te=requ
169
169
  .ago-dev-card .dev-runner-result:empty { display: none; }
170
170
  .ago-dev-card .dev-runner-bytes { color: #7c8a99; font-size: 10px; margin-top: 2px; }
171
171
  .ago-dev-card .dev-runner-bytes:empty { display: none; }
172
- `;exports.initDevPanel=de;
172
+ `;exports.initDevPanel=se;