@syntrologie/runtime-sdk 2.4.1 → 2.6.0-canary.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/CAPABILITIES.md +66 -1
  2. package/dist/SmartCanvasApp.d.ts +5 -3
  3. package/dist/actions/executors/index.d.ts +1 -2
  4. package/dist/actions/index.d.ts +2 -2
  5. package/dist/actions/schema.d.ts +19111 -20709
  6. package/dist/actions/schema.js +5 -2
  7. package/dist/actions/types.d.ts +45 -48
  8. package/dist/anchor/AnchorResolver.d.ts +18 -0
  9. package/dist/anchor/index.d.ts +2 -0
  10. package/dist/api.d.ts +3 -8
  11. package/dist/apps/examples/gamification-app.example.d.ts +8 -8
  12. package/dist/{chunk-4NYS7GAW.js → chunk-BU4Z6PD7.js} +45 -7
  13. package/dist/chunk-BU4Z6PD7.js.map +7 -0
  14. package/dist/{chunk-QGWATS3Z.js → chunk-Q4WGXNKC.js} +2775 -1052
  15. package/dist/chunk-Q4WGXNKC.js.map +7 -0
  16. package/dist/{chunk-OGTCFYR3.js → chunk-R5DNAIRI.js} +45 -34
  17. package/dist/chunk-R5DNAIRI.js.map +7 -0
  18. package/dist/chunk-XDYJ64IN.js +178 -0
  19. package/dist/chunk-XDYJ64IN.js.map +7 -0
  20. package/dist/components/ShadowCanvasOverlay.d.ts +2 -20
  21. package/dist/components/TileIcon.d.ts +14 -0
  22. package/dist/config/schema.d.ts +5529 -3620
  23. package/dist/config/schema.js +21 -61
  24. package/dist/config/schema.js.map +3 -3
  25. package/dist/context/schema.d.ts +16 -16
  26. package/dist/decisions/schema.d.ts +357 -2789
  27. package/dist/decisions/schema.js +7 -1
  28. package/dist/decisions/types.d.ts +24 -2
  29. package/dist/events/registerConfigPredicates.d.ts +7 -10
  30. package/dist/events/schema.d.ts +12 -12
  31. package/dist/experiments/adapters/growthbook.d.ts +2 -0
  32. package/dist/experiments/types.d.ts +7 -0
  33. package/dist/hooks/useShadowCanvasConfig.d.ts +6 -4
  34. package/dist/index.d.ts +1 -0
  35. package/dist/index.js +154 -186
  36. package/dist/index.js.map +3 -3
  37. package/dist/overlays/schema.d.ts +70 -70
  38. package/dist/react.js +4 -3
  39. package/dist/react.js.map +1 -1
  40. package/dist/runtime.d.ts +3 -0
  41. package/dist/smart-canvas.esm.js +123 -84
  42. package/dist/smart-canvas.esm.js.map +4 -4
  43. package/dist/smart-canvas.js +3271 -1210
  44. package/dist/smart-canvas.js.map +4 -4
  45. package/dist/smart-canvas.min.js +123 -84
  46. package/dist/smart-canvas.min.js.map +4 -4
  47. package/dist/surfaces/types.d.ts +2 -1
  48. package/dist/theme/ThemeProvider.d.ts +11 -16
  49. package/dist/theme/defaultTheme.d.ts +6 -1
  50. package/dist/theme/index.d.ts +3 -4
  51. package/dist/theme/types.d.ts +11 -0
  52. package/dist/version.d.ts +1 -1
  53. package/dist/widgets/WidgetRegistry.d.ts +1 -0
  54. package/package.json +9 -8
  55. package/schema/canvas-config.schema.json +10583 -1049
  56. package/scripts/validate-config.mjs +180 -0
  57. package/dist/actions/executors/tour.d.ts +0 -18
  58. package/dist/chunk-4NYS7GAW.js.map +0 -7
  59. package/dist/chunk-OGTCFYR3.js.map +0 -7
  60. package/dist/chunk-QGWATS3Z.js.map +0 -7
  61. package/dist/hooks/useHostPatches.d.ts +0 -9
  62. package/dist/theme/extractHostTheme.d.ts +0 -14
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  AddClassZ,
3
+ AnchorIdZ,
3
4
  BadgePositionZ,
4
5
  BadgeZ,
5
6
  CtaButtonZ,
@@ -30,10 +31,12 @@ import {
30
31
  WaitZ,
31
32
  WidgetConfigZ,
32
33
  coreActionStepSchemas
33
- } from "../chunk-OGTCFYR3.js";
34
- import "../chunk-4NYS7GAW.js";
34
+ } from "../chunk-R5DNAIRI.js";
35
+ import "../chunk-XDYJ64IN.js";
36
+ import "../chunk-BU4Z6PD7.js";
35
37
  export {
36
38
  AddClassZ,
39
+ AnchorIdZ,
37
40
  BadgePositionZ,
38
41
  BadgeZ,
39
42
  CtaButtonZ,
@@ -5,6 +5,8 @@
5
5
  * (highlight, tooltip, badge, DOM modifications, navigation).
6
6
  */
7
7
  import type { Placement } from '@floating-ui/dom';
8
+ import type { BadgePosition, CtaButton, HighlightStyle, InsertPosition, ModalContent, ModalWaitFor, TooltipTrigger, TooltipWaitFor } from '@syntrologie/sdk-contracts';
9
+ export type { BadgePosition, CtaButton, HighlightStyle, InsertPosition, ModalContent, ModalWaitFor, TooltipTrigger, TooltipWaitFor, };
8
10
  /** Static surface slots with fixed positioning */
9
11
  export type StaticSurfaceSlot = 'drawer_right' | 'drawer_left' | 'drawer_bottom' | 'overlay_center' | 'overlay_corner_br' | 'overlay_corner_bl' | 'toast_top' | 'toast_bottom';
10
12
  /** Dynamic inline slot (rendered inside anchor) */
@@ -13,31 +15,7 @@ export type InlineSurfaceSlot = `inline:${string}`;
13
15
  export type AdjacentSurfaceSlot = `adjacent:${string}`;
14
16
  /** All surface slot types */
15
17
  export type SurfaceSlot = StaticSurfaceSlot | InlineSurfaceSlot | AdjacentSurfaceSlot;
16
- /** Highlight style configuration */
17
- export interface HighlightStyle {
18
- /** Ring color (default: "#5b8cff") */
19
- color?: string;
20
- /** Backdrop scrim opacity 0-1 (default: 0.55, set to 0 to hide) */
21
- scrimOpacity?: number;
22
- /** Space between element and ring in pixels (default: 12) */
23
- paddingPx?: number;
24
- /** Ring corner radius in pixels (default: 12) */
25
- radiusPx?: number;
26
- }
27
- /** Badge position relative to anchor */
28
- export type BadgePosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
29
- /** CTA button configuration for tooltips/modals */
30
- export interface CtaButton {
31
- label: string;
32
- actionId: string;
33
- primary?: boolean;
34
- }
35
- /** Modal content configuration */
36
- export interface ModalContent {
37
- title?: string;
38
- body: string;
39
- }
40
- /** Tooltip content configuration */
18
+ /** Tooltip content configuration (uses ActionStep for cta.action, narrower than sdk-contracts' unknown) */
41
19
  export interface TooltipContent {
42
20
  title?: string;
43
21
  body: string;
@@ -47,25 +25,30 @@ export interface TooltipContent {
47
25
  };
48
26
  ctaButtons?: CtaButton[];
49
27
  }
50
- /** Tooltip trigger mode */
51
- export type TooltipTrigger = 'immediate' | 'hover' | 'click';
52
- /** Position where HTML/content should be inserted */
53
- export type InsertPosition = 'before' | 'after' | 'prepend' | 'append' | 'replace';
54
28
  /** Widget configuration for surface mounting */
55
29
  export interface WidgetConfig {
56
30
  widgetId: string;
57
31
  props?: Record<string, unknown>;
58
32
  priority?: number;
59
33
  }
34
+ /** Route-scoped anchor identifier */
35
+ export interface AnchorId {
36
+ /** CSS selector for the anchor element */
37
+ selector: string;
38
+ /** Route pattern(s) where this anchor applies. Uses matchRoutePattern (**, *, :param). Use "**" for all routes. */
39
+ route: string | string[];
40
+ }
60
41
  /** Base action with common properties */
61
42
  interface BaseAction {
62
43
  /** Optional label for debugging/telemetry */
63
44
  label?: string;
45
+ /** Optional conditional trigger — when present, action only fires if strategy evaluates to true */
46
+ triggerWhen?: import('../decisions/types').DecisionStrategy<boolean>;
64
47
  }
65
48
  /** Highlight an anchor element with spotlight effect */
66
49
  export interface HighlightAction extends BaseAction {
67
50
  kind: 'overlays:highlight';
68
- anchorId: string;
51
+ anchorId: AnchorId;
69
52
  style?: HighlightStyle;
70
53
  /** Duration in ms before auto-cleanup (for use in sequences) */
71
54
  duration?: number;
@@ -73,30 +56,26 @@ export interface HighlightAction extends BaseAction {
73
56
  /** Pulse animation on an anchor element */
74
57
  export interface PulseAction extends BaseAction {
75
58
  kind: 'overlays:pulse';
76
- anchorId: string;
59
+ anchorId: AnchorId;
77
60
  duration?: number;
78
61
  }
79
62
  /** Add a badge near an anchor element */
80
63
  export interface BadgeAction extends BaseAction {
81
64
  kind: 'overlays:badge';
82
- anchorId: string;
65
+ anchorId: AnchorId;
83
66
  content: string;
84
67
  position?: BadgePosition;
85
68
  }
86
- /** Tooltip lifecycle - when the action completes (for sequences) */
87
- export type TooltipWaitFor = 'dismissed' | 'cta-click' | `timeout:${number}`;
88
69
  /** Show a tooltip near an anchor element */
89
70
  export interface TooltipAction extends BaseAction {
90
71
  kind: 'overlays:tooltip';
91
- anchorId: string;
72
+ anchorId: AnchorId;
92
73
  content: TooltipContent;
93
74
  trigger?: TooltipTrigger;
94
75
  placement?: Placement;
95
76
  /** When the action completes (for use in sequences). Publishes event to EventBus. */
96
77
  waitFor?: TooltipWaitFor;
97
78
  }
98
- /** Modal lifecycle - when the action completes (for sequences) */
99
- export type ModalWaitFor = 'dismissed' | 'cta-click' | `timeout:${number}`;
100
79
  /** Show a centered modal dialog */
101
80
  export interface ModalAction extends BaseAction {
102
81
  kind: 'overlays:modal';
@@ -118,39 +97,39 @@ export interface ModalAction extends BaseAction {
118
97
  /** Insert HTML content relative to anchor */
119
98
  export interface InsertHtmlAction extends BaseAction {
120
99
  kind: 'content:insertHtml';
121
- anchorId: string;
100
+ anchorId: AnchorId;
122
101
  html: string;
123
102
  position: InsertPosition;
124
103
  }
125
104
  /** Set text content of an anchor */
126
105
  export interface SetTextAction extends BaseAction {
127
106
  kind: 'content:setText';
128
- anchorId: string;
107
+ anchorId: AnchorId;
129
108
  text: string;
130
109
  }
131
110
  /** Set an attribute on an anchor */
132
111
  export interface SetAttrAction extends BaseAction {
133
112
  kind: 'content:setAttr';
134
- anchorId: string;
113
+ anchorId: AnchorId;
135
114
  attr: string;
136
115
  value: string;
137
116
  }
138
117
  /** Add a CSS class to an anchor */
139
118
  export interface AddClassAction extends BaseAction {
140
119
  kind: 'content:addClass';
141
- anchorId: string;
120
+ anchorId: AnchorId;
142
121
  className: string;
143
122
  }
144
123
  /** Remove a CSS class from an anchor */
145
124
  export interface RemoveClassAction extends BaseAction {
146
125
  kind: 'content:removeClass';
147
- anchorId: string;
126
+ anchorId: AnchorId;
148
127
  className: string;
149
128
  }
150
129
  /** Set inline styles on an anchor */
151
130
  export interface SetStyleAction extends BaseAction {
152
131
  kind: 'content:setStyle';
153
- anchorId: string;
132
+ anchorId: AnchorId;
154
133
  styles: Record<string, string>;
155
134
  }
156
135
  /** Mount a widget to a surface slot */
@@ -162,7 +141,7 @@ export interface MountWidgetAction extends BaseAction {
162
141
  /** Scroll to an anchor element */
163
142
  export interface ScrollToAction extends BaseAction {
164
143
  kind: 'navigation:scrollTo';
165
- anchorId: string;
144
+ anchorId: AnchorId;
166
145
  behavior?: ScrollBehavior;
167
146
  block?: ScrollLogicalPosition;
168
147
  inline?: ScrollLogicalPosition;
@@ -213,7 +192,7 @@ export type ActionStep = HighlightAction | PulseAction | BadgeAction | TooltipAc
213
192
  /** Extract action kind literal types */
214
193
  export type ActionKind = ActionStep['kind'];
215
194
  /** State of an action */
216
- export type ActionState = 'pending' | 'applied' | 'reverted' | 'failed';
195
+ export type ActionState = 'pending' | 'applied' | 'reverted' | 'failed' | 'deferred';
217
196
  /** Handle returned when an action is applied */
218
197
  export interface ActionHandle {
219
198
  /** Unique ID for this action instance */
@@ -289,13 +268,18 @@ export interface ExecutorContext {
289
268
  /** Overlay root element for rendering */
290
269
  overlayRoot: HTMLElement;
291
270
  /** Resolve an anchor ID to an element */
292
- resolveAnchor: (anchorId: string) => HTMLElement | null;
271
+ resolveAnchor: (anchorId: AnchorId) => HTMLElement | null;
293
272
  /** Generate unique IDs */
294
273
  generateId: () => string;
295
274
  /** Publish events to EventBus */
296
275
  publishEvent: (name: string, props?: Record<string, unknown>) => void;
297
276
  /** Get the current adaptive ID (if any) */
298
277
  adaptiveId?: string;
278
+ /**
279
+ * Async anchor resolver — waits for a DOM element to appear.
280
+ * Returns null on timeout or route mismatch (never throws).
281
+ */
282
+ waitForAnchor?: (anchorId: AnchorId, timeoutMs?: number) => Promise<HTMLElement | null>;
299
283
  /**
300
284
  * Execute a nested action (for composite executors like tours).
301
285
  * Returns a handle that can be used to revert the action.
@@ -337,13 +321,27 @@ export interface ActionEngineOptions {
337
321
  mount: (slot: SurfaceSlot, content: RenderableContent, opts?: MountOptions) => MountHandle;
338
322
  };
339
323
  /** Function to resolve anchor IDs to elements */
340
- anchorResolver: (anchorId: string) => HTMLElement | null;
324
+ anchorResolver: (anchorId: AnchorId) => HTMLElement | null;
325
+ /** Async anchor resolver — waits for a DOM element to appear */
326
+ waitForAnchor?: (anchorId: AnchorId, timeoutMs?: number) => Promise<HTMLElement | null>;
341
327
  /** Current adaptive ID for attribution */
342
328
  adaptiveId?: string;
343
329
  /** Optional executor registry (uses default singleton if not provided) */
344
330
  executorRegistry?: ActionEngineExecutorRegistry;
345
331
  /** Subscribe to navigation changes (from NavigationMonitor) */
346
332
  subscribeNavigation?: (callback: (url: string, method: string) => void) => () => void;
333
+ /** Runtime for evaluating DecisionStrategy conditions (e.g., triggerWhen) */
334
+ runtime?: {
335
+ evaluateSync: <T>(strategy: import('../decisions/types').DecisionStrategy<T>) => {
336
+ value: T;
337
+ };
338
+ context?: {
339
+ subscribe: (cb: () => void) => () => void;
340
+ };
341
+ accumulator?: {
342
+ subscribe: (cb: () => void) => () => void;
343
+ };
344
+ };
347
345
  }
348
346
  /** The ActionEngine interface */
349
347
  export interface ActionEngine {
@@ -403,4 +401,3 @@ export interface MountHandle {
403
401
  isMounted: () => boolean;
404
402
  getContainer: () => HTMLElement | null;
405
403
  }
406
- export {};
@@ -0,0 +1,18 @@
1
+ /**
2
+ * AnchorResolver — Centralized DOM observation for anchor element resolution.
3
+ *
4
+ * Provides a single MutationObserver that multiple callers share to wait for
5
+ * DOM elements to appear. Replaces scattered observation mechanisms.
6
+ */
7
+ export interface AnchorResolverOptions {
8
+ root?: HTMLElement;
9
+ defaultTimeoutMs?: number;
10
+ }
11
+ export interface AnchorResolver {
12
+ resolve(selector: string): HTMLElement | null;
13
+ waitFor(selector: string, timeoutMs?: number): Promise<HTMLElement>;
14
+ onAppear(selector: string, cb: (el: HTMLElement) => void): () => void;
15
+ pendingCount(): number;
16
+ destroy(): void;
17
+ }
18
+ export declare function createAnchorResolver(opts?: AnchorResolverOptions): AnchorResolver;
@@ -0,0 +1,2 @@
1
+ export type { AnchorResolver, AnchorResolverOptions } from './AnchorResolver';
2
+ export { createAnchorResolver } from './AnchorResolver';
package/dist/api.d.ts CHANGED
@@ -4,13 +4,13 @@
4
4
  * Entry point for the SmartCanvas SDK. Creates and manages the canvas element,
5
5
  * handles configuration, and coordinates between the ActionEngine and UI.
6
6
  */
7
- import type { CanvasTheme } from './components/ShadowCanvasOverlay';
8
7
  import type { ExperimentClient } from './experiments/types';
9
8
  import type { OverlayRecipeFetcher } from './overlays/fetcher';
10
9
  import type { ActionHandler, AppearanceConfig, RenderProps } from './render/types';
11
10
  import type { SmartCanvasRuntime } from './runtime';
12
11
  import { type SmartCanvasElement } from './SmartCanvasElement';
13
12
  import type { TelemetryClient } from './telemetry/types';
13
+ import type { CanvasThemeConfig } from './theme';
14
14
  import type { CanvasConfigFetcher, CanvasConfigResponse } from './types';
15
15
  export interface SmartCanvasIntegrations {
16
16
  experiments?: ExperimentClient;
@@ -35,16 +35,16 @@ export interface SmartCanvasConfig {
35
35
  className?: string;
36
36
  };
37
37
  editorUrl?: string;
38
- theme?: Partial<CanvasTheme>;
39
38
  /**
40
39
  * v2 Runtime instance.
41
40
  * Required for action execution. If not provided, actions will not be applied.
42
41
  */
43
42
  runtime?: SmartCanvasRuntime;
44
- autoDetectTheme?: boolean;
45
43
  appearance?: AppearanceConfig;
46
44
  renderProps?: RenderProps;
47
45
  actionHandlers?: ActionHandler;
46
+ /** Workspace-level theme for 3-layer inheritance (defaults → workspace → config) */
47
+ workspaceTheme?: CanvasThemeConfig;
48
48
  }
49
49
  /**
50
50
  * Handle for interacting with a SmartCanvas instance.
@@ -59,11 +59,6 @@ export interface SmartCanvasHandle {
59
59
  * Get the current config.
60
60
  */
61
61
  getConfig(): Promise<CanvasConfigResponse>;
62
- /**
63
- * Update the config and re-apply actions.
64
- * This is the primary way to modify what the canvas displays.
65
- */
66
- updateConfig(newConfig: CanvasConfigResponse): Promise<void>;
67
62
  /**
68
63
  * Enable or disable the canvas.
69
64
  * When disabled, all actions are reverted.
@@ -40,8 +40,8 @@ export declare const configSchema: z.ZodObject<{
40
40
  count?: number | undefined;
41
41
  };
42
42
  id: string;
43
- name: string;
44
43
  icon: string;
44
+ name: string;
45
45
  description?: string | undefined;
46
46
  }, {
47
47
  trigger: {
@@ -49,8 +49,8 @@ export declare const configSchema: z.ZodObject<{
49
49
  count?: number | undefined;
50
50
  };
51
51
  id: string;
52
- name: string;
53
52
  icon: string;
53
+ name: string;
54
54
  description?: string | undefined;
55
55
  }>, "many">>;
56
56
  showProgress: z.ZodDefault<z.ZodBoolean>;
@@ -62,8 +62,8 @@ export declare const configSchema: z.ZodObject<{
62
62
  count?: number | undefined;
63
63
  };
64
64
  id: string;
65
- name: string;
66
65
  icon: string;
66
+ name: string;
67
67
  description?: string | undefined;
68
68
  }[];
69
69
  showProgress: boolean;
@@ -75,8 +75,8 @@ export declare const configSchema: z.ZodObject<{
75
75
  count?: number | undefined;
76
76
  };
77
77
  id: string;
78
- name: string;
79
78
  icon: string;
79
+ name: string;
80
80
  description?: string | undefined;
81
81
  }[] | undefined;
82
82
  showProgress?: boolean | undefined;
@@ -247,8 +247,8 @@ export declare const manifest: {
247
247
  count?: number | undefined;
248
248
  };
249
249
  id: string;
250
- name: string;
251
250
  icon: string;
251
+ name: string;
252
252
  description?: string | undefined;
253
253
  }, {
254
254
  trigger: {
@@ -256,8 +256,8 @@ export declare const manifest: {
256
256
  count?: number | undefined;
257
257
  };
258
258
  id: string;
259
- name: string;
260
259
  icon: string;
260
+ name: string;
261
261
  description?: string | undefined;
262
262
  }>, "many">>;
263
263
  showProgress: z.ZodDefault<z.ZodBoolean>;
@@ -269,8 +269,8 @@ export declare const manifest: {
269
269
  count?: number | undefined;
270
270
  };
271
271
  id: string;
272
- name: string;
273
272
  icon: string;
273
+ name: string;
274
274
  description?: string | undefined;
275
275
  }[];
276
276
  showProgress: boolean;
@@ -282,8 +282,8 @@ export declare const manifest: {
282
282
  count?: number | undefined;
283
283
  };
284
284
  id: string;
285
- name: string;
286
285
  icon: string;
286
+ name: string;
287
287
  description?: string | undefined;
288
288
  }[] | undefined;
289
289
  showProgress?: boolean | undefined;
@@ -10,7 +10,14 @@ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot
10
10
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
11
11
 
12
12
  // src/decisions/schema.ts
13
+ import { z as z2 } from "zod";
14
+
15
+ // ../sdk-contracts/dist/schemas.js
13
16
  import { z } from "zod";
17
+ var AnchorIdZ = z.object({
18
+ selector: z.string(),
19
+ route: z.union([z.string(), z.array(z.string())])
20
+ }).strict();
14
21
  var PageUrlConditionZ = z.object({
15
22
  type: z.literal("page_url"),
16
23
  url: z.string()
@@ -63,12 +70,21 @@ var FrequencyLimitConditionZ = z.object({
63
70
  limit: z.number(),
64
71
  inverted: z.boolean().optional()
65
72
  });
73
+ var MatchOpZ = z.object({
74
+ equals: z.union([z.string(), z.number(), z.boolean()]).optional(),
75
+ contains: z.string().optional()
76
+ });
77
+ var CounterDefZ = z.object({
78
+ events: z.array(z.string()).min(1),
79
+ match: z.record(z.string(), MatchOpZ).optional()
80
+ });
66
81
  var EventCountConditionZ = z.object({
67
82
  type: z.literal("event_count"),
68
83
  key: z.string(),
69
84
  operator: z.enum(["gte", "lte", "eq", "gt", "lt"]),
70
85
  count: z.number().int().min(0),
71
- withinMs: z.number().positive().optional()
86
+ withinMs: z.number().positive().optional(),
87
+ counter: CounterDefZ.optional()
72
88
  });
73
89
  var ConditionZ = z.discriminatedUnion("type", [
74
90
  PageUrlConditionZ,
@@ -119,13 +135,30 @@ var DecisionStrategyZ = z.discriminatedUnion("type", [
119
135
  ModelStrategyZ,
120
136
  ExternalStrategyZ
121
137
  ]);
122
- var RouteFilterZ = z.object({
123
- include: z.array(z.string()).optional(),
124
- exclude: z.array(z.string()).optional()
138
+ var TriggerWhenZ = DecisionStrategyZ.nullable().optional();
139
+ var EventScopeZ = z.object({
140
+ events: z.array(z.string()),
141
+ urlContains: z.string().optional(),
142
+ props: z.record(z.union([z.string(), z.number(), z.boolean()])).optional()
143
+ });
144
+ var NotifyZ = z.object({
145
+ title: z.string().optional(),
146
+ body: z.string().optional(),
147
+ icon: z.string().optional()
148
+ }).nullable().optional();
149
+
150
+ // src/decisions/schema.ts
151
+ var RouteFilterZ = z2.object({
152
+ include: z2.array(z2.string()).optional().describe(
153
+ "URL patterns where this tile appears. Supports *, **, :param wildcards. Use sparingly \u2014 mostly to isolate to specific webapp functionality. Omit to appear on all routes."
154
+ ),
155
+ exclude: z2.array(z2.string()).optional().describe("URL patterns where this tile should NOT appear. Evaluated before include.")
125
156
  });
126
- var ActivationConfigZ = z.object({
157
+ var ActivationConfigZ = z2.object({
127
158
  routes: RouteFilterZ,
128
- strategy: DecisionStrategyZ.optional()
159
+ onlyIfPopulated: z2.boolean().optional().describe(
160
+ "When true, tile is hidden if none of its props.actions[] have an active triggerWhen. Useful for tiles with all-deferred FAQ questions or nav tips. Default: false."
161
+ )
129
162
  });
130
163
  function validateCondition(data) {
131
164
  return ConditionZ.safeParse(data);
@@ -137,6 +170,8 @@ function validateActivationConfig(data) {
137
170
  return ActivationConfigZ.safeParse(data);
138
171
  }
139
172
  var decisionSchemas = [
173
+ { defName: "matchOp", schema: MatchOpZ },
174
+ { defName: "counterDef", schema: CounterDefZ },
140
175
  { defName: "activationConfig", schema: ActivationConfigZ },
141
176
  { defName: "routeFilter", schema: RouteFilterZ },
142
177
  { defName: "ruleStrategy", schema: RuleStrategyZ },
@@ -162,6 +197,8 @@ export {
162
197
  DismissedConditionZ,
163
198
  CooldownActiveConditionZ,
164
199
  FrequencyLimitConditionZ,
200
+ MatchOpZ,
201
+ CounterDefZ,
165
202
  EventCountConditionZ,
166
203
  ConditionZ,
167
204
  RuleZ,
@@ -170,6 +207,7 @@ export {
170
207
  ModelStrategyZ,
171
208
  ExternalStrategyZ,
172
209
  DecisionStrategyZ,
210
+ TriggerWhenZ,
173
211
  RouteFilterZ,
174
212
  ActivationConfigZ,
175
213
  validateCondition,
@@ -177,4 +215,4 @@ export {
177
215
  validateActivationConfig,
178
216
  decisionSchemas
179
217
  };
180
- //# sourceMappingURL=chunk-4NYS7GAW.js.map
218
+ //# sourceMappingURL=chunk-BU4Z6PD7.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/decisions/schema.ts", "../../sdk-contracts/dist/schemas.js"],
4
+ "sourcesContent": ["/**\n * Zod schemas for decision strategy validation.\n *\n * Condition and strategy schemas are canonical in @syntrologie/sdk-contracts.\n * This module re-exports them and adds runtime-specific schemas\n * (ActivationConfig, RouteFilter) plus the decisionSchemas array for\n * unified JSON Schema generation.\n */\nimport { z } from 'zod';\n\n// Re-export all condition + strategy schemas from the single source of truth\nexport {\n AnchorVisibleConditionZ,\n type ConditionSchema,\n ConditionZ,\n CooldownActiveConditionZ,\n CounterDefZ,\n type DecisionStrategySchema,\n DecisionStrategyZ,\n DismissedConditionZ,\n EventCountConditionZ,\n EventOccurredConditionZ,\n ExternalStrategyZ,\n FrequencyLimitConditionZ,\n MatchOpZ,\n ModelStrategyZ,\n PageUrlConditionZ,\n RouteConditionZ,\n type RuleSchema,\n RuleStrategyZ,\n RuleZ,\n ScoreStrategyZ,\n SessionMetricConditionZ,\n StateEqualsConditionZ,\n TriggerWhenZ,\n ViewportConditionZ,\n} from '@syntrologie/sdk-contracts';\n\nimport {\n ConditionZ,\n CounterDefZ,\n DecisionStrategyZ,\n ExternalStrategyZ,\n MatchOpZ,\n ModelStrategyZ,\n RuleStrategyZ,\n RuleZ,\n ScoreStrategyZ,\n} from '@syntrologie/sdk-contracts';\n\n// =============================================================================\n// ACTIVATION CONFIG SCHEMA (runtime-specific)\n// =============================================================================\n\nexport const RouteFilterZ = z.object({\n include: z\n .array(z.string())\n .optional()\n .describe(\n 'URL patterns where this tile appears. Supports *, **, :param wildcards. ' +\n 'Use sparingly \u2014 mostly to isolate to specific webapp functionality. ' +\n 'Omit to appear on all routes.'\n ),\n exclude: z\n .array(z.string())\n .optional()\n .describe('URL patterns where this tile should NOT appear. Evaluated before include.'),\n});\n\nexport const ActivationConfigZ = z.object({\n routes: RouteFilterZ,\n onlyIfPopulated: z\n .boolean()\n .optional()\n .describe(\n 'When true, tile is hidden if none of its props.actions[] have an active triggerWhen. ' +\n 'Useful for tiles with all-deferred FAQ questions or nav tips. Default: false.'\n ),\n});\n\n// =============================================================================\n// VALIDATION FUNCTIONS\n// =============================================================================\n\n/**\n * Validate a Condition object.\n */\nexport function validateCondition(data: unknown) {\n return ConditionZ.safeParse(data);\n}\n\n/**\n * Validate a DecisionStrategy object.\n */\nexport function validateStrategy(data: unknown) {\n return DecisionStrategyZ.safeParse(data);\n}\n\n/**\n * Validate an ActivationConfig object.\n */\nexport function validateActivationConfig(data: unknown) {\n return ActivationConfigZ.safeParse(data);\n}\n\n// =============================================================================\n// Export: Array for unified schema generation\n// =============================================================================\n\n/**\n * Decision schemas for unified JSON Schema generation.\n * The generator imports this array and converts each to a JSON Schema $def.\n *\n * Note: `decisionStrategy` is NOT included here \u2014 it's a oneOf wrapper that\n * the generator builds from $refs to the four strategy defs.\n */\nexport const decisionSchemas = [\n { defName: 'matchOp', schema: MatchOpZ },\n { defName: 'counterDef', schema: CounterDefZ },\n { defName: 'activationConfig', schema: ActivationConfigZ },\n { defName: 'routeFilter', schema: RouteFilterZ },\n { defName: 'ruleStrategy', schema: RuleStrategyZ },\n { defName: 'scoreStrategy', schema: ScoreStrategyZ },\n { defName: 'modelStrategy', schema: ModelStrategyZ },\n { defName: 'externalStrategy', schema: ExternalStrategyZ },\n { defName: 'rule', schema: RuleZ },\n { defName: 'condition', schema: ConditionZ },\n];\n\n// =============================================================================\n// TYPE INFERENCE\n// =============================================================================\n\nexport type ActivationConfigSchema = z.infer<typeof ActivationConfigZ>;\n", "/**\n * Shared Zod schemas for decision strategies, conditions, and event scoping.\n *\n * These are the canonical definitions \u2014 runtime-sdk and all adaptive packages\n * should import from here instead of duplicating.\n */\nimport { z } from 'zod';\n// =============================================================================\n// ANCHOR ID SCHEMA\n// =============================================================================\nexport const AnchorIdZ = z\n .object({\n selector: z.string(),\n route: z.union([z.string(), z.array(z.string())]),\n})\n .strict();\n// =============================================================================\n// CONDITION SCHEMAS\n// =============================================================================\nexport const PageUrlConditionZ = z.object({\n type: z.literal('page_url'),\n url: z.string(),\n});\nexport const RouteConditionZ = z.object({\n type: z.literal('route'),\n routeId: z.string(),\n});\nexport const AnchorVisibleConditionZ = z.object({\n type: z.literal('anchor_visible'),\n anchorId: z.string(),\n state: z.enum(['visible', 'present', 'absent']),\n});\nexport const EventOccurredConditionZ = z.object({\n type: z.literal('event_occurred'),\n eventName: z.string(),\n withinMs: z.number().optional(),\n});\nexport const StateEqualsConditionZ = z.object({\n type: z.literal('state_equals'),\n key: z.string(),\n value: z.unknown(),\n});\nexport const ViewportConditionZ = z.object({\n type: z.literal('viewport'),\n minWidth: z.number().optional(),\n maxWidth: z.number().optional(),\n minHeight: z.number().optional(),\n maxHeight: z.number().optional(),\n});\nexport const SessionMetricConditionZ = z.object({\n type: z.literal('session_metric'),\n key: z.string(),\n operator: z.enum(['gte', 'lte', 'eq', 'gt', 'lt']),\n threshold: z.number(),\n});\nexport const DismissedConditionZ = z.object({\n type: z.literal('dismissed'),\n key: z.string(),\n inverted: z.boolean().optional(),\n});\nexport const CooldownActiveConditionZ = z.object({\n type: z.literal('cooldown_active'),\n key: z.string(),\n inverted: z.boolean().optional(),\n});\nexport const FrequencyLimitConditionZ = z.object({\n type: z.literal('frequency_limit'),\n key: z.string(),\n limit: z.number(),\n inverted: z.boolean().optional(),\n});\nexport const MatchOpZ = z.object({\n equals: z.union([z.string(), z.number(), z.boolean()]).optional(),\n contains: z.string().optional(),\n});\nexport const CounterDefZ = z.object({\n events: z.array(z.string()).min(1),\n match: z.record(z.string(), MatchOpZ).optional(),\n});\nexport const EventCountConditionZ = z.object({\n type: z.literal('event_count'),\n key: z.string(),\n operator: z.enum(['gte', 'lte', 'eq', 'gt', 'lt']),\n count: z.number().int().min(0),\n withinMs: z.number().positive().optional(),\n counter: CounterDefZ.optional(),\n});\nexport const ConditionZ = z.discriminatedUnion('type', [\n PageUrlConditionZ,\n RouteConditionZ,\n AnchorVisibleConditionZ,\n EventOccurredConditionZ,\n StateEqualsConditionZ,\n ViewportConditionZ,\n SessionMetricConditionZ,\n DismissedConditionZ,\n CooldownActiveConditionZ,\n FrequencyLimitConditionZ,\n EventCountConditionZ,\n]);\n// =============================================================================\n// STRATEGY SCHEMAS\n// =============================================================================\nexport const RuleZ = z.object({\n conditions: z.array(ConditionZ),\n value: z.unknown(),\n});\nexport const RuleStrategyZ = z.object({\n type: z.literal('rules'),\n rules: z.array(RuleZ),\n default: z.unknown(),\n});\nexport const ScoreStrategyZ = z.object({\n type: z.literal('score'),\n field: z.string(),\n threshold: z.number(),\n above: z.unknown(),\n below: z.unknown(),\n});\nexport const ModelStrategyZ = z.object({\n type: z.literal('model'),\n modelId: z.string(),\n inputs: z.array(z.string()),\n outputMapping: z.record(z.string(), z.unknown()),\n default: z.unknown(),\n});\nexport const ExternalStrategyZ = z.object({\n type: z.literal('external'),\n endpoint: z.string(),\n method: z.enum(['GET', 'POST']).optional(),\n default: z.unknown(),\n timeoutMs: z.number().optional(),\n});\nexport const DecisionStrategyZ = z.discriminatedUnion('type', [\n RuleStrategyZ,\n ScoreStrategyZ,\n ModelStrategyZ,\n ExternalStrategyZ,\n]);\n/** Canonical Zod schema for the optional triggerWhen field on actions and adaptive items. */\nexport const TriggerWhenZ = DecisionStrategyZ.nullable().optional();\n// =============================================================================\n// EVENT SCOPE SCHEMA\n// =============================================================================\n/** Scopes a widget to specific events/URLs. */\nexport const EventScopeZ = z.object({\n events: z.array(z.string()),\n urlContains: z.string().optional(),\n props: z.record(z.union([z.string(), z.number(), z.boolean()])).optional(),\n});\n// =============================================================================\n// NOTIFY SCHEMA\n// =============================================================================\n/** Toast notification config for triggerWhen transitions. */\nexport const NotifyZ = z\n .object({\n title: z.string().optional(),\n body: z.string().optional(),\n icon: z.string().optional(),\n})\n .nullable()\n .optional();\n"],
5
+ "mappings": ";;;;;;;;;;;;AAQA,SAAS,KAAAA,UAAS;;;ACFlB,SAAS,SAAS;AAIX,IAAM,YAAY,EACpB,OAAO;AAAA,EACR,UAAU,EAAE,OAAO;AAAA,EACnB,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AACpD,CAAC,EACI,OAAO;AAIL,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACtC,MAAM,EAAE,QAAQ,UAAU;AAAA,EAC1B,KAAK,EAAE,OAAO;AAClB,CAAC;AACM,IAAM,kBAAkB,EAAE,OAAO;AAAA,EACpC,MAAM,EAAE,QAAQ,OAAO;AAAA,EACvB,SAAS,EAAE,OAAO;AACtB,CAAC;AACM,IAAM,0BAA0B,EAAE,OAAO;AAAA,EAC5C,MAAM,EAAE,QAAQ,gBAAgB;AAAA,EAChC,UAAU,EAAE,OAAO;AAAA,EACnB,OAAO,EAAE,KAAK,CAAC,WAAW,WAAW,QAAQ,CAAC;AAClD,CAAC;AACM,IAAM,0BAA0B,EAAE,OAAO;AAAA,EAC5C,MAAM,EAAE,QAAQ,gBAAgB;AAAA,EAChC,WAAW,EAAE,OAAO;AAAA,EACpB,UAAU,EAAE,OAAO,EAAE,SAAS;AAClC,CAAC;AACM,IAAM,wBAAwB,EAAE,OAAO;AAAA,EAC1C,MAAM,EAAE,QAAQ,cAAc;AAAA,EAC9B,KAAK,EAAE,OAAO;AAAA,EACd,OAAO,EAAE,QAAQ;AACrB,CAAC;AACM,IAAM,qBAAqB,EAAE,OAAO;AAAA,EACvC,MAAM,EAAE,QAAQ,UAAU;AAAA,EAC1B,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,WAAW,EAAE,OAAO,EAAE,SAAS;AACnC,CAAC;AACM,IAAM,0BAA0B,EAAE,OAAO;AAAA,EAC5C,MAAM,EAAE,QAAQ,gBAAgB;AAAA,EAChC,KAAK,EAAE,OAAO;AAAA,EACd,UAAU,EAAE,KAAK,CAAC,OAAO,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,EACjD,WAAW,EAAE,OAAO;AACxB,CAAC;AACM,IAAM,sBAAsB,EAAE,OAAO;AAAA,EACxC,MAAM,EAAE,QAAQ,WAAW;AAAA,EAC3B,KAAK,EAAE,OAAO;AAAA,EACd,UAAU,EAAE,QAAQ,EAAE,SAAS;AACnC,CAAC;AACM,IAAM,2BAA2B,EAAE,OAAO;AAAA,EAC7C,MAAM,EAAE,QAAQ,iBAAiB;AAAA,EACjC,KAAK,EAAE,OAAO;AAAA,EACd,UAAU,EAAE,QAAQ,EAAE,SAAS;AACnC,CAAC;AACM,IAAM,2BAA2B,EAAE,OAAO;AAAA,EAC7C,MAAM,EAAE,QAAQ,iBAAiB;AAAA,EACjC,KAAK,EAAE,OAAO;AAAA,EACd,OAAO,EAAE,OAAO;AAAA,EAChB,UAAU,EAAE,QAAQ,EAAE,SAAS;AACnC,CAAC;AACM,IAAM,WAAW,EAAE,OAAO;AAAA,EAC7B,QAAQ,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,SAAS;AAAA,EAChE,UAAU,EAAE,OAAO,EAAE,SAAS;AAClC,CAAC;AACM,IAAM,cAAc,EAAE,OAAO;AAAA,EAChC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC;AAAA,EACjC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,QAAQ,EAAE,SAAS;AACnD,CAAC;AACM,IAAM,uBAAuB,EAAE,OAAO;AAAA,EACzC,MAAM,EAAE,QAAQ,aAAa;AAAA,EAC7B,KAAK,EAAE,OAAO;AAAA,EACd,UAAU,EAAE,KAAK,CAAC,OAAO,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,EACjD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAC7B,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACzC,SAAS,YAAY,SAAS;AAClC,CAAC;AACM,IAAM,aAAa,EAAE,mBAAmB,QAAQ;AAAA,EACnD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,CAAC;AAIM,IAAM,QAAQ,EAAE,OAAO;AAAA,EAC1B,YAAY,EAAE,MAAM,UAAU;AAAA,EAC9B,OAAO,EAAE,QAAQ;AACrB,CAAC;AACM,IAAM,gBAAgB,EAAE,OAAO;AAAA,EAClC,MAAM,EAAE,QAAQ,OAAO;AAAA,EACvB,OAAO,EAAE,MAAM,KAAK;AAAA,EACpB,SAAS,EAAE,QAAQ;AACvB,CAAC;AACM,IAAM,iBAAiB,EAAE,OAAO;AAAA,EACnC,MAAM,EAAE,QAAQ,OAAO;AAAA,EACvB,OAAO,EAAE,OAAO;AAAA,EAChB,WAAW,EAAE,OAAO;AAAA,EACpB,OAAO,EAAE,QAAQ;AAAA,EACjB,OAAO,EAAE,QAAQ;AACrB,CAAC;AACM,IAAM,iBAAiB,EAAE,OAAO;AAAA,EACnC,MAAM,EAAE,QAAQ,OAAO;AAAA,EACvB,SAAS,EAAE,OAAO;AAAA,EAClB,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,EAC1B,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC;AAAA,EAC/C,SAAS,EAAE,QAAQ;AACvB,CAAC;AACM,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACtC,MAAM,EAAE,QAAQ,UAAU;AAAA,EAC1B,UAAU,EAAE,OAAO;AAAA,EACnB,QAAQ,EAAE,KAAK,CAAC,OAAO,MAAM,CAAC,EAAE,SAAS;AAAA,EACzC,SAAS,EAAE,QAAQ;AAAA,EACnB,WAAW,EAAE,OAAO,EAAE,SAAS;AACnC,CAAC;AACM,IAAM,oBAAoB,EAAE,mBAAmB,QAAQ;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,CAAC;AAEM,IAAM,eAAe,kBAAkB,SAAS,EAAE,SAAS;AAK3D,IAAM,cAAc,EAAE,OAAO;AAAA,EAChC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,EAC1B,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS;AAC7E,CAAC;AAKM,IAAM,UAAU,EAClB,OAAO;AAAA,EACR,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,MAAM,EAAE,OAAO,EAAE,SAAS;AAC9B,CAAC,EACI,SAAS,EACT,SAAS;;;AD3GP,IAAM,eAAeC,GAAE,OAAO;AAAA,EACnC,SAASA,GACN,MAAMA,GAAE,OAAO,CAAC,EAChB,SAAS,EACT;AAAA,IACC;AAAA,EAGF;AAAA,EACF,SAASA,GACN,MAAMA,GAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,2EAA2E;AACzF,CAAC;AAEM,IAAM,oBAAoBA,GAAE,OAAO;AAAA,EACxC,QAAQ;AAAA,EACR,iBAAiBA,GACd,QAAQ,EACR,SAAS,EACT;AAAA,IACC;AAAA,EAEF;AACJ,CAAC;AASM,SAAS,kBAAkB,MAAe;AAC/C,SAAO,WAAW,UAAU,IAAI;AAClC;AAKO,SAAS,iBAAiB,MAAe;AAC9C,SAAO,kBAAkB,UAAU,IAAI;AACzC;AAKO,SAAS,yBAAyB,MAAe;AACtD,SAAO,kBAAkB,UAAU,IAAI;AACzC;AAaO,IAAM,kBAAkB;AAAA,EAC7B,EAAE,SAAS,WAAW,QAAQ,SAAS;AAAA,EACvC,EAAE,SAAS,cAAc,QAAQ,YAAY;AAAA,EAC7C,EAAE,SAAS,oBAAoB,QAAQ,kBAAkB;AAAA,EACzD,EAAE,SAAS,eAAe,QAAQ,aAAa;AAAA,EAC/C,EAAE,SAAS,gBAAgB,QAAQ,cAAc;AAAA,EACjD,EAAE,SAAS,iBAAiB,QAAQ,eAAe;AAAA,EACnD,EAAE,SAAS,iBAAiB,QAAQ,eAAe;AAAA,EACnD,EAAE,SAAS,oBAAoB,QAAQ,kBAAkB;AAAA,EACzD,EAAE,SAAS,QAAQ,QAAQ,MAAM;AAAA,EACjC,EAAE,SAAS,aAAa,QAAQ,WAAW;AAC7C;",
6
+ "names": ["z", "z"]
7
+ }