@syntrologie/runtime-sdk 2.8.0-canary.191 → 2.8.0-canary.192

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.
@@ -74,13 +74,13 @@ export declare const BoundingBoxZ: z.ZodObject<{
74
74
  }, "strip", z.ZodTypeAny, {
75
75
  x: number;
76
76
  y: number;
77
- w: number;
78
77
  h: number;
78
+ w: number;
79
79
  }, {
80
80
  x: number;
81
81
  y: number;
82
- w: number;
83
82
  h: number;
83
+ w: number;
84
84
  }>;
85
85
  export declare const AnchorStateZ: z.ZodObject<{
86
86
  anchorId: z.ZodString;
@@ -94,13 +94,13 @@ export declare const AnchorStateZ: z.ZodObject<{
94
94
  }, "strip", z.ZodTypeAny, {
95
95
  x: number;
96
96
  y: number;
97
- w: number;
98
97
  h: number;
98
+ w: number;
99
99
  }, {
100
100
  x: number;
101
101
  y: number;
102
- w: number;
103
102
  h: number;
103
+ w: number;
104
104
  }>>;
105
105
  }, "strip", z.ZodTypeAny, {
106
106
  present: boolean;
@@ -109,8 +109,8 @@ export declare const AnchorStateZ: z.ZodObject<{
109
109
  boundingBox?: {
110
110
  x: number;
111
111
  y: number;
112
- w: number;
113
112
  h: number;
113
+ w: number;
114
114
  } | undefined;
115
115
  }, {
116
116
  present: boolean;
@@ -119,8 +119,8 @@ export declare const AnchorStateZ: z.ZodObject<{
119
119
  boundingBox?: {
120
120
  x: number;
121
121
  y: number;
122
- w: number;
123
122
  h: number;
123
+ w: number;
124
124
  } | undefined;
125
125
  }>;
126
126
  export declare const AugmentationZ: z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodNumber, z.ZodString, z.ZodBoolean, z.ZodUndefined]>>;
@@ -191,13 +191,13 @@ export declare const RuntimeContextZ: z.ZodObject<{
191
191
  }, "strip", z.ZodTypeAny, {
192
192
  x: number;
193
193
  y: number;
194
- w: number;
195
194
  h: number;
195
+ w: number;
196
196
  }, {
197
197
  x: number;
198
198
  y: number;
199
- w: number;
200
199
  h: number;
200
+ w: number;
201
201
  }>>;
202
202
  }, "strip", z.ZodTypeAny, {
203
203
  present: boolean;
@@ -206,8 +206,8 @@ export declare const RuntimeContextZ: z.ZodObject<{
206
206
  boundingBox?: {
207
207
  x: number;
208
208
  y: number;
209
- w: number;
210
209
  h: number;
210
+ w: number;
211
211
  } | undefined;
212
212
  }, {
213
213
  present: boolean;
@@ -216,8 +216,8 @@ export declare const RuntimeContextZ: z.ZodObject<{
216
216
  boundingBox?: {
217
217
  x: number;
218
218
  y: number;
219
- w: number;
220
219
  h: number;
220
+ w: number;
221
221
  } | undefined;
222
222
  }>, "many">>;
223
223
  augmented: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodNumber, z.ZodString, z.ZodBoolean, z.ZodUndefined]>>>;
@@ -247,8 +247,8 @@ export declare const RuntimeContextZ: z.ZodObject<{
247
247
  boundingBox?: {
248
248
  x: number;
249
249
  y: number;
250
- w: number;
251
250
  h: number;
251
+ w: number;
252
252
  } | undefined;
253
253
  }[] | undefined;
254
254
  augmented?: Record<string, string | number | boolean | undefined> | undefined;
@@ -278,8 +278,8 @@ export declare const RuntimeContextZ: z.ZodObject<{
278
278
  boundingBox?: {
279
279
  x: number;
280
280
  y: number;
281
- w: number;
282
281
  h: number;
282
+ w: number;
283
283
  } | undefined;
284
284
  }[] | undefined;
285
285
  augmented?: Record<string, string | number | boolean | undefined> | undefined;
@@ -313,8 +313,8 @@ export declare function validateRuntimeContext(data: unknown): z.SafeParseReturn
313
313
  boundingBox?: {
314
314
  x: number;
315
315
  y: number;
316
- w: number;
317
316
  h: number;
317
+ w: number;
318
318
  } | undefined;
319
319
  }[] | undefined;
320
320
  augmented?: Record<string, string | number | boolean | undefined> | undefined;
@@ -344,8 +344,8 @@ export declare function validateRuntimeContext(data: unknown): z.SafeParseReturn
344
344
  boundingBox?: {
345
345
  x: number;
346
346
  y: number;
347
- w: number;
348
347
  h: number;
348
+ w: number;
349
349
  } | undefined;
350
350
  }[] | undefined;
351
351
  augmented?: Record<string, string | number | boolean | undefined> | undefined;
package/dist/index.js CHANGED
@@ -9576,8 +9576,231 @@ function error(prefix, message, data) {
9576
9576
  }
9577
9577
  }
9578
9578
 
9579
+ // src/observability/healthReporter.ts
9580
+ var HealthReporter = class {
9581
+ constructor(config) {
9582
+ this.config = config;
9583
+ __publicField(this, "resource");
9584
+ __publicField(this, "flushIntervalMs");
9585
+ __publicField(this, "counters", /* @__PURE__ */ new Map());
9586
+ __publicField(this, "histograms", /* @__PURE__ */ new Map());
9587
+ __publicField(this, "windowStartMs", Date.now());
9588
+ __publicField(this, "timer", null);
9589
+ __publicField(this, "pagehideHandler", null);
9590
+ __publicField(this, "runtime", null);
9591
+ var _a3;
9592
+ this.resource = config.resource;
9593
+ this.flushIntervalMs = (_a3 = config.flushIntervalMs) != null ? _a3 : 6e4;
9594
+ }
9595
+ /**
9596
+ * Bind runtime-derived attribute resolvers. Called after the canvas/telemetry
9597
+ * are fully initialized. Must never throw — resolvers are wrapped in
9598
+ * null-safe access at flush time.
9599
+ */
9600
+ bindRuntime(binding) {
9601
+ this.runtime = binding;
9602
+ }
9603
+ increment(signal, by = 1) {
9604
+ var _a3;
9605
+ this.counters.set(signal, ((_a3 = this.counters.get(signal)) != null ? _a3 : 0) + by);
9606
+ }
9607
+ /**
9608
+ * @internal — exposed for test inspection only. Mid-window state is intentionally
9609
+ * unstable; consumers should subscribe to flush payloads instead.
9610
+ */
9611
+ snapshotCounters() {
9612
+ const out = {};
9613
+ for (const [k2, v2] of this.counters) out[k2] = v2;
9614
+ return out;
9615
+ }
9616
+ recordHistogram(signal, valueMs) {
9617
+ var _a3;
9618
+ const arr = (_a3 = this.histograms.get(signal)) != null ? _a3 : [];
9619
+ arr.push(valueMs);
9620
+ this.histograms.set(signal, arr);
9621
+ }
9622
+ /**
9623
+ * @internal — exposed for test inspection only. Mid-window state is intentionally
9624
+ * unstable; consumers should subscribe to flush payloads instead.
9625
+ */
9626
+ snapshotHistograms() {
9627
+ const out = {};
9628
+ for (const [k2, samples] of this.histograms) {
9629
+ if (samples.length === 0) continue;
9630
+ const sorted = [...samples].sort((a, b2) => a - b2);
9631
+ out[k2] = {
9632
+ count: sorted.length,
9633
+ p50: percentile(sorted, 0.5),
9634
+ p95: percentile(sorted, 0.95)
9635
+ };
9636
+ }
9637
+ return out;
9638
+ }
9639
+ async flush() {
9640
+ var _a3, _b, _c, _d, _e2, _f, _g, _h;
9641
+ const counters = this.snapshotCounters();
9642
+ const histograms = this.snapshotHistograms();
9643
+ const hasData = Object.keys(counters).length > 0 || Object.keys(histograms).length > 0;
9644
+ if (!hasData) return;
9645
+ let surface = null;
9646
+ let sessionId = "";
9647
+ try {
9648
+ surface = (_b = (_a3 = this.runtime) == null ? void 0 : _a3.getSurface()) != null ? _b : null;
9649
+ } catch {
9650
+ }
9651
+ try {
9652
+ sessionId = (_d = (_c = this.runtime) == null ? void 0 : _c.getSessionId()) != null ? _d : "";
9653
+ } catch {
9654
+ }
9655
+ const payload = {
9656
+ resource: {
9657
+ ...this.resource,
9658
+ sessionId,
9659
+ surfaceType: (_e2 = surface == null ? void 0 : surface.type) != null ? _e2 : "unknown",
9660
+ surfaceHost: (_f = surface == null ? void 0 : surface.host) != null ? _f : "unknown",
9661
+ surfaceDevice: (_g = surface == null ? void 0 : surface.device) != null ? _g : "unknown",
9662
+ surfaceMode: (_h = surface == null ? void 0 : surface.mode) != null ? _h : "unknown"
9663
+ },
9664
+ windowSeconds: Math.max(1, Math.round((Date.now() - this.windowStartMs) / 1e3)),
9665
+ windowStartUnixMs: this.windowStartMs,
9666
+ counters,
9667
+ histograms
9668
+ };
9669
+ this.counters.clear();
9670
+ this.histograms.clear();
9671
+ this.windowStartMs = Date.now();
9672
+ try {
9673
+ await this.config.emit(payload);
9674
+ } catch {
9675
+ }
9676
+ }
9677
+ start() {
9678
+ if (this.timer !== null) return;
9679
+ this.timer = setInterval(() => {
9680
+ void this.flush();
9681
+ }, this.flushIntervalMs);
9682
+ if (typeof window !== "undefined") {
9683
+ this.pagehideHandler = () => {
9684
+ void this.flush();
9685
+ };
9686
+ window.addEventListener("pagehide", this.pagehideHandler);
9687
+ }
9688
+ }
9689
+ stop() {
9690
+ if (this.timer !== null) {
9691
+ clearInterval(this.timer);
9692
+ this.timer = null;
9693
+ }
9694
+ if (this.pagehideHandler !== null && typeof window !== "undefined") {
9695
+ window.removeEventListener("pagehide", this.pagehideHandler);
9696
+ this.pagehideHandler = null;
9697
+ }
9698
+ }
9699
+ };
9700
+ function percentile(sortedAsc, q2) {
9701
+ if (sortedAsc.length === 0) return 0;
9702
+ const pos = (sortedAsc.length - 1) * q2;
9703
+ const lo = Math.floor(pos);
9704
+ const hi = Math.ceil(pos);
9705
+ if (lo === hi) return sortedAsc[lo];
9706
+ return sortedAsc[lo] + (sortedAsc[hi] - sortedAsc[lo]) * (pos - lo);
9707
+ }
9708
+ var singleton = null;
9709
+ function initHealthReporter(config) {
9710
+ singleton == null ? void 0 : singleton.stop();
9711
+ singleton = new HealthReporter(config);
9712
+ singleton.start();
9713
+ return singleton;
9714
+ }
9715
+ function getHealthReporter() {
9716
+ return singleton;
9717
+ }
9718
+
9719
+ // src/observability/otlpEmitter.ts
9720
+ var stringAttr = (key, value) => ({ key, value: { stringValue: value } });
9721
+ var intAttr = (key, value) => ({
9722
+ key,
9723
+ value: { intValue: Math.round(value) }
9724
+ });
9725
+ var doubleAttr = (key, value) => ({ key, value: { doubleValue: value } });
9726
+ function buildOtlpPayload(flush) {
9727
+ const { resource, counters, histograms, windowSeconds, windowStartUnixMs } = flush;
9728
+ const resourceAttrs = [
9729
+ stringAttr("service.name", resource.serviceName),
9730
+ stringAttr("service.version", resource.serviceVersion),
9731
+ stringAttr("syntro.posthog_key", resource.posthogKey),
9732
+ stringAttr("syntro.session_id", resource.sessionId),
9733
+ stringAttr("syntro.surface_type", resource.surfaceType),
9734
+ stringAttr("syntro.surface_host", resource.surfaceHost),
9735
+ stringAttr("syntro.surface_device", resource.surfaceDevice),
9736
+ stringAttr("syntro.surface_mode", resource.surfaceMode),
9737
+ stringAttr("syntro.host_origin", resource.hostOrigin)
9738
+ ];
9739
+ const recordAttrs = [intAttr("window_seconds", windowSeconds)];
9740
+ for (const [k2, v2] of Object.entries(counters)) {
9741
+ if (v2 !== void 0) recordAttrs.push(intAttr(k2, v2));
9742
+ }
9743
+ for (const [k2, h] of Object.entries(histograms)) {
9744
+ if (h === void 0) continue;
9745
+ recordAttrs.push(intAttr(`${k2}_count`, h.count));
9746
+ recordAttrs.push(doubleAttr(`${k2}_p50`, h.p50));
9747
+ recordAttrs.push(doubleAttr(`${k2}_p95`, h.p95));
9748
+ }
9749
+ const nowNano = `${Date.now()}000000`;
9750
+ const startNano = `${windowStartUnixMs}000000`;
9751
+ return {
9752
+ resourceLogs: [
9753
+ {
9754
+ resource: { attributes: resourceAttrs },
9755
+ scopeLogs: [
9756
+ {
9757
+ scope: { name: "syntro.sdk.health" },
9758
+ logRecords: [
9759
+ {
9760
+ timeUnixNano: startNano,
9761
+ observedTimeUnixNano: nowNano,
9762
+ severityText: "INFO",
9763
+ body: { stringValue: "sdk_health_window" },
9764
+ attributes: recordAttrs
9765
+ }
9766
+ ]
9767
+ }
9768
+ ]
9769
+ }
9770
+ ]
9771
+ };
9772
+ }
9773
+ function createOtlpEmitter(cfg) {
9774
+ var _a3;
9775
+ const fetchImpl = (_a3 = cfg.fetchImpl) != null ? _a3 : fetch;
9776
+ return async (flush) => {
9777
+ const body = JSON.stringify(buildOtlpPayload(flush));
9778
+ const post = () => fetchImpl(cfg.endpoint, {
9779
+ method: "POST",
9780
+ headers: { "Content-Type": "application/json" },
9781
+ body,
9782
+ keepalive: true,
9783
+ mode: "cors"
9784
+ });
9785
+ try {
9786
+ const resp = await post();
9787
+ if (!resp.ok && resp.status >= 500) {
9788
+ try {
9789
+ await post();
9790
+ } catch {
9791
+ }
9792
+ }
9793
+ } catch {
9794
+ try {
9795
+ await post();
9796
+ } catch {
9797
+ }
9798
+ }
9799
+ };
9800
+ }
9801
+
9579
9802
  // src/version.ts
9580
- var SDK_VERSION = "2.8.0-canary.191";
9803
+ var SDK_VERSION = "2.8.0-canary.192";
9581
9804
 
9582
9805
  // src/types.ts
9583
9806
  var SDK_SCHEMA_VERSION = "2.0";
@@ -9696,7 +9919,7 @@ var createCanvasConfigFetcher = ({
9696
9919
  variantFlagPrefix,
9697
9920
  sdkVersion
9698
9921
  }) => async () => {
9699
- var _a3, _b;
9922
+ var _a3, _b, _c, _d, _e2, _f;
9700
9923
  if (experiments && configFeatureKey) {
9701
9924
  const directConfig = (_a3 = experiments.getFeatureValue) == null ? void 0 : _a3.call(experiments, configFeatureKey, null);
9702
9925
  if (directConfig && typeof directConfig === "object") {
@@ -9735,6 +9958,8 @@ var createCanvasConfigFetcher = ({
9735
9958
  throw new Error(`SmartCanvas: config URI not allowed: ${uri}`);
9736
9959
  }
9737
9960
  const effectiveCredentials = credentials != null ? credentials : isSameOrigin2(uri) ? "include" : "omit";
9961
+ const fetchStart = performance.now();
9962
+ let errorAlreadyCounted = false;
9738
9963
  try {
9739
9964
  const response = await fetch(uri, {
9740
9965
  credentials: effectiveCredentials,
@@ -9744,15 +9969,23 @@ var createCanvasConfigFetcher = ({
9744
9969
  }
9745
9970
  });
9746
9971
  if (!response.ok) {
9972
+ (_c = getHealthReporter()) == null ? void 0 : _c.increment("flag_fetch_errors");
9973
+ errorAlreadyCounted = true;
9747
9974
  throw new Error(`SmartCanvas: failed to fetch config (${response.status})`);
9748
9975
  }
9749
9976
  const config = await response.json();
9977
+ const latencyMs = performance.now() - fetchStart;
9978
+ (_d = getHealthReporter()) == null ? void 0 : _d.increment("flag_fetch_count");
9979
+ (_e2 = getHealthReporter()) == null ? void 0 : _e2.recordHistogram("flag_fetch_latency_ms", latencyMs);
9750
9980
  debug("SmartCanvas Config", "Fetched config from URI", config);
9751
9981
  if (sdkVersion) {
9752
9982
  cacheConfig(config, sdkVersion);
9753
9983
  }
9754
9984
  return config;
9755
9985
  } catch (error2) {
9986
+ if (!errorAlreadyCounted) {
9987
+ (_f = getHealthReporter()) == null ? void 0 : _f.increment("flag_fetch_errors");
9988
+ }
9756
9989
  if (sdkVersion) {
9757
9990
  const cached = getCachedConfig(sdkVersion);
9758
9991
  if (cached) {
@@ -17965,7 +18198,7 @@ function createTelemetryClient(provider, config) {
17965
18198
 
17966
18199
  // src/bootstrap-runtime.ts
17967
18200
  async function _initCore(options) {
17968
- var _a3, _b, _c, _d, _e2, _f, _g, _h, _i, _j, _k, _l;
18201
+ var _a3, _b, _c, _d, _e2, _f, _g, _h, _i, _j, _k, _l, _m, _n;
17969
18202
  initLogger();
17970
18203
  debug("Syntro Bootstrap", "====== INIT ======");
17971
18204
  debug("Syntro Bootstrap", "Options:", {
@@ -18027,13 +18260,30 @@ async function _initCore(options) {
18027
18260
  } else {
18028
18261
  debug("Syntro Bootstrap", `\u2713 No token, but ${sdkMode} mode - proceeding`);
18029
18262
  }
18263
+ if (payload != null && payload.obd !== true) {
18264
+ try {
18265
+ const otlpEndpoint = (_b = payload.obe) != null ? _b : "https://telemetry.syntrologie.com/sdk-otel/v1/logs";
18266
+ initHealthReporter({
18267
+ resource: {
18268
+ serviceName: "syntro-runtime-sdk",
18269
+ serviceVersion: SDK_VERSION,
18270
+ // PostHog project SDK key — canonical workspace identifier for ops.
18271
+ // Telemetry lives in PostHog, so its primary key is the right join column.
18272
+ posthogKey: (_c = payload.t) != null ? _c : "",
18273
+ hostOrigin: typeof window !== "undefined" ? window.location.origin : ""
18274
+ },
18275
+ emit: createOtlpEmitter({ endpoint: otlpEndpoint })
18276
+ });
18277
+ } catch {
18278
+ }
18279
+ }
18030
18280
  const experimentHost = getEnvVar("NEXT_PUBLIC_SYNTRO_EXPERIMENT_HOST") || getEnvVar("VITE_SYNTRO_EXPERIMENT_HOST") || (payload == null ? void 0 : payload.eh);
18031
18281
  const telemetryHost = getEnvVar("NEXT_PUBLIC_SYNTRO_TELEMETRY_HOST") || getEnvVar("VITE_SYNTRO_TELEMETRY_HOST") || (payload == null ? void 0 : payload.th);
18032
- const editorUrl = getEnvVar("NEXT_PUBLIC_SYNTRO_EDITOR_URL") || getEnvVar("VITE_SYNTRO_EDITOR_URL") || ((_b = options.canvas) == null ? void 0 : _b.editorUrl);
18282
+ const editorUrl = getEnvVar("NEXT_PUBLIC_SYNTRO_EDITOR_URL") || getEnvVar("VITE_SYNTRO_EDITOR_URL") || ((_d = options.canvas) == null ? void 0 : _d.editorUrl);
18033
18283
  const geoHost = (payload == null ? void 0 : payload.g) || getEnvVar("NEXT_PUBLIC_SYNTRO_GEO_HOST") || getEnvVar("VITE_SYNTRO_GEO_HOST") || GEO_DEFAULT_HOST;
18034
18284
  const cachedSegmentAttrs = loadCachedSegmentAttributes();
18035
18285
  const browserMetadata = collectBrowserMetadata();
18036
- const appSignalsInit = (_c = options.appSignalsInit) != null ? _c : {};
18286
+ const appSignalsInit = (_e2 = options.appSignalsInit) != null ? _e2 : {};
18037
18287
  const phaseOneAttrs = { ...browserMetadata, ...cachedSegmentAttrs, ...appSignalsInit };
18038
18288
  debug("Syntro Bootstrap", "Phase 1: Browser metadata:", browserMetadata);
18039
18289
  debug("Syntro Bootstrap", "Phase 1: Cached segment attributes:", cachedSegmentAttrs);
@@ -18177,7 +18427,7 @@ async function _initCore(options) {
18177
18427
  });
18178
18428
  console.log(`[Syntro Bootstrap] Telemetry client created (${provider}) with EventBus wiring`);
18179
18429
  if (Object.keys(appSignalsInit).length > 0) {
18180
- (_d = telemetry.track) == null ? void 0 : _d.call(telemetry, "app_signals_init", appSignalsInit);
18430
+ (_f = telemetry.track) == null ? void 0 : _f.call(telemetry, "app_signals_init", appSignalsInit);
18181
18431
  debug("Syntro Bootstrap", "Tracked app signals event:", appSignalsInit);
18182
18432
  }
18183
18433
  const telemetryForCapture = telemetry;
@@ -18235,7 +18485,7 @@ async function _initCore(options) {
18235
18485
  if ((platformAdapter == null ? void 0 : platformAdapter.name) === "shopify" && telemetryHost) {
18236
18486
  try {
18237
18487
  shopifyPixelBridge = new ShopifyPixelBridge({
18238
- distinctId: (_f = (_e2 = telemetry.getDistinctId) == null ? void 0 : _e2.call(telemetry)) != null ? _f : "",
18488
+ distinctId: (_h = (_g = telemetry.getDistinctId) == null ? void 0 : _g.call(telemetry)) != null ? _h : "",
18239
18489
  telemetryHost,
18240
18490
  telemetryKey: payload.t
18241
18491
  });
@@ -18323,7 +18573,7 @@ async function _initCore(options) {
18323
18573
  debug("Syntro Bootstrap", "auto-load of adaptive-mcp failed (non-fatal):", err);
18324
18574
  });
18325
18575
  }
18326
- const registeredApps = (_i = (_h = (_g = runtime5.apps).list) == null ? void 0 : _h.call(_g)) != null ? _i : [];
18576
+ const registeredApps = (_k = (_j = (_i = runtime5.apps).list) == null ? void 0 : _j.call(_i)) != null ? _k : [];
18327
18577
  console.log(
18328
18578
  `[DIAG] Activation loop: ${registeredApps.length} apps in registry:`,
18329
18579
  registeredApps.map((a) => `${a.manifest.id}(${a.state})`).join(", ")
@@ -18354,13 +18604,13 @@ async function _initCore(options) {
18354
18604
  if (experiments && Object.keys(geoData).length > 0) {
18355
18605
  const mergedAttrs = { ...browserMetadata, ...geoData, ...appSignalsInit };
18356
18606
  debug("Syntro Bootstrap", "Merging geo data into GrowthBook attributes:", geoData);
18357
- (_j = experiments.setAttributes) == null ? void 0 : _j.call(experiments, mergedAttrs);
18607
+ (_l = experiments.setAttributes) == null ? void 0 : _l.call(experiments, mergedAttrs);
18358
18608
  }
18359
18609
  const mcpHost = await mcpPromise;
18360
18610
  if (mcpHost && experiments) {
18361
18611
  browserMetadata.surface_type = "mcp-app";
18362
18612
  browserMetadata.surface_host = mcpHost.name;
18363
- (_k = experiments.setAttributes) == null ? void 0 : _k.call(experiments, { ...browserMetadata, ...geoData });
18613
+ (_m = experiments.setAttributes) == null ? void 0 : _m.call(experiments, { ...browserMetadata, ...geoData });
18364
18614
  runtime5.context.setSurfaceType("mcp-app");
18365
18615
  runtime5.context.setSurfaceHost(mcpHost.name);
18366
18616
  debug("Syntro Bootstrap", "MCP App detected:", mcpHost.name);
@@ -18369,7 +18619,7 @@ async function _initCore(options) {
18369
18619
  if (options.fetcher) {
18370
18620
  baseFetcher = options.fetcher;
18371
18621
  } else if (payload == null ? void 0 : payload.f) {
18372
- const configFetcher = createConfigFetcher(payload.f, (_l = payload.o) != null ? _l : {});
18622
+ const configFetcher = createConfigFetcher(payload.f, (_n = payload.o) != null ? _n : {});
18373
18623
  baseFetcher = async () => {
18374
18624
  var _a4;
18375
18625
  const result = await configFetcher.fetch();
@@ -18383,7 +18633,7 @@ async function _initCore(options) {
18383
18633
  }
18384
18634
  const warnedAppFailures = /* @__PURE__ */ new Set();
18385
18635
  const appLoadingFetcher = baseFetcher ? async () => {
18386
- var _a4, _b2, _c2, _d2, _e3, _f2, _g2, _h2, _i2, _j2, _k2, _l2, _m;
18636
+ var _a4, _b2, _c2, _d2, _e3, _f2, _g2, _h2, _i2, _j2, _k2, _l2, _m2;
18387
18637
  const config = await baseFetcher();
18388
18638
  const tileCount = (_b2 = (_a4 = config.tiles) == null ? void 0 : _a4.length) != null ? _b2 : 0;
18389
18639
  const actionCount = (_d2 = (_c2 = config.actions) == null ? void 0 : _c2.length) != null ? _d2 : 0;
@@ -18416,7 +18666,7 @@ async function _initCore(options) {
18416
18666
  `actions=${(_j2 = (_i2 = config.actions) == null ? void 0 : _i2.length) != null ? _j2 : 0},`,
18417
18667
  `theme=${(_l2 = (_k2 = config.theme) == null ? void 0 : _k2.name) != null ? _l2 : "none"}`
18418
18668
  );
18419
- if (((_m = config.actions) == null ? void 0 : _m.length) > 0) {
18669
+ if (((_m2 = config.actions) == null ? void 0 : _m2.length) > 0) {
18420
18670
  console.log(
18421
18671
  "[Syntro Bootstrap] Actions in config:",
18422
18672
  config.actions.map(
@@ -18509,19 +18759,47 @@ async function _initCore(options) {
18509
18759
  originalSetOverrideFetcher(wrappedFetcher);
18510
18760
  };
18511
18761
  }
18762
+ const healthReporter = getHealthReporter();
18763
+ if (healthReporter !== null) {
18764
+ try {
18765
+ const boundTelemetry = telemetry;
18766
+ const boundRuntime = runtime5;
18767
+ healthReporter.bindRuntime({
18768
+ getSessionId: () => {
18769
+ var _a4, _b2;
18770
+ try {
18771
+ return (_b2 = (_a4 = boundTelemetry == null ? void 0 : boundTelemetry.getSessionId) == null ? void 0 : _a4.call(boundTelemetry)) != null ? _b2 : "";
18772
+ } catch {
18773
+ return "";
18774
+ }
18775
+ },
18776
+ getSurface: () => {
18777
+ try {
18778
+ const surface = boundRuntime.context.get().surface;
18779
+ return surface ? { ...surface } : null;
18780
+ } catch {
18781
+ return null;
18782
+ }
18783
+ }
18784
+ });
18785
+ } catch {
18786
+ }
18787
+ }
18788
+ healthReporter == null ? void 0 : healthReporter.increment("bootstrap_ok");
18512
18789
  return { canvas, runtime: runtime5, experiments, telemetry, sessionMetrics, appLoader };
18513
18790
  }
18514
18791
 
18515
18792
  // src/bootstrap.ts
18516
18793
  async function init(options) {
18517
- var _a3;
18794
+ var _a3, _b;
18518
18795
  try {
18519
18796
  return await _initCore(options);
18520
18797
  } catch (err) {
18521
18798
  const message = err instanceof Error ? err.message : String(err);
18522
18799
  console.warn("[Syntrologie] SDK initialization failed:", message);
18800
+ (_a3 = getHealthReporter()) == null ? void 0 : _a3.increment("bootstrap_errors");
18523
18801
  if (typeof document !== "undefined") {
18524
- (_a3 = document.getElementById("syntrologie-anti-flicker")) == null ? void 0 : _a3.remove();
18802
+ (_b = document.getElementById("syntrologie-anti-flicker")) == null ? void 0 : _b.remove();
18525
18803
  }
18526
18804
  return void 0;
18527
18805
  }