@active-reach/web-sdk 1.41.0 → 1.43.0

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 (181) hide show
  1. package/package.json +1 -1
  2. package/dist/aegis-push.min.js +0 -2
  3. package/dist/aegis-push.min.js.map +0 -1
  4. package/dist/aegis-sw.js +0 -1
  5. package/dist/aegis.min.js +0 -2
  6. package/dist/aegis.min.js.map +0 -1
  7. package/dist/analytics-C-Go3Pm5.mjs +0 -3509
  8. package/dist/analytics-C-Go3Pm5.mjs.map +0 -1
  9. package/dist/cdn.d.ts +0 -26
  10. package/dist/cdn.d.ts.map +0 -1
  11. package/dist/chat/AegisChat.d.ts +0 -169
  12. package/dist/chat/AegisChat.d.ts.map +0 -1
  13. package/dist/chat/index.d.ts +0 -3
  14. package/dist/chat/index.d.ts.map +0 -1
  15. package/dist/core/analytics.d.ts +0 -320
  16. package/dist/core/analytics.d.ts.map +0 -1
  17. package/dist/core/bootstrap.d.ts +0 -96
  18. package/dist/core/bootstrap.d.ts.map +0 -1
  19. package/dist/core/prefetch-bundle-client.d.ts +0 -175
  20. package/dist/core/prefetch-bundle-client.d.ts.map +0 -1
  21. package/dist/core/queue.d.ts +0 -35
  22. package/dist/core/queue.d.ts.map +0 -1
  23. package/dist/core/rate-limiter.d.ts +0 -45
  24. package/dist/core/rate-limiter.d.ts.map +0 -1
  25. package/dist/core/sdk-config-poller.d.ts +0 -59
  26. package/dist/core/sdk-config-poller.d.ts.map +0 -1
  27. package/dist/core/session.d.ts +0 -52
  28. package/dist/core/session.d.ts.map +0 -1
  29. package/dist/core/transport.d.ts +0 -50
  30. package/dist/core/transport.d.ts.map +0 -1
  31. package/dist/core/user-namespace.d.ts +0 -48
  32. package/dist/core/user-namespace.d.ts.map +0 -1
  33. package/dist/ecommerce/index.d.ts +0 -94
  34. package/dist/ecommerce/index.d.ts.map +0 -1
  35. package/dist/ecommerce/types.d.ts +0 -81
  36. package/dist/ecommerce/types.d.ts.map +0 -1
  37. package/dist/governance/bloom-filter.d.ts +0 -47
  38. package/dist/governance/bloom-filter.d.ts.map +0 -1
  39. package/dist/governance/index.d.ts +0 -8
  40. package/dist/governance/index.d.ts.map +0 -1
  41. package/dist/governance/murmur3.d.ts +0 -43
  42. package/dist/governance/murmur3.d.ts.map +0 -1
  43. package/dist/governance/name-governor.d.ts +0 -98
  44. package/dist/governance/name-governor.d.ts.map +0 -1
  45. package/dist/governance/trait-governor.d.ts +0 -63
  46. package/dist/governance/trait-governor.d.ts.map +0 -1
  47. package/dist/inapp/AegisInAppManager.d.ts +0 -877
  48. package/dist/inapp/AegisInAppManager.d.ts.map +0 -1
  49. package/dist/inapp/actions.d.ts +0 -91
  50. package/dist/inapp/actions.d.ts.map +0 -1
  51. package/dist/inapp/devicePairing.d.ts +0 -70
  52. package/dist/inapp/devicePairing.d.ts.map +0 -1
  53. package/dist/inapp/eval-throttle.d.ts +0 -33
  54. package/dist/inapp/eval-throttle.d.ts.map +0 -1
  55. package/dist/inapp/font.d.ts +0 -16
  56. package/dist/inapp/font.d.ts.map +0 -1
  57. package/dist/inapp/index.d.ts +0 -8
  58. package/dist/inapp/index.d.ts.map +0 -1
  59. package/dist/inapp/lucide-svg.d.ts +0 -46
  60. package/dist/inapp/lucide-svg.d.ts.map +0 -1
  61. package/dist/inapp/renderPreview.d.ts +0 -40
  62. package/dist/inapp/renderPreview.d.ts.map +0 -1
  63. package/dist/inapp/renderers/active-web-chat.d.ts +0 -45
  64. package/dist/inapp/renderers/active-web-chat.d.ts.map +0 -1
  65. package/dist/inapp/renderers/card-style.d.ts +0 -31
  66. package/dist/inapp/renderers/card-style.d.ts.map +0 -1
  67. package/dist/inapp/renderers/card-template.d.ts +0 -233
  68. package/dist/inapp/renderers/card-template.d.ts.map +0 -1
  69. package/dist/inapp/renderers/carousel-cards.d.ts +0 -15
  70. package/dist/inapp/renderers/carousel-cards.d.ts.map +0 -1
  71. package/dist/inapp/renderers/coachmark-tour.d.ts +0 -24
  72. package/dist/inapp/renderers/coachmark-tour.d.ts.map +0 -1
  73. package/dist/inapp/renderers/games.d.ts +0 -27
  74. package/dist/inapp/renderers/games.d.ts.map +0 -1
  75. package/dist/inapp/renderers/hero.d.ts +0 -23
  76. package/dist/inapp/renderers/hero.d.ts.map +0 -1
  77. package/dist/inapp/renderers/index.d.ts +0 -22
  78. package/dist/inapp/renderers/index.d.ts.map +0 -1
  79. package/dist/inapp/renderers/interactive-contract.d.ts +0 -48
  80. package/dist/inapp/renderers/interactive-contract.d.ts.map +0 -1
  81. package/dist/inapp/renderers/product-recommendation.d.ts +0 -37
  82. package/dist/inapp/renderers/product-recommendation.d.ts.map +0 -1
  83. package/dist/inapp/renderers/progress-bar.d.ts +0 -38
  84. package/dist/inapp/renderers/progress-bar.d.ts.map +0 -1
  85. package/dist/inapp/renderers/progress-core.d.ts +0 -80
  86. package/dist/inapp/renderers/progress-core.d.ts.map +0 -1
  87. package/dist/inapp/renderers/reviews.d.ts +0 -38
  88. package/dist/inapp/renderers/reviews.d.ts.map +0 -1
  89. package/dist/inapp/renderers/sticky-bar.d.ts +0 -14
  90. package/dist/inapp/renderers/sticky-bar.d.ts.map +0 -1
  91. package/dist/inapp/renderers/stories.d.ts +0 -31
  92. package/dist/inapp/renderers/stories.d.ts.map +0 -1
  93. package/dist/inapp/renderers/types.d.ts +0 -147
  94. package/dist/inapp/renderers/types.d.ts.map +0 -1
  95. package/dist/inapp/renderers/video.d.ts +0 -20
  96. package/dist/inapp/renderers/video.d.ts.map +0 -1
  97. package/dist/inbox/AegisInbox.d.ts +0 -106
  98. package/dist/inbox/AegisInbox.d.ts.map +0 -1
  99. package/dist/inbox/index.d.ts +0 -3
  100. package/dist/inbox/index.d.ts.map +0 -1
  101. package/dist/index.d.ts +0 -40
  102. package/dist/index.d.ts.map +0 -1
  103. package/dist/index.js +0 -15127
  104. package/dist/index.js.map +0 -1
  105. package/dist/integrations/react.d.ts +0 -19
  106. package/dist/integrations/react.d.ts.map +0 -1
  107. package/dist/loyalty/AegisLoyaltyManager.d.ts +0 -120
  108. package/dist/loyalty/AegisLoyaltyManager.d.ts.map +0 -1
  109. package/dist/loyalty/index.d.ts +0 -3
  110. package/dist/loyalty/index.d.ts.map +0 -1
  111. package/dist/plugins/registry.d.ts +0 -13
  112. package/dist/plugins/registry.d.ts.map +0 -1
  113. package/dist/push/AegisWebPush.d.ts +0 -199
  114. package/dist/push/AegisWebPush.d.ts.map +0 -1
  115. package/dist/push/AegisWebPush.js +0 -542
  116. package/dist/push/AegisWebPush.js.map +0 -1
  117. package/dist/push/cdn-push.d.ts +0 -21
  118. package/dist/push/cdn-push.d.ts.map +0 -1
  119. package/dist/react.js +0 -70
  120. package/dist/react.js.map +0 -1
  121. package/dist/runtime/AegisMessageRuntime.d.ts +0 -274
  122. package/dist/runtime/AegisMessageRuntime.d.ts.map +0 -1
  123. package/dist/runtime/index.d.ts +0 -3
  124. package/dist/runtime/index.d.ts.map +0 -1
  125. package/dist/snippet.min.js +0 -1
  126. package/dist/state/intent_ledger.d.ts +0 -136
  127. package/dist/state/intent_ledger.d.ts.map +0 -1
  128. package/dist/triggers/ContactScoresFetcher.d.ts +0 -113
  129. package/dist/triggers/ContactScoresFetcher.d.ts.map +0 -1
  130. package/dist/triggers/IntentRuleEvaluator.d.ts +0 -213
  131. package/dist/triggers/IntentRuleEvaluator.d.ts.map +0 -1
  132. package/dist/triggers/IntentSnapshotCollector.d.ts +0 -83
  133. package/dist/triggers/IntentSnapshotCollector.d.ts.map +0 -1
  134. package/dist/triggers/SelectorBinder.d.ts +0 -118
  135. package/dist/triggers/SelectorBinder.d.ts.map +0 -1
  136. package/dist/triggers/TriggerEngine.d.ts +0 -296
  137. package/dist/triggers/TriggerEngine.d.ts.map +0 -1
  138. package/dist/triggers/behaviouralTriggers.d.ts +0 -41
  139. package/dist/triggers/behaviouralTriggers.d.ts.map +0 -1
  140. package/dist/triggers/index.d.ts +0 -11
  141. package/dist/triggers/index.d.ts.map +0 -1
  142. package/dist/types/config.d.ts +0 -77
  143. package/dist/types/config.d.ts.map +0 -1
  144. package/dist/types/events.d.ts +0 -147
  145. package/dist/types/events.d.ts.map +0 -1
  146. package/dist/types/index.d.ts +0 -5
  147. package/dist/types/index.d.ts.map +0 -1
  148. package/dist/types/plugin.d.ts +0 -21
  149. package/dist/types/plugin.d.ts.map +0 -1
  150. package/dist/types/type-safe-events.d.ts +0 -14
  151. package/dist/types/type-safe-events.d.ts.map +0 -1
  152. package/dist/utils/canonical-identity.d.ts +0 -29
  153. package/dist/utils/canonical-identity.d.ts.map +0 -1
  154. package/dist/utils/consent.d.ts +0 -40
  155. package/dist/utils/consent.d.ts.map +0 -1
  156. package/dist/utils/debounce.d.ts +0 -3
  157. package/dist/utils/debounce.d.ts.map +0 -1
  158. package/dist/utils/device.d.ts +0 -6
  159. package/dist/utils/device.d.ts.map +0 -1
  160. package/dist/utils/identity.d.ts +0 -27
  161. package/dist/utils/identity.d.ts.map +0 -1
  162. package/dist/utils/index.d.ts +0 -7
  163. package/dist/utils/index.d.ts.map +0 -1
  164. package/dist/utils/logger.d.ts +0 -15
  165. package/dist/utils/logger.d.ts.map +0 -1
  166. package/dist/utils/meta-cookies.d.ts +0 -65
  167. package/dist/utils/meta-cookies.d.ts.map +0 -1
  168. package/dist/utils/redact-url.d.ts +0 -56
  169. package/dist/utils/redact-url.d.ts.map +0 -1
  170. package/dist/utils/storage.d.ts +0 -20
  171. package/dist/utils/storage.d.ts.map +0 -1
  172. package/dist/utils/url-parser.d.ts +0 -61
  173. package/dist/utils/url-parser.d.ts.map +0 -1
  174. package/dist/utils/uuid.d.ts +0 -4
  175. package/dist/utils/uuid.d.ts.map +0 -1
  176. package/dist/utils/visitor.d.ts +0 -43
  177. package/dist/utils/visitor.d.ts.map +0 -1
  178. package/dist/widgets/AegisWidgetManager.d.ts +0 -209
  179. package/dist/widgets/AegisWidgetManager.d.ts.map +0 -1
  180. package/dist/widgets/index.d.ts +0 -3
  181. package/dist/widgets/index.d.ts.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"cdn-push.d.ts","sourceRoot":"","sources":["../../src/push/cdn-push.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,YAAY,EAAE,OAAO,YAAY,CAAC;KACnC;CACF;AAID,OAAO,EAAE,YAAY,EAAE,CAAC"}
package/dist/react.js DELETED
@@ -1,70 +0,0 @@
1
- import React, { createContext, useState, useEffect, useContext } from "react";
2
- import { A as Aegis } from "./analytics-C-Go3Pm5.mjs";
3
- const AegisContext = createContext({
4
- aegis: null,
5
- isReady: false
6
- });
7
- const AegisProvider = ({
8
- writeKey,
9
- config,
10
- children
11
- }) => {
12
- const [aegis] = useState(() => new Aegis());
13
- const [isReady, setIsReady] = useState(false);
14
- useEffect(() => {
15
- aegis.init(writeKey, config).then(() => {
16
- setIsReady(true);
17
- }).catch((error) => {
18
- console.error("[Active Reach] Initialization failed:", error);
19
- });
20
- return () => {
21
- aegis.destroy();
22
- };
23
- }, [aegis, writeKey, config]);
24
- return /* @__PURE__ */ React.createElement(AegisContext.Provider, { value: { aegis, isReady } }, children);
25
- };
26
- const useAegis = () => {
27
- const context = useContext(AegisContext);
28
- if (!context) {
29
- throw new Error("useAegis must be used within AegisProvider");
30
- }
31
- return context;
32
- };
33
- const useTrackEvent = () => {
34
- const { aegis, isReady } = useAegis();
35
- return React.useCallback(
36
- (eventName, properties) => {
37
- if (isReady && aegis) {
38
- aegis.track(eventName, properties);
39
- }
40
- },
41
- [aegis, isReady]
42
- );
43
- };
44
- const usePageView = (pageName, properties, dependencies = []) => {
45
- const { aegis, isReady } = useAegis();
46
- useEffect(() => {
47
- if (isReady && aegis) {
48
- aegis.page(pageName, properties);
49
- }
50
- }, [aegis, isReady, pageName, ...dependencies]);
51
- };
52
- const useIdentifyUser = () => {
53
- const { aegis, isReady } = useAegis();
54
- return React.useCallback(
55
- (userId, traits) => {
56
- if (isReady && aegis) {
57
- aegis.identify(userId, traits);
58
- }
59
- },
60
- [aegis, isReady]
61
- );
62
- };
63
- export {
64
- AegisProvider,
65
- useAegis,
66
- useIdentifyUser,
67
- usePageView,
68
- useTrackEvent
69
- };
70
- //# sourceMappingURL=react.js.map
package/dist/react.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"react.js","sources":["../src/integrations/react.tsx"],"sourcesContent":["import React, { createContext, useContext, useEffect, useState } from 'react';\nimport { Aegis } from '../core/analytics';\nimport { AegisConfig } from '../types/config';\n\ninterface AegisContextValue {\n aegis: Aegis | null;\n isReady: boolean;\n}\n\nconst AegisContext = createContext<AegisContextValue>({\n aegis: null,\n isReady: false,\n});\n\nexport interface AegisProviderProps {\n writeKey: string;\n config?: Partial<AegisConfig>;\n children: React.ReactNode;\n}\n\nexport const AegisProvider: React.FC<AegisProviderProps> = ({\n writeKey,\n config,\n children,\n}) => {\n const [aegis] = useState(() => new Aegis());\n const [isReady, setIsReady] = useState(false);\n\n useEffect(() => {\n aegis\n .init(writeKey, config)\n .then(() => {\n setIsReady(true);\n })\n .catch((error) => {\n console.error('[Active Reach] Initialization failed:', error);\n });\n\n return () => {\n aegis.destroy();\n };\n }, [aegis, writeKey, config]);\n\n return (\n <AegisContext.Provider value={{ aegis, isReady }}>\n {children}\n </AegisContext.Provider>\n );\n};\n\nexport const useAegis = (): AegisContextValue => {\n const context = useContext(AegisContext);\n\n if (!context) {\n throw new Error('useAegis must be used within AegisProvider');\n }\n\n return context;\n};\n\nexport const useTrackEvent = () => {\n const { aegis, isReady } = useAegis();\n\n return React.useCallback(\n (eventName: string, properties?: Record<string, any>) => {\n if (isReady && aegis) {\n aegis.track(eventName, properties);\n }\n },\n [aegis, isReady]\n );\n};\n\nexport const usePageView = (\n pageName?: string,\n properties?: Record<string, any>,\n dependencies: any[] = []\n) => {\n const { aegis, isReady } = useAegis();\n\n useEffect(() => {\n if (isReady && aegis) {\n aegis.page(pageName, properties);\n }\n }, [aegis, isReady, pageName, ...dependencies]);\n};\n\nexport const useIdentifyUser = () => {\n const { aegis, isReady } = useAegis();\n\n return React.useCallback(\n (userId: string, traits?: Record<string, any>) => {\n if (isReady && aegis) {\n aegis.identify(userId, traits);\n }\n },\n [aegis, isReady]\n );\n};\n"],"names":[],"mappings":";;AASA,MAAM,eAAe,cAAiC;AAAA,EACpD,OAAO;AAAA,EACP,SAAS;AACX,CAAC;AAQM,MAAM,gBAA8C,CAAC;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,CAAC,KAAK,IAAI,SAAS,MAAM,IAAI,OAAO;AAC1C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,YAAU,MAAM;AACd,UACG,KAAK,UAAU,MAAM,EACrB,KAAK,MAAM;AACV,iBAAW,IAAI;AAAA,IACjB,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,cAAQ,MAAM,yCAAyC,KAAK;AAAA,IAC9D,CAAC;AAEH,WAAO,MAAM;AACX,YAAM,QAAA;AAAA,IACR;AAAA,EACF,GAAG,CAAC,OAAO,UAAU,MAAM,CAAC;AAE5B,SACE,sBAAA,cAAC,aAAa,UAAb,EAAsB,OAAO,EAAE,OAAO,UAAQ,GAC5C,QACH;AAEJ;AAEO,MAAM,WAAW,MAAyB;AAC/C,QAAM,UAAU,WAAW,YAAY;AAEvC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AAEA,SAAO;AACT;AAEO,MAAM,gBAAgB,MAAM;AACjC,QAAM,EAAE,OAAO,QAAA,IAAY,SAAA;AAE3B,SAAO,MAAM;AAAA,IACX,CAAC,WAAmB,eAAqC;AACvD,UAAI,WAAW,OAAO;AACpB,cAAM,MAAM,WAAW,UAAU;AAAA,MACnC;AAAA,IACF;AAAA,IACA,CAAC,OAAO,OAAO;AAAA,EAAA;AAEnB;AAEO,MAAM,cAAc,CACzB,UACA,YACA,eAAsB,CAAA,MACnB;AACH,QAAM,EAAE,OAAO,QAAA,IAAY,SAAA;AAE3B,YAAU,MAAM;AACd,QAAI,WAAW,OAAO;AACpB,YAAM,KAAK,UAAU,UAAU;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,OAAO,SAAS,UAAU,GAAG,YAAY,CAAC;AAChD;AAEO,MAAM,kBAAkB,MAAM;AACnC,QAAM,EAAE,OAAO,QAAA,IAAY,SAAA;AAE3B,SAAO,MAAM;AAAA,IACX,CAAC,QAAgB,WAAiC;AAChD,UAAI,WAAW,OAAO;AACpB,cAAM,SAAS,QAAQ,MAAM;AAAA,MAC/B;AAAA,IACF;AAAA,IACA,CAAC,OAAO,OAAO;AAAA,EAAA;AAEnB;"}
@@ -1,274 +0,0 @@
1
- /**
2
- * AegisMessageRuntime — unified facade for in-app messaging.
3
- *
4
- * The sole public entry point for all 20 in-app types (announce +
5
- * collect + assist buckets) plus the legacy gamification surface
6
- * (chat_bubble / toast / exit_intent_popup configured via
7
- * /v1/widgets/config). Under the hood it composes an
8
- * `AegisInAppManager` + `AegisWidgetManager`; callers never touch them
9
- * directly.
10
- *
11
- * Public API:
12
- * new AegisMessageRuntime({ writeKey, apiHost, ... })
13
- * await runtime.initialize()
14
- * await runtime.updateContactId(id)
15
- * runtime.onClientEvent(eventName, data)
16
- * runtime.destroy()
17
- *
18
- * Internal wiring: spin_wheel + scratch_card campaigns render in the
19
- * InAppManager like every other in-app type (one engine: a turn posts
20
- * /in-app/responses). The facade owns the page's TriggerEngine: it arms the
21
- * behavioural `client_trigger`s (exit intent / scroll depth / time on page /
22
- * inactivity) of every campaign load, forwards each firing to
23
- * `inApp.onClientEvent`, and starts the engine it created.
24
- */
25
- import { AegisInAppManager, type AegisInAppConfig, type InAppCampaign, type CartState, type AegisAction } from '../inapp';
26
- import { AegisWidgetManager, type AegisWidgetConfig } from '../widgets';
27
- import { IntentRuleEvaluator } from '../triggers/IntentRuleEvaluator';
28
- import { ContactScoresFetcher } from '../triggers/ContactScoresFetcher';
29
- import { AegisLoyaltyManager } from '../loyalty';
30
- import { AegisChat, type AegisChatConfig } from '../chat';
31
- export interface AegisMessageRuntimeConfig extends AegisInAppConfig {
32
- /** If set, a `TriggerEngine` from the SDK is wired to the WidgetManager
33
- * for its exit-intent / scroll-velocity / inactivity handlers. Leave
34
- * undefined to have the runtime construct one internally. */
35
- triggerEngine?: AegisWidgetConfig['triggerEngine'];
36
- /** WidgetManager prefetch toggle. Defaults to true — the exit-intent
37
- * popup config comes from `/v1/widgets/config/prefetch`. */
38
- enableWidgetPrefetch?: boolean;
39
- /** Source platform for gamification attribution (shopify / woocommerce
40
- * / magento / mobile_sdk / web). Passed through to WidgetManager. */
41
- sourcePlatform?: AegisWidgetConfig['sourcePlatform'];
42
- /** Storefront slug for the loyalty subsystem — needed when the host
43
- * app calls `runtime.loyalty.storeCredit.*` / `runtime.loyalty.giftCards.*`.
44
- * When omitted, the loyalty manager is constructed but every call
45
- * will throw until configure() is invoked. */
46
- storefrontSlug?: string;
47
- /** Mount the customer chat launcher ("Shopping Assistant") — a floating
48
- * bubble that talks to the channel-neutral chat agent (Track A). Off by
49
- * default; opt in per host page. */
50
- enableChat?: boolean;
51
- /** Presentation overrides for the chat launcher (title / greeting / accent),
52
- * plus proactive auto-open. writeKey / apiHost / org / contact are inherited
53
- * from the runtime. */
54
- chat?: Pick<AegisChatConfig, 'title' | 'greeting' | 'accentColor' | 'surfaceStyle' | 'channel' | 'icon' | 'logoUrl' | 'position' | 'displayMode'> & {
55
- /** Client-side TriggerEngine events that auto-open the launcher (e.g.
56
- * ['exit_intent', 'inactivity_90']). The trigger ONLY opens the panel —
57
- * it never creates an offer. The proactive *opener* is owned server-side
58
- * by the journey→warm-offer-queue bridge (Track B B4); the bot surfaces it
59
- * on the customer's first turn. This keeps a single offer source — no
60
- * parallel client-side offer infra. */
61
- proactiveTriggers?: string[];
62
- };
63
- /** "Rich, not overwhelming" interruption governance (plan
64
- * ACS_ENGAGEMENT_COMMERCE_PACK §5). Applied to the shared
65
- * `intentRuleEvaluator` on construct. Default off (base SDK contract is
66
- * unchanged for existing consumers); the storefront opts in. */
67
- governance?: {
68
- /** Cap interruptive overlays at one per session. */
69
- oneInterruptionPerSession?: boolean;
70
- /** TTFI floor (ms) — no overlay in the session's first N ms (exit/back exempt). */
71
- ttfiMs?: number;
72
- };
73
- }
74
- /**
75
- * One runtime, all in-app types. Consumers should prefer this over
76
- * importing AegisInAppManager / AegisWidgetManager directly. Those two
77
- * classes remain exported for a deprecation window — see `./deprecated.ts`.
78
- */
79
- export declare class AegisMessageRuntime {
80
- /** Guards the one-time console version banner across multiple instances. */
81
- private static _bannerPrinted;
82
- readonly inApp: AegisInAppManager;
83
- readonly widgets: AegisWidgetManager;
84
- /** Shared IntentRuleEvaluator for identified-contact micro-intent
85
- * patterns. The ContactScoresFetcher writes Layer-1 signals into its
86
- * snapshot; IntentSnapshotCollector (if wired by the consumer) writes
87
- * Layer-2 signals. Exposed so apps that pre-existed P4a can swap in
88
- * their own evaluator if they need to. */
89
- readonly intentRuleEvaluator: IntentRuleEvaluator;
90
- /** Bridges GET /v1/sdk/contact-scores into the evaluator snapshot.
91
- * Triggered automatically on initialize() and updateContactId(). */
92
- readonly contactScores: ContactScoresFetcher;
93
- /** Closed-loop store credit + directed gift cards (Phase 7).
94
- * Usage:
95
- * await runtime.loyalty.storeCredit.listActive(phone)
96
- * await runtime.loyalty.storeCredit.startReload({ phone, workspaceId, amountPaise })
97
- * await runtime.loyalty.giftCards.startPurchase({ ... })
98
- * await runtime.loyalty.giftCards.claim({ giftCardId, phone })
99
- * Tracker: docs/architecture/ACTIVE_LOYALTY_STORE_CREDIT_GIFT_CARDS_TRACKER.md */
100
- readonly loyalty: AegisLoyaltyManager;
101
- /** Customer chat launcher ("Shopping Assistant"). Constructed only when
102
- * `enableChat` is set; undefined otherwise. (Track A) */
103
- readonly chat?: AegisChat;
104
- private contactId?;
105
- private contactToken?;
106
- private initialized;
107
- private readonly triggerEngine;
108
- private readonly ownsTriggerEngine;
109
- /** Engine events already armed for in-app client triggers (one subscription each). */
110
- private readonly armedInAppTriggers;
111
- private readonly unsubscribeCampaignsLoaded;
112
- /** apiHost captured for the device-pairing entry (`?aegis_pair=CODE`). */
113
- private readonly pairingApiHost;
114
- constructor(config: AegisMessageRuntimeConfig);
115
- /** No hovering pointer (phones, tablets): exit intent is a fast scroll up,
116
- * not the mouse leaving the window. */
117
- private static hasNoHover;
118
- /**
119
- * Boots both managers in parallel. Safe to call multiple times — the
120
- * second + subsequent calls are no-ops.
121
- */
122
- initialize(): Promise<void>;
123
- /**
124
- * Both managers carry contactId. Updates both so the server-side
125
- * targeting pipeline sees the identity for campaign eligibility AND
126
- * the widget prefetch includes per-contact segment configs. The
127
- * widgets call is async (may re-fetch prefetch configs) but we don't
128
- * wait — callers that care about the fetched state await on the
129
- * returned promise.
130
- */
131
- updateContactId(contactId: string, contactToken?: string): Promise<void>;
132
- /**
133
- * Forward a client-side event (product_viewed, cart_idle_90s, etc.)
134
- * to the in-app manager's client-trigger evaluator. The WidgetManager
135
- * has its own TriggerEngine wiring (exit-intent, scroll-velocity) so
136
- * we don't forward there — events it cares about arrive through that
137
- * channel already.
138
- */
139
- onClientEvent(eventName: string, eventData?: Record<string, unknown>): void;
140
- /**
141
- * Unified reactive context — the GENERAL imperative state API (Plotline-style
142
- * "global context state engine"). The host app feeds named namespaces:
143
- * runtime.updateContext('cart', { total: 540, items: 3, currency: 'INR' })
144
- * runtime.updateContext('user', { tier: 'gold', lifecycle: 'active' })
145
- * runtime.updateContext('session', { idle_s: 60 })
146
- *
147
- * Held in PRIVATE runtime state (no `window` pollution). Merged shallowly per
148
- * namespace and evaluated entirely client-side — no round-trip. This supersedes
149
- * the single-purpose `setCartState` (kept as a thin wrapper for back-compat).
150
- *
151
- * Design note (vs the proposed rewrite): we DELIBERATELY do NOT introduce a
152
- * parallel rule schema. Our canonical `IntentRule` (shared with the cell-plane
153
- * Pydantic schema + the editor + seeded campaigns) stays the source of truth.
154
- * `updateContext` BRIDGES known paths into the existing enum-keyed
155
- * `IntentSnapshot` (e.g. cart.total → the `cart_value` signal) so today's rules
156
- * keep firing — fed by the generic API. Arbitrary dot-path leaves
157
- * (`cart.foo`) are a forward-compatible follow-up that adds an optional `path`
158
- * to the canonical `IntentLeaf` (schema-mirrored + drift-guarded), NOT a second
159
- * evaluator. Tri-state (null = unprovable) evaluation is preserved — we do not
160
- * regress missing paths to `false`.
161
- */
162
- updateContext(namespace: string, data: Record<string, unknown>): void;
163
- /** Read the current client-side context snapshot (for the editor scrubber /
164
- * preview bridge to mirror live values). Read-only view of the ONE store. */
165
- getContext(): Readonly<Record<string, Readonly<Record<string, unknown>>>>;
166
- /**
167
- * Bridge well-known context paths into the canonical enum-keyed IntentSnapshot,
168
- * so existing signal-based rules (cart_value) keep firing off the generic
169
- * `updateContext`. Reads from the ONE store (the evaluator). Extend here as new
170
- * signals map to context paths — no parallel engine.
171
- */
172
- private bridgeContextToSignals;
173
- /** Derive the typed cart snapshot for the progress-bar renderer reader from
174
- * the ONE context store (the `cart` namespace). No separate cart field. */
175
- private deriveCartState;
176
- /**
177
- * Back-compat wrapper over `updateContext('cart', …)`. The single-purpose cart
178
- * feed for headless storefronts; prefer `updateContext` for new code.
179
- */
180
- setCartState(state: CartState): void;
181
- /**
182
- * Register the canonical CTA-action handler — the CEP-standard single callback
183
- * that receives every in-app intent (add_to_cart / open_product / open_cart /
184
- * open_login / navigate / custom). Return `true` when handled; otherwise the SDK
185
- * applies the graceful fallback. The construct-time `onAction` config is the
186
- * equivalent; this lets a host register/replace it once it holds the runtime.
187
- * See CANONICAL_ACTION_MODEL_TRACKER.md.
188
- */
189
- onAction(handler: (action: AegisAction) => boolean | void): void;
190
- /**
191
- * The ONE cart writer. Normalizes any cart-ish shape and funnels it into the
192
- * single `cart` context namespace (read by the Free-Delivery progress card,
193
- * the progress-bar widget, and rule eval via the `cart_value` signal). EVERY
194
- * cart feed routes through here: ecommerce events (`bindEcommerce`), platform
195
- * auto-detect + `widgets.setCartData` (`onCartDetected`), and the explicit
196
- * `setCartState` escape hatch. See CART_STORE_UNIFICATION_TRACKER.md.
197
- */
198
- applyCart(cart: {
199
- total?: number;
200
- itemCount?: number;
201
- items?: number;
202
- currency?: string;
203
- }): void;
204
- /**
205
- * Wire the analytics ecommerce tracker into the cart store — the CEP-standard
206
- * path. After this, a host firing `aegis.ecommerce.addToCart(...)` /
207
- * `cartViewed(...)` automatically drives every cart-reactive surface; no
208
- * separate `setCartState` call is needed. Call once after constructing both
209
- * the analytics SDK and the runtime. Idempotent.
210
- */
211
- bindEcommerce(tracker: {
212
- onCartChange(sink: (c: {
213
- total: number;
214
- itemCount: number;
215
- currency: string;
216
- }) => void): void;
217
- }): void;
218
- /**
219
- * Notify the in-app subsystem that a tracked event occurred. Schedules
220
- * a debounced refresh of armed campaigns so newly eligible in-app
221
- * messages (e.g., trigger-gated on `cart_item_added`) become visible
222
- * within ~300ms — bursts coalesce. See
223
- * `AegisInAppManager.refreshOnEvent` for debounce semantics and why
224
- * this matters under storefront polling.
225
- */
226
- track(eventName: string): void;
227
- /**
228
- * Notify the in-app subsystem that a URL-bound page view occurred.
229
- * Mirrors `aegis.page()` semantics — fires `'page_view'` as the
230
- * qualifying event so the trailing debounce covers SPA route bursts
231
- * (history.pushState rapid-fire) without spamming the endpoint.
232
- */
233
- page(name?: string): void;
234
- /**
235
- * Notify the in-app subsystem that a SPA-logical screen view occurred
236
- * (cart drawer open, checkout step transition — anywhere `aegis.screen()`
237
- * is called). Refresh-on-screen lets per-screen-targeted campaigns
238
- * arm without a URL change.
239
- */
240
- screen(name: string): void;
241
- /**
242
- * Conversion-aware suppression — call when the host app observes a
243
- * goal event (purchase / order_completed / checkout_completed / custom).
244
- *
245
- * Forwards to AegisInAppManager.notifyConversion() which:
246
- * - Persists the conversion in sessionStorage so subsequent page loads
247
- * in the same tab keep armed campaigns silenced.
248
- * - For every armed campaign whose
249
- * `frequency.suppress_after_conversion_seconds` is set, computes an
250
- * expiry epoch_ms and silences it until then.
251
- *
252
- * Storefronts integrate via the React provider's useCommerceEvents
253
- * helper which calls this after `ecom.orderCompleted(...)`. Direct SDK
254
- * users call it themselves.
255
- *
256
- * Added by Micro-Intent Engine P0a Task 6 (2026-04-30).
257
- */
258
- notifyConversion(goalName: string): void;
259
- /**
260
- * Tear down both managers. Used by React component unmounts + during
261
- * identity switches where we want a full reset. If the facade created
262
- * its own TriggerEngine, WidgetManager.destroy() will stop it;
263
- * caller-supplied engines are left alone.
264
- */
265
- destroy(): void;
266
- /**
267
- * Current armed campaigns visible to the InAppManager. Accessible for
268
- * the Prefetch Inspector and for debugging. WidgetManager's prefetched
269
- * exit-intent popup config is NOT in this list — it lives in
270
- * `this.widgets` and has its own lifecycle.
271
- */
272
- getCampaigns(): InAppCampaign[];
273
- }
274
- //# sourceMappingURL=AegisMessageRuntime.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AegisMessageRuntime.d.ts","sourceRoot":"","sources":["../../src/runtime/AegisMessageRuntime.ts"],"names":[],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- export { AegisMessageRuntime } from './AegisMessageRuntime';
2
- export type { AegisMessageRuntimeConfig } from './AegisMessageRuntime';
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -1 +0,0 @@
1
- !function(){var e=window.aegis=window.aegis||[];if(!e.invoked){e.invoked=!0,e.methods=["init","track","identify","page","screen","group","alias","reset","flush","use","debug","setCell","getCellInfo","getAnonymousId","getUserId","getSessionId","setConsent","grantConsent","denyConsent","hasConsent","getConsentPreferences","onConsentChange","user.login","user.logout","user.setAttribute","user.setAttributes","user.setEmail","user.setPhone","user.setHashedEmail","user.setHashedPhone","user.setBirthDate","user.setOptIn","user.setSecureToken"],e.factory=function(t){return function(){var n=Array.prototype.slice.call(arguments);return n.unshift(t),e.push(n),e}};for(var t=0;t<e.methods.length;t++){var n=e.methods[t];if(-1===n.indexOf("."))e[n]=e.factory(n);else{for(var s=n.split("."),r=e,o=0;o<s.length-1;o++)r[s[o]]=r[s[o]]||{},r=r[s[o]];r[s[s.length-1]]=e.factory(n)}}e.load=function(t,n){var s=document.createElement("script");s.type="text/javascript",s.async=!0,s.src=n&&n.cdnUrl?n.cdnUrl:"https://cdn.activereach.ai/sdk/aegis.min.js",s.onerror=function(){window.console&&console.error("Active Reach SDK failed to load")};var r=document.getElementsByTagName("script")[0];r.parentNode.insertBefore(s,r),e._loadOptions={key:t,options:n}},e.SNIPPET_VERSION="1.1.0"}}();
@@ -1,136 +0,0 @@
1
- /**
2
- * Micro-Intent Engine — anonymous-visitor cross-session ledger
3
- * (P1 Task 7 + P2 Task 4 full implementation).
4
- *
5
- * Stores `cum_dwell_sku` (rolling cumulative time on PDP per SKU) and
6
- * `session_count_for_sku` for anonymous visitors so the Returning
7
- * Hover-Browser pattern (catalog ID 4) can fire when an unknown
8
- * visitor has accumulated meaningful engagement across multiple sessions.
9
- *
10
- * ─────────────────────────────────────────────────────────────────────
11
- * SAFARI / ITP ACKNOWLEDGEMENT (Robustness #2 — load-bearing)
12
- * ─────────────────────────────────────────────────────────────────────
13
- *
14
- * Apple's Intelligent Tracking Prevention (ITP) caps client-side
15
- * `localStorage` to **7 days** for non-interactive third-party browsing
16
- * on iOS Safari + macOS Safari.
17
- *
18
- * The `aegis_intent_ledger` key persisted here decays for anonymous
19
- * Safari users faster than for Chrome / Firefox users. Concrete
20
- * downstream impact:
21
- *
22
- * - Pattern 4 "Returning Hover-Browser" is the ONLY pattern whose
23
- * trigger depends on cross-session anonymous accumulation. On Safari
24
- * it is reliable only within a 7-day window. After that, an
25
- * anonymous returning visitor looks like a new visitor.
26
- *
27
- * - All other patterns are session-scoped (Layer-2 only, in-tab) or
28
- * identified-contact-scoped (Layer-1 fetched per identify()), so
29
- * they are unaffected by ITP storage decay.
30
- *
31
- * DOCUMENTATION REQUIREMENT — when P3a ships the Pattern Detail screen
32
- * for Returning Hover-Browser, its UI must carry the footnote:
33
- *
34
- * "On Safari, this pattern is reliable for visitors who return within
35
- * 7 days. For longer windows, consider identifying customers via
36
- * signed-in checkout."
37
- *
38
- * SERVER-SIDE FALLBACK (deferred to P5) — when a contact eventually
39
- * identifies (sign-in / OTP / checkout), we promote this localStorage
40
- * ledger to a server-side `contact_intent_ledger` row. That bypasses
41
- * ITP entirely for identified users. Implementation tracked in
42
- * MICRO_INTENT_ENGINE.md §"Robustness 2" → "Server-side fallback".
43
- *
44
- * ─────────────────────────────────────────────────────────────────────
45
- * Implementation (P2 Task 4)
46
- * ─────────────────────────────────────────────────────────────────────
47
- *
48
- * The IntentLedger class implements IIntentLedger with localStorage as
49
- * the backing store. Capped-LRU at INTENT_LEDGER_MAX_SKUS, rolling
50
- * INTENT_LEDGER_WINDOW_DAYS window, hydrate-on-construct, debounced
51
- * persistence (250ms) to avoid write-amplification on rapid dwell
52
- * ticks. In-memory state is always fresh for synchronous reads.
53
- *
54
- * The constructor accepts an optional Storage-shaped object for
55
- * testability; in production it defaults to `globalThis.localStorage`.
56
- * The P2 Task 4 forward-marker below remains so the drift-anchor
57
- * test (test_intent_ledger_itp_doc.py) keeps tracking the right
58
- * scope reference even after the class lands.
59
- *
60
- * P2 Task 4 implementation complete (2026-05-11). The acknowledgement
61
- * comment above is retained so future engineers reading a Safari bug
62
- * report can find the source-of-truth explanation here, not in a plan
63
- * doc that may have rotted.
64
- */
65
- /** localStorage key the ledger persists under. Same key in stub and
66
- * P2 Task 4 implementation so the stub-to-full upgrade is non-
67
- * breaking (no key migration). */
68
- export declare const INTENT_LEDGER_STORAGE_KEY = "aegis_intent_ledger";
69
- /** Max number of SKU entries persisted. Beyond this, the LRU evicts
70
- * least-recently-touched. Picked to stay well under typical Safari /
71
- * Chrome localStorage caps (~5MB origin quota; we use <2KB). */
72
- export declare const INTENT_LEDGER_MAX_SKUS = 50;
73
- /** Rolling window for `cum_dwell_sku` accumulation. Aligns with the
74
- * Safari ITP 7-day cap above — values older than this are dropped on
75
- * every read so the data set doesn't outlive the storage's own
76
- * reliability window. */
77
- export declare const INTENT_LEDGER_WINDOW_DAYS = 7;
78
- export interface SkuLedgerEntry {
79
- /** Rolling cumulative dwell on this SKU's PDP, in milliseconds. */
80
- cumDwellMs: number;
81
- /** Distinct session count for this SKU. */
82
- sessionCount: number;
83
- /** Epoch ms of last update; used for LRU eviction + window pruning. */
84
- lastSeenAt: number;
85
- }
86
- /** Storage interface — matches the surface of `window.localStorage` we
87
- * actually use. Allows injection in tests without depending on the
88
- * full DOM Storage type. */
89
- export interface LedgerStorage {
90
- getItem(key: string): string | null;
91
- setItem(key: string, value: string): void;
92
- removeItem(key: string): void;
93
- }
94
- /** P1 Task 7 stub. P2 Task 4 fills in the methods. Defining the shape
95
- * here means TriggerEngine + IntentRuleEvaluator can begin importing
96
- * the type without waiting on the storage code. */
97
- export interface IIntentLedger {
98
- /** Add dwell time on the current SKU. No-op on Safari past day 7 due
99
- * to ITP — see module docstring. */
100
- addDwell(skuId: string, deltaMs: number): void;
101
- /** Increment session count for a SKU. Called once per session per SKU. */
102
- noteSession(skuId: string): void;
103
- /** Read current accumulated values for a SKU. Returns null for
104
- * unknown / evicted / decayed-out SKUs. */
105
- getEntry(skuId: string): SkuLedgerEntry | null;
106
- }
107
- export declare class IntentLedger implements IIntentLedger {
108
- private readonly storage;
109
- private readonly entries;
110
- /** Now provider — injectable so tests can simulate time progression
111
- * without faking globalThis.Date.now. */
112
- private readonly now;
113
- private pendingFlush;
114
- constructor(opts?: {
115
- storage?: LedgerStorage | null;
116
- now?: () => number;
117
- });
118
- addDwell(skuId: string, deltaMs: number): void;
119
- noteSession(skuId: string): void;
120
- getEntry(skuId: string): SkuLedgerEntry | null;
121
- /** Force a synchronous persistence flush. Caller invokes from the
122
- * SDK's pagehide / beforeunload hook so in-flight dwell isn't lost
123
- * when the tab closes inside the debounce window. */
124
- flush(): void;
125
- /** Forget every entry — used by `aegis.reset()` and similar. Wipes
126
- * the localStorage row too. */
127
- clear(): void;
128
- /** Snapshot of all currently-known SKU ids. For tests + the SDK's
129
- * debug surface. */
130
- knownSkus(): string[];
131
- private hydrate;
132
- private evictIfOverCap;
133
- private schedulePersist;
134
- private persistNow;
135
- }
136
- //# sourceMappingURL=intent_ledger.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"intent_ledger.d.ts","sourceRoot":"","sources":["../../src/state/intent_ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAEH;;mCAEmC;AACnC,eAAO,MAAM,yBAAyB,wBAAwB,CAAC;AAE/D;;iEAEiE;AACjE,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC;;;0BAG0B;AAC1B,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;6BAE6B;AAC7B,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED;;oDAEoD;AACpD,MAAM,WAAW,aAAa;IAC5B;yCACqC;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,0EAA0E;IAC1E,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;gDAC4C;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAAC;CAChD;AAsBD,qBAAa,YAAa,YAAW,aAAa;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAC7D;8CAC0C;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,YAAY,CAA8C;gBAEtD,IAAI,GAAE;QAChB,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;QAC/B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;KACf;IAaN,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAsB9C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAoBhC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAe9C;;0DAEsD;IACtD,KAAK,IAAI,IAAI;IAQb;oCACgC;IAChC,KAAK,IAAI,IAAI;IAeb;yBACqB;IACrB,SAAS,IAAI,MAAM,EAAE;IAMrB,OAAO,CAAC,OAAO;IAwCf,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,UAAU;CAanB"}
@@ -1,113 +0,0 @@
1
- /**
2
- * Micro-Intent Engine — contact-scores fetcher (P4a bridge).
3
- *
4
- * Bridges `GET /v1/sdk/contact-scores` into the SDK's
5
- * `IntentRuleEvaluator` snapshot. Without this, identified-contact
6
- * micro-intent patterns (VIP Whisper, Win-back At-Risk, Price-Sensitive
7
- * Nudge, etc.) cannot fire because their AND-compound rules evaluate
8
- * `rfm_segment` / `lifecycle_stage` / `churn_risk_tier` /
9
- * `predicted_ltv_tier` / `price_sensitivity_score` against an empty
10
- * snapshot and always return false.
11
- *
12
- * Lifecycle
13
- * ---------
14
- * AegisMessageRuntime.initialize() → fetch if contactId known
15
- * AegisMessageRuntime.updateContactId → fetch for the new contact
16
- *
17
- * The fetcher is session-deduped: a second `fetchForContact(sameId)`
18
- * call within `dedupWindowMs` is a no-op. This stops a hot navigation
19
- * loop from hammering the endpoint when SPA route changes re-call
20
- * identify() with the same id.
21
- *
22
- * Empty state
23
- * -----------
24
- * The endpoint returns 204 for unknown contacts AND for contacts whose
25
- * `scoring_tier='none'`. Either way the fetcher leaves the snapshot
26
- * unchanged — the evaluator's leaf eval treats absent Layer-1 keys as
27
- * null, which fail-closes any AND clause involving them. Anonymous
28
- * patterns continue to work normally.
29
- *
30
- * Privacy posture
31
- * ---------------
32
- * The endpoint's default response is the tiered form (`predicted_ltv_tier`).
33
- * Tenants who opt into raw `predicted_ltv` via
34
- * `organizations.settings.score_serving_raw_ltv = true` will see the
35
- * float on the snapshot too. Both are valid IntentSignals; rule
36
- * authors pick whichever matches their tenant config.
37
- *
38
- * Plan reference: docs/architecture/MICRO_INTENT_ENGINE.md §P4a.
39
- */
40
- import type { IntentRuleEvaluator, IntentSnapshot } from './IntentRuleEvaluator';
41
- /** Shape of the Layer-1 score response from /v1/sdk/contact-scores. */
42
- export interface ContactScoresResponse {
43
- rfm_segment?: string;
44
- lifecycle_stage?: string;
45
- /** 'unscored' = the model never scored this contact (never 'low'). */
46
- churn_risk_tier?: 'low' | 'medium' | 'high' | 'unscored';
47
- predicted_ltv_tier?: 'low' | 'medium' | 'high';
48
- predicted_ltv?: number;
49
- price_sensitivity_score?: number;
50
- scoring_tier?: string;
51
- scores_updated_at?: string | null;
52
- /** Governed contact context — namespaced { user: { custom: {…} }, loyalty:
53
- * { points, tier } } from contacts.attributes + the loyalty record (the SAME
54
- * source segments + {{custom.x}} merge fields use). Pushed into the rule
55
- * engine's namespaces so `user.custom.<attr>` / `loyalty.points` path-leaves
56
- * resolve client-side off one catalog. */
57
- context?: Record<string, Record<string, unknown>>;
58
- }
59
- export interface ContactScoresFetcherConfig {
60
- apiHost: string;
61
- writeKey: string;
62
- organizationId?: string;
63
- /** Optional. When provided, the fetcher pushes the response into the
64
- * evaluator's snapshot automatically on every successful fetch. */
65
- evaluator?: IntentRuleEvaluator;
66
- /** Minimum time between repeat fetches for the same contactId.
67
- * Default 60 seconds. */
68
- dedupWindowMs?: number;
69
- /** Override for tests / non-browser environments. */
70
- fetchImpl?: typeof fetch;
71
- /** Console.warn channel. */
72
- onError?: (err: unknown, contactId: string) => void;
73
- }
74
- export declare class ContactScoresFetcher {
75
- private readonly apiHost;
76
- private readonly writeKey;
77
- private organizationId?;
78
- private readonly evaluator?;
79
- private readonly dedupWindowMs;
80
- private readonly fetchImpl;
81
- private readonly onError?;
82
- private lastFetchedContactId?;
83
- private lastFetchedAt;
84
- private latestSnapshot;
85
- constructor(cfg: ContactScoresFetcherConfig);
86
- /** Update the org so subsequent fetches scope correctly (e.g. when
87
- * the SDK resolves an org id after init). */
88
- updateOrganizationId(organizationId: string | undefined): void;
89
- /** Most recent successful response. `null` when no fetch has succeeded
90
- * yet, OR when the endpoint returned 204 (unscored). Consumers can
91
- * poll this for diagnostic UIs; campaign evaluation does not need to
92
- * read it directly because the evaluator (if configured) already has
93
- * the snapshot applied. */
94
- getSnapshot(): Readonly<ContactScoresResponse> | null;
95
- /** Fetch scores for `contactId` and apply to the configured evaluator
96
- * (if any). Returns the response on success, null on 204 / error.
97
- *
98
- * Session-dedup: repeat calls for the same contactId within
99
- * `dedupWindowMs` are no-ops. Pass `force: true` to override. */
100
- fetchForContact(contactId: string, opts?: {
101
- force?: boolean;
102
- contactToken?: string;
103
- }): Promise<ContactScoresResponse | null>;
104
- }
105
- /** Project the wire response onto the evaluator's IntentSnapshot shape.
106
- * Strings (rfm_segment / lifecycle_stage / *_tier) map straight across;
107
- * numerics (price_sensitivity_score / predicted_ltv) are passed through
108
- * as numbers. Missing keys are omitted so the evaluator's leaf eval
109
- * treats them as null (per IntentRuleEvaluator semantics).
110
- *
111
- * Exported for the smoke test — drift guard pins the mapping. */
112
- export declare function toIntentSnapshot(r: ContactScoresResponse): IntentSnapshot;
113
- //# sourceMappingURL=ContactScoresFetcher.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ContactScoresFetcher.d.ts","sourceRoot":"","sources":["../../src/triggers/ContactScoresFetcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEjF,uEAAuE;AACvE,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,eAAe,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IACzD,kBAAkB,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;;;;+CAI2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;wEACoE;IACpE,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC;8BAC0B;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qDAAqD;IACrD,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,cAAc,CAAC,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAA4C;IAErE,OAAO,CAAC,oBAAoB,CAAC,CAAS;IACtC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,cAAc,CAAsC;gBAEhD,GAAG,EAAE,0BAA0B;IAU3C;kDAC8C;IAC9C,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAI9D;;;;gCAI4B;IAC5B,WAAW,IAAI,QAAQ,CAAC,qBAAqB,CAAC,GAAG,IAAI;IAIrD;;;;sEAIkE;IAC5D,eAAe,CACnB,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAO,GACpD,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;CAsEzC;AAED;;;;;;kEAMkE;AAClE,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,qBAAqB,GAAG,cAAc,CAYzE"}