@syntrologie/runtime-sdk 2.12.0 → 2.14.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 (37) hide show
  1. package/CAPABILITIES.md +96 -67
  2. package/dist/actions/schema.d.ts +776 -776
  3. package/dist/actions/schema.js +3 -3
  4. package/dist/bootstrap.d.ts +2 -0
  5. package/dist/{chunk-L6RJMBR2.js → chunk-77TNZ66J.js} +3 -3
  6. package/dist/{chunk-XDYJ64IN.js → chunk-IR6UOR63.js} +4 -4
  7. package/dist/chunk-IR6UOR63.js.map +7 -0
  8. package/dist/{chunk-J2LGX2PV.js → chunk-JCDCANR7.js} +296 -75
  9. package/dist/chunk-JCDCANR7.js.map +7 -0
  10. package/dist/chunk-YLLWLUQX.js +241 -0
  11. package/dist/chunk-YLLWLUQX.js.map +7 -0
  12. package/dist/components/ShadowCanvasOverlay.d.ts +1 -2
  13. package/dist/config/schema.d.ts +147 -136
  14. package/dist/config/schema.js +2 -2
  15. package/dist/decisions/schema.d.ts +47 -47
  16. package/dist/decisions/schema.js +1 -1
  17. package/dist/fetchers/experimentsFetcher.d.ts +3 -3
  18. package/dist/fetchers/mergeConfigs.d.ts +7 -7
  19. package/dist/index.js +6 -4
  20. package/dist/index.js.map +1 -1
  21. package/dist/react.js +4 -4
  22. package/dist/smart-canvas.esm.js +44 -44
  23. package/dist/smart-canvas.esm.js.map +4 -4
  24. package/dist/smart-canvas.js +341 -109
  25. package/dist/smart-canvas.js.map +4 -4
  26. package/dist/smart-canvas.min.js +43 -43
  27. package/dist/smart-canvas.min.js.map +4 -4
  28. package/dist/telemetry/InterventionTracker.d.ts +23 -0
  29. package/dist/telemetry/index.d.ts +1 -0
  30. package/dist/version.d.ts +1 -1
  31. package/package.json +1 -1
  32. package/schema/canvas-config.schema.json +2347 -11396
  33. package/dist/chunk-BU4Z6PD7.js +0 -218
  34. package/dist/chunk-BU4Z6PD7.js.map +0 -7
  35. package/dist/chunk-J2LGX2PV.js.map +0 -7
  36. package/dist/chunk-XDYJ64IN.js.map +0 -7
  37. /package/dist/{chunk-L6RJMBR2.js.map → chunk-77TNZ66J.js.map} +0 -0
@@ -3,7 +3,7 @@ import {
3
3
  __privateGet,
4
4
  __privateSet,
5
5
  __publicField
6
- } from "./chunk-BU4Z6PD7.js";
6
+ } from "./chunk-YLLWLUQX.js";
7
7
 
8
8
  // ../adaptives/adaptive-content/dist/reconciliation-guard.js
9
9
  function guardAgainstReconciliation(container, anchor, reinsertFn, opts) {
@@ -3456,14 +3456,20 @@ function getAntiFlickerSnippet(config = {}) {
3456
3456
  }
3457
3457
 
3458
3458
  // src/version.ts
3459
- var SDK_VERSION = "2.12.0";
3459
+ var SDK_VERSION = "2.14.0";
3460
3460
 
3461
3461
  // src/types.ts
3462
3462
  var SDK_SCHEMA_VERSION = "2.0";
3463
3463
 
3464
3464
  // src/fetchers/mergeConfigs.ts
3465
- function resolveVariantConfigs(client, keys, _strategy = "first-match") {
3466
- var _a2, _b, _c, _d;
3465
+ function resolveVariantConfigs(client, keys, strategy = "merge") {
3466
+ if (strategy === "first-match") {
3467
+ return resolveFirstMatch(client, keys);
3468
+ }
3469
+ return resolveMerge(client, keys);
3470
+ }
3471
+ function resolveFirstMatch(client, keys) {
3472
+ var _a2;
3467
3473
  for (const key of keys) {
3468
3474
  const value = (_a2 = client.getFeatureValue) == null ? void 0 : _a2.call(client, key, null);
3469
3475
  if (!value || typeof value !== "object") continue;
@@ -3471,20 +3477,60 @@ function resolveVariantConfigs(client, keys, _strategy = "first-match") {
3471
3477
  const hasTiles = variant.tiles && variant.tiles.length > 0;
3472
3478
  const hasActions = variant.actions && variant.actions.length > 0;
3473
3479
  if (hasTiles || hasActions) {
3474
- return {
3475
- tiles: (_b = variant.tiles) != null ? _b : [],
3476
- actions: (_c = variant.actions) != null ? _c : [],
3477
- fetchedAt: (_d = variant.fetchedAt) != null ? _d : (/* @__PURE__ */ new Date()).toISOString(),
3478
- ...variant.schemaVersion && { schemaVersion: variant.schemaVersion },
3479
- ...variant.configVersion && { configVersion: variant.configVersion },
3480
- ...variant.canvasTitle && { canvasTitle: variant.canvasTitle },
3481
- ...variant.theme && { theme: variant.theme },
3482
- ...variant.launcher && { launcher: variant.launcher }
3483
- };
3480
+ return buildConfig([variant]);
3484
3481
  }
3485
3482
  }
3486
3483
  return null;
3487
3484
  }
3485
+ function resolveMerge(client, keys) {
3486
+ var _a2;
3487
+ const variants = [];
3488
+ for (const key of keys) {
3489
+ const value = (_a2 = client.getFeatureValue) == null ? void 0 : _a2.call(client, key, null);
3490
+ if (!value || typeof value !== "object") continue;
3491
+ const variant = value;
3492
+ const hasTiles = variant.tiles && variant.tiles.length > 0;
3493
+ const hasActions = variant.actions && variant.actions.length > 0;
3494
+ if (hasTiles || hasActions) {
3495
+ variants.push(variant);
3496
+ }
3497
+ }
3498
+ if (variants.length === 0) return null;
3499
+ return buildConfig(variants);
3500
+ }
3501
+ function buildConfig(variants) {
3502
+ const allTiles = [];
3503
+ const allActions = [];
3504
+ let fetchedAt;
3505
+ let schemaVersion;
3506
+ let configVersion;
3507
+ let canvasTitle;
3508
+ let theme;
3509
+ let launcher;
3510
+ let meta;
3511
+ for (const variant of variants) {
3512
+ if (variant.tiles) allTiles.push(...variant.tiles);
3513
+ if (variant.actions) allActions.push(...variant.actions);
3514
+ fetchedAt != null ? fetchedAt : fetchedAt = variant.fetchedAt;
3515
+ schemaVersion != null ? schemaVersion : schemaVersion = variant.schemaVersion;
3516
+ configVersion != null ? configVersion : configVersion = variant.configVersion;
3517
+ canvasTitle != null ? canvasTitle : canvasTitle = variant.canvasTitle;
3518
+ theme != null ? theme : theme = variant.theme;
3519
+ launcher != null ? launcher : launcher = variant.launcher;
3520
+ meta != null ? meta : meta = variant.meta;
3521
+ }
3522
+ return {
3523
+ tiles: allTiles,
3524
+ actions: allActions,
3525
+ fetchedAt: fetchedAt != null ? fetchedAt : (/* @__PURE__ */ new Date()).toISOString(),
3526
+ ...schemaVersion && { schemaVersion },
3527
+ ...configVersion && { configVersion },
3528
+ ...canvasTitle && { canvasTitle },
3529
+ ...theme && { theme },
3530
+ ...launcher && { launcher },
3531
+ ...meta && { meta }
3532
+ };
3533
+ }
3488
3534
 
3489
3535
  // src/logger.ts
3490
3536
  var debugEnabled = false;
@@ -3611,9 +3657,8 @@ var resolveConfigUri = ({
3611
3657
  }) => {
3612
3658
  var _a2;
3613
3659
  if (configUri) return configUri;
3614
- if (experiments) {
3615
- const key = featureKey != null ? featureKey : "smart-canvas-config";
3616
- const fromFeature = (_a2 = experiments.getFeatureValue) == null ? void 0 : _a2.call(experiments, key, null);
3660
+ if (experiments && featureKey) {
3661
+ const fromFeature = (_a2 = experiments.getFeatureValue) == null ? void 0 : _a2.call(experiments, featureKey, null);
3617
3662
  if (fromFeature) return fromFeature;
3618
3663
  }
3619
3664
  return void 0;
@@ -3647,9 +3692,8 @@ var createCanvasConfigFetcher = ({
3647
3692
  sdkVersion
3648
3693
  }) => async () => {
3649
3694
  var _a2;
3650
- const effectiveConfigKey = configFeatureKey != null ? configFeatureKey : "smart-canvas-config";
3651
- if (experiments) {
3652
- const directConfig = (_a2 = experiments.getFeatureValue) == null ? void 0 : _a2.call(experiments, effectiveConfigKey, null);
3695
+ if (experiments && configFeatureKey) {
3696
+ const directConfig = (_a2 = experiments.getFeatureValue) == null ? void 0 : _a2.call(experiments, configFeatureKey, null);
3653
3697
  if (directConfig && typeof directConfig === "object") {
3654
3698
  debug("SmartCanvas Config", "Resolved config directly from feature flag", directConfig);
3655
3699
  return directConfig;
@@ -3933,6 +3977,36 @@ function getEventName(phEvent) {
3933
3977
  return eventName.replace("$", "posthog.");
3934
3978
  }
3935
3979
  var INTERACTIVE_TAGS = /* @__PURE__ */ new Set(["a", "button", "input", "select", "textarea"]);
3980
+ function parseElementsChain(chain) {
3981
+ if (!chain)
3982
+ return void 0;
3983
+ return chain.split(";").map((segment) => {
3984
+ const el = {};
3985
+ const colonIdx = segment.indexOf(":");
3986
+ const tagPart = colonIdx >= 0 ? segment.slice(0, colonIdx) : segment;
3987
+ const attrPart = colonIdx >= 0 ? segment.slice(colonIdx + 1) : "";
3988
+ const dotIdx = tagPart.indexOf(".");
3989
+ if (dotIdx >= 0) {
3990
+ el.tag_name = tagPart.slice(0, dotIdx);
3991
+ el.attr__class = tagPart.slice(dotIdx + 1).replace(/\./g, " ");
3992
+ } else {
3993
+ el.tag_name = tagPart;
3994
+ }
3995
+ const attrRegex = /([\w$]+)="([^"]*)"/g;
3996
+ let match;
3997
+ while ((match = attrRegex.exec(attrPart)) !== null) {
3998
+ const [, key, value] = match;
3999
+ if (key === "nth-child" || key === "nth-of-type")
4000
+ continue;
4001
+ el[key] = value;
4002
+ }
4003
+ if (el.text) {
4004
+ el.$el_text = el.text;
4005
+ delete el.text;
4006
+ }
4007
+ return el;
4008
+ });
4009
+ }
3936
4010
  function resolveInteractiveTag(elements, directTag) {
3937
4011
  if (directTag && INTERACTIVE_TAGS.has(directTag))
3938
4012
  return directTag;
@@ -3946,17 +4020,20 @@ function resolveInteractiveTag(elements, directTag) {
3946
4020
  return directTag;
3947
4021
  }
3948
4022
  function extractProps(phEvent) {
3949
- var _a2, _b;
4023
+ var _a2, _b, _c;
3950
4024
  const props = {};
3951
4025
  const phProps = phEvent.properties || {};
3952
- const elements = phProps.$elements;
3953
- const directTag = (_b = phProps.$tag_name) != null ? _b : (_a2 = elements == null ? void 0 : elements[0]) == null ? void 0 : _a2.tag_name;
4026
+ const elements = (_a2 = phProps.$elements) != null ? _a2 : typeof phProps.$elements_chain === "string" ? parseElementsChain(phProps.$elements_chain) : void 0;
4027
+ const directTag = (_c = phProps.$tag_name) != null ? _c : (_b = elements == null ? void 0 : elements[0]) == null ? void 0 : _b.tag_name;
3954
4028
  const isClickEvent = phEvent.event === "$autocapture" || phEvent.event === "$click";
3955
4029
  props.tagName = isClickEvent ? resolveInteractiveTag(elements, directTag) : directTag;
3956
4030
  if (phProps.$el_text)
3957
4031
  props.elementText = phProps.$el_text;
3958
4032
  if (elements)
3959
4033
  props.elements = elements;
4034
+ if (isClickEvent && !elements) {
4035
+ console.warn(`[PostHogNormalizer] $autocapture click has no element chain. PostHog may have changed wire format. Properties: $elements=${!!phProps.$elements}, $elements_chain=${typeof phProps.$elements_chain}`);
4036
+ }
3960
4037
  if (phProps.$current_url)
3961
4038
  props.url = phProps.$current_url;
3962
4039
  if (phProps.$pathname)
@@ -5075,6 +5152,19 @@ function WidgetMount({ widgetId, props }) {
5075
5152
  }
5076
5153
  return /* @__PURE__ */ jsx6("div", { ref: parentRef });
5077
5154
  }
5155
+ var INTERACTION_PATTERNS = [
5156
+ ":toggled",
5157
+ ":clicked",
5158
+ ":feedback",
5159
+ ":navigate",
5160
+ ":expanded",
5161
+ ":collapsed",
5162
+ ":dismissed",
5163
+ ":submitted",
5164
+ ":interacted",
5165
+ ":tip_clicked",
5166
+ ":tip_focused"
5167
+ ];
5078
5168
  function TileCard({
5079
5169
  config,
5080
5170
  surface: _surface,
@@ -5083,10 +5173,42 @@ function TileCard({
5083
5173
  }) {
5084
5174
  const { title, subtitle, widget, props, icon } = config;
5085
5175
  const [, setTick] = useState4(0);
5176
+ const articleRef = useRef4(null);
5086
5177
  const runtime3 = useRuntime();
5087
5178
  useEffect5(() => {
5088
5179
  if (runtime3) setTick((t) => t + 1);
5089
5180
  }, [runtime3]);
5181
+ useEffect5(() => {
5182
+ var _a2;
5183
+ const tracker = typeof window !== "undefined" ? (_a2 = window.SynOS) == null ? void 0 : _a2.interventionTracker : null;
5184
+ if (!articleRef.current || !tracker) return;
5185
+ const observer = new IntersectionObserver(
5186
+ ([entry]) => {
5187
+ var _a3;
5188
+ if (entry.isIntersecting) {
5189
+ tracker.trackSeen(config.id, (_a3 = config.widget) != null ? _a3 : "unknown");
5190
+ observer.disconnect();
5191
+ }
5192
+ },
5193
+ { threshold: 0.5 }
5194
+ );
5195
+ observer.observe(articleRef.current);
5196
+ return () => observer.disconnect();
5197
+ }, [config.id, config.widget]);
5198
+ useEffect5(() => {
5199
+ var _a2;
5200
+ const tracker = typeof window !== "undefined" ? (_a2 = window.SynOS) == null ? void 0 : _a2.interventionTracker : null;
5201
+ if (!(runtime3 == null ? void 0 : runtime3.events) || !tracker) return;
5202
+ return runtime3.events.subscribe((event) => {
5203
+ var _a3, _b;
5204
+ if (!INTERACTION_PATTERNS.some((p) => {
5205
+ var _a4;
5206
+ return (_a4 = event.name) == null ? void 0 : _a4.includes(p);
5207
+ })) return;
5208
+ if (((_a3 = event.props) == null ? void 0 : _a3.instanceId) !== config.id) return;
5209
+ tracker.trackInteracted(config.id, (_b = config.widget) != null ? _b : "unknown", event.name);
5210
+ });
5211
+ }, [runtime3 == null ? void 0 : runtime3.events, config.id, config.widget]);
5090
5212
  const registration = useMemo3(
5091
5213
  () => {
5092
5214
  var _a2, _b;
@@ -5140,6 +5262,7 @@ function TileCard({
5140
5262
  return /* @__PURE__ */ jsxs2(
5141
5263
  "article",
5142
5264
  {
5265
+ ref: articleRef,
5143
5266
  "data-shadow-canvas-id": `tile-${config.id}`,
5144
5267
  style: cardStyle,
5145
5268
  onMouseEnter,
@@ -5651,7 +5774,6 @@ function ShadowCanvasOverlay({
5651
5774
  onToggle,
5652
5775
  telemetry,
5653
5776
  launcherLabel: _launcherLabel = "Adaptives",
5654
- launcherIcon,
5655
5777
  launcherAnimate = false,
5656
5778
  launcherAnimationStyle: _launcherAnimationStyle = "pulse",
5657
5779
  notificationCount: _notificationCount,
@@ -5662,7 +5784,7 @@ function ShadowCanvasOverlay({
5662
5784
  canvasTitle,
5663
5785
  displayMode = "standard"
5664
5786
  }) {
5665
- var _a2, _b, _c, _d;
5787
+ var _a2, _b, _c, _d, _e;
5666
5788
  const [mounted, setMounted] = useState5(false);
5667
5789
  const [launcherPos, setLauncherPos] = useState5(null);
5668
5790
  const dragRef = useRef5(null);
@@ -5795,7 +5917,7 @@ function ShadowCanvasOverlay({
5795
5917
  }
5796
5918
  }, []);
5797
5919
  const onLauncherPointerUp = useCallback4(
5798
- (_e) => {
5920
+ (_e2) => {
5799
5921
  const drag = dragRef.current;
5800
5922
  dragRef.current = null;
5801
5923
  if (drag && !drag.dragged) {
@@ -6063,10 +6185,10 @@ function ShadowCanvasOverlay({
6063
6185
  /* @__PURE__ */ jsx8("path", { d: "M6 6l12 12" })
6064
6186
  ]
6065
6187
  }
6066
- ) : launcherIcon ? /* @__PURE__ */ jsx8(
6188
+ ) : ((_e = config.launcher) == null ? void 0 : _e.icon) ? /* @__PURE__ */ jsx8(
6067
6189
  "img",
6068
6190
  {
6069
- src: launcherIcon,
6191
+ src: config.launcher.icon,
6070
6192
  alt: "",
6071
6193
  "aria-hidden": "true",
6072
6194
  style: {
@@ -6162,6 +6284,14 @@ var sortTiles = (tiles) => [...tiles].sort((a, b) => {
6162
6284
  var _a2, _b;
6163
6285
  return ((_a2 = b.priority) != null ? _a2 : 0) - ((_b = a.priority) != null ? _b : 0);
6164
6286
  });
6287
+ function fireTriggeredForTiles(tiles) {
6288
+ var _a2, _b;
6289
+ const tracker = typeof window !== "undefined" ? (_a2 = window.SynOS) == null ? void 0 : _a2.interventionTracker : null;
6290
+ if (!tracker) return;
6291
+ for (const tile of tiles) {
6292
+ tracker.trackTriggered(tile.id, (_b = tile.widget) != null ? _b : "unknown");
6293
+ }
6294
+ }
6165
6295
  function useShadowCanvasConfig({
6166
6296
  fetcher,
6167
6297
  experiments,
@@ -6184,6 +6314,7 @@ function useShadowCanvasConfig({
6184
6314
  if (experiments) {
6185
6315
  tiles = tiles.filter((tile) => experiments.shouldRenderRectangle(tile));
6186
6316
  }
6317
+ fireTriggeredForTiles(tiles);
6187
6318
  setState((prev) => ({ ...prev, tiles: sortTiles(tiles) }));
6188
6319
  }, [runtime3, experiments]);
6189
6320
  const load = useCallback5(async () => {
@@ -6201,6 +6332,7 @@ function useShadowCanvasConfig({
6201
6332
  } else if (experiments) {
6202
6333
  tiles = tiles.filter((tile) => experiments.shouldRenderRectangle(tile));
6203
6334
  }
6335
+ fireTriggeredForTiles(tiles);
6204
6336
  debug("SmartCanvas Config", `Tile count after filtering: ${tiles.length}`);
6205
6337
  const newActions = response.actions || [];
6206
6338
  const newActionsJson = JSON.stringify(newActions);
@@ -6351,7 +6483,7 @@ function SmartCanvasAppInner({
6351
6483
  initialBatchHandle,
6352
6484
  workspaceTheme
6353
6485
  }) {
6354
- var _a2, _b, _c, _d, _e, _f, _g;
6486
+ var _a2, _b, _c, _d, _e, _f;
6355
6487
  const [open, setOpen] = useState7(controller.getState().open);
6356
6488
  const pageContext = usePageContext();
6357
6489
  const [localUrl, setLocalUrl] = useState7(
@@ -6407,6 +6539,7 @@ function SmartCanvasAppInner({
6407
6539
  const batchHandleRef = useRef7(initialBatchHandle != null ? initialBatchHandle : null);
6408
6540
  const adoptedInitialRef = useRef7(!!initialBatchHandle);
6409
6541
  const runVersionRef = useRef7(0);
6542
+ const pendingRevertRef = useRef7(null);
6410
6543
  useEffect9(() => {
6411
6544
  if (!(runtime3 == null ? void 0 : runtime3.actions)) return;
6412
6545
  if (adoptedInitialRef.current) {
@@ -6418,6 +6551,10 @@ function SmartCanvasAppInner({
6418
6551
  const version = ++runVersionRef.current;
6419
6552
  const stale = () => version !== runVersionRef.current;
6420
6553
  const run = async () => {
6554
+ if (pendingRevertRef.current) {
6555
+ await pendingRevertRef.current;
6556
+ pendingRevertRef.current = null;
6557
+ }
6421
6558
  if (batchHandleRef.current) {
6422
6559
  try {
6423
6560
  await batchHandleRef.current.revertAll();
@@ -6445,7 +6582,7 @@ function SmartCanvasAppInner({
6445
6582
  run();
6446
6583
  return () => {
6447
6584
  if (batchHandleRef.current) {
6448
- batchHandleRef.current.revertAll().catch((err) => {
6585
+ pendingRevertRef.current = batchHandleRef.current.revertAll().catch((err) => {
6449
6586
  console.error("[SmartCanvasApp] Failed to revert actions on cleanup:", err);
6450
6587
  });
6451
6588
  batchHandleRef.current = null;
@@ -6476,10 +6613,9 @@ function SmartCanvasAppInner({
6476
6613
  canvasTitle: configState.canvasTitle,
6477
6614
  telemetry,
6478
6615
  launcherLabel: launcherLabel != null ? launcherLabel : (_b = configState.launcher) == null ? void 0 : _b.label,
6479
- launcherIcon: (_c = configState.launcher) == null ? void 0 : _c.icon,
6480
- launcherAnimate: (_d = configState.launcher) == null ? void 0 : _d.animate,
6481
- launcherAnimationStyle: (_e = configState.launcher) == null ? void 0 : _e.animationStyle,
6482
- notificationCount: (_g = (_f = configState.launcher) == null ? void 0 : _f.notificationCount) != null ? _g : configState.tiles.length,
6616
+ launcherAnimate: (_c = configState.launcher) == null ? void 0 : _c.animate,
6617
+ launcherAnimationStyle: (_d = configState.launcher) == null ? void 0 : _d.animationStyle,
6618
+ notificationCount: (_f = (_e = configState.launcher) == null ? void 0 : _e.notificationCount) != null ? _f : configState.tiles.length,
6483
6619
  footerSlot,
6484
6620
  isOpen: open,
6485
6621
  onToggle: () => controller.toggle(),
@@ -7679,33 +7815,7 @@ var PostHogAdapter = class {
7679
7815
  // Capture performance metrics
7680
7816
  capture_performance: true,
7681
7817
  // Enable web vitals
7682
- enable_recording_console_log: true,
7683
- // Bootstrap callback for when flags are loaded
7684
- loaded: (ph) => {
7685
- if (enableFeatureFlags && this.featureFlagsCallback) {
7686
- ph.onFeatureFlags(() => {
7687
- const allFlags = this.getAllFeatureFlags();
7688
- if (allFlags && this.featureFlagsCallback) {
7689
- this.featureFlagsCallback(allFlags);
7690
- }
7691
- });
7692
- const existingFlags = this.getAllFeatureFlags();
7693
- if (existingFlags && Object.keys(existingFlags).length > 0) {
7694
- this.featureFlagsCallback(existingFlags);
7695
- }
7696
- }
7697
- if (this.captureCallback) {
7698
- ph.on("eventCaptured", (...args) => {
7699
- var _a3;
7700
- const data = args[0];
7701
- const eventName = typeof data === "string" ? data : data == null ? void 0 : data.event;
7702
- const properties = typeof data === "string" ? void 0 : data == null ? void 0 : data.properties;
7703
- if (typeof eventName === "string") {
7704
- (_a3 = this.captureCallback) == null ? void 0 : _a3.call(this, eventName, properties);
7705
- }
7706
- });
7707
- }
7708
- }
7818
+ enable_recording_console_log: true
7709
7819
  };
7710
7820
  const result = posthog.init(
7711
7821
  options.apiKey,
@@ -7715,6 +7825,29 @@ var PostHogAdapter = class {
7715
7825
  if (result) {
7716
7826
  this.client = result;
7717
7827
  }
7828
+ if (this.captureCallback && this.client) {
7829
+ this.client.on("eventCaptured", (...args) => {
7830
+ var _a3;
7831
+ const data = args[0];
7832
+ const eventName = typeof data === "string" ? data : data == null ? void 0 : data.event;
7833
+ const properties = typeof data === "string" ? void 0 : data == null ? void 0 : data.properties;
7834
+ if (typeof eventName === "string") {
7835
+ (_a3 = this.captureCallback) == null ? void 0 : _a3.call(this, eventName, properties);
7836
+ }
7837
+ });
7838
+ }
7839
+ if (enableFeatureFlags && this.featureFlagsCallback && this.client) {
7840
+ this.client.onFeatureFlags(() => {
7841
+ const allFlags = this.getAllFeatureFlags();
7842
+ if (allFlags && this.featureFlagsCallback) {
7843
+ this.featureFlagsCallback(allFlags);
7844
+ }
7845
+ });
7846
+ const existingFlags = this.getAllFeatureFlags();
7847
+ if (existingFlags && Object.keys(existingFlags).length > 0) {
7848
+ this.featureFlagsCallback(existingFlags);
7849
+ }
7850
+ }
7718
7851
  if (this.rrwebCallback && this.client) {
7719
7852
  this.setupRRWebIntercept();
7720
7853
  }
@@ -7851,6 +7984,59 @@ function createPostHogClient(options = {}) {
7851
7984
  return new PostHogAdapter(options);
7852
7985
  }
7853
7986
 
7987
+ // src/telemetry/InterventionTracker.ts
7988
+ var InterventionTracker = class {
7989
+ constructor(telemetry, variantId) {
7990
+ __publicField(this, "telemetry");
7991
+ __publicField(this, "variantId");
7992
+ __publicField(this, "seenSet", /* @__PURE__ */ new Set());
7993
+ __publicField(this, "triggeredSet", /* @__PURE__ */ new Set());
7994
+ this.telemetry = telemetry;
7995
+ this.variantId = variantId;
7996
+ }
7997
+ trackServed(tiles, actions) {
7998
+ var _a2, _b;
7999
+ (_b = (_a2 = this.telemetry).track) == null ? void 0 : _b.call(_a2, "syntro_config_served", {
8000
+ variant_id: this.variantId,
8001
+ tiles,
8002
+ actions
8003
+ });
8004
+ }
8005
+ trackSeen(interventionId, interventionKind) {
8006
+ var _a2, _b;
8007
+ if (this.seenSet.has(interventionId)) return;
8008
+ this.seenSet.add(interventionId);
8009
+ (_b = (_a2 = this.telemetry).track) == null ? void 0 : _b.call(_a2, "syntro_intervention_seen", {
8010
+ variant_id: this.variantId,
8011
+ intervention_id: interventionId,
8012
+ intervention_kind: interventionKind
8013
+ });
8014
+ }
8015
+ trackTriggered(interventionId, interventionKind) {
8016
+ var _a2, _b;
8017
+ if (this.triggeredSet.has(interventionId)) return;
8018
+ this.triggeredSet.add(interventionId);
8019
+ (_b = (_a2 = this.telemetry).track) == null ? void 0 : _b.call(_a2, "syntro_intervention_triggered", {
8020
+ variant_id: this.variantId,
8021
+ intervention_id: interventionId,
8022
+ intervention_kind: interventionKind
8023
+ });
8024
+ }
8025
+ trackInteracted(interventionId, interventionKind, interactionType) {
8026
+ var _a2, _b;
8027
+ (_b = (_a2 = this.telemetry).track) == null ? void 0 : _b.call(_a2, "syntro_intervention_interacted", {
8028
+ variant_id: this.variantId,
8029
+ intervention_id: interventionId,
8030
+ intervention_kind: interventionKind,
8031
+ interaction_type: interactionType
8032
+ });
8033
+ }
8034
+ resetPage() {
8035
+ this.seenSet.clear();
8036
+ this.triggeredSet.clear();
8037
+ }
8038
+ };
8039
+
7854
8040
  // src/actions/executors/core-flow.ts
7855
8041
  var executeSequence = async (action, context) => {
7856
8042
  const handles = [];
@@ -9006,15 +9192,30 @@ function createActionEngine(options) {
9006
9192
  const handles = [];
9007
9193
  const appliedHandles = [];
9008
9194
  try {
9009
- for (const action of actions) {
9010
- const handle = await apply(action);
9011
- handles.push(handle);
9012
- appliedHandles.push(handle);
9195
+ const results = await Promise.allSettled(actions.map((action) => apply(action)));
9196
+ const errors = [];
9197
+ for (const result of results) {
9198
+ if (result.status === "fulfilled") {
9199
+ handles.push(result.value);
9200
+ appliedHandles.push(result.value);
9201
+ } else {
9202
+ errors.push(
9203
+ result.reason instanceof Error ? result.reason : new Error(String(result.reason))
9204
+ );
9205
+ }
9206
+ }
9207
+ if (errors.length > 0 && appliedHandles.length === 0) {
9208
+ throw errors[0];
9209
+ }
9210
+ if (errors.length > 0) {
9211
+ console.warn(
9212
+ `[ActionEngine] ${errors.length}/${actions.length} action(s) failed in batch:`,
9213
+ errors.map((e) => e.message).join("; ")
9214
+ );
9013
9215
  }
9014
9216
  } catch (error2) {
9015
9217
  console.error(
9016
- `[ActionEngine] Batch apply FAILED at action ${appliedHandles.length + 1}/${actions.length}.`,
9017
- `Successfully applied: ${appliedHandles.length}. Rolling back...`,
9218
+ `[ActionEngine] Batch apply FAILED. Successfully applied: ${appliedHandles.length}. Rolling back...`,
9018
9219
  error2
9019
9220
  );
9020
9221
  for (const handle of appliedHandles) {
@@ -11612,9 +11813,8 @@ var ExperimentsFetcher = class {
11612
11813
  __publicField(this, "featureKey");
11613
11814
  __publicField(this, "manifestKey");
11614
11815
  __publicField(this, "variantFlagPrefix");
11615
- var _a2;
11616
11816
  this.client = options.client;
11617
- this.featureKey = (_a2 = options.featureKey) != null ? _a2 : "smart-canvas-config";
11817
+ this.featureKey = options.featureKey;
11618
11818
  this.manifestKey = options.manifestKey;
11619
11819
  this.variantFlagPrefix = options.variantFlagPrefix;
11620
11820
  }
@@ -12037,15 +12237,35 @@ async function _initCore(options) {
12037
12237
  }
12038
12238
  const warnedAppFailures = /* @__PURE__ */ new Set();
12039
12239
  const appLoadingFetcher = baseFetcher ? async () => {
12040
- var _a3, _b2, _c2, _d2, _e2, _f2, _g2;
12240
+ var _a3, _b2, _c2, _d2, _e2, _f2, _g2, _h, _i, _j, _k, _l;
12041
12241
  const config = await baseFetcher();
12242
+ const tileCount = (_b2 = (_a3 = config.tiles) == null ? void 0 : _a3.length) != null ? _b2 : 0;
12243
+ const actionCount = (_d2 = (_c2 = config.actions) == null ? void 0 : _c2.length) != null ? _d2 : 0;
12244
+ const variantId = (_e2 = config.meta) == null ? void 0 : _e2.variant_id;
12245
+ if (tileCount > 0 || actionCount > 0) {
12246
+ if (!variantId) {
12247
+ console.warn(
12248
+ "[Syntro] Config has content but no meta.variant_id \u2014 intervention tracking disabled"
12249
+ );
12250
+ }
12251
+ }
12252
+ if (telemetry && variantId) {
12253
+ const tracker = new InterventionTracker(telemetry, variantId);
12254
+ tracker.trackServed(tileCount, actionCount);
12255
+ if (typeof window !== "undefined") {
12256
+ window.SynOS.interventionTracker = tracker;
12257
+ }
12258
+ runtime3.navigation.subscribe(() => {
12259
+ tracker.resetPage();
12260
+ });
12261
+ }
12042
12262
  console.log(
12043
12263
  "[Syntro Bootstrap] Config fetched:",
12044
- `tiles=${(_b2 = (_a3 = config.tiles) == null ? void 0 : _a3.length) != null ? _b2 : 0},`,
12045
- `actions=${(_d2 = (_c2 = config.actions) == null ? void 0 : _c2.length) != null ? _d2 : 0},`,
12046
- `theme=${(_f2 = (_e2 = config.theme) == null ? void 0 : _e2.name) != null ? _f2 : "none"}`
12264
+ `tiles=${(_g2 = (_f2 = config.tiles) == null ? void 0 : _f2.length) != null ? _g2 : 0},`,
12265
+ `actions=${(_i = (_h = config.actions) == null ? void 0 : _h.length) != null ? _i : 0},`,
12266
+ `theme=${(_k = (_j = config.theme) == null ? void 0 : _j.name) != null ? _k : "none"}`
12047
12267
  );
12048
- if (((_g2 = config.actions) == null ? void 0 : _g2.length) > 0) {
12268
+ if (((_l = config.actions) == null ? void 0 : _l.length) > 0) {
12049
12269
  console.log(
12050
12270
  "[Syntro Bootstrap] Actions in config:",
12051
12271
  config.actions.map(
@@ -12200,6 +12420,7 @@ export {
12200
12420
  createSessionMetricTracker,
12201
12421
  createNoopClient,
12202
12422
  createPostHogClient,
12423
+ InterventionTracker,
12203
12424
  ExecutorRegistry,
12204
12425
  executorRegistry,
12205
12426
  getExecutor,
@@ -12246,4 +12467,4 @@ export {
12246
12467
  encodeToken,
12247
12468
  Syntro
12248
12469
  };
12249
- //# sourceMappingURL=chunk-J2LGX2PV.js.map
12470
+ //# sourceMappingURL=chunk-JCDCANR7.js.map