@useago/sdk 1.5.2 → 1.5.4

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 (45) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +10 -0
  3. package/dist/AgoClient-BW0YZsis.js +1681 -0
  4. package/dist/AgoClient-Ba3ICq4K.cjs +8 -0
  5. package/dist/angular.cjs +1 -1
  6. package/dist/angular.d.cts +352 -0
  7. package/dist/angular.d.ts +352 -0
  8. package/dist/angular.js +1 -1
  9. package/dist/{createConversationSession-DPrrr70o.js → createConversationSession-BjsgjL-v.js} +3 -3
  10. package/dist/createConversationSession-okoz3teC.cjs +1 -0
  11. package/dist/createFormCollector-BWIh1pMl.cjs +1 -0
  12. package/dist/createFormCollector-Bay2UpRv.js +279 -0
  13. package/dist/createMockClient-DcuNlufr.js +97 -0
  14. package/dist/createMockClient-Dw-cyISN.cjs +1 -0
  15. package/dist/devtools.d.cts +352 -0
  16. package/dist/devtools.d.ts +352 -0
  17. package/dist/index.cjs +1 -1
  18. package/dist/index.d.cts +564 -0
  19. package/dist/index.d.ts +564 -0
  20. package/dist/index.js +97 -90
  21. package/dist/react.cjs +3 -3
  22. package/dist/react.d.cts +430 -0
  23. package/dist/react.d.ts +430 -0
  24. package/dist/react.js +600 -443
  25. package/dist/testing.cjs +1 -1
  26. package/dist/testing.d.cts +352 -0
  27. package/dist/testing.d.ts +352 -0
  28. package/dist/testing.js +1 -1
  29. package/dist/vue.cjs +1 -1
  30. package/dist/vue.d.cts +373 -0
  31. package/dist/vue.d.ts +373 -0
  32. package/dist/vue.js +133 -110
  33. package/dist/widget.cjs +1 -1
  34. package/dist/widget.d.cts +349 -0
  35. package/dist/widget.d.ts +349 -0
  36. package/dist/widget.js +7 -7
  37. package/llms-full.txt +29 -0
  38. package/package.json +1 -1
  39. package/dist/AgoClient-5VGybmvz.cjs +0 -8
  40. package/dist/AgoClient-DXrH2AMi.js +0 -964
  41. package/dist/createConversationSession-0WTqcCLK.cjs +0 -1
  42. package/dist/createFormCollector-1GKKwQV_.cjs +0 -1
  43. package/dist/createFormCollector-DYh90kiG.js +0 -305
  44. package/dist/createMockClient-C-wrjb2C.cjs +0 -1
  45. package/dist/createMockClient-we-XoPom.js +0 -79
package/dist/index.d.cts CHANGED
@@ -1,3 +1,30 @@
1
+ export declare interface ActivityEntry {
2
+ ts: number;
3
+ actor: "user" | "agent";
4
+ name: string;
5
+ summary: string;
6
+ data?: Record<string, unknown>;
7
+ }
8
+
9
+ export declare interface ActivityInput {
10
+ actor?: "user" | "agent";
11
+ name: string;
12
+ summary: string;
13
+ data?: Record<string, unknown>;
14
+ ts?: number;
15
+ }
16
+
17
+ /** Capped, in-memory log of recent user and agent actions (oldest dropped first). */
18
+ export declare class ActivityLedger {
19
+ private entries;
20
+ private readonly maxEntries;
21
+ constructor(maxEntries?: number);
22
+ add(input: ActivityInput): ActivityEntry;
23
+ getRecent(): ActivityEntry[];
24
+ get size(): number;
25
+ clear(): void;
26
+ }
27
+
1
28
  /**
2
29
  * Agent information
3
30
  */
@@ -64,6 +91,8 @@ export declare class AgoClient {
64
91
  private functionRegistry;
65
92
  private contextRegistry;
66
93
  private eventEmitter;
94
+ private activityLedger;
95
+ private lastSentPageState;
67
96
  private config;
68
97
  /** Conversations already warned about an empty reply (one warning each). */
69
98
  private warnedEmptyConversations;
@@ -77,6 +106,12 @@ export declare class AgoClient {
77
106
  private pendingApprovals;
78
107
  /** App-provided gate deciding WHEN a paused turn resumes (see {@link registerResumeGate}). */
79
108
  private resumeGate;
109
+ /**
110
+ * Proactive-mode controller, set when the client was created with
111
+ * `proactive` options or when `createAgoProactive(client, opts)` was called.
112
+ * `null` otherwise.
113
+ */
114
+ proactive: ProactiveController | null;
80
115
  constructor(config: AgoConfig);
81
116
  /**
82
117
  * Send a message and receive a streaming response
@@ -247,6 +282,14 @@ export declare class AgoClient {
247
282
  * Get all registered function schemas
248
283
  */
249
284
  getRegisteredFunctions(): ClientFunctionSchema[];
285
+ /**
286
+ * Execute a registered client function locally, through the same
287
+ * FunctionRegistry path (result-size guard, error wrapping) as agent-invoked
288
+ * calls. Used by proactive nudge actions, where the user's explicit click on
289
+ * the action button constitutes the approval — nothing is submitted to the
290
+ * backend (there is no tool call to answer).
291
+ */
292
+ executeClientFunction(name: string, args: Record<string, unknown>): Promise<unknown>;
250
293
  /**
251
294
  * Register a navigation function that lets AGO navigate users to different pages.
252
295
  *
@@ -348,6 +391,9 @@ export declare class AgoClient {
348
391
  */
349
392
  notifyContextChanged(): void;
350
393
  /* Excluded from this release type: emitFormEvent */
394
+ /* Excluded from this release type: emitProactiveEvent */
395
+ /* Excluded from this release type: getHttp */
396
+ /* Excluded from this release type: getConfiguredAgent */
351
397
  /**
352
398
  * Enable automatic capture of the current browser page (URL + title).
353
399
  * Injected as a dynamic context entry named `browser-page`.
@@ -357,6 +403,19 @@ export declare class AgoClient {
357
403
  * Get the current context snapshot.
358
404
  */
359
405
  getContextSnapshot(): ContextSnapshot | null;
406
+ private buildSendContext;
407
+ /**
408
+ * Record something the user just did so the agent is aware of it on the next
409
+ * message. `actor` defaults to `"user"`. Keep `summary` short and high-signal
410
+ * (no raw payloads, secrets, or PII).
411
+ */
412
+ recordActivity(entry: ActivityInput): void;
413
+ /** Recent user + agent actions, oldest first (a copy). */
414
+ getRecentActivity(): ActivityEntry[];
415
+ clearActivity(): void;
416
+ private addActivity;
417
+ private recordAgentAction;
418
+ private registerActivityContext;
360
419
  /**
361
420
  * Subscribe to an event
362
421
  */
@@ -392,6 +451,7 @@ export declare class AgoClient {
392
451
  * Clean up resources
393
452
  */
394
453
  destroy(): void;
454
+ /* Excluded from this release type: reviveAfterDestroy */
395
455
  }
396
456
 
397
457
  /**
@@ -508,6 +568,27 @@ export declare interface AgoClientEvents {
508
568
  "connection:status": {
509
569
  connected: boolean;
510
570
  };
571
+ /**
572
+ * A proactive nudge passed every governor gate and is ready to display.
573
+ * `useProactiveNudge` / `<AgoNudge>` consume this; custom UIs should call
574
+ * `client.proactive.shown(nudge)` when they render it (impression tracking
575
+ * + frequency caps), then `accept(nudge)` / `dismiss(nudge)`.
576
+ */
577
+ "nudge:ready": ProactiveNudgeInstance;
578
+ /** A nudge was displayed to the user (fires once per nudge). */
579
+ "nudge:shown": {
580
+ nudge: ProactiveNudgeInstance;
581
+ };
582
+ /** The user dismissed the nudge (its trigger is suppressed, see governor). */
583
+ "nudge:dismissed": {
584
+ nudge: ProactiveNudgeInstance;
585
+ };
586
+ /** The user accepted the nudge (its action ran / the chat is being seeded). */
587
+ "nudge:accepted": {
588
+ nudge: ProactiveNudgeInstance;
589
+ };
590
+ /** A user- or agent-action was recorded into the activity ledger. */
591
+ "activity:recorded": ActivityEntry;
511
592
  }
512
593
 
513
594
  /**
@@ -569,6 +650,24 @@ export declare interface AgoConfig {
569
650
  * with `maxResultBytes` on its definition; `Infinity` disables the guard.
570
651
  */
571
652
  maxFunctionResultBytes?: number;
653
+ /**
654
+ * Max number of recent actions kept in the in-memory activity ledger that
655
+ * rides along as the `activity:recent` context entry. Older entries drop
656
+ * first. Default `10`. Larger values give the agent more history at the cost
657
+ * of tokens on every message. Each entry's `data` is also size-clamped (long
658
+ * strings truncated, large arrays capped) so one event can't bloat the context.
659
+ */
660
+ maxActivityEntries?: number;
661
+ /**
662
+ * Enable the proactive mode: declarative triggers evaluated client-side
663
+ * against friction signals (dwell/idle time, rage clicks, route bounces…)
664
+ * that can surface a nudge before the user opens the chat. Equivalent to
665
+ * calling `createAgoProactive(client, proactive)` — the resulting controller
666
+ * is available as `client.proactive`. Requires the tenant-level kill-switch
667
+ * (`GET /api/sdk/v1/config` → `proactive.enabled`) to be on; disabled by
668
+ * default otherwise.
669
+ */
670
+ proactive?: ProactiveOptions;
572
671
  }
573
672
 
574
673
  /**
@@ -1044,6 +1143,35 @@ export declare const copyToClipboard: ClientFunctionDefinition;
1044
1143
  */
1045
1144
  export declare function createAgo(overrides?: Partial<AgoConfig>): AgoClient;
1046
1145
 
1146
+ /**
1147
+ * Attach the proactive mode to a client: starts the signal collector, the
1148
+ * trigger engine, and the nudge governor, and registers the aggregated
1149
+ * friction snapshot as a dynamic context provider so the reactive mode
1150
+ * benefits too (the agent "knows" the user hesitated on every message).
1151
+ *
1152
+ * ```ts
1153
+ * const proactive = createAgoProactive(client, {
1154
+ * triggers: [{
1155
+ * id: "kyc-doc-stuck",
1156
+ * when: { route: "/dossier/*", idleMs: 20000, pageState: { step: "documents" } },
1157
+ * cooldownMs: 300_000,
1158
+ * intervene: "agent",
1159
+ * goal: "Help the user upload their KYC documents",
1160
+ * }],
1161
+ * frequencyCap: { perSession: 3, perDay: 5 },
1162
+ * });
1163
+ * // later: proactive.destroy();
1164
+ * ```
1165
+ *
1166
+ * Also wired through the config: `new AgoClient({ ..., proactive })` attaches
1167
+ * it automatically and exposes it as `client.proactive`.
1168
+ *
1169
+ * Nothing fires until the backend confirms the feature: the engine reads the
1170
+ * `proactive.enabled` kill-switch from `GET /api/sdk/v1/config` and stays
1171
+ * disabled by default.
1172
+ */
1173
+ export declare function createAgoProactive(client: AgoClient, options: ProactiveOptions): ProactiveController;
1174
+
1047
1175
  /**
1048
1176
  * Identify a returning visitor with a single, stable anon id (one id, generated
1049
1177
  * once and reused forever) and resume their last active thread.
@@ -1162,6 +1290,8 @@ export declare function createMockClient(options?: MockAgoClientOptions): MockAg
1162
1290
 
1163
1291
  export declare function createStore<T>(initial: T, persist?: PersistOptions): Store<T>;
1164
1292
 
1293
+ export declare const DEFAULT_MAX_ACTIVITY_ENTRIES = 10;
1294
+
1165
1295
  /**
1166
1296
  * Create a reusable function definition.
1167
1297
  * Returns the same object — this is an identity function for discoverability and type-checking.
@@ -1495,6 +1625,43 @@ export declare const getUserLocation: ClientFunctionDefinition;
1495
1625
  */
1496
1626
  export declare const highlightElement: ClientFunctionDefinition;
1497
1627
 
1628
+ /**
1629
+ * HTTP client with authentication headers
1630
+ */
1631
+ declare class HttpClient {
1632
+ private baseUrl;
1633
+ private headers;
1634
+ constructor(config: AgoConfig);
1635
+ /**
1636
+ * Update configuration (e.g., JWT token)
1637
+ */
1638
+ updateConfig(config: Partial<AgoConfig>): void;
1639
+ /**
1640
+ * Make a GET request
1641
+ */
1642
+ get<T>(path: string): Promise<T>;
1643
+ /**
1644
+ * Make a POST request with JSON body.
1645
+ *
1646
+ * `keepalive: true` lets the request survive a page unload (used by the
1647
+ * proactive event tracker's flush-on-hide — sendBeacon can't carry the auth
1648
+ * headers, so it's a keepalive fetch instead).
1649
+ */
1650
+ post<T>(path: string, body?: unknown, options?: {
1651
+ keepalive?: boolean;
1652
+ }): Promise<T>;
1653
+ /**
1654
+ * Make a POST request and return the raw Response (for streaming)
1655
+ */
1656
+ postStream(path: string, body?: unknown): Promise<Response>;
1657
+ /**
1658
+ * Make a POST request with FormData (for file uploads)
1659
+ */
1660
+ postFormData(path: string, formData: FormData): Promise<Response>;
1661
+ private request;
1662
+ private handleErrorResponse;
1663
+ }
1664
+
1498
1665
  /**
1499
1666
  * Check if an error is a network error that should trigger polling fallback
1500
1667
  */
@@ -1540,6 +1707,29 @@ declare class Logger {
1540
1707
 
1541
1708
  export declare const logger: Logger;
1542
1709
 
1710
+ /**
1711
+ * Match a pathname against a trigger route pattern. Mirrors the styles the
1712
+ * navigation function already understands (`:param` segments), plus globs:
1713
+ *
1714
+ * - exact: `/billing`
1715
+ * - `:param`: `/users/:id` matches `/users/42`
1716
+ * - `*` mid-path: matches exactly one segment (`/a/*` / `/b`)
1717
+ * - trailing `/*`: matches one or MORE remaining segments (`/dossier/*`
1718
+ * matches `/dossier/1` and `/dossier/1/docs`, not `/dossier`)
1719
+ * - `*` alone matches everything
1720
+ *
1721
+ * Trailing slashes on the pathname are tolerated.
1722
+ */
1723
+ export declare function matchesRoutePattern(pattern: string, pathname: string): boolean;
1724
+
1725
+ /**
1726
+ * Evaluate a trigger's `when` clause against a signals snapshot. Pure
1727
+ * conjunction: every specified matcher must pass. Numeric fields are `>=`
1728
+ * thresholds; `pageState` is a partial deep match; `fieldErrors` are per-name
1729
+ * minimum counts.
1730
+ */
1731
+ export declare function matchesWhen(when: ProactiveTriggerWhen, snapshot: SignalsSnapshot): boolean;
1732
+
1543
1733
  export declare type MessageStatus = "IN_PROGRESS" | "DONE" | "ERROR" | "TODO" | "CANCELED"
1544
1734
  /**
1545
1735
  * The turn paused on client function call(s) (pause mode): the agent waits for
@@ -1578,6 +1768,21 @@ export declare interface MockAgoClientOptions {
1578
1768
 
1579
1769
  declare type MockFn = (...args: any[]) => any;
1580
1770
 
1771
+ /**
1772
+ * Optional action attached to a nudge. Accepting a `functionName` action
1773
+ * executes the registered client function (same `FunctionRegistry` path as
1774
+ * agent-invoked calls); `setPageState` applies values through the registered
1775
+ * page-state controls.
1776
+ */
1777
+ export declare type NudgeAction = {
1778
+ label: string;
1779
+ functionName: string;
1780
+ arguments?: Record<string, unknown>;
1781
+ } | {
1782
+ label: string;
1783
+ setPageState: Record<string, unknown>;
1784
+ };
1785
+
1581
1786
  /**
1582
1787
  * Subscribe to failed form collector submissions (network/server failures).
1583
1788
  */
@@ -1641,6 +1846,13 @@ export declare function onToolCall(client: AgoClient, callback: (toolCall: ToolC
1641
1846
  */
1642
1847
  export declare const openUrl: ClientFunctionDefinition;
1643
1848
 
1849
+ /**
1850
+ * Partial deep match: every key/value present in `expected` must match the
1851
+ * corresponding value in `actual`. Nested objects recurse (partially); arrays
1852
+ * and primitives compare by deep equality.
1853
+ */
1854
+ export declare function partialDeepMatch(expected: unknown, actual: unknown): boolean;
1855
+
1644
1856
  export declare interface PersistOptions {
1645
1857
  /** Key under which the state is JSON-serialized. */
1646
1858
  key: string;
@@ -1648,6 +1860,196 @@ export declare interface PersistOptions {
1648
1860
  storage?: StorageLike;
1649
1861
  }
1650
1862
 
1863
+ /**
1864
+ * Controller returned by {@link createAgoProactive} (also available as
1865
+ * `client.proactive`).
1866
+ */
1867
+ export declare interface ProactiveController {
1868
+ /** Persistently opt this browser out of proactive nudges. */
1869
+ optOut(): void;
1870
+ /** Undo {@link optOut}. */
1871
+ optIn(): void;
1872
+ isOptedOut(): boolean;
1873
+ /**
1874
+ * Tell the governor the user is already engaged (e.g. the chat widget is
1875
+ * open) — nudges are suppressed while `true`. Call from the UI layer.
1876
+ */
1877
+ setEngaged(engaged: boolean): void;
1878
+ /** App-pushed field error counter (field NAME only — never values). */
1879
+ signalFieldError(fieldName: string): void;
1880
+ /** Current aggregated friction snapshot. */
1881
+ getSignalsSnapshot(): SignalsSnapshot;
1882
+ /** The nudge currently occupying the single-nudge slot, if any. */
1883
+ getActiveNudge(): ProactiveNudgeInstance | null;
1884
+ /**
1885
+ * Mark the nudge as displayed. Idempotent per nudge; counts it against the
1886
+ * frequency caps, tracks the impression, and emits `nudge:shown`.
1887
+ */
1888
+ shown(nudge: ProactiveNudgeInstance): void;
1889
+ /**
1890
+ * Accept the nudge: run its action (if any), emit `nudge:accepted`, track,
1891
+ * and — for agent nudges or nudges with a `goal` — pre-seed the chat with a
1892
+ * hidden kickoff message so the agent starts the turn with full context.
1893
+ */
1894
+ accept(nudge: ProactiveNudgeInstance): Promise<void>;
1895
+ /** Dismiss the nudge: suppress the trigger, track, emit `nudge:dismissed`. */
1896
+ dismiss(nudge: ProactiveNudgeInstance): void;
1897
+ /** Report a downstream conversion attributable to the nudge (analytics only). */
1898
+ markConverted(nudge: ProactiveNudgeInstance): void;
1899
+ /** Detach everything: listeners, timers, context provider, event flush. */
1900
+ destroy(): void;
1901
+ }
1902
+
1903
+ /**
1904
+ * Response of `POST {baseUrl}/api/sdk/v1/proactive/evaluate` (snake_case, as
1905
+ * on the wire). On 429 or any error the SDK treats the call as
1906
+ * `intervene: false`, silently (debug log only).
1907
+ */
1908
+ export declare interface ProactiveEvaluateResponse {
1909
+ intervene: boolean;
1910
+ message: string | null;
1911
+ action: {
1912
+ label: string;
1913
+ function_name: string;
1914
+ arguments?: Record<string, unknown>;
1915
+ } | null;
1916
+ /** Server-generated nudge uuid. */
1917
+ nudge_id: string;
1918
+ }
1919
+
1920
+ /** A concrete nudge produced by the engine, carried by every `nudge:*` event. */
1921
+ export declare interface ProactiveNudgeInstance {
1922
+ /** Client-generated uuid for this nudge instance (`client_nudge_id`). */
1923
+ id: string;
1924
+ triggerId: string;
1925
+ /** `static` = configured message; `agent` = backend LLM evaluation. */
1926
+ source: "static" | "agent";
1927
+ message: string;
1928
+ action?: NudgeAction;
1929
+ goal?: string;
1930
+ /** See {@link ProactiveTrigger.kickoff}. */
1931
+ kickoff?: string;
1932
+ createdAt: Date;
1933
+ /** Server-side nudge id (agent nudges only). */
1934
+ serverNudgeId?: string;
1935
+ }
1936
+
1937
+ /** Options for {@link createAgoProactive} / `AgoConfig.proactive`. */
1938
+ export declare interface ProactiveOptions {
1939
+ triggers: ProactiveTrigger[];
1940
+ /**
1941
+ * Global caps on nudges actually shown. `perSession` is in-memory (page
1942
+ * lifetime); `perDay` is persisted in localStorage with a date rollover —
1943
+ * best-effort by design (private browsing resets it); the costly LLM path is
1944
+ * additionally capped server-side.
1945
+ */
1946
+ frequencyCap?: {
1947
+ perSession?: number;
1948
+ perDay?: number;
1949
+ };
1950
+ /** Evaluation tick, ms. Default 1000. Zero network per tick. */
1951
+ tickMs?: number;
1952
+ /** Storage backend for persisted governance state. Default `localStorage`. */
1953
+ storage?: StorageLike;
1954
+ /** Storage key for persisted governance state. Default `"ago_proactive"`. */
1955
+ storageKey?: string;
1956
+ /** Tuning of the signal detectors (rage-click window, throttles…). */
1957
+ signals?: SignalCollectorTuning;
1958
+ /**
1959
+ * Local demos and tests ONLY: bypass the remote kill-switch. When set, the
1960
+ * `GET /config` fetch is skipped and the kill-switch takes this value.
1961
+ * Leave unset in production — the tenant admin controls the feature, and
1962
+ * the evaluate endpoint stays gated server-side regardless.
1963
+ */
1964
+ enabledOverride?: boolean;
1965
+ }
1966
+
1967
+ /** One entry of the `POST {baseUrl}/api/sdk/v1/proactive/events` batch. */
1968
+ export declare interface ProactiveTrackedEvent {
1969
+ clientNudgeId: string;
1970
+ triggerId: string;
1971
+ source: "static" | "agent";
1972
+ type: "shown" | "dismissed" | "accepted" | "converted";
1973
+ /** Nudge text, optional. */
1974
+ message?: string;
1975
+ /** Epoch ms; serialized as ISO-8601 `occurred_at`. */
1976
+ occurredAt: number;
1977
+ }
1978
+
1979
+ /** A declarative proactive trigger. */
1980
+ export declare interface ProactiveTrigger {
1981
+ /** Stable id, used for cooldowns, dismissal memory, and analytics. */
1982
+ id: string;
1983
+ /** Conjunction of matchers (see {@link ProactiveTriggerWhen}). */
1984
+ when: ProactiveTriggerWhen;
1985
+ /**
1986
+ * Min time between two firings of this trigger (persisted across reloads).
1987
+ * A firing is the moment the trigger passes the gates — including an agent
1988
+ * evaluation that decides NOT to intervene, so a persistent condition can't
1989
+ * hammer the evaluate endpoint. Default 60 000.
1990
+ */
1991
+ cooldownMs?: number;
1992
+ /**
1993
+ * `'agent'` asks the backend's fast-LLM second filter whether (and how) to
1994
+ * intervene; a `static` object shows the given message with no network call.
1995
+ */
1996
+ intervene: "agent" | {
1997
+ type: "static";
1998
+ message: string;
1999
+ action?: NudgeAction;
2000
+ };
2001
+ /**
2002
+ * What the agent should help with. Sent to the evaluate endpoint, and used to
2003
+ * pre-seed the chat turn when the user accepts the nudge.
2004
+ */
2005
+ goal?: string;
2006
+ /**
2007
+ * User-voice line used to OPEN the conversation when the user accepts this
2008
+ * nudge and no conversation exists yet — a hidden kickoff cannot start one
2009
+ * (the backend rejects it). Sent as a visible user message, so write it in
2010
+ * the app's language ("Oui, aidez-moi à choisir !"). When a conversation is
2011
+ * already open, the SDK sends a hidden meta kickoff instead and this field
2012
+ * is unused. Without it, accepting with no open conversation skips the chat
2013
+ * pre-seed (the nudge action still runs).
2014
+ */
2015
+ kickoff?: string;
2016
+ /**
2017
+ * How long a dismissal of this trigger's nudge suppresses it (persisted).
2018
+ * Default 24h.
2019
+ */
2020
+ resurfaceAfterMs?: number;
2021
+ }
2022
+
2023
+ /**
2024
+ * Conditions of a proactive trigger. Pure conjunction: EVERY specified matcher
2025
+ * must pass against the current {@link SignalsSnapshot}. Numeric fields are
2026
+ * `>=` thresholds.
2027
+ */
2028
+ export declare interface ProactiveTriggerWhen {
2029
+ /**
2030
+ * Route pattern the current pathname must match. Supports the SDK's route
2031
+ * styles: exact (`/billing`), `:param` segments (`/users/:id`), single-segment
2032
+ * wildcards (`/a/*` / `/b`), and a trailing `/*` that matches one or more
2033
+ * remaining segments (`/dossier/*`).
2034
+ */
2035
+ route?: string;
2036
+ /** Min time since the last user activity, ms. */
2037
+ idleMs?: number;
2038
+ /** Min time spent on the current route, ms. */
2039
+ dwellMs?: number;
2040
+ /**
2041
+ * Partial deep match against the registered page state (funnel step,
2042
+ * filters…). Every key present here must deep-match the live value.
2043
+ */
2044
+ pageState?: Partial<Record<string, unknown>>;
2045
+ /** Min rage-click bursts on the current route. */
2046
+ rageClicks?: number;
2047
+ /** Min A→B→A→B route oscillations this session. */
2048
+ routeBounces?: number;
2049
+ /** Per-field minimum error counts (field NAME → min count). */
2050
+ fieldErrors?: Record<string, number>;
2051
+ }
2052
+
1651
2053
  /**
1652
2054
  * Registered function with handler
1653
2055
  */
@@ -1739,6 +2141,168 @@ export declare const showNotification: ClientFunctionDefinition;
1739
2141
  */
1740
2142
  export declare const showToast: ClientFunctionDefinition;
1741
2143
 
2144
+ /** One entry of the collector's ring buffer. */
2145
+ export declare interface Signal {
2146
+ type: SignalType;
2147
+ /** Pathname the signal happened on. */
2148
+ route: string;
2149
+ /** Epoch ms. */
2150
+ at: number;
2151
+ /** Optional counter (e.g. how many errors this field has produced so far). */
2152
+ count?: number;
2153
+ /** Small, PII-free metadata (field names, previous route…). */
2154
+ meta?: Record<string, string | number>;
2155
+ }
2156
+
2157
+ /**
2158
+ * Framework-agnostic collector of client-side friction signals: per-route
2159
+ * dwell time, idle time, route bounces (A→B→A→B), rage clicks, and app-pushed
2160
+ * field error counters. Attached to an `AgoClient` by `createAgoProactive`,
2161
+ * the same way `ClientContextRegistry` is attached.
2162
+ *
2163
+ * Route observation is poll-on-demand rather than a `history.pushState` patch:
2164
+ * the SDK must never mutate host globals (see CLAUDE.md scoping rules), so the
2165
+ * current pathname is (re)checked on `popstate`/`hashchange`, on throttled user
2166
+ * activity, and on every `getSnapshot()` — the proactive engine's ~1s tick
2167
+ * makes that an effective 1s poll, plenty for multi-second dwell thresholds.
2168
+ *
2169
+ * Privacy: only enums, counters, and paths are recorded. Field VALUES are never
2170
+ * read — `signalFieldError(fieldName)` takes the field name only.
2171
+ *
2172
+ * Listeners are passive and throttled, attached only by `start()` (i.e. only
2173
+ * when proactive mode is configured) and fully removed by `destroy()`.
2174
+ */
2175
+ export declare class SignalCollector {
2176
+ private readonly getPageState?;
2177
+ private readonly activityThrottleMs;
2178
+ private readonly rageClickCount;
2179
+ private readonly rageClickWindowMs;
2180
+ private readonly rageClickRadiusPx;
2181
+ private readonly maxRecentRoutes;
2182
+ private readonly maxSignals;
2183
+ private started;
2184
+ private teardowns;
2185
+ private route;
2186
+ private routeEnteredAt;
2187
+ private lastActivityAt;
2188
+ private lastHeavyActivityAt;
2189
+ private recentRoutes;
2190
+ private routeBounces;
2191
+ private rageClicks;
2192
+ private fieldErrors;
2193
+ private recentClicks;
2194
+ private signals;
2195
+ private listeners;
2196
+ constructor(options?: SignalCollectorOptions);
2197
+ /**
2198
+ * Attach the DOM listeners and start tracking. Idempotent; no-op outside a
2199
+ * browser (SSR).
2200
+ */
2201
+ start(): void;
2202
+ /** Remove every listener and reset transient buffers. */
2203
+ destroy(): void;
2204
+ /**
2205
+ * App-pushed signal: a form field produced a (repeated) validation error.
2206
+ * Pass the field NAME only — values are never read, so no PII is collected.
2207
+ */
2208
+ signalFieldError(fieldName: string): void;
2209
+ /**
2210
+ * Subscribe to raw signals (route changes, bounces, rage clicks, field
2211
+ * errors). Returns an unsubscribe function. Used by the proactive engine to
2212
+ * evaluate promptly instead of waiting for the next tick.
2213
+ */
2214
+ subscribe(listener: (signal: Signal) => void): () => void;
2215
+ /** The typed-signal ring buffer (most recent last, bounded). */
2216
+ getSignals(): Signal[];
2217
+ /**
2218
+ * Aggregated snapshot of the current friction state. Re-checks the route
2219
+ * first, so calling this on a periodic tick doubles as the route poll.
2220
+ *
2221
+ * `pageState: false` skips the page-state read — used by the
2222
+ * `friction_signals` dynamic context provider, both because page state
2223
+ * already rides in `client_context` under its own `page-state:*` entries and
2224
+ * because reading it from inside a context provider would recurse.
2225
+ */
2226
+ getSnapshot(opts?: {
2227
+ pageState?: boolean;
2228
+ }): SignalsSnapshot;
2229
+ private currentPathname;
2230
+ private readPageState;
2231
+ private recordActivity;
2232
+ /** Compare the live pathname with the tracked one; handle a route change. */
2233
+ private checkRoute;
2234
+ private onClick;
2235
+ /** Cheap fingerprint of the page state, for "did this click change anything". */
2236
+ private pageStateKey;
2237
+ private pushSignal;
2238
+ }
2239
+
2240
+ export declare interface SignalCollectorOptions extends SignalCollectorTuning {
2241
+ /**
2242
+ * Reads the current page state (the registered `AgoStateControl.get()`
2243
+ * snapshot). Wired by `createAgoProactive` to the client's `page-state:*`
2244
+ * dynamic context entries so funnel state is available to trigger matchers
2245
+ * without new plumbing.
2246
+ */
2247
+ getPageState?: () => Record<string, unknown> | null;
2248
+ }
2249
+
2250
+ /** Tuning knobs for the collector's detectors. All optional. */
2251
+ export declare interface SignalCollectorTuning {
2252
+ /** Min gap between heavy activity work (route checks, notifications), ms. Default 250. */
2253
+ activityThrottleMs?: number;
2254
+ /** Rage click: clicks needed to count a burst. Default 3. */
2255
+ rageClickCount?: number;
2256
+ /** Rage click: max time between first and last click of a burst, ms. Default 1000. */
2257
+ rageClickWindowMs?: number;
2258
+ /** Rage click: max radius between clicks of a burst, px. Default 24. */
2259
+ rageClickRadiusPx?: number;
2260
+ /** Max routes kept in the recent-route sequence. Default 10. */
2261
+ maxRecentRoutes?: number;
2262
+ /** Max typed signals kept in the ring buffer. Default 50. */
2263
+ maxSignals?: number;
2264
+ }
2265
+
2266
+ /**
2267
+ * Aggregated view of the current friction state. Registered as a dynamic
2268
+ * context provider (key `friction_signals`) so it rides along as
2269
+ * `client_context` on every message, and sent as `signals` to the proactive
2270
+ * evaluate endpoint.
2271
+ */
2272
+ export declare interface SignalsSnapshot {
2273
+ /** Current pathname. */
2274
+ route: string;
2275
+ /** Time spent on the current route, ms. */
2276
+ dwellMs: number;
2277
+ /** Time since the last user activity (pointer/key/scroll/touch), ms. */
2278
+ idleMs: number;
2279
+ /** Rage-click bursts detected on the current route. */
2280
+ rageClicks: number;
2281
+ /**
2282
+ * A→B→A→B route oscillations detected in the recent route sequence. Rolling
2283
+ * session counter (cross-route by nature); trigger cooldowns and dismissal
2284
+ * memory keep it from re-firing forever.
2285
+ */
2286
+ routeBounces: number;
2287
+ /** App-pushed field error counters (field NAME → count), current route only. */
2288
+ fieldErrors: Record<string, number>;
2289
+ /** Most recent pathnames, oldest first (bounded). */
2290
+ recentRoutes: string[];
2291
+ /**
2292
+ * Merged `AgoStateControl.get()` snapshot of the registered page-state
2293
+ * controls (funnel step, filters…), or `null` when none are registered.
2294
+ */
2295
+ pageState: Record<string, unknown> | null;
2296
+ }
2297
+
2298
+ /**
2299
+ * Typed friction signals collected client-side by the {@link SignalCollector}.
2300
+ *
2301
+ * Privacy rule: signals carry **enums, counters, and paths only** — never field
2302
+ * values or free text — so no PII ever leaves the page through this channel.
2303
+ */
2304
+ export declare type SignalType = "route_change" | "route_bounce" | "rage_click" | "field_error";
2305
+
1742
2306
  /**
1743
2307
  * SSE stream chunk data
1744
2308
  */