@useago/sdk 1.5.0 → 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 (46) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/dist/AgoClient-BGkFSNZF.cjs +8 -0
  3. package/dist/AgoClient-CW-BLT1_.js +1542 -0
  4. package/dist/angular.cjs +1 -1
  5. package/dist/angular.d.cts +390 -2
  6. package/dist/angular.d.ts +390 -2
  7. package/dist/angular.js +1 -1
  8. package/dist/createConversationSession-BCb0D6bt.cjs +1 -0
  9. package/dist/{createConversationSession-DCSWShaW.js → createConversationSession-C7cnnWKW.js} +3 -3
  10. package/dist/createFormCollector-iCDwAwYJ.js +279 -0
  11. package/dist/createFormCollector-t_fGyuTD.cjs +1 -0
  12. package/dist/createMockClient-Br0TWgLO.js +97 -0
  13. package/dist/createMockClient-BwNLPjeT.cjs +1 -0
  14. package/dist/devtools.d.cts +390 -2
  15. package/dist/devtools.d.ts +390 -2
  16. package/dist/helpers.d.cts +5 -0
  17. package/dist/helpers.d.ts +5 -0
  18. package/dist/index.cjs +1 -1
  19. package/dist/index.d.cts +605 -4
  20. package/dist/index.d.ts +605 -4
  21. package/dist/index.js +95 -90
  22. package/dist/react.cjs +3 -3
  23. package/dist/react.d.cts +561 -4
  24. package/dist/react.d.ts +561 -4
  25. package/dist/react.js +849 -517
  26. package/dist/testing.cjs +1 -1
  27. package/dist/testing.d.cts +390 -2
  28. package/dist/testing.d.ts +390 -2
  29. package/dist/testing.js +1 -1
  30. package/dist/vue.cjs +1 -1
  31. package/dist/vue.d.cts +411 -2
  32. package/dist/vue.d.ts +411 -2
  33. package/dist/vue.js +133 -110
  34. package/dist/widget.cjs +4 -4
  35. package/dist/widget.d.cts +387 -2
  36. package/dist/widget.d.ts +387 -2
  37. package/dist/widget.js +437 -423
  38. package/llms-full.txt +74 -2
  39. package/package.json +1 -1
  40. package/dist/AgoClient-q39FIjSC.js +0 -912
  41. package/dist/AgoClient-wcPRaIMs.cjs +0 -8
  42. package/dist/createConversationSession-BBYfQLLS.cjs +0 -1
  43. package/dist/createFormCollector-eimwwWEi.cjs +0 -1
  44. package/dist/createFormCollector-sB6rMccD.js +0 -299
  45. package/dist/createMockClient-BUc9PSbo.js +0 -79
  46. package/dist/createMockClient-CjdCqixj.cjs +0 -1
package/dist/widget.d.cts CHANGED
@@ -41,8 +41,20 @@ declare class AgoClient {
41
41
  private warnedEmptyConversations;
42
42
  /** Paused turns awaiting auto-resume, keyed by assistant message id. */
43
43
  private pendingResumes;
44
+ /**
45
+ * Client function invocations held pending user approval, keyed by
46
+ * invocationId (the tool-call id). Populated when {@link requiresApproval}
47
+ * matches; drained by {@link approveFunction} / {@link rejectFunction}.
48
+ */
49
+ private pendingApprovals;
44
50
  /** App-provided gate deciding WHEN a paused turn resumes (see {@link registerResumeGate}). */
45
51
  private resumeGate;
52
+ /**
53
+ * Proactive-mode controller, set when the client was created with
54
+ * `proactive` options or when `createAgoProactive(client, opts)` was called.
55
+ * `null` otherwise.
56
+ */
57
+ proactive: ProactiveController | null;
46
58
  constructor(config: AgoConfig);
47
59
  /**
48
60
  * Send a message and receive a streaming response
@@ -91,6 +103,24 @@ declare class AgoClient {
91
103
  */
92
104
  private maybeFlagEmptyReply;
93
105
  private handleClientFunctionInvocation;
106
+ /**
107
+ * Whether a client function invocation must wait for explicit user approval.
108
+ * True when the {@link AgoConfig.approvalPolicy} returns true OR the function
109
+ * was registered with `requiresApproval: true` — the two OR together.
110
+ */
111
+ private requiresApproval;
112
+ /**
113
+ * Approve a client function call held by the approval gate: run it, submit its
114
+ * result, and let the paused turn resume. No-op if the invocation is unknown
115
+ * (already handled, or never gated).
116
+ */
117
+ approveFunction(invocationId: string): Promise<void>;
118
+ /**
119
+ * Reject a client function call held by the approval gate: submit a rejection
120
+ * result so the agent sees the user declined, and let the paused turn resume
121
+ * (the agent decides what to do next). No-op if the invocation is unknown.
122
+ */
123
+ rejectFunction(invocationId: string): Promise<void>;
94
124
  /**
95
125
  * Get list of conversations
96
126
  */
@@ -120,8 +150,10 @@ declare class AgoClient {
120
150
  *
121
151
  * Opt-in on purpose — re-running functions on reload can be surprising (e.g. a
122
152
  * navigation function would navigate again), so the app decides. Returns the
123
- * resumed turn's final message, or `null` when there was nothing to resume or
124
- * some waiting function is not registered on this page.
153
+ * resumed turn's final message, or `null` when there was nothing to resume,
154
+ * some waiting function is not registered on this page, or a waiting call is
155
+ * gated by the approval policy (it is held for `approveFunction` /
156
+ * `rejectFunction` and the turn stays paused, exactly as on the live stream).
125
157
  */
126
158
  resumePendingClientFunctions(conversation: Conversation): Promise<AgoMessage | null>;
127
159
  /**
@@ -193,6 +225,14 @@ declare class AgoClient {
193
225
  * Get all registered function schemas
194
226
  */
195
227
  getRegisteredFunctions(): ClientFunctionSchema[];
228
+ /**
229
+ * Execute a registered client function locally, through the same
230
+ * FunctionRegistry path (result-size guard, error wrapping) as agent-invoked
231
+ * calls. Used by proactive nudge actions, where the user's explicit click on
232
+ * the action button constitutes the approval — nothing is submitted to the
233
+ * backend (there is no tool call to answer).
234
+ */
235
+ executeClientFunction(name: string, args: Record<string, unknown>): Promise<unknown>;
196
236
  /**
197
237
  * Register a navigation function that lets AGO navigate users to different pages.
198
238
  *
@@ -294,6 +334,9 @@ declare class AgoClient {
294
334
  */
295
335
  notifyContextChanged(): void;
296
336
  /* Excluded from this release type: emitFormEvent */
337
+ /* Excluded from this release type: emitProactiveEvent */
338
+ /* Excluded from this release type: getHttp */
339
+ /* Excluded from this release type: getConfiguredAgent */
297
340
  /**
298
341
  * Enable automatic capture of the current browser page (URL + title).
299
342
  * Injected as a dynamic context entry named `browser-page`.
@@ -338,6 +381,7 @@ declare class AgoClient {
338
381
  * Clean up resources
339
382
  */
340
383
  destroy(): void;
384
+ /* Excluded from this release type: reviveAfterDestroy */
341
385
  }
342
386
 
343
387
  /**
@@ -416,6 +460,15 @@ declare interface AgoClientEvents {
416
460
  "toolCall:received": ToolCallData;
417
461
  "toolCall:form": ToolCallData;
418
462
  "function:invoke": ClientFunctionInvocation;
463
+ /**
464
+ * A client function call is held pending the user's approval (pause mode +
465
+ * an {@link AgoConfig.approvalPolicy}/`requiresApproval` match). The turn stays
466
+ * at `WAITING_CLIENT`; call `approveFunction(invocationId)` to run it and
467
+ * resume, or `rejectFunction(invocationId)` to decline. Fires after
468
+ * `function:invoke` (which still fires for every call) and instead of the
469
+ * call running immediately.
470
+ */
471
+ "function:awaiting-approval": ClientFunctionInvocation;
419
472
  "function:result": {
420
473
  invocationId: string;
421
474
  result: unknown;
@@ -445,6 +498,25 @@ declare interface AgoClientEvents {
445
498
  "connection:status": {
446
499
  connected: boolean;
447
500
  };
501
+ /**
502
+ * A proactive nudge passed every governor gate and is ready to display.
503
+ * `useProactiveNudge` / `<AgoNudge>` consume this; custom UIs should call
504
+ * `client.proactive.shown(nudge)` when they render it (impression tracking
505
+ * + frequency caps), then `accept(nudge)` / `dismiss(nudge)`.
506
+ */
507
+ "nudge:ready": ProactiveNudgeInstance;
508
+ /** A nudge was displayed to the user (fires once per nudge). */
509
+ "nudge:shown": {
510
+ nudge: ProactiveNudgeInstance;
511
+ };
512
+ /** The user dismissed the nudge (its trigger is suppressed, see governor). */
513
+ "nudge:dismissed": {
514
+ nudge: ProactiveNudgeInstance;
515
+ };
516
+ /** The user accepted the nudge (its action ran / the chat is being seeded). */
517
+ "nudge:accepted": {
518
+ nudge: ProactiveNudgeInstance;
519
+ };
448
520
  }
449
521
 
450
522
  /**
@@ -484,6 +556,20 @@ declare interface AgoConfig {
484
556
  * Older backends ignore the flag, so `"pause"` degrades to legacy behavior.
485
557
  */
486
558
  clientFunctionsMode?: ClientFunctionsMode;
559
+ /**
560
+ * Gate client function calls behind explicit user approval. Return `true` for
561
+ * an invocation the user must approve/reject before it runs; return `false`
562
+ * (or omit the policy) to let it run immediately as before.
563
+ *
564
+ * Only effective in pause mode (`clientFunctionsMode: "pause"`) — a gated call
565
+ * holds at `WAITING_CLIENT`, the SDK emits `function:awaiting-approval`, and it
566
+ * runs (and the turn resumes) only after `approveFunction(invocationId)`; a
567
+ * `rejectFunction(invocationId)` submits a rejection so the agent sees the
568
+ * decline. In placeholder mode there is no pause to hold, so the policy is a
569
+ * no-op and the call runs normally. A per-function `requiresApproval: true`
570
+ * also gates a call; the policy and the flag OR together.
571
+ */
572
+ approvalPolicy?: (invocation: ClientFunctionInvocation) => boolean;
487
573
  /**
488
574
  * Max serialized size (bytes) of a client function result before the SDK
489
575
  * replaces it with a flagged, truncated preview. Everything a handler
@@ -492,6 +578,16 @@ declare interface AgoConfig {
492
578
  * with `maxResultBytes` on its definition; `Infinity` disables the guard.
493
579
  */
494
580
  maxFunctionResultBytes?: number;
581
+ /**
582
+ * Enable the proactive mode: declarative triggers evaluated client-side
583
+ * against friction signals (dwell/idle time, rage clicks, route bounces…)
584
+ * that can surface a nudge before the user opens the chat. Equivalent to
585
+ * calling `createAgoProactive(client, proactive)` — the resulting controller
586
+ * is available as `client.proactive`. Requires the tenant-level kill-switch
587
+ * (`GET /api/sdk/v1/config` → `proactive.enabled`) to be on; disabled by
588
+ * default otherwise.
589
+ */
590
+ proactive?: ProactiveOptions;
495
591
  }
496
592
 
497
593
  declare type AgoEventHandler<K extends AgoEventName> = (data: AgoClientEvents[K]) => void;
@@ -528,6 +624,11 @@ declare interface AgoMessage {
528
624
  declare interface AgoPageStateOptions {
529
625
  /** Name of the synthesized client function. Defaults to "setPageState". */
530
626
  functionName?: string;
627
+ /**
628
+ * Require explicit user approval before this state change runs. See
629
+ * {@link AgoConfig.approvalPolicy} — pause mode only. Defaults to `false`.
630
+ */
631
+ requiresApproval?: boolean;
531
632
  }
532
633
 
533
634
  /**
@@ -652,6 +753,11 @@ declare interface ClientFunctionDefinition {
652
753
  * `Infinity` disables the guard for this function.
653
754
  */
654
755
  maxResultBytes?: number;
756
+ /**
757
+ * Require explicit user approval before this function runs. See
758
+ * {@link AgoConfig.approvalPolicy} — pause mode only. ORs with the policy.
759
+ */
760
+ requiresApproval?: boolean;
655
761
  }
656
762
 
657
763
  /**
@@ -678,6 +784,11 @@ declare type ClientFunctionRegisterOptions = Omit<ClientFunctionSchema, "name">
678
784
  * disables the guard for this function.
679
785
  */
680
786
  maxResultBytes?: number;
787
+ /**
788
+ * Require explicit user approval before this function runs. See
789
+ * {@link AgoConfig.approvalPolicy} — pause mode only. ORs with the policy.
790
+ */
791
+ requiresApproval?: boolean;
681
792
  };
682
793
 
683
794
  /**
@@ -718,6 +829,19 @@ declare interface ContextEntry {
718
829
  description?: string;
719
830
  /** Arbitrary structured data the AI should know about */
720
831
  data?: Record<string, unknown>;
832
+ /**
833
+ * Marks the entry as constant for the whole conversation. The backend then
834
+ * pins it right after the system prompt, where LLM providers cache it across
835
+ * turns, instead of re-processing it next to every new user message.
836
+ *
837
+ * Only set this when the entry's content is byte-identical on every message
838
+ * of a conversation (a schema, a capability list, static instructions). A
839
+ * stable entry that changes between messages invalidates the provider's
840
+ * cache for the entire conversation history, which costs more than leaving
841
+ * the flag off. Default: `false` (re-sent near the newest user message).
842
+ * Backends that don't know the flag ignore it.
843
+ */
844
+ stable?: boolean;
721
845
  }
722
846
 
723
847
  /**
@@ -918,6 +1042,43 @@ declare interface FormSchema {
918
1042
  required?: string[];
919
1043
  }
920
1044
 
1045
+ /**
1046
+ * HTTP client with authentication headers
1047
+ */
1048
+ declare class HttpClient {
1049
+ private baseUrl;
1050
+ private headers;
1051
+ constructor(config: AgoConfig);
1052
+ /**
1053
+ * Update configuration (e.g., JWT token)
1054
+ */
1055
+ updateConfig(config: Partial<AgoConfig>): void;
1056
+ /**
1057
+ * Make a GET request
1058
+ */
1059
+ get<T>(path: string): Promise<T>;
1060
+ /**
1061
+ * Make a POST request with JSON body.
1062
+ *
1063
+ * `keepalive: true` lets the request survive a page unload (used by the
1064
+ * proactive event tracker's flush-on-hide — sendBeacon can't carry the auth
1065
+ * headers, so it's a keepalive fetch instead).
1066
+ */
1067
+ post<T>(path: string, body?: unknown, options?: {
1068
+ keepalive?: boolean;
1069
+ }): Promise<T>;
1070
+ /**
1071
+ * Make a POST request and return the raw Response (for streaming)
1072
+ */
1073
+ postStream(path: string, body?: unknown): Promise<Response>;
1074
+ /**
1075
+ * Make a POST request with FormData (for file uploads)
1076
+ */
1077
+ postFormData(path: string, formData: FormData): Promise<Response>;
1078
+ private request;
1079
+ private handleErrorResponse;
1080
+ }
1081
+
921
1082
  /**
922
1083
  * Options for {@link loadFormCollector} / the name-only form of `useFormCollector`:
923
1084
  * the `name` is required and the definition is fetched from the backend, while any
@@ -1154,6 +1315,182 @@ export declare interface MountChatWidgetOptions {
1154
1315
  }) => void;
1155
1316
  }
1156
1317
 
1318
+ /**
1319
+ * Optional action attached to a nudge. Accepting a `functionName` action
1320
+ * executes the registered client function (same `FunctionRegistry` path as
1321
+ * agent-invoked calls); `setPageState` applies values through the registered
1322
+ * page-state controls.
1323
+ */
1324
+ declare type NudgeAction = {
1325
+ label: string;
1326
+ functionName: string;
1327
+ arguments?: Record<string, unknown>;
1328
+ } | {
1329
+ label: string;
1330
+ setPageState: Record<string, unknown>;
1331
+ };
1332
+
1333
+ /**
1334
+ * Controller returned by {@link createAgoProactive} (also available as
1335
+ * `client.proactive`).
1336
+ */
1337
+ declare interface ProactiveController {
1338
+ /** Persistently opt this browser out of proactive nudges. */
1339
+ optOut(): void;
1340
+ /** Undo {@link optOut}. */
1341
+ optIn(): void;
1342
+ isOptedOut(): boolean;
1343
+ /**
1344
+ * Tell the governor the user is already engaged (e.g. the chat widget is
1345
+ * open) — nudges are suppressed while `true`. Call from the UI layer.
1346
+ */
1347
+ setEngaged(engaged: boolean): void;
1348
+ /** App-pushed field error counter (field NAME only — never values). */
1349
+ signalFieldError(fieldName: string): void;
1350
+ /** Current aggregated friction snapshot. */
1351
+ getSignalsSnapshot(): SignalsSnapshot;
1352
+ /** The nudge currently occupying the single-nudge slot, if any. */
1353
+ getActiveNudge(): ProactiveNudgeInstance | null;
1354
+ /**
1355
+ * Mark the nudge as displayed. Idempotent per nudge; counts it against the
1356
+ * frequency caps, tracks the impression, and emits `nudge:shown`.
1357
+ */
1358
+ shown(nudge: ProactiveNudgeInstance): void;
1359
+ /**
1360
+ * Accept the nudge: run its action (if any), emit `nudge:accepted`, track,
1361
+ * and — for agent nudges or nudges with a `goal` — pre-seed the chat with a
1362
+ * hidden kickoff message so the agent starts the turn with full context.
1363
+ */
1364
+ accept(nudge: ProactiveNudgeInstance): Promise<void>;
1365
+ /** Dismiss the nudge: suppress the trigger, track, emit `nudge:dismissed`. */
1366
+ dismiss(nudge: ProactiveNudgeInstance): void;
1367
+ /** Report a downstream conversion attributable to the nudge (analytics only). */
1368
+ markConverted(nudge: ProactiveNudgeInstance): void;
1369
+ /** Detach everything: listeners, timers, context provider, event flush. */
1370
+ destroy(): void;
1371
+ }
1372
+
1373
+ /** A concrete nudge produced by the engine, carried by every `nudge:*` event. */
1374
+ declare interface ProactiveNudgeInstance {
1375
+ /** Client-generated uuid for this nudge instance (`client_nudge_id`). */
1376
+ id: string;
1377
+ triggerId: string;
1378
+ /** `static` = configured message; `agent` = backend LLM evaluation. */
1379
+ source: "static" | "agent";
1380
+ message: string;
1381
+ action?: NudgeAction;
1382
+ goal?: string;
1383
+ /** See {@link ProactiveTrigger.kickoff}. */
1384
+ kickoff?: string;
1385
+ createdAt: Date;
1386
+ /** Server-side nudge id (agent nudges only). */
1387
+ serverNudgeId?: string;
1388
+ }
1389
+
1390
+ /** Options for {@link createAgoProactive} / `AgoConfig.proactive`. */
1391
+ declare interface ProactiveOptions {
1392
+ triggers: ProactiveTrigger[];
1393
+ /**
1394
+ * Global caps on nudges actually shown. `perSession` is in-memory (page
1395
+ * lifetime); `perDay` is persisted in localStorage with a date rollover —
1396
+ * best-effort by design (private browsing resets it); the costly LLM path is
1397
+ * additionally capped server-side.
1398
+ */
1399
+ frequencyCap?: {
1400
+ perSession?: number;
1401
+ perDay?: number;
1402
+ };
1403
+ /** Evaluation tick, ms. Default 1000. Zero network per tick. */
1404
+ tickMs?: number;
1405
+ /** Storage backend for persisted governance state. Default `localStorage`. */
1406
+ storage?: StorageLike;
1407
+ /** Storage key for persisted governance state. Default `"ago_proactive"`. */
1408
+ storageKey?: string;
1409
+ /** Tuning of the signal detectors (rage-click window, throttles…). */
1410
+ signals?: SignalCollectorTuning;
1411
+ /**
1412
+ * Local demos and tests ONLY: bypass the remote kill-switch. When set, the
1413
+ * `GET /config` fetch is skipped and the kill-switch takes this value.
1414
+ * Leave unset in production — the tenant admin controls the feature, and
1415
+ * the evaluate endpoint stays gated server-side regardless.
1416
+ */
1417
+ enabledOverride?: boolean;
1418
+ }
1419
+
1420
+ /** A declarative proactive trigger. */
1421
+ declare interface ProactiveTrigger {
1422
+ /** Stable id, used for cooldowns, dismissal memory, and analytics. */
1423
+ id: string;
1424
+ /** Conjunction of matchers (see {@link ProactiveTriggerWhen}). */
1425
+ when: ProactiveTriggerWhen;
1426
+ /**
1427
+ * Min time between two firings of this trigger (persisted across reloads).
1428
+ * A firing is the moment the trigger passes the gates — including an agent
1429
+ * evaluation that decides NOT to intervene, so a persistent condition can't
1430
+ * hammer the evaluate endpoint. Default 60 000.
1431
+ */
1432
+ cooldownMs?: number;
1433
+ /**
1434
+ * `'agent'` asks the backend's fast-LLM second filter whether (and how) to
1435
+ * intervene; a `static` object shows the given message with no network call.
1436
+ */
1437
+ intervene: "agent" | {
1438
+ type: "static";
1439
+ message: string;
1440
+ action?: NudgeAction;
1441
+ };
1442
+ /**
1443
+ * What the agent should help with. Sent to the evaluate endpoint, and used to
1444
+ * pre-seed the chat turn when the user accepts the nudge.
1445
+ */
1446
+ goal?: string;
1447
+ /**
1448
+ * User-voice line used to OPEN the conversation when the user accepts this
1449
+ * nudge and no conversation exists yet — a hidden kickoff cannot start one
1450
+ * (the backend rejects it). Sent as a visible user message, so write it in
1451
+ * the app's language ("Oui, aidez-moi à choisir !"). When a conversation is
1452
+ * already open, the SDK sends a hidden meta kickoff instead and this field
1453
+ * is unused. Without it, accepting with no open conversation skips the chat
1454
+ * pre-seed (the nudge action still runs).
1455
+ */
1456
+ kickoff?: string;
1457
+ /**
1458
+ * How long a dismissal of this trigger's nudge suppresses it (persisted).
1459
+ * Default 24h.
1460
+ */
1461
+ resurfaceAfterMs?: number;
1462
+ }
1463
+
1464
+ /**
1465
+ * Conditions of a proactive trigger. Pure conjunction: EVERY specified matcher
1466
+ * must pass against the current {@link SignalsSnapshot}. Numeric fields are
1467
+ * `>=` thresholds.
1468
+ */
1469
+ declare interface ProactiveTriggerWhen {
1470
+ /**
1471
+ * Route pattern the current pathname must match. Supports the SDK's route
1472
+ * styles: exact (`/billing`), `:param` segments (`/users/:id`), single-segment
1473
+ * wildcards (`/a/*` / `/b`), and a trailing `/*` that matches one or more
1474
+ * remaining segments (`/dossier/*`).
1475
+ */
1476
+ route?: string;
1477
+ /** Min time since the last user activity, ms. */
1478
+ idleMs?: number;
1479
+ /** Min time spent on the current route, ms. */
1480
+ dwellMs?: number;
1481
+ /**
1482
+ * Partial deep match against the registered page state (funnel step,
1483
+ * filters…). Every key present here must deep-match the live value.
1484
+ */
1485
+ pageState?: Partial<Record<string, unknown>>;
1486
+ /** Min rage-click bursts on the current route. */
1487
+ rageClicks?: number;
1488
+ /** Min A→B→A→B route oscillations this session. */
1489
+ routeBounces?: number;
1490
+ /** Per-field minimum error counts (field NAME → min count). */
1491
+ fieldErrors?: Record<string, number>;
1492
+ }
1493
+
1157
1494
  /**
1158
1495
  * Tiny, dependency-free markdown → DOM renderer for the vanilla chat widget.
1159
1496
  *
@@ -1214,6 +1551,54 @@ declare interface SendMessageOptions {
1214
1551
  clientFunctionsMode?: ClientFunctionsMode;
1215
1552
  }
1216
1553
 
1554
+ /** Tuning knobs for the collector's detectors. All optional. */
1555
+ declare interface SignalCollectorTuning {
1556
+ /** Min gap between heavy activity work (route checks, notifications), ms. Default 250. */
1557
+ activityThrottleMs?: number;
1558
+ /** Rage click: clicks needed to count a burst. Default 3. */
1559
+ rageClickCount?: number;
1560
+ /** Rage click: max time between first and last click of a burst, ms. Default 1000. */
1561
+ rageClickWindowMs?: number;
1562
+ /** Rage click: max radius between clicks of a burst, px. Default 24. */
1563
+ rageClickRadiusPx?: number;
1564
+ /** Max routes kept in the recent-route sequence. Default 10. */
1565
+ maxRecentRoutes?: number;
1566
+ /** Max typed signals kept in the ring buffer. Default 50. */
1567
+ maxSignals?: number;
1568
+ }
1569
+
1570
+ /**
1571
+ * Aggregated view of the current friction state. Registered as a dynamic
1572
+ * context provider (key `friction_signals`) so it rides along as
1573
+ * `client_context` on every message, and sent as `signals` to the proactive
1574
+ * evaluate endpoint.
1575
+ */
1576
+ declare interface SignalsSnapshot {
1577
+ /** Current pathname. */
1578
+ route: string;
1579
+ /** Time spent on the current route, ms. */
1580
+ dwellMs: number;
1581
+ /** Time since the last user activity (pointer/key/scroll/touch), ms. */
1582
+ idleMs: number;
1583
+ /** Rage-click bursts detected on the current route. */
1584
+ rageClicks: number;
1585
+ /**
1586
+ * A→B→A→B route oscillations detected in the recent route sequence. Rolling
1587
+ * session counter (cross-route by nature); trigger cooldowns and dismissal
1588
+ * memory keep it from re-firing forever.
1589
+ */
1590
+ routeBounces: number;
1591
+ /** App-pushed field error counters (field NAME → count), current route only. */
1592
+ fieldErrors: Record<string, number>;
1593
+ /** Most recent pathnames, oldest first (bounded). */
1594
+ recentRoutes: string[];
1595
+ /**
1596
+ * Merged `AgoStateControl.get()` snapshot of the registered page-state
1597
+ * controls (funnel step, filters…), or `null` when none are registered.
1598
+ */
1599
+ pageState: Record<string, unknown> | null;
1600
+ }
1601
+
1217
1602
  /**
1218
1603
  * SSE stream chunk data
1219
1604
  */