@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.
- package/CAPABILITIES.md +96 -67
- package/dist/actions/schema.d.ts +776 -776
- package/dist/actions/schema.js +3 -3
- package/dist/bootstrap.d.ts +2 -0
- package/dist/{chunk-L6RJMBR2.js → chunk-77TNZ66J.js} +3 -3
- package/dist/{chunk-XDYJ64IN.js → chunk-IR6UOR63.js} +4 -4
- package/dist/chunk-IR6UOR63.js.map +7 -0
- package/dist/{chunk-J2LGX2PV.js → chunk-JCDCANR7.js} +296 -75
- package/dist/chunk-JCDCANR7.js.map +7 -0
- package/dist/chunk-YLLWLUQX.js +241 -0
- package/dist/chunk-YLLWLUQX.js.map +7 -0
- package/dist/components/ShadowCanvasOverlay.d.ts +1 -2
- package/dist/config/schema.d.ts +147 -136
- package/dist/config/schema.js +2 -2
- package/dist/decisions/schema.d.ts +47 -47
- package/dist/decisions/schema.js +1 -1
- package/dist/fetchers/experimentsFetcher.d.ts +3 -3
- package/dist/fetchers/mergeConfigs.d.ts +7 -7
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/react.js +4 -4
- package/dist/smart-canvas.esm.js +44 -44
- package/dist/smart-canvas.esm.js.map +4 -4
- package/dist/smart-canvas.js +341 -109
- package/dist/smart-canvas.js.map +4 -4
- package/dist/smart-canvas.min.js +43 -43
- package/dist/smart-canvas.min.js.map +4 -4
- package/dist/telemetry/InterventionTracker.d.ts +23 -0
- package/dist/telemetry/index.d.ts +1 -0
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/schema/canvas-config.schema.json +2347 -11396
- package/dist/chunk-BU4Z6PD7.js +0 -218
- package/dist/chunk-BU4Z6PD7.js.map +0 -7
- package/dist/chunk-J2LGX2PV.js.map +0 -7
- package/dist/chunk-XDYJ64IN.js.map +0 -7
- /package/dist/{chunk-L6RJMBR2.js.map → chunk-77TNZ66J.js.map} +0 -0
package/dist/smart-canvas.js
CHANGED
|
@@ -12802,6 +12802,7 @@ var SyntrologieSDK = (() => {
|
|
|
12802
12802
|
HighlightZ: () => HighlightZ,
|
|
12803
12803
|
InsertHtmlZ: () => InsertHtmlZ,
|
|
12804
12804
|
InsertPositionZ: () => InsertPositionZ,
|
|
12805
|
+
InterventionTracker: () => InterventionTracker,
|
|
12805
12806
|
MAX_VISIBLE_TOASTS: () => MAX_VISIBLE_TOASTS,
|
|
12806
12807
|
MatchOpZ: () => MatchOpZ,
|
|
12807
12808
|
ModalContentZ: () => ModalContentZ,
|
|
@@ -20608,7 +20609,13 @@ Please report this to https://github.com/markedjs/marked.`, e2) {
|
|
|
20608
20609
|
}
|
|
20609
20610
|
|
|
20610
20611
|
// src/fetchers/mergeConfigs.ts
|
|
20611
|
-
function resolveVariantConfigs(client, keys,
|
|
20612
|
+
function resolveVariantConfigs(client, keys, strategy = "merge") {
|
|
20613
|
+
if (strategy === "first-match") {
|
|
20614
|
+
return resolveFirstMatch(client, keys);
|
|
20615
|
+
}
|
|
20616
|
+
return resolveMerge(client, keys);
|
|
20617
|
+
}
|
|
20618
|
+
function resolveFirstMatch(client, keys) {
|
|
20612
20619
|
for (const key of keys) {
|
|
20613
20620
|
const value = client.getFeatureValue?.(key, null);
|
|
20614
20621
|
if (!value || typeof value !== "object") continue;
|
|
@@ -20616,20 +20623,59 @@ Please report this to https://github.com/markedjs/marked.`, e2) {
|
|
|
20616
20623
|
const hasTiles = variant.tiles && variant.tiles.length > 0;
|
|
20617
20624
|
const hasActions = variant.actions && variant.actions.length > 0;
|
|
20618
20625
|
if (hasTiles || hasActions) {
|
|
20619
|
-
return
|
|
20620
|
-
tiles: variant.tiles ?? [],
|
|
20621
|
-
actions: variant.actions ?? [],
|
|
20622
|
-
fetchedAt: variant.fetchedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
20623
|
-
...variant.schemaVersion && { schemaVersion: variant.schemaVersion },
|
|
20624
|
-
...variant.configVersion && { configVersion: variant.configVersion },
|
|
20625
|
-
...variant.canvasTitle && { canvasTitle: variant.canvasTitle },
|
|
20626
|
-
...variant.theme && { theme: variant.theme },
|
|
20627
|
-
...variant.launcher && { launcher: variant.launcher }
|
|
20628
|
-
};
|
|
20626
|
+
return buildConfig([variant]);
|
|
20629
20627
|
}
|
|
20630
20628
|
}
|
|
20631
20629
|
return null;
|
|
20632
20630
|
}
|
|
20631
|
+
function resolveMerge(client, keys) {
|
|
20632
|
+
const variants = [];
|
|
20633
|
+
for (const key of keys) {
|
|
20634
|
+
const value = client.getFeatureValue?.(key, null);
|
|
20635
|
+
if (!value || typeof value !== "object") continue;
|
|
20636
|
+
const variant = value;
|
|
20637
|
+
const hasTiles = variant.tiles && variant.tiles.length > 0;
|
|
20638
|
+
const hasActions = variant.actions && variant.actions.length > 0;
|
|
20639
|
+
if (hasTiles || hasActions) {
|
|
20640
|
+
variants.push(variant);
|
|
20641
|
+
}
|
|
20642
|
+
}
|
|
20643
|
+
if (variants.length === 0) return null;
|
|
20644
|
+
return buildConfig(variants);
|
|
20645
|
+
}
|
|
20646
|
+
function buildConfig(variants) {
|
|
20647
|
+
const allTiles = [];
|
|
20648
|
+
const allActions = [];
|
|
20649
|
+
let fetchedAt;
|
|
20650
|
+
let schemaVersion;
|
|
20651
|
+
let configVersion;
|
|
20652
|
+
let canvasTitle;
|
|
20653
|
+
let theme;
|
|
20654
|
+
let launcher;
|
|
20655
|
+
let meta;
|
|
20656
|
+
for (const variant of variants) {
|
|
20657
|
+
if (variant.tiles) allTiles.push(...variant.tiles);
|
|
20658
|
+
if (variant.actions) allActions.push(...variant.actions);
|
|
20659
|
+
fetchedAt ?? (fetchedAt = variant.fetchedAt);
|
|
20660
|
+
schemaVersion ?? (schemaVersion = variant.schemaVersion);
|
|
20661
|
+
configVersion ?? (configVersion = variant.configVersion);
|
|
20662
|
+
canvasTitle ?? (canvasTitle = variant.canvasTitle);
|
|
20663
|
+
theme ?? (theme = variant.theme);
|
|
20664
|
+
launcher ?? (launcher = variant.launcher);
|
|
20665
|
+
meta ?? (meta = variant.meta);
|
|
20666
|
+
}
|
|
20667
|
+
return {
|
|
20668
|
+
tiles: allTiles,
|
|
20669
|
+
actions: allActions,
|
|
20670
|
+
fetchedAt: fetchedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
20671
|
+
...schemaVersion && { schemaVersion },
|
|
20672
|
+
...configVersion && { configVersion },
|
|
20673
|
+
...canvasTitle && { canvasTitle },
|
|
20674
|
+
...theme && { theme },
|
|
20675
|
+
...launcher && { launcher },
|
|
20676
|
+
...meta && { meta }
|
|
20677
|
+
};
|
|
20678
|
+
}
|
|
20633
20679
|
|
|
20634
20680
|
// src/logger.ts
|
|
20635
20681
|
var debugEnabled = false;
|
|
@@ -20677,7 +20723,7 @@ Please report this to https://github.com/markedjs/marked.`, e2) {
|
|
|
20677
20723
|
}
|
|
20678
20724
|
|
|
20679
20725
|
// src/version.ts
|
|
20680
|
-
var SDK_VERSION = "2.
|
|
20726
|
+
var SDK_VERSION = "2.14.0";
|
|
20681
20727
|
|
|
20682
20728
|
// src/types.ts
|
|
20683
20729
|
var SDK_SCHEMA_VERSION = "2.0";
|
|
@@ -20761,9 +20807,8 @@ Please report this to https://github.com/markedjs/marked.`, e2) {
|
|
|
20761
20807
|
featureKey
|
|
20762
20808
|
}) => {
|
|
20763
20809
|
if (configUri) return configUri;
|
|
20764
|
-
if (experiments) {
|
|
20765
|
-
const
|
|
20766
|
-
const fromFeature = experiments.getFeatureValue?.(key, null);
|
|
20810
|
+
if (experiments && featureKey) {
|
|
20811
|
+
const fromFeature = experiments.getFeatureValue?.(featureKey, null);
|
|
20767
20812
|
if (fromFeature) return fromFeature;
|
|
20768
20813
|
}
|
|
20769
20814
|
return void 0;
|
|
@@ -20795,9 +20840,8 @@ Please report this to https://github.com/markedjs/marked.`, e2) {
|
|
|
20795
20840
|
variantFlagPrefix,
|
|
20796
20841
|
sdkVersion
|
|
20797
20842
|
}) => async () => {
|
|
20798
|
-
|
|
20799
|
-
|
|
20800
|
-
const directConfig = experiments.getFeatureValue?.(effectiveConfigKey, null);
|
|
20843
|
+
if (experiments && configFeatureKey) {
|
|
20844
|
+
const directConfig = experiments.getFeatureValue?.(configFeatureKey, null);
|
|
20801
20845
|
if (directConfig && typeof directConfig === "object") {
|
|
20802
20846
|
debug("SmartCanvas Config", "Resolved config directly from feature flag", directConfig);
|
|
20803
20847
|
return directConfig;
|
|
@@ -21846,6 +21890,36 @@ Please report this to https://github.com/markedjs/marked.`, e2) {
|
|
|
21846
21890
|
return eventName.replace("$", "posthog.");
|
|
21847
21891
|
}
|
|
21848
21892
|
var INTERACTIVE_TAGS = /* @__PURE__ */ new Set(["a", "button", "input", "select", "textarea"]);
|
|
21893
|
+
function parseElementsChain(chain) {
|
|
21894
|
+
if (!chain)
|
|
21895
|
+
return void 0;
|
|
21896
|
+
return chain.split(";").map((segment) => {
|
|
21897
|
+
const el = {};
|
|
21898
|
+
const colonIdx = segment.indexOf(":");
|
|
21899
|
+
const tagPart = colonIdx >= 0 ? segment.slice(0, colonIdx) : segment;
|
|
21900
|
+
const attrPart = colonIdx >= 0 ? segment.slice(colonIdx + 1) : "";
|
|
21901
|
+
const dotIdx = tagPart.indexOf(".");
|
|
21902
|
+
if (dotIdx >= 0) {
|
|
21903
|
+
el.tag_name = tagPart.slice(0, dotIdx);
|
|
21904
|
+
el.attr__class = tagPart.slice(dotIdx + 1).replace(/\./g, " ");
|
|
21905
|
+
} else {
|
|
21906
|
+
el.tag_name = tagPart;
|
|
21907
|
+
}
|
|
21908
|
+
const attrRegex = /([\w$]+)="([^"]*)"/g;
|
|
21909
|
+
let match;
|
|
21910
|
+
while ((match = attrRegex.exec(attrPart)) !== null) {
|
|
21911
|
+
const [, key, value] = match;
|
|
21912
|
+
if (key === "nth-child" || key === "nth-of-type")
|
|
21913
|
+
continue;
|
|
21914
|
+
el[key] = value;
|
|
21915
|
+
}
|
|
21916
|
+
if (el.text) {
|
|
21917
|
+
el.$el_text = el.text;
|
|
21918
|
+
delete el.text;
|
|
21919
|
+
}
|
|
21920
|
+
return el;
|
|
21921
|
+
});
|
|
21922
|
+
}
|
|
21849
21923
|
function resolveInteractiveTag(elements2, directTag) {
|
|
21850
21924
|
if (directTag && INTERACTIVE_TAGS.has(directTag))
|
|
21851
21925
|
return directTag;
|
|
@@ -21861,7 +21935,7 @@ Please report this to https://github.com/markedjs/marked.`, e2) {
|
|
|
21861
21935
|
function extractProps(phEvent) {
|
|
21862
21936
|
const props = {};
|
|
21863
21937
|
const phProps = phEvent.properties || {};
|
|
21864
|
-
const elements2 = phProps.$elements;
|
|
21938
|
+
const elements2 = phProps.$elements ?? (typeof phProps.$elements_chain === "string" ? parseElementsChain(phProps.$elements_chain) : void 0);
|
|
21865
21939
|
const directTag = phProps.$tag_name ?? elements2?.[0]?.tag_name;
|
|
21866
21940
|
const isClickEvent = phEvent.event === "$autocapture" || phEvent.event === "$click";
|
|
21867
21941
|
props.tagName = isClickEvent ? resolveInteractiveTag(elements2, directTag) : directTag;
|
|
@@ -21869,6 +21943,9 @@ Please report this to https://github.com/markedjs/marked.`, e2) {
|
|
|
21869
21943
|
props.elementText = phProps.$el_text;
|
|
21870
21944
|
if (elements2)
|
|
21871
21945
|
props.elements = elements2;
|
|
21946
|
+
if (isClickEvent && !elements2) {
|
|
21947
|
+
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}`);
|
|
21948
|
+
}
|
|
21872
21949
|
if (phProps.$current_url)
|
|
21873
21950
|
props.url = phProps.$current_url;
|
|
21874
21951
|
if (phProps.$pathname)
|
|
@@ -23454,6 +23531,19 @@ ${cssRules}
|
|
|
23454
23531
|
}
|
|
23455
23532
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { ref: parentRef });
|
|
23456
23533
|
}
|
|
23534
|
+
var INTERACTION_PATTERNS = [
|
|
23535
|
+
":toggled",
|
|
23536
|
+
":clicked",
|
|
23537
|
+
":feedback",
|
|
23538
|
+
":navigate",
|
|
23539
|
+
":expanded",
|
|
23540
|
+
":collapsed",
|
|
23541
|
+
":dismissed",
|
|
23542
|
+
":submitted",
|
|
23543
|
+
":interacted",
|
|
23544
|
+
":tip_clicked",
|
|
23545
|
+
":tip_focused"
|
|
23546
|
+
];
|
|
23457
23547
|
function TileCard({
|
|
23458
23548
|
config,
|
|
23459
23549
|
surface: _surface,
|
|
@@ -23462,10 +23552,35 @@ ${cssRules}
|
|
|
23462
23552
|
}) {
|
|
23463
23553
|
const { title, subtitle, widget, props, icon } = config;
|
|
23464
23554
|
const [, setTick] = (0, import_react13.useState)(0);
|
|
23555
|
+
const articleRef = (0, import_react13.useRef)(null);
|
|
23465
23556
|
const runtime7 = useRuntime();
|
|
23466
23557
|
(0, import_react13.useEffect)(() => {
|
|
23467
23558
|
if (runtime7) setTick((t2) => t2 + 1);
|
|
23468
23559
|
}, [runtime7]);
|
|
23560
|
+
(0, import_react13.useEffect)(() => {
|
|
23561
|
+
const tracker = typeof window !== "undefined" ? window.SynOS?.interventionTracker : null;
|
|
23562
|
+
if (!articleRef.current || !tracker) return;
|
|
23563
|
+
const observer2 = new IntersectionObserver(
|
|
23564
|
+
([entry]) => {
|
|
23565
|
+
if (entry.isIntersecting) {
|
|
23566
|
+
tracker.trackSeen(config.id, config.widget ?? "unknown");
|
|
23567
|
+
observer2.disconnect();
|
|
23568
|
+
}
|
|
23569
|
+
},
|
|
23570
|
+
{ threshold: 0.5 }
|
|
23571
|
+
);
|
|
23572
|
+
observer2.observe(articleRef.current);
|
|
23573
|
+
return () => observer2.disconnect();
|
|
23574
|
+
}, [config.id, config.widget]);
|
|
23575
|
+
(0, import_react13.useEffect)(() => {
|
|
23576
|
+
const tracker = typeof window !== "undefined" ? window.SynOS?.interventionTracker : null;
|
|
23577
|
+
if (!runtime7?.events || !tracker) return;
|
|
23578
|
+
return runtime7.events.subscribe((event) => {
|
|
23579
|
+
if (!INTERACTION_PATTERNS.some((p2) => event.name?.includes(p2))) return;
|
|
23580
|
+
if (event.props?.instanceId !== config.id) return;
|
|
23581
|
+
tracker.trackInteracted(config.id, config.widget ?? "unknown", event.name);
|
|
23582
|
+
});
|
|
23583
|
+
}, [runtime7?.events, config.id, config.widget]);
|
|
23469
23584
|
const registration = (0, import_react13.useMemo)(
|
|
23470
23585
|
() => runtime7?.widgets?.getRegistration?.(widget),
|
|
23471
23586
|
[runtime7?.widgets, widget]
|
|
@@ -23514,6 +23629,7 @@ ${cssRules}
|
|
|
23514
23629
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
23515
23630
|
"article",
|
|
23516
23631
|
{
|
|
23632
|
+
ref: articleRef,
|
|
23517
23633
|
"data-shadow-canvas-id": `tile-${config.id}`,
|
|
23518
23634
|
style: cardStyle,
|
|
23519
23635
|
onMouseEnter,
|
|
@@ -23584,7 +23700,6 @@ ${cssRules}
|
|
|
23584
23700
|
onToggle,
|
|
23585
23701
|
telemetry,
|
|
23586
23702
|
launcherLabel: _launcherLabel = "Adaptives",
|
|
23587
|
-
launcherIcon,
|
|
23588
23703
|
launcherAnimate = false,
|
|
23589
23704
|
launcherAnimationStyle: _launcherAnimationStyle = "pulse",
|
|
23590
23705
|
notificationCount: _notificationCount,
|
|
@@ -23989,10 +24104,10 @@ ${cssRules}
|
|
|
23989
24104
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M6 6l12 12" })
|
|
23990
24105
|
]
|
|
23991
24106
|
}
|
|
23992
|
-
) :
|
|
24107
|
+
) : config.launcher?.icon ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
23993
24108
|
"img",
|
|
23994
24109
|
{
|
|
23995
|
-
src:
|
|
24110
|
+
src: config.launcher.icon,
|
|
23996
24111
|
alt: "",
|
|
23997
24112
|
"aria-hidden": "true",
|
|
23998
24113
|
style: {
|
|
@@ -24085,6 +24200,13 @@ ${cssRules}
|
|
|
24085
24200
|
// src/hooks/useShadowCanvasConfig.ts
|
|
24086
24201
|
var import_react15 = __toESM(require_react(), 1);
|
|
24087
24202
|
var sortTiles = (tiles) => [...tiles].sort((a2, b3) => (b3.priority ?? 0) - (a2.priority ?? 0));
|
|
24203
|
+
function fireTriggeredForTiles(tiles) {
|
|
24204
|
+
const tracker = typeof window !== "undefined" ? window.SynOS?.interventionTracker : null;
|
|
24205
|
+
if (!tracker) return;
|
|
24206
|
+
for (const tile of tiles) {
|
|
24207
|
+
tracker.trackTriggered(tile.id, tile.widget ?? "unknown");
|
|
24208
|
+
}
|
|
24209
|
+
}
|
|
24088
24210
|
function useShadowCanvasConfig({
|
|
24089
24211
|
fetcher,
|
|
24090
24212
|
experiments,
|
|
@@ -24107,6 +24229,7 @@ ${cssRules}
|
|
|
24107
24229
|
if (experiments) {
|
|
24108
24230
|
tiles = tiles.filter((tile) => experiments.shouldRenderRectangle(tile));
|
|
24109
24231
|
}
|
|
24232
|
+
fireTriggeredForTiles(tiles);
|
|
24110
24233
|
setState((prev) => ({ ...prev, tiles: sortTiles(tiles) }));
|
|
24111
24234
|
}, [runtime7, experiments]);
|
|
24112
24235
|
const load = (0, import_react15.useCallback)(async () => {
|
|
@@ -24124,6 +24247,7 @@ ${cssRules}
|
|
|
24124
24247
|
} else if (experiments) {
|
|
24125
24248
|
tiles = tiles.filter((tile) => experiments.shouldRenderRectangle(tile));
|
|
24126
24249
|
}
|
|
24250
|
+
fireTriggeredForTiles(tiles);
|
|
24127
24251
|
debug("SmartCanvas Config", `Tile count after filtering: ${tiles.length}`);
|
|
24128
24252
|
const newActions = response.actions || [];
|
|
24129
24253
|
const newActionsJson = JSON.stringify(newActions);
|
|
@@ -24328,6 +24452,7 @@ ${cssRules}
|
|
|
24328
24452
|
const batchHandleRef = (0, import_react16.useRef)(initialBatchHandle ?? null);
|
|
24329
24453
|
const adoptedInitialRef = (0, import_react16.useRef)(!!initialBatchHandle);
|
|
24330
24454
|
const runVersionRef = (0, import_react16.useRef)(0);
|
|
24455
|
+
const pendingRevertRef = (0, import_react16.useRef)(null);
|
|
24331
24456
|
(0, import_react16.useEffect)(() => {
|
|
24332
24457
|
if (!runtime7?.actions) return;
|
|
24333
24458
|
if (adoptedInitialRef.current) {
|
|
@@ -24339,6 +24464,10 @@ ${cssRules}
|
|
|
24339
24464
|
const version = ++runVersionRef.current;
|
|
24340
24465
|
const stale = () => version !== runVersionRef.current;
|
|
24341
24466
|
const run = async () => {
|
|
24467
|
+
if (pendingRevertRef.current) {
|
|
24468
|
+
await pendingRevertRef.current;
|
|
24469
|
+
pendingRevertRef.current = null;
|
|
24470
|
+
}
|
|
24342
24471
|
if (batchHandleRef.current) {
|
|
24343
24472
|
try {
|
|
24344
24473
|
await batchHandleRef.current.revertAll();
|
|
@@ -24366,7 +24495,7 @@ ${cssRules}
|
|
|
24366
24495
|
run();
|
|
24367
24496
|
return () => {
|
|
24368
24497
|
if (batchHandleRef.current) {
|
|
24369
|
-
batchHandleRef.current.revertAll().catch((err) => {
|
|
24498
|
+
pendingRevertRef.current = batchHandleRef.current.revertAll().catch((err) => {
|
|
24370
24499
|
console.error("[SmartCanvasApp] Failed to revert actions on cleanup:", err);
|
|
24371
24500
|
});
|
|
24372
24501
|
batchHandleRef.current = null;
|
|
@@ -24397,7 +24526,6 @@ ${cssRules}
|
|
|
24397
24526
|
canvasTitle: configState.canvasTitle,
|
|
24398
24527
|
telemetry,
|
|
24399
24528
|
launcherLabel: launcherLabel ?? configState.launcher?.label,
|
|
24400
|
-
launcherIcon: configState.launcher?.icon,
|
|
24401
24529
|
launcherAnimate: configState.launcher?.animate,
|
|
24402
24530
|
launcherAnimationStyle: configState.launcher?.animationStyle,
|
|
24403
24531
|
notificationCount: configState.launcher?.notificationCount ?? configState.tiles.length,
|
|
@@ -36991,32 +37119,7 @@ ${cssRules}
|
|
|
36991
37119
|
// Capture performance metrics
|
|
36992
37120
|
capture_performance: true,
|
|
36993
37121
|
// Enable web vitals
|
|
36994
|
-
enable_recording_console_log: true
|
|
36995
|
-
// Bootstrap callback for when flags are loaded
|
|
36996
|
-
loaded: (ph) => {
|
|
36997
|
-
if (enableFeatureFlags && this.featureFlagsCallback) {
|
|
36998
|
-
ph.onFeatureFlags(() => {
|
|
36999
|
-
const allFlags = this.getAllFeatureFlags();
|
|
37000
|
-
if (allFlags && this.featureFlagsCallback) {
|
|
37001
|
-
this.featureFlagsCallback(allFlags);
|
|
37002
|
-
}
|
|
37003
|
-
});
|
|
37004
|
-
const existingFlags = this.getAllFeatureFlags();
|
|
37005
|
-
if (existingFlags && Object.keys(existingFlags).length > 0) {
|
|
37006
|
-
this.featureFlagsCallback(existingFlags);
|
|
37007
|
-
}
|
|
37008
|
-
}
|
|
37009
|
-
if (this.captureCallback) {
|
|
37010
|
-
ph.on("eventCaptured", (...args) => {
|
|
37011
|
-
const data = args[0];
|
|
37012
|
-
const eventName = typeof data === "string" ? data : data?.event;
|
|
37013
|
-
const properties = typeof data === "string" ? void 0 : data?.properties;
|
|
37014
|
-
if (typeof eventName === "string") {
|
|
37015
|
-
this.captureCallback?.(eventName, properties);
|
|
37016
|
-
}
|
|
37017
|
-
});
|
|
37018
|
-
}
|
|
37019
|
-
}
|
|
37122
|
+
enable_recording_console_log: true
|
|
37020
37123
|
};
|
|
37021
37124
|
const result = Jo.init(
|
|
37022
37125
|
options.apiKey,
|
|
@@ -37026,6 +37129,28 @@ ${cssRules}
|
|
|
37026
37129
|
if (result) {
|
|
37027
37130
|
this.client = result;
|
|
37028
37131
|
}
|
|
37132
|
+
if (this.captureCallback && this.client) {
|
|
37133
|
+
this.client.on("eventCaptured", (...args) => {
|
|
37134
|
+
const data = args[0];
|
|
37135
|
+
const eventName = typeof data === "string" ? data : data?.event;
|
|
37136
|
+
const properties = typeof data === "string" ? void 0 : data?.properties;
|
|
37137
|
+
if (typeof eventName === "string") {
|
|
37138
|
+
this.captureCallback?.(eventName, properties);
|
|
37139
|
+
}
|
|
37140
|
+
});
|
|
37141
|
+
}
|
|
37142
|
+
if (enableFeatureFlags && this.featureFlagsCallback && this.client) {
|
|
37143
|
+
this.client.onFeatureFlags(() => {
|
|
37144
|
+
const allFlags = this.getAllFeatureFlags();
|
|
37145
|
+
if (allFlags && this.featureFlagsCallback) {
|
|
37146
|
+
this.featureFlagsCallback(allFlags);
|
|
37147
|
+
}
|
|
37148
|
+
});
|
|
37149
|
+
const existingFlags = this.getAllFeatureFlags();
|
|
37150
|
+
if (existingFlags && Object.keys(existingFlags).length > 0) {
|
|
37151
|
+
this.featureFlagsCallback(existingFlags);
|
|
37152
|
+
}
|
|
37153
|
+
}
|
|
37029
37154
|
if (this.rrwebCallback && this.client) {
|
|
37030
37155
|
this.setupRRWebIntercept();
|
|
37031
37156
|
}
|
|
@@ -37150,6 +37275,55 @@ ${cssRules}
|
|
|
37150
37275
|
return new PostHogAdapter(options);
|
|
37151
37276
|
}
|
|
37152
37277
|
|
|
37278
|
+
// src/telemetry/InterventionTracker.ts
|
|
37279
|
+
var InterventionTracker = class {
|
|
37280
|
+
constructor(telemetry, variantId) {
|
|
37281
|
+
__publicField(this, "telemetry");
|
|
37282
|
+
__publicField(this, "variantId");
|
|
37283
|
+
__publicField(this, "seenSet", /* @__PURE__ */ new Set());
|
|
37284
|
+
__publicField(this, "triggeredSet", /* @__PURE__ */ new Set());
|
|
37285
|
+
this.telemetry = telemetry;
|
|
37286
|
+
this.variantId = variantId;
|
|
37287
|
+
}
|
|
37288
|
+
trackServed(tiles, actions) {
|
|
37289
|
+
this.telemetry.track?.("syntro_config_served", {
|
|
37290
|
+
variant_id: this.variantId,
|
|
37291
|
+
tiles,
|
|
37292
|
+
actions
|
|
37293
|
+
});
|
|
37294
|
+
}
|
|
37295
|
+
trackSeen(interventionId, interventionKind) {
|
|
37296
|
+
if (this.seenSet.has(interventionId)) return;
|
|
37297
|
+
this.seenSet.add(interventionId);
|
|
37298
|
+
this.telemetry.track?.("syntro_intervention_seen", {
|
|
37299
|
+
variant_id: this.variantId,
|
|
37300
|
+
intervention_id: interventionId,
|
|
37301
|
+
intervention_kind: interventionKind
|
|
37302
|
+
});
|
|
37303
|
+
}
|
|
37304
|
+
trackTriggered(interventionId, interventionKind) {
|
|
37305
|
+
if (this.triggeredSet.has(interventionId)) return;
|
|
37306
|
+
this.triggeredSet.add(interventionId);
|
|
37307
|
+
this.telemetry.track?.("syntro_intervention_triggered", {
|
|
37308
|
+
variant_id: this.variantId,
|
|
37309
|
+
intervention_id: interventionId,
|
|
37310
|
+
intervention_kind: interventionKind
|
|
37311
|
+
});
|
|
37312
|
+
}
|
|
37313
|
+
trackInteracted(interventionId, interventionKind, interactionType) {
|
|
37314
|
+
this.telemetry.track?.("syntro_intervention_interacted", {
|
|
37315
|
+
variant_id: this.variantId,
|
|
37316
|
+
intervention_id: interventionId,
|
|
37317
|
+
intervention_kind: interventionKind,
|
|
37318
|
+
interaction_type: interactionType
|
|
37319
|
+
});
|
|
37320
|
+
}
|
|
37321
|
+
resetPage() {
|
|
37322
|
+
this.seenSet.clear();
|
|
37323
|
+
this.triggeredSet.clear();
|
|
37324
|
+
}
|
|
37325
|
+
};
|
|
37326
|
+
|
|
37153
37327
|
// src/actions/executors/core-flow.ts
|
|
37154
37328
|
var executeSequence = async (action, context) => {
|
|
37155
37329
|
const handles = [];
|
|
@@ -38298,15 +38472,30 @@ ${cssRules}
|
|
|
38298
38472
|
const handles = [];
|
|
38299
38473
|
const appliedHandles = [];
|
|
38300
38474
|
try {
|
|
38301
|
-
|
|
38302
|
-
|
|
38303
|
-
|
|
38304
|
-
|
|
38475
|
+
const results = await Promise.allSettled(actions.map((action) => apply(action)));
|
|
38476
|
+
const errors = [];
|
|
38477
|
+
for (const result of results) {
|
|
38478
|
+
if (result.status === "fulfilled") {
|
|
38479
|
+
handles.push(result.value);
|
|
38480
|
+
appliedHandles.push(result.value);
|
|
38481
|
+
} else {
|
|
38482
|
+
errors.push(
|
|
38483
|
+
result.reason instanceof Error ? result.reason : new Error(String(result.reason))
|
|
38484
|
+
);
|
|
38485
|
+
}
|
|
38486
|
+
}
|
|
38487
|
+
if (errors.length > 0 && appliedHandles.length === 0) {
|
|
38488
|
+
throw errors[0];
|
|
38489
|
+
}
|
|
38490
|
+
if (errors.length > 0) {
|
|
38491
|
+
console.warn(
|
|
38492
|
+
`[ActionEngine] ${errors.length}/${actions.length} action(s) failed in batch:`,
|
|
38493
|
+
errors.map((e2) => e2.message).join("; ")
|
|
38494
|
+
);
|
|
38305
38495
|
}
|
|
38306
38496
|
} catch (error2) {
|
|
38307
38497
|
console.error(
|
|
38308
|
-
`[ActionEngine] Batch apply FAILED
|
|
38309
|
-
`Successfully applied: ${appliedHandles.length}. Rolling back...`,
|
|
38498
|
+
`[ActionEngine] Batch apply FAILED. Successfully applied: ${appliedHandles.length}. Rolling back...`,
|
|
38310
38499
|
error2
|
|
38311
38500
|
);
|
|
38312
38501
|
for (const handle of appliedHandles) {
|
|
@@ -38382,74 +38571,97 @@ ${cssRules}
|
|
|
38382
38571
|
selector: external_exports.string(),
|
|
38383
38572
|
route: external_exports.union([external_exports.string(), external_exports.array(external_exports.string())])
|
|
38384
38573
|
}).strict();
|
|
38574
|
+
var COUNTABLE_EVENTS = [
|
|
38575
|
+
// User interactions (from PostHog autocapture normalization)
|
|
38576
|
+
"ui.click",
|
|
38577
|
+
"ui.scroll",
|
|
38578
|
+
"ui.input",
|
|
38579
|
+
"ui.change",
|
|
38580
|
+
"ui.submit",
|
|
38581
|
+
// Behavioral detectors (from event-processor)
|
|
38582
|
+
"ui.hover",
|
|
38583
|
+
"ui.idle",
|
|
38584
|
+
"ui.scroll_thrash",
|
|
38585
|
+
"ui.focus_bounce",
|
|
38586
|
+
// Navigation
|
|
38587
|
+
"nav.page_view",
|
|
38588
|
+
"nav.page_leave",
|
|
38589
|
+
// Derived behavioral signals
|
|
38590
|
+
"behavior.rage_click",
|
|
38591
|
+
"behavior.hesitation",
|
|
38592
|
+
"behavior.confusion"
|
|
38593
|
+
];
|
|
38594
|
+
var CountableEventZ = external_exports.enum(COUNTABLE_EVENTS).describe("Event name to count. ui.* = user interactions and behavioral detectors, nav.* = page navigation, behavior.* = derived behavioral signals.");
|
|
38595
|
+
var SESSION_METRIC_KEYS = ["time_on_page", "page_views", "scroll_depth"];
|
|
38596
|
+
var SessionMetricKeyZ = external_exports.enum(SESSION_METRIC_KEYS).describe("Session metric key. time_on_page = seconds on current page, page_views = pages visited this session, scroll_depth = 0-100 percentage.");
|
|
38385
38597
|
var PageUrlConditionZ = external_exports.object({
|
|
38386
38598
|
type: external_exports.literal("page_url"),
|
|
38387
|
-
url: external_exports.string()
|
|
38388
|
-
});
|
|
38599
|
+
url: external_exports.string().describe('URL path to match (e.g. "/pricing", "/dashboard")')
|
|
38600
|
+
}).describe('Fires when the current page URL matches. Use for page-specific actions. Example: {"type": "page_url", "url": "/pricing"}');
|
|
38389
38601
|
var RouteConditionZ = external_exports.object({
|
|
38390
38602
|
type: external_exports.literal("route"),
|
|
38391
|
-
routeId: external_exports.string()
|
|
38392
|
-
});
|
|
38603
|
+
routeId: external_exports.string().describe("Named route ID from the route filter")
|
|
38604
|
+
}).describe("Fires when the current route matches a named route ID.");
|
|
38393
38605
|
var AnchorVisibleConditionZ = external_exports.object({
|
|
38394
38606
|
type: external_exports.literal("anchor_visible"),
|
|
38395
|
-
anchorId: external_exports.string(),
|
|
38396
|
-
state: external_exports.enum(["visible", "present", "absent"])
|
|
38397
|
-
});
|
|
38607
|
+
anchorId: external_exports.string().describe("CSS selector of the anchor element"),
|
|
38608
|
+
state: external_exports.enum(["visible", "present", "absent"]).describe('"visible" = in viewport, "present" = in DOM, "absent" = not in DOM')
|
|
38609
|
+
}).describe(`Fires based on a DOM element's visibility state. Example: {"type": "anchor_visible", "anchorId": "#cta-button", "state": "visible"}`);
|
|
38398
38610
|
var EventOccurredConditionZ = external_exports.object({
|
|
38399
38611
|
type: external_exports.literal("event_occurred"),
|
|
38400
|
-
eventName: external_exports.string(),
|
|
38401
|
-
withinMs: external_exports.number().optional()
|
|
38402
|
-
});
|
|
38612
|
+
eventName: external_exports.string().describe('Event name (e.g. "ui.click", "$pageview")'),
|
|
38613
|
+
withinMs: external_exports.number().optional().describe("Time window in ms. Omit = any time this session.")
|
|
38614
|
+
}).describe('Fires when a specific event has occurred during this session. Example: {"type": "event_occurred", "eventName": "ui.click", "withinMs": 5000}');
|
|
38403
38615
|
var StateEqualsConditionZ = external_exports.object({
|
|
38404
38616
|
type: external_exports.literal("state_equals"),
|
|
38405
|
-
key: external_exports.string(),
|
|
38406
|
-
value: external_exports.unknown()
|
|
38407
|
-
});
|
|
38617
|
+
key: external_exports.string().describe("Key in the SDK persistent state store (localStorage). Only valid for keys the host app explicitly sets via syntro.state.set()."),
|
|
38618
|
+
value: external_exports.unknown().describe("Expected value to match against")
|
|
38619
|
+
}).describe("Checks the SDK persistent state store (localStorage). ONLY for host-app state set via syntro.state.set() \u2014 NOT for user attributes like region, device, or UTM params (those are handled by segment targeting). Do NOT use this for targeting. If you do not know the valid state keys, do not use this condition type.");
|
|
38408
38620
|
var ViewportConditionZ = external_exports.object({
|
|
38409
38621
|
type: external_exports.literal("viewport"),
|
|
38410
|
-
minWidth: external_exports.number().optional(),
|
|
38411
|
-
maxWidth: external_exports.number().optional(),
|
|
38412
|
-
minHeight: external_exports.number().optional(),
|
|
38413
|
-
maxHeight: external_exports.number().optional()
|
|
38414
|
-
});
|
|
38622
|
+
minWidth: external_exports.number().optional().describe("Minimum viewport width in pixels"),
|
|
38623
|
+
maxWidth: external_exports.number().optional().describe("Maximum viewport width in pixels"),
|
|
38624
|
+
minHeight: external_exports.number().optional().describe("Minimum viewport height in pixels"),
|
|
38625
|
+
maxHeight: external_exports.number().optional().describe("Maximum viewport height in pixels")
|
|
38626
|
+
}).describe('Fires based on viewport (screen) size. Use for responsive behavior. Example: {"type": "viewport", "minWidth": 768} \u2014 fires on tablet and larger.');
|
|
38415
38627
|
var SessionMetricConditionZ = external_exports.object({
|
|
38416
38628
|
type: external_exports.literal("session_metric"),
|
|
38417
|
-
key:
|
|
38629
|
+
key: SessionMetricKeyZ,
|
|
38418
38630
|
operator: external_exports.enum(["gte", "lte", "eq", "gt", "lt"]),
|
|
38419
|
-
threshold: external_exports.number()
|
|
38420
|
-
});
|
|
38631
|
+
threshold: external_exports.number().describe("Numeric threshold to compare against")
|
|
38632
|
+
}).describe('Fires when a session metric crosses a threshold. Valid keys: "time_on_page" (seconds), "page_views" (count), "scroll_depth" (0-100). Example: {"type": "session_metric", "key": "time_on_page", "operator": "gte", "threshold": 30}');
|
|
38421
38633
|
var DismissedConditionZ = external_exports.object({
|
|
38422
38634
|
type: external_exports.literal("dismissed"),
|
|
38423
|
-
key: external_exports.string(),
|
|
38424
|
-
inverted: external_exports.boolean().optional()
|
|
38425
|
-
});
|
|
38635
|
+
key: external_exports.string().describe("Dismissal key (usually a tile or action ID)"),
|
|
38636
|
+
inverted: external_exports.boolean().optional().describe("When true, fires if NOT dismissed (default behavior)")
|
|
38637
|
+
}).describe("Checks if an item has been dismissed by the user. Use with inverted: true to show only if not dismissed.");
|
|
38426
38638
|
var CooldownActiveConditionZ = external_exports.object({
|
|
38427
38639
|
type: external_exports.literal("cooldown_active"),
|
|
38428
|
-
key: external_exports.string(),
|
|
38429
|
-
inverted: external_exports.boolean().optional()
|
|
38430
|
-
});
|
|
38640
|
+
key: external_exports.string().describe("Cooldown key"),
|
|
38641
|
+
inverted: external_exports.boolean().optional().describe("When true, fires if cooldown is NOT active")
|
|
38642
|
+
}).describe("Checks if a cooldown timer is currently active. Use to prevent showing the same intervention too frequently.");
|
|
38431
38643
|
var FrequencyLimitConditionZ = external_exports.object({
|
|
38432
38644
|
type: external_exports.literal("frequency_limit"),
|
|
38433
|
-
key: external_exports.string(),
|
|
38434
|
-
limit: external_exports.number(),
|
|
38435
|
-
inverted: external_exports.boolean().optional()
|
|
38436
|
-
});
|
|
38645
|
+
key: external_exports.string().describe("Frequency counter key"),
|
|
38646
|
+
limit: external_exports.number().describe("Maximum allowed count"),
|
|
38647
|
+
inverted: external_exports.boolean().optional().describe("When true, fires if limit NOT reached")
|
|
38648
|
+
}).describe("Checks if a frequency limit has been reached. Use to cap how many times an action fires per session.");
|
|
38437
38649
|
var MatchOpZ = external_exports.object({
|
|
38438
38650
|
equals: external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()]).optional(),
|
|
38439
38651
|
contains: external_exports.string().optional()
|
|
38440
|
-
});
|
|
38652
|
+
}).describe("Match operator for counter filters. Exactly one of equals or contains must be specified.");
|
|
38441
38653
|
var CounterDefZ = external_exports.object({
|
|
38442
|
-
events: external_exports.array(
|
|
38443
|
-
match: external_exports.record(external_exports.string(), MatchOpZ).optional()
|
|
38444
|
-
});
|
|
38654
|
+
events: external_exports.array(CountableEventZ).min(1).describe("Event names to count. Use values from the countable events enum."),
|
|
38655
|
+
match: external_exports.record(external_exports.string(), MatchOpZ).optional().describe("Property filters. Keys are event prop names or element-chain fields (tag_name, $el_text, attr__*). All entries AND together.")
|
|
38656
|
+
}).describe("Defines what events to count. Registered as an accumulator predicate at config-load time.");
|
|
38445
38657
|
var EventCountConditionZ = external_exports.object({
|
|
38446
38658
|
type: external_exports.literal("event_count"),
|
|
38447
|
-
key: external_exports.string(),
|
|
38659
|
+
key: external_exports.string().describe("Unique key for this counter (used for accumulator registration)"),
|
|
38448
38660
|
operator: external_exports.enum(["gte", "lte", "eq", "gt", "lt"]),
|
|
38449
|
-
count: external_exports.number().int().min(0),
|
|
38450
|
-
withinMs: external_exports.number().positive().optional(),
|
|
38451
|
-
counter: CounterDefZ.optional()
|
|
38452
|
-
});
|
|
38661
|
+
count: external_exports.number().int().min(0).describe("Target count threshold"),
|
|
38662
|
+
withinMs: external_exports.number().positive().optional().describe("Time window in ms. Omit = count across entire session."),
|
|
38663
|
+
counter: CounterDefZ.optional().describe("Inline counter definition. Defines what events to count.")
|
|
38664
|
+
}).describe('Fires when accumulated event count crosses a threshold. Most powerful trigger type. Example: {"type": "event_count", "key": "pricing-clicks", "operator": "gte", "count": 3, "counter": {"events": ["ui.click"], "match": {"attr__data-cta": {"contains": "pricing"}}}}');
|
|
38453
38665
|
var ConditionZ = external_exports.discriminatedUnion("type", [
|
|
38454
38666
|
PageUrlConditionZ,
|
|
38455
38667
|
RouteConditionZ,
|
|
@@ -38464,35 +38676,35 @@ ${cssRules}
|
|
|
38464
38676
|
EventCountConditionZ
|
|
38465
38677
|
]);
|
|
38466
38678
|
var RuleZ = external_exports.object({
|
|
38467
|
-
conditions: external_exports.array(ConditionZ),
|
|
38468
|
-
value: external_exports.unknown()
|
|
38469
|
-
});
|
|
38679
|
+
conditions: external_exports.array(ConditionZ).describe("Array of conditions \u2014 ALL must match (AND logic) for this rule to fire."),
|
|
38680
|
+
value: external_exports.unknown().describe("Value returned when all conditions match. For triggerWhen: true = fire the action.")
|
|
38681
|
+
}).describe("A single rule. ALL conditions must match (AND logic). Rules in a strategy are evaluated top-to-bottom \u2014 first rule where all conditions match wins and returns its value.");
|
|
38470
38682
|
var RuleStrategyZ = external_exports.object({
|
|
38471
38683
|
type: external_exports.literal("rules"),
|
|
38472
|
-
rules: external_exports.array(RuleZ),
|
|
38473
|
-
default: external_exports.unknown()
|
|
38474
|
-
});
|
|
38684
|
+
rules: external_exports.array(RuleZ).describe("Ordered list of rules. Evaluated top-to-bottom \u2014 first match wins."),
|
|
38685
|
+
default: external_exports.unknown().describe("Fallback value when no rule matches. For triggerWhen: false = do not fire by default.")
|
|
38686
|
+
}).describe("Rule-based strategy. Evaluates rules top-to-bottom. First rule where ALL conditions match returns its value. If no rule matches, returns default. For triggerWhen: set value=true on matching rules, default=false.");
|
|
38475
38687
|
var ScoreStrategyZ = external_exports.object({
|
|
38476
38688
|
type: external_exports.literal("score"),
|
|
38477
38689
|
field: external_exports.string(),
|
|
38478
38690
|
threshold: external_exports.number(),
|
|
38479
38691
|
above: external_exports.unknown(),
|
|
38480
38692
|
below: external_exports.unknown()
|
|
38481
|
-
});
|
|
38693
|
+
}).describe("Score-based strategy. Compares a field value against a threshold.");
|
|
38482
38694
|
var ModelStrategyZ = external_exports.object({
|
|
38483
38695
|
type: external_exports.literal("model"),
|
|
38484
38696
|
modelId: external_exports.string(),
|
|
38485
38697
|
inputs: external_exports.array(external_exports.string()),
|
|
38486
38698
|
outputMapping: external_exports.record(external_exports.string(), external_exports.unknown()),
|
|
38487
38699
|
default: external_exports.unknown()
|
|
38488
|
-
});
|
|
38700
|
+
}).describe("ML model strategy. Sends inputs to a model and maps outputs.");
|
|
38489
38701
|
var ExternalStrategyZ = external_exports.object({
|
|
38490
38702
|
type: external_exports.literal("external"),
|
|
38491
38703
|
endpoint: external_exports.string(),
|
|
38492
38704
|
method: external_exports.enum(["GET", "POST"]).optional(),
|
|
38493
38705
|
default: external_exports.unknown(),
|
|
38494
38706
|
timeoutMs: external_exports.number().optional()
|
|
38495
|
-
});
|
|
38707
|
+
}).describe("External API strategy. Calls an endpoint to determine the value.");
|
|
38496
38708
|
var DecisionStrategyZ = external_exports.discriminatedUnion("type", [
|
|
38497
38709
|
RuleStrategyZ,
|
|
38498
38710
|
ScoreStrategyZ,
|
|
@@ -38588,7 +38800,8 @@ ${cssRules}
|
|
|
38588
38800
|
color: external_exports.string().optional(),
|
|
38589
38801
|
size: external_exports.string().optional(),
|
|
38590
38802
|
shadow: external_exports.string().optional(),
|
|
38591
|
-
borderRadius: external_exports.string().optional()
|
|
38803
|
+
borderRadius: external_exports.string().optional(),
|
|
38804
|
+
icon: external_exports.string().optional()
|
|
38592
38805
|
});
|
|
38593
38806
|
var TileElementConfigZ = external_exports.object({
|
|
38594
38807
|
background: external_exports.string().optional(),
|
|
@@ -38668,7 +38881,6 @@ ${cssRules}
|
|
|
38668
38881
|
var LauncherConfigZ = external_exports.object({
|
|
38669
38882
|
enabled: external_exports.boolean().optional(),
|
|
38670
38883
|
label: external_exports.string().optional(),
|
|
38671
|
-
icon: external_exports.string().optional(),
|
|
38672
38884
|
position: external_exports.string().optional(),
|
|
38673
38885
|
animate: external_exports.boolean().optional(),
|
|
38674
38886
|
animationStyle: external_exports.enum(["pulse", "bounce", "glow"]).optional(),
|
|
@@ -41489,7 +41701,7 @@ ${cssRules}
|
|
|
41489
41701
|
__publicField(this, "manifestKey");
|
|
41490
41702
|
__publicField(this, "variantFlagPrefix");
|
|
41491
41703
|
this.client = options.client;
|
|
41492
|
-
this.featureKey = options.featureKey
|
|
41704
|
+
this.featureKey = options.featureKey;
|
|
41493
41705
|
this.manifestKey = options.manifestKey;
|
|
41494
41706
|
this.variantFlagPrefix = options.variantFlagPrefix;
|
|
41495
41707
|
}
|
|
@@ -41906,6 +42118,26 @@ ${cssRules}
|
|
|
41906
42118
|
const warnedAppFailures = /* @__PURE__ */ new Set();
|
|
41907
42119
|
const appLoadingFetcher = baseFetcher ? async () => {
|
|
41908
42120
|
const config = await baseFetcher();
|
|
42121
|
+
const tileCount = config.tiles?.length ?? 0;
|
|
42122
|
+
const actionCount = config.actions?.length ?? 0;
|
|
42123
|
+
const variantId = config.meta?.variant_id;
|
|
42124
|
+
if (tileCount > 0 || actionCount > 0) {
|
|
42125
|
+
if (!variantId) {
|
|
42126
|
+
console.warn(
|
|
42127
|
+
"[Syntro] Config has content but no meta.variant_id \u2014 intervention tracking disabled"
|
|
42128
|
+
);
|
|
42129
|
+
}
|
|
42130
|
+
}
|
|
42131
|
+
if (telemetry && variantId) {
|
|
42132
|
+
const tracker = new InterventionTracker(telemetry, variantId);
|
|
42133
|
+
tracker.trackServed(tileCount, actionCount);
|
|
42134
|
+
if (typeof window !== "undefined") {
|
|
42135
|
+
window.SynOS.interventionTracker = tracker;
|
|
42136
|
+
}
|
|
42137
|
+
runtime7.navigation.subscribe(() => {
|
|
42138
|
+
tracker.resetPage();
|
|
42139
|
+
});
|
|
42140
|
+
}
|
|
41909
42141
|
console.log(
|
|
41910
42142
|
"[Syntro Bootstrap] Config fetched:",
|
|
41911
42143
|
`tiles=${config.tiles?.length ?? 0},`,
|
|
@@ -42005,7 +42237,7 @@ ${cssRules}
|
|
|
42005
42237
|
}
|
|
42006
42238
|
|
|
42007
42239
|
// src/index.ts
|
|
42008
|
-
var RUNTIME_SDK_BUILD = true ? `${"2026-04-
|
|
42240
|
+
var RUNTIME_SDK_BUILD = true ? `${"2026-04-15T20:50:41.408Z"} (${"acd804e29d3"})` : "dev";
|
|
42009
42241
|
if (typeof window !== "undefined") {
|
|
42010
42242
|
console.log(`[Syntro Runtime] Build: ${RUNTIME_SDK_BUILD}`);
|
|
42011
42243
|
const existing = window.SynOS;
|