@useago/sdk 1.5.2 → 1.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/AgoClient-BGkFSNZF.cjs +8 -0
  2. package/dist/AgoClient-CW-BLT1_.js +1542 -0
  3. package/dist/angular.cjs +1 -1
  4. package/dist/angular.d.cts +311 -0
  5. package/dist/angular.d.ts +311 -0
  6. package/dist/angular.js +2 -2
  7. package/dist/createConversationSession-BCb0D6bt.cjs +1 -0
  8. package/dist/{createConversationSession-DPrrr70o.js → createConversationSession-C7cnnWKW.js} +3 -3
  9. package/dist/createFormCollector-iCDwAwYJ.js +279 -0
  10. package/dist/createFormCollector-t_fGyuTD.cjs +1 -0
  11. package/dist/createMockClient-Br0TWgLO.js +97 -0
  12. package/dist/createMockClient-BwNLPjeT.cjs +1 -0
  13. package/dist/devtools.d.cts +311 -0
  14. package/dist/devtools.d.ts +311 -0
  15. package/dist/functions-IGSjjvF4.cjs +1 -0
  16. package/dist/helpers.cjs +1 -1
  17. package/dist/helpers.js +1 -1
  18. package/dist/index.cjs +1 -1
  19. package/dist/index.d.cts +510 -0
  20. package/dist/index.d.ts +510 -0
  21. package/dist/index.js +95 -90
  22. package/dist/react.cjs +3 -3
  23. package/dist/react.d.cts +375 -0
  24. package/dist/react.d.ts +375 -0
  25. package/dist/react.js +559 -422
  26. package/dist/rolldown-runtime-16Nf8qvH.cjs +1 -0
  27. package/dist/testing.cjs +1 -1
  28. package/dist/testing.d.cts +311 -0
  29. package/dist/testing.d.ts +311 -0
  30. package/dist/testing.js +1 -1
  31. package/dist/vue.cjs +1 -1
  32. package/dist/vue.d.cts +332 -0
  33. package/dist/vue.d.ts +332 -0
  34. package/dist/vue.js +133 -110
  35. package/dist/widget.cjs +1 -1
  36. package/dist/widget.d.cts +308 -0
  37. package/dist/widget.d.ts +308 -0
  38. package/dist/widget.js +7 -7
  39. package/package.json +1 -1
  40. package/dist/AgoClient-5VGybmvz.cjs +0 -8
  41. package/dist/AgoClient-DXrH2AMi.js +0 -964
  42. package/dist/createConversationSession-0WTqcCLK.cjs +0 -1
  43. package/dist/createFormCollector-1GKKwQV_.cjs +0 -1
  44. package/dist/createFormCollector-DYh90kiG.js +0 -305
  45. package/dist/createMockClient-C-wrjb2C.cjs +0 -1
  46. package/dist/createMockClient-we-XoPom.js +0 -79
  47. package/dist/functions-CPs7omgM.cjs +0 -1
  48. /package/dist/{autoContinue-CP9pJR-V.cjs → autoContinue-CcCTva-D.cjs} +0 -0
  49. /package/dist/{autoContinue-CC8K9mBU.js → autoContinue-D3Mmaaca.js} +0 -0
  50. /package/dist/{functions-tzyOZNp6.js → functions-CApuQZ2b.js} +0 -0
package/dist/angular.d.ts CHANGED
@@ -66,6 +66,12 @@ declare class AgoClient {
66
66
  private pendingApprovals;
67
67
  /** App-provided gate deciding WHEN a paused turn resumes (see {@link registerResumeGate}). */
68
68
  private resumeGate;
69
+ /**
70
+ * Proactive-mode controller, set when the client was created with
71
+ * `proactive` options or when `createAgoProactive(client, opts)` was called.
72
+ * `null` otherwise.
73
+ */
74
+ proactive: ProactiveController | null;
69
75
  constructor(config: AgoConfig);
70
76
  /**
71
77
  * Send a message and receive a streaming response
@@ -236,6 +242,14 @@ declare class AgoClient {
236
242
  * Get all registered function schemas
237
243
  */
238
244
  getRegisteredFunctions(): ClientFunctionSchema[];
245
+ /**
246
+ * Execute a registered client function locally, through the same
247
+ * FunctionRegistry path (result-size guard, error wrapping) as agent-invoked
248
+ * calls. Used by proactive nudge actions, where the user's explicit click on
249
+ * the action button constitutes the approval — nothing is submitted to the
250
+ * backend (there is no tool call to answer).
251
+ */
252
+ executeClientFunction(name: string, args: Record<string, unknown>): Promise<unknown>;
239
253
  /**
240
254
  * Register a navigation function that lets AGO navigate users to different pages.
241
255
  *
@@ -337,6 +351,9 @@ declare class AgoClient {
337
351
  */
338
352
  notifyContextChanged(): void;
339
353
  /* Excluded from this release type: emitFormEvent */
354
+ /* Excluded from this release type: emitProactiveEvent */
355
+ /* Excluded from this release type: getHttp */
356
+ /* Excluded from this release type: getConfiguredAgent */
340
357
  /**
341
358
  * Enable automatic capture of the current browser page (URL + title).
342
359
  * Injected as a dynamic context entry named `browser-page`.
@@ -381,6 +398,7 @@ declare class AgoClient {
381
398
  * Clean up resources
382
399
  */
383
400
  destroy(): void;
401
+ /* Excluded from this release type: reviveAfterDestroy */
384
402
  }
385
403
 
386
404
  /**
@@ -497,6 +515,25 @@ export declare interface AgoClientEvents {
497
515
  "connection:status": {
498
516
  connected: boolean;
499
517
  };
518
+ /**
519
+ * A proactive nudge passed every governor gate and is ready to display.
520
+ * `useProactiveNudge` / `<AgoNudge>` consume this; custom UIs should call
521
+ * `client.proactive.shown(nudge)` when they render it (impression tracking
522
+ * + frequency caps), then `accept(nudge)` / `dismiss(nudge)`.
523
+ */
524
+ "nudge:ready": ProactiveNudgeInstance;
525
+ /** A nudge was displayed to the user (fires once per nudge). */
526
+ "nudge:shown": {
527
+ nudge: ProactiveNudgeInstance;
528
+ };
529
+ /** The user dismissed the nudge (its trigger is suppressed, see governor). */
530
+ "nudge:dismissed": {
531
+ nudge: ProactiveNudgeInstance;
532
+ };
533
+ /** The user accepted the nudge (its action ran / the chat is being seeded). */
534
+ "nudge:accepted": {
535
+ nudge: ProactiveNudgeInstance;
536
+ };
500
537
  }
501
538
 
502
539
  /**
@@ -558,6 +595,16 @@ export declare interface AgoConfig {
558
595
  * with `maxResultBytes` on its definition; `Infinity` disables the guard.
559
596
  */
560
597
  maxFunctionResultBytes?: number;
598
+ /**
599
+ * Enable the proactive mode: declarative triggers evaluated client-side
600
+ * against friction signals (dwell/idle time, rage clicks, route bounces…)
601
+ * that can surface a nudge before the user opens the chat. Equivalent to
602
+ * calling `createAgoProactive(client, proactive)` — the resulting controller
603
+ * is available as `client.proactive`. Requires the tenant-level kill-switch
604
+ * (`GET /api/sdk/v1/config` → `proactive.enabled`) to be on; disabled by
605
+ * default otherwise.
606
+ */
607
+ proactive?: ProactiveOptions;
561
608
  }
562
609
 
563
610
  declare type AgoEventHandler<K extends AgoEventName> = (data: AgoClientEvents[K]) => void;
@@ -992,6 +1039,43 @@ declare interface FormSchema {
992
1039
  required?: string[];
993
1040
  }
994
1041
 
1042
+ /**
1043
+ * HTTP client with authentication headers
1044
+ */
1045
+ declare class HttpClient {
1046
+ private baseUrl;
1047
+ private headers;
1048
+ constructor(config: AgoConfig);
1049
+ /**
1050
+ * Update configuration (e.g., JWT token)
1051
+ */
1052
+ updateConfig(config: Partial<AgoConfig>): void;
1053
+ /**
1054
+ * Make a GET request
1055
+ */
1056
+ get<T>(path: string): Promise<T>;
1057
+ /**
1058
+ * Make a POST request with JSON body.
1059
+ *
1060
+ * `keepalive: true` lets the request survive a page unload (used by the
1061
+ * proactive event tracker's flush-on-hide — sendBeacon can't carry the auth
1062
+ * headers, so it's a keepalive fetch instead).
1063
+ */
1064
+ post<T>(path: string, body?: unknown, options?: {
1065
+ keepalive?: boolean;
1066
+ }): Promise<T>;
1067
+ /**
1068
+ * Make a POST request and return the raw Response (for streaming)
1069
+ */
1070
+ postStream(path: string, body?: unknown): Promise<Response>;
1071
+ /**
1072
+ * Make a POST request with FormData (for file uploads)
1073
+ */
1074
+ postFormData(path: string, formData: FormData): Promise<Response>;
1075
+ private request;
1076
+ private handleErrorResponse;
1077
+ }
1078
+
995
1079
  declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCELED"
996
1080
  /**
997
1081
  * The turn paused on client function call(s) (pause mode): the agent waits for
@@ -1000,6 +1084,21 @@ declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCEL
1000
1084
  */
1001
1085
  | "WAITING_CLIENT";
1002
1086
 
1087
+ /**
1088
+ * Optional action attached to a nudge. Accepting a `functionName` action
1089
+ * executes the registered client function (same `FunctionRegistry` path as
1090
+ * agent-invoked calls); `setPageState` applies values through the registered
1091
+ * page-state controls.
1092
+ */
1093
+ declare type NudgeAction = {
1094
+ label: string;
1095
+ functionName: string;
1096
+ arguments?: Record<string, unknown>;
1097
+ } | {
1098
+ label: string;
1099
+ setPageState: Record<string, unknown>;
1100
+ };
1101
+
1003
1102
  declare interface Observable<T> {
1004
1103
  subscribe(observer: {
1005
1104
  next?: (value: T) => void;
@@ -1009,6 +1108,167 @@ declare interface Observable<T> {
1009
1108
  };
1010
1109
  }
1011
1110
 
1111
+ /**
1112
+ * Controller returned by {@link createAgoProactive} (also available as
1113
+ * `client.proactive`).
1114
+ */
1115
+ declare interface ProactiveController {
1116
+ /** Persistently opt this browser out of proactive nudges. */
1117
+ optOut(): void;
1118
+ /** Undo {@link optOut}. */
1119
+ optIn(): void;
1120
+ isOptedOut(): boolean;
1121
+ /**
1122
+ * Tell the governor the user is already engaged (e.g. the chat widget is
1123
+ * open) — nudges are suppressed while `true`. Call from the UI layer.
1124
+ */
1125
+ setEngaged(engaged: boolean): void;
1126
+ /** App-pushed field error counter (field NAME only — never values). */
1127
+ signalFieldError(fieldName: string): void;
1128
+ /** Current aggregated friction snapshot. */
1129
+ getSignalsSnapshot(): SignalsSnapshot;
1130
+ /** The nudge currently occupying the single-nudge slot, if any. */
1131
+ getActiveNudge(): ProactiveNudgeInstance | null;
1132
+ /**
1133
+ * Mark the nudge as displayed. Idempotent per nudge; counts it against the
1134
+ * frequency caps, tracks the impression, and emits `nudge:shown`.
1135
+ */
1136
+ shown(nudge: ProactiveNudgeInstance): void;
1137
+ /**
1138
+ * Accept the nudge: run its action (if any), emit `nudge:accepted`, track,
1139
+ * and — for agent nudges or nudges with a `goal` — pre-seed the chat with a
1140
+ * hidden kickoff message so the agent starts the turn with full context.
1141
+ */
1142
+ accept(nudge: ProactiveNudgeInstance): Promise<void>;
1143
+ /** Dismiss the nudge: suppress the trigger, track, emit `nudge:dismissed`. */
1144
+ dismiss(nudge: ProactiveNudgeInstance): void;
1145
+ /** Report a downstream conversion attributable to the nudge (analytics only). */
1146
+ markConverted(nudge: ProactiveNudgeInstance): void;
1147
+ /** Detach everything: listeners, timers, context provider, event flush. */
1148
+ destroy(): void;
1149
+ }
1150
+
1151
+ /** A concrete nudge produced by the engine, carried by every `nudge:*` event. */
1152
+ declare interface ProactiveNudgeInstance {
1153
+ /** Client-generated uuid for this nudge instance (`client_nudge_id`). */
1154
+ id: string;
1155
+ triggerId: string;
1156
+ /** `static` = configured message; `agent` = backend LLM evaluation. */
1157
+ source: "static" | "agent";
1158
+ message: string;
1159
+ action?: NudgeAction;
1160
+ goal?: string;
1161
+ /** See {@link ProactiveTrigger.kickoff}. */
1162
+ kickoff?: string;
1163
+ createdAt: Date;
1164
+ /** Server-side nudge id (agent nudges only). */
1165
+ serverNudgeId?: string;
1166
+ }
1167
+
1168
+ /** Options for {@link createAgoProactive} / `AgoConfig.proactive`. */
1169
+ declare interface ProactiveOptions {
1170
+ triggers: ProactiveTrigger[];
1171
+ /**
1172
+ * Global caps on nudges actually shown. `perSession` is in-memory (page
1173
+ * lifetime); `perDay` is persisted in localStorage with a date rollover —
1174
+ * best-effort by design (private browsing resets it); the costly LLM path is
1175
+ * additionally capped server-side.
1176
+ */
1177
+ frequencyCap?: {
1178
+ perSession?: number;
1179
+ perDay?: number;
1180
+ };
1181
+ /** Evaluation tick, ms. Default 1000. Zero network per tick. */
1182
+ tickMs?: number;
1183
+ /** Storage backend for persisted governance state. Default `localStorage`. */
1184
+ storage?: StorageLike;
1185
+ /** Storage key for persisted governance state. Default `"ago_proactive"`. */
1186
+ storageKey?: string;
1187
+ /** Tuning of the signal detectors (rage-click window, throttles…). */
1188
+ signals?: SignalCollectorTuning;
1189
+ /**
1190
+ * Local demos and tests ONLY: bypass the remote kill-switch. When set, the
1191
+ * `GET /config` fetch is skipped and the kill-switch takes this value.
1192
+ * Leave unset in production — the tenant admin controls the feature, and
1193
+ * the evaluate endpoint stays gated server-side regardless.
1194
+ */
1195
+ enabledOverride?: boolean;
1196
+ }
1197
+
1198
+ /** A declarative proactive trigger. */
1199
+ declare interface ProactiveTrigger {
1200
+ /** Stable id, used for cooldowns, dismissal memory, and analytics. */
1201
+ id: string;
1202
+ /** Conjunction of matchers (see {@link ProactiveTriggerWhen}). */
1203
+ when: ProactiveTriggerWhen;
1204
+ /**
1205
+ * Min time between two firings of this trigger (persisted across reloads).
1206
+ * A firing is the moment the trigger passes the gates — including an agent
1207
+ * evaluation that decides NOT to intervene, so a persistent condition can't
1208
+ * hammer the evaluate endpoint. Default 60 000.
1209
+ */
1210
+ cooldownMs?: number;
1211
+ /**
1212
+ * `'agent'` asks the backend's fast-LLM second filter whether (and how) to
1213
+ * intervene; a `static` object shows the given message with no network call.
1214
+ */
1215
+ intervene: "agent" | {
1216
+ type: "static";
1217
+ message: string;
1218
+ action?: NudgeAction;
1219
+ };
1220
+ /**
1221
+ * What the agent should help with. Sent to the evaluate endpoint, and used to
1222
+ * pre-seed the chat turn when the user accepts the nudge.
1223
+ */
1224
+ goal?: string;
1225
+ /**
1226
+ * User-voice line used to OPEN the conversation when the user accepts this
1227
+ * nudge and no conversation exists yet — a hidden kickoff cannot start one
1228
+ * (the backend rejects it). Sent as a visible user message, so write it in
1229
+ * the app's language ("Oui, aidez-moi à choisir !"). When a conversation is
1230
+ * already open, the SDK sends a hidden meta kickoff instead and this field
1231
+ * is unused. Without it, accepting with no open conversation skips the chat
1232
+ * pre-seed (the nudge action still runs).
1233
+ */
1234
+ kickoff?: string;
1235
+ /**
1236
+ * How long a dismissal of this trigger's nudge suppresses it (persisted).
1237
+ * Default 24h.
1238
+ */
1239
+ resurfaceAfterMs?: number;
1240
+ }
1241
+
1242
+ /**
1243
+ * Conditions of a proactive trigger. Pure conjunction: EVERY specified matcher
1244
+ * must pass against the current {@link SignalsSnapshot}. Numeric fields are
1245
+ * `>=` thresholds.
1246
+ */
1247
+ declare interface ProactiveTriggerWhen {
1248
+ /**
1249
+ * Route pattern the current pathname must match. Supports the SDK's route
1250
+ * styles: exact (`/billing`), `:param` segments (`/users/:id`), single-segment
1251
+ * wildcards (`/a/*` / `/b`), and a trailing `/*` that matches one or more
1252
+ * remaining segments (`/dossier/*`).
1253
+ */
1254
+ route?: string;
1255
+ /** Min time since the last user activity, ms. */
1256
+ idleMs?: number;
1257
+ /** Min time spent on the current route, ms. */
1258
+ dwellMs?: number;
1259
+ /**
1260
+ * Partial deep match against the registered page state (funnel step,
1261
+ * filters…). Every key present here must deep-match the live value.
1262
+ */
1263
+ pageState?: Partial<Record<string, unknown>>;
1264
+ /** Min rage-click bursts on the current route. */
1265
+ rageClicks?: number;
1266
+ /** Min A→B→A→B route oscillations this session. */
1267
+ routeBounces?: number;
1268
+ /** Per-field minimum error counts (field NAME → min count). */
1269
+ fieldErrors?: Record<string, number>;
1270
+ }
1271
+
1012
1272
  /**
1013
1273
  * Factory function that returns an Angular-compatible provider.
1014
1274
  * Use in your app's `providers` array or `bootstrapApplication`:
@@ -1065,6 +1325,54 @@ declare interface SendMessageOptions {
1065
1325
  clientFunctionsMode?: ClientFunctionsMode;
1066
1326
  }
1067
1327
 
1328
+ /** Tuning knobs for the collector's detectors. All optional. */
1329
+ declare interface SignalCollectorTuning {
1330
+ /** Min gap between heavy activity work (route checks, notifications), ms. Default 250. */
1331
+ activityThrottleMs?: number;
1332
+ /** Rage click: clicks needed to count a burst. Default 3. */
1333
+ rageClickCount?: number;
1334
+ /** Rage click: max time between first and last click of a burst, ms. Default 1000. */
1335
+ rageClickWindowMs?: number;
1336
+ /** Rage click: max radius between clicks of a burst, px. Default 24. */
1337
+ rageClickRadiusPx?: number;
1338
+ /** Max routes kept in the recent-route sequence. Default 10. */
1339
+ maxRecentRoutes?: number;
1340
+ /** Max typed signals kept in the ring buffer. Default 50. */
1341
+ maxSignals?: number;
1342
+ }
1343
+
1344
+ /**
1345
+ * Aggregated view of the current friction state. Registered as a dynamic
1346
+ * context provider (key `friction_signals`) so it rides along as
1347
+ * `client_context` on every message, and sent as `signals` to the proactive
1348
+ * evaluate endpoint.
1349
+ */
1350
+ declare interface SignalsSnapshot {
1351
+ /** Current pathname. */
1352
+ route: string;
1353
+ /** Time spent on the current route, ms. */
1354
+ dwellMs: number;
1355
+ /** Time since the last user activity (pointer/key/scroll/touch), ms. */
1356
+ idleMs: number;
1357
+ /** Rage-click bursts detected on the current route. */
1358
+ rageClicks: number;
1359
+ /**
1360
+ * A→B→A→B route oscillations detected in the recent route sequence. Rolling
1361
+ * session counter (cross-route by nature); trigger cooldowns and dismissal
1362
+ * memory keep it from re-firing forever.
1363
+ */
1364
+ routeBounces: number;
1365
+ /** App-pushed field error counters (field NAME → count), current route only. */
1366
+ fieldErrors: Record<string, number>;
1367
+ /** Most recent pathnames, oldest first (bounded). */
1368
+ recentRoutes: string[];
1369
+ /**
1370
+ * Merged `AgoStateControl.get()` snapshot of the registered page-state
1371
+ * controls (funnel step, filters…), or `null` when none are registered.
1372
+ */
1373
+ pageState: Record<string, unknown> | null;
1374
+ }
1375
+
1068
1376
  /**
1069
1377
  * SSE stream chunk data
1070
1378
  */
@@ -1108,6 +1416,9 @@ declare interface SSEChunkData {
1108
1416
  waiting_tool_call_ids?: string[];
1109
1417
  }
1110
1418
 
1419
+ /** The slice of the Web Storage API that {@link createStore} relies on. */
1420
+ declare type StorageLike = Pick<Storage, "getItem" | "setItem">;
1421
+
1111
1422
  /**
1112
1423
  * Where a completed form is sent.
1113
1424
  * - `"https://..."` (a bare string) — shorthand for `{ via: "client", url }`: the browser
package/dist/angular.js CHANGED
@@ -1,5 +1,5 @@
1
- import { t as o } from "./AgoClient-DXrH2AMi.js";
2
- import { t as c } from "./autoContinue-CC8K9mBU.js";
1
+ import { t as o } from "./AgoClient-CW-BLT1_.js";
2
+ import { t as c } from "./autoContinue-D3Mmaaca.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");
@@ -0,0 +1 @@
1
+ const d=require("./AgoClient-BGkFSNZF.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 { i as d } from "./createFormCollector-DYh90kiG.js";
1
+ import { h as d } from "./AgoClient-CW-BLT1_.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) => {
@@ -6,7 +6,7 @@ function v() {
6
6
  return (e === "x" ? r : r & 3 | 8).toString(16);
7
7
  });
8
8
  }
9
- function D(e = {}) {
9
+ function h(e = {}) {
10
10
  const r = e.key ?? f, c = e.threadKey ?? g, u = e.ttlMs ?? y, l = e.storage ?? (typeof localStorage < "u" ? localStorage : void 0);
11
11
  let n = e.widgetId ?? "";
12
12
  if (!n && l) try {
@@ -54,5 +54,5 @@ function D(e = {}) {
54
54
  };
55
55
  }
56
56
  export {
57
- D as t
57
+ h as t
58
58
  };
@@ -0,0 +1,279 @@
1
+ import { h as R, v as w } from "./AgoClient-CW-BLT1_.js";
2
+ var j = /^[a-zA-Z0-9_-]{1,40}$/, V = (s) => s == null || s === "";
3
+ function S(s, e) {
4
+ if ("anyOf" in s) return s.anyOf.some((c) => S(c, e));
5
+ if ("allOf" in s) return s.allOf.every((c) => S(c, e));
6
+ const l = e[s.property];
7
+ if (V(l)) return !1;
8
+ if (Array.isArray(s.value)) return s.value.some((c) => String(l) === String(c));
9
+ if (!s.op) return String(l) === String(s.value);
10
+ const i = Number(l), a = Number(s.value);
11
+ if (Number.isNaN(i) || Number.isNaN(a)) return !1;
12
+ switch (s.op) {
13
+ case ">=":
14
+ return i >= a;
15
+ case "<=":
16
+ return i <= a;
17
+ case ">":
18
+ return i > a;
19
+ case "<":
20
+ return i < a;
21
+ default:
22
+ return w.warn(`Unknown requiredWhen op "${s.op}"; treating as not required.`), !1;
23
+ }
24
+ }
25
+ function p(s, e) {
26
+ const l = s.properties ?? {}, i = /* @__PURE__ */ new Set();
27
+ for (const c of s.required ?? []) {
28
+ const d = l[c]?.requiredWhen;
29
+ (!d || S(d, e)) && i.add(c);
30
+ }
31
+ for (const [c, d] of Object.entries(l)) d.requiredWhen && S(d.requiredWhen, e) && i.add(c);
32
+ const a = [...i].filter((c) => V(e[c]));
33
+ return {
34
+ missing: a,
35
+ complete: a.length === 0
36
+ };
37
+ }
38
+ function B(s) {
39
+ const e = {};
40
+ for (const [l, i] of Object.entries(s.properties ?? {})) e[l] = {
41
+ type: i.type,
42
+ ...i.description != null && { description: i.description },
43
+ ...i.enum && { enum: i.enum },
44
+ ...i.default !== void 0 && { default: i.default }
45
+ };
46
+ return {
47
+ type: "object",
48
+ properties: e,
49
+ required: []
50
+ };
51
+ }
52
+ function L(s) {
53
+ const { name: e, description: l, schema: i } = s;
54
+ if (!j.test(e)) throw new Error(`Invalid form collector name "${e}": must match ${j} (it becomes the update_/submit_ function names).`);
55
+ const a = typeof s.submit == "string" ? s.submit ? {
56
+ via: "client",
57
+ url: s.submit
58
+ } : !1 : s.submit ?? !1;
59
+ s.autoSubmit === !0 && !a && w.warn(`FormCollector "${e}": autoSubmit is ignored because no submit target is configured.`);
60
+ const c = (s.autoSubmit ?? !0) && !!a, d = i.properties ?? {}, $ = (t) => {
61
+ const r = {};
62
+ for (const [o, n] of Object.entries(t)) {
63
+ const u = d[o];
64
+ if (u)
65
+ if (n == null) r[o] = n;
66
+ else if (u.type === "number" || u.type === "integer") {
67
+ const f = typeof n == "number" ? n : Number(n);
68
+ r[o] = Number.isNaN(f) ? n : f;
69
+ } else u.type === "boolean" ? r[o] = typeof n == "boolean" ? n : n === "true" ? !0 : n === "false" ? !1 : !!n : r[o] = n;
70
+ }
71
+ return r;
72
+ }, C = s.initialValues ?? {}, m = R({
73
+ values: C,
74
+ submitted: !1
75
+ }), F = (t) => {
76
+ const r = m.get(), o = {
77
+ ...r,
78
+ values: {
79
+ ...r.values,
80
+ ...t
81
+ }
82
+ };
83
+ return m.set(o), o;
84
+ };
85
+ let b = null;
86
+ const k = (t, r) => {
87
+ b?.emitFormEvent("form:error", {
88
+ name: e,
89
+ values: t,
90
+ error: r
91
+ });
92
+ };
93
+ let h = null;
94
+ const A = async () => {
95
+ const { values: t } = m.get(), { complete: r, missing: o } = p(i, t);
96
+ if (!r) return {
97
+ ok: !1,
98
+ missing: o
99
+ };
100
+ if (!a) return {
101
+ ok: !1,
102
+ error: "No submit target configured for this form collector."
103
+ };
104
+ const n = t;
105
+ try {
106
+ let u;
107
+ if (a.via === "client") if ("handler" in a) u = await a.handler(n);
108
+ else {
109
+ const f = await fetch(a.url, {
110
+ method: "POST",
111
+ headers: { "Content-Type": "application/json" },
112
+ credentials: "include",
113
+ body: JSON.stringify(n)
114
+ });
115
+ if (!f.ok) {
116
+ const W = `Submit failed: HTTP ${f.status}`;
117
+ return k(n, W), {
118
+ ok: !1,
119
+ error: W
120
+ };
121
+ }
122
+ u = await f.json().catch(() => {
123
+ });
124
+ }
125
+ else {
126
+ if (!b) return {
127
+ ok: !1,
128
+ error: "Backend submit requires install(client) (or useFormCollector) first."
129
+ };
130
+ u = await b.submitFormCollector(e, n);
131
+ }
132
+ return m.set({
133
+ ...m.get(),
134
+ submitted: !0,
135
+ submitResult: u
136
+ }), b?.emitFormEvent("form:submitted", {
137
+ name: e,
138
+ values: n,
139
+ result: u
140
+ }), {
141
+ ok: !0,
142
+ result: u
143
+ };
144
+ } catch (u) {
145
+ const f = u instanceof Error ? u.message : "Submit failed";
146
+ return w.error(`FormCollector "${e}" submit failed:`, u), k(n, f), {
147
+ ok: !1,
148
+ error: f
149
+ };
150
+ }
151
+ }, N = () => h || (h = (async () => {
152
+ try {
153
+ return await A();
154
+ } finally {
155
+ h = null;
156
+ }
157
+ })(), h), q = async () => {
158
+ if (!c || !a) return null;
159
+ const { values: t, submitted: r } = m.get();
160
+ return r || !p(i, t).complete ? null : N();
161
+ }, x = {
162
+ name: `update_${e}`,
163
+ 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.`,
164
+ parameters: B(i),
165
+ handler: async (t) => {
166
+ const r = F($(t)), { missing: o } = p(i, r.values), n = await q();
167
+ return n ? n.ok ? {
168
+ ok: !0,
169
+ values: r.values,
170
+ missing: o,
171
+ submitted: !0
172
+ } : {
173
+ ok: !0,
174
+ values: r.values,
175
+ missing: o,
176
+ submitted: !1,
177
+ submitError: n.error
178
+ } : {
179
+ ok: !0,
180
+ values: r.values,
181
+ missing: o
182
+ };
183
+ }
184
+ }, y = [x];
185
+ a && !c && y.push({
186
+ name: `submit_${e}`,
187
+ 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.`,
188
+ parameters: {
189
+ type: "object",
190
+ properties: {}
191
+ },
192
+ handler: () => N()
193
+ });
194
+ const I = "client__", _ = a ? `submit_${e}` : null, D = (t) => {
195
+ const r = t.functionName ?? t.toolName;
196
+ if (r)
197
+ return r.startsWith(I) ? r.slice(8) : r;
198
+ }, O = (t) => {
199
+ let r = { ...C }, o = !1;
200
+ for (const n of t) {
201
+ const u = D(n);
202
+ u === x.name ? n.arguments && (r = {
203
+ ...r,
204
+ ...$(n.arguments)
205
+ }) : _ && u === _ && n.status?.toLowerCase() === "done" && (o = !0);
206
+ }
207
+ m.set({
208
+ values: r,
209
+ submitted: o
210
+ });
211
+ }, g = `form:${e}`, v = `${g}:definition`, T = () => ({
212
+ name: `Form definition: ${e}`,
213
+ 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)}.`,
214
+ stable: !0
215
+ }), E = () => {
216
+ const { values: t, submitted: r } = m.get(), { missing: o, complete: n } = p(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.`;
217
+ return {
218
+ name: `Form: ${e}`,
219
+ 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}`,
220
+ data: {
221
+ values: t,
222
+ missing: o,
223
+ complete: n,
224
+ submitted: r
225
+ }
226
+ };
227
+ }, P = (t) => {
228
+ O((t.messages ?? []).flatMap((r) => r.toolCalls ?? []));
229
+ };
230
+ return {
231
+ name: e,
232
+ store: m,
233
+ functions: y,
234
+ contextKey: g,
235
+ contextProvider: E,
236
+ definitionContextKey: v,
237
+ definitionContextProvider: T,
238
+ install: (t) => {
239
+ b = t;
240
+ for (const o of y) t.register(o);
241
+ t.addDynamicContext(v, T), t.addDynamicContext(g, E);
242
+ const r = m.subscribe(() => t.notifyContextChanged());
243
+ return t.on("conversation:loaded", P), () => {
244
+ r();
245
+ for (const o of y) t.unregisterFunction(o.name);
246
+ t.removeDynamicContext(g), t.removeDynamicContext(v), t.off("conversation:loaded", P), b === t && (b = null);
247
+ };
248
+ },
249
+ hydrate: O,
250
+ submit: N,
251
+ getValues: () => m.get().values,
252
+ setValues: (t) => {
253
+ F($(t)), q();
254
+ },
255
+ reset: () => {
256
+ m.set({
257
+ values: C,
258
+ submitted: !1
259
+ });
260
+ },
261
+ getStatus: () => p(i, m.get().values)
262
+ };
263
+ }
264
+ async function K(s, e) {
265
+ const l = await s.getFormCollector(e.name);
266
+ return L({
267
+ name: l.name,
268
+ description: e.description ?? l.description,
269
+ schema: e.schema ?? l.schema,
270
+ submit: e.submit ?? l.submit,
271
+ initialValues: e.initialValues,
272
+ autoSubmit: e.autoSubmit ?? l.autoSubmit
273
+ });
274
+ }
275
+ export {
276
+ p as n,
277
+ K as r,
278
+ L as t
279
+ };