camstack 1.2.193 → 1.2.194

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.
@@ -24024,9 +24024,9 @@ var require_zod = __commonJS({
24024
24024
  }
24025
24025
  });
24026
24026
 
24027
- // ../system/dist/dist-C89nqNnn.js
24028
- var require_dist_C89nqNnn = __commonJS({
24029
- "../system/dist/dist-C89nqNnn.js"(exports) {
24027
+ // ../system/dist/dist-BZQjLPiz.js
24028
+ var require_dist_BZQjLPiz = __commonJS({
24029
+ "../system/dist/dist-BZQjLPiz.js"(exports) {
24030
24030
  "use strict";
24031
24031
  var zod = require_zod();
24032
24032
  __require("crypto");
@@ -81000,9 +81000,24 @@ var require_dist_C89nqNnn = __commonJS({
81000
81000
  name: zod.z.string().optional(),
81001
81001
  generation: zod.z.enum(["xdna1", "xdna2"]).optional()
81002
81002
  });
81003
+ var CoralBusSchema = zod.z.enum(["usb", "pci"]);
81003
81004
  var CoralInfoSchema = zod.z.object({
81004
81005
  type: zod.z.literal("coral-edgetpu"),
81005
- bus: zod.z.string().optional()
81006
+ /** Legacy single-bus report (older nodes) — read via `coralUsableUnits`. */
81007
+ bus: zod.z.string().optional(),
81008
+ /** Legacy USB unit count (older nodes) — read via `coralUsableUnits`. */
81009
+ count: zod.z.number().int().nonnegative().optional(),
81010
+ /** Usable units per bus — each one is its own `edgetpu:<bus>[:N]` device. */
81011
+ units: zod.z.array(zod.z.object({
81012
+ bus: CoralBusSchema,
81013
+ count: zod.z.number().int().nonnegative()
81014
+ })).readonly().optional(),
81015
+ /** Present-but-unusable units, each with its typed reason (never "absent"). */
81016
+ unavailable: zod.z.array(zod.z.object({
81017
+ bus: CoralBusSchema,
81018
+ count: zod.z.number().int().nonnegative(),
81019
+ reason: zod.z.enum(["driver-missing", "device-not-accessible"])
81020
+ })).readonly().optional()
81006
81021
  });
81007
81022
  var HardwareInfoSchema = zod.z.object({
81008
81023
  platform: HardwarePlatformSchema,
@@ -100562,6 +100577,27 @@ var require_dist_C89nqNnn = __commonJS({
100562
100577
  function vectorDimFromBase64(encoded) {
100563
100578
  return Math.floor(Buffer.from(encoded, "base64").byteLength / 4);
100564
100579
  }
100580
+ var BUS_ORDER = ["usb", "pci"];
100581
+ function unitDevice(bus, index) {
100582
+ return index === 0 ? bus : `${bus}:${index}`;
100583
+ }
100584
+ function countOn(coral, bus) {
100585
+ if (coral.units !== void 0) return coral.units.filter((u) => u.bus === bus).reduce((n, u) => n + Math.max(0, u.count), 0);
100586
+ return bus === (coral.bus === "pci" ? "pci" : "usb") ? Math.max(1, coral.count ?? 1) : 0;
100587
+ }
100588
+ function coralUsableUnits(coral) {
100589
+ if (coral == null) return [];
100590
+ const out = [];
100591
+ for (const bus of BUS_ORDER) {
100592
+ const count = countOn(coral, bus);
100593
+ for (let index = 0; index < count; index++) out.push({
100594
+ bus,
100595
+ index,
100596
+ device: unitDevice(bus, index)
100597
+ });
100598
+ }
100599
+ return out;
100600
+ }
100565
100601
  var AUTO = {
100566
100602
  value: "auto",
100567
100603
  label: "Auto"
@@ -100574,6 +100610,14 @@ var require_dist_C89nqNnn = __commonJS({
100574
100610
  value: "usb",
100575
100611
  label: "Coral USB"
100576
100612
  };
100613
+ function coralUnitOption(unit) {
100614
+ const bus = unit.bus === "pci" ? "PCIe" : "USB";
100615
+ const label = unit.index === 0 ? `Coral ${bus}` : `Coral ${bus} ${unit.index + 1}`;
100616
+ return {
100617
+ value: unit.device,
100618
+ label
100619
+ };
100620
+ }
100577
100621
  var RUNTIMES = [
100578
100622
  {
100579
100623
  id: "onnx",
@@ -100640,8 +100684,11 @@ var require_dist_C89nqNnn = __commonJS({
100640
100684
  },
100641
100685
  {
100642
100686
  id: "edgetpu",
100643
- supports: (hw) => hw?.coral != null,
100644
- devices: () => [USB],
100687
+ supports: (hw) => coralUsableUnits(hw?.coral).length > 0,
100688
+ devices: (hw) => {
100689
+ const units = coralUsableUnits(hw?.coral);
100690
+ return units.length > 0 ? units.map(coralUnitOption) : [USB];
100691
+ },
100645
100692
  defaultDevice: "usb"
100646
100693
  }
100647
100694
  ];
@@ -100695,7 +100742,7 @@ var require_dist_C89nqNnn = __commonJS({
100695
100742
  available: true
100696
100743
  });
100697
100744
  }
100698
- if (hw.coral != null) scores.push({
100745
+ if (coralUsableUnits(hw.coral).length > 0) scores.push({
100699
100746
  runtime: "python",
100700
100747
  backend: "edgetpu",
100701
100748
  format: "tflite",
@@ -100745,11 +100792,7 @@ var require_dist_C89nqNnn = __commonJS({
100745
100792
  continue;
100746
100793
  }
100747
100794
  if (s.backend === "edgetpu") {
100748
- const coralCount = Math.max(1, hw.coral?.count ?? 1);
100749
- for (let i = 0; i < coralCount; i++) {
100750
- const dev2 = i === 0 ? "usb" : `usb:${i}`;
100751
- out.push(device("edgetpu", dev2, s.format, s.score));
100752
- }
100795
+ for (const unit of coralUsableUnits(hw.coral)) out.push(device("edgetpu", unit.device, s.format, s.score));
100753
100796
  continue;
100754
100797
  }
100755
100798
  if (s.backend === "onnx" && s.reason.startsWith("ONNX WebGPU")) {
@@ -114121,11 +114164,11 @@ ${values.join("\n")}` : `${blockName} :`;
114121
114164
  }
114122
114165
  });
114123
114166
 
114124
- // ../system/dist/device-ca-CVK3YcR_.js
114125
- var require_device_ca_CVK3YcR = __commonJS({
114126
- "../system/dist/device-ca-CVK3YcR_.js"(exports) {
114167
+ // ../system/dist/device-ca-BrVK_5s3.js
114168
+ var require_device_ca_BrVK_5s3 = __commonJS({
114169
+ "../system/dist/device-ca-BrVK_5s3.js"(exports) {
114127
114170
  "use strict";
114128
- var require_dist10 = require_dist_C89nqNnn();
114171
+ var require_dist10 = require_dist_BZQjLPiz();
114129
114172
  var require_x509_es = require_x509_es_C4cOo48M();
114130
114173
  var node_crypto = __require("crypto");
114131
114174
  var SYSTEM_SECRET_OWNER = "system";
@@ -114540,11 +114583,11 @@ var require_device_ca_CVK3YcR = __commonJS({
114540
114583
  }
114541
114584
  });
114542
114585
 
114543
- // ../system/dist/phase6-declare-gate-BO-_jLh_.js
114544
- var require_phase6_declare_gate_BO_jLh = __commonJS({
114545
- "../system/dist/phase6-declare-gate-BO-_jLh_.js"(exports) {
114586
+ // ../system/dist/phase6-declare-gate-Dag1_WR2.js
114587
+ var require_phase6_declare_gate_Dag1_WR2 = __commonJS({
114588
+ "../system/dist/phase6-declare-gate-Dag1_WR2.js"(exports) {
114546
114589
  "use strict";
114547
- var require_dist10 = require_dist_C89nqNnn();
114590
+ var require_dist10 = require_dist_BZQjLPiz();
114548
114591
  function legacyTableRowCountFromList(tables, collection) {
114549
114592
  return tables.find((t) => t.name === collection)?.rows ?? 0;
114550
114593
  }
@@ -114638,9 +114681,9 @@ var require_alerts_addon = __commonJS({
114638
114681
  [Symbol.toStringTag]: { value: "Module" }
114639
114682
  });
114640
114683
  require_chunk_Cek0wNdY();
114641
- var require_dist10 = require_dist_C89nqNnn();
114684
+ var require_dist10 = require_dist_BZQjLPiz();
114642
114685
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
114643
- var require_phase6_declare_gate = require_phase6_declare_gate_BO_jLh();
114686
+ var require_phase6_declare_gate = require_phase6_declare_gate_Dag1_WR2();
114644
114687
  function nextEpisodeId(input) {
114645
114688
  const { previous } = input;
114646
114689
  if (previous !== null && require_dist10.isAlertEpisodeOpen(previous.status)) {
@@ -116045,7 +116088,7 @@ var require_calendars_addon = __commonJS({
116045
116088
  [Symbol.toStringTag]: { value: "Module" }
116046
116089
  });
116047
116090
  require_chunk_Cek0wNdY();
116048
- var require_dist10 = require_dist_C89nqNnn();
116091
+ var require_dist10 = require_dist_BZQjLPiz();
116049
116092
  var require_settle_sources = require_settle_sources_Bhsy57y();
116050
116093
  var zod = require_zod();
116051
116094
  var CALENDAR_COLOR_PALETTE = [
@@ -116263,11 +116306,11 @@ var require_calendars = __commonJS({
116263
116306
  }
116264
116307
  });
116265
116308
 
116266
- // ../system/dist/composition-sources-qKyvMAvc.js
116267
- var require_composition_sources_qKyvMAvc = __commonJS({
116268
- "../system/dist/composition-sources-qKyvMAvc.js"(exports) {
116309
+ // ../system/dist/composition-sources-DURQNDJ4.js
116310
+ var require_composition_sources_DURQNDJ4 = __commonJS({
116311
+ "../system/dist/composition-sources-DURQNDJ4.js"(exports) {
116269
116312
  "use strict";
116270
- var require_dist10 = require_dist_C89nqNnn();
116313
+ var require_dist10 = require_dist_BZQjLPiz();
116271
116314
  function normalizedNativeOwner(owner) {
116272
116315
  const trimmed = owner?.trim();
116273
116316
  return trimmed ? trimmed : null;
@@ -116382,8 +116425,8 @@ var require_composer_addon = __commonJS({
116382
116425
  [Symbol.toStringTag]: { value: "Module" }
116383
116426
  });
116384
116427
  require_chunk_Cek0wNdY();
116385
- var require_dist10 = require_dist_C89nqNnn();
116386
- var require_composition_sources = require_composition_sources_qKyvMAvc();
116428
+ var require_dist10 = require_dist_BZQjLPiz();
116429
+ var require_composition_sources = require_composition_sources_DURQNDJ4();
116387
116430
  var zod = require_zod();
116388
116431
  function isRecord$2(value) {
116389
116432
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -120193,7 +120236,7 @@ var require_console_logging = __commonJS({
120193
120236
  [Symbol.toStringTag]: { value: "Module" }
120194
120237
  });
120195
120238
  require_chunk_Cek0wNdY();
120196
- var require_dist10 = require_dist_C89nqNnn();
120239
+ var require_dist10 = require_dist_BZQjLPiz();
120197
120240
  var require_formatter = require_formatter_DqAKDlvN();
120198
120241
  var LEVEL_RANK = {
120199
120242
  debug: 0,
@@ -124583,9 +124626,9 @@ var require_core_blocks_addon = __commonJS({
124583
124626
  "use strict";
124584
124627
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
124585
124628
  var require_chunk = require_chunk_Cek0wNdY();
124586
- var require_dist10 = require_dist_C89nqNnn();
124629
+ var require_dist10 = require_dist_BZQjLPiz();
124587
124630
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
124588
- var require_composition_sources = require_composition_sources_qKyvMAvc();
124631
+ var require_composition_sources = require_composition_sources_DURQNDJ4();
124589
124632
  var require_prefix_range = require_prefix_range_D_KueXbQ();
124590
124633
  var require_prefix_walk = require_prefix_walk_Dv6MLZlM();
124591
124634
  var zod = require_zod();
@@ -137241,7 +137284,7 @@ var require_device_manager_addon = __commonJS({
137241
137284
  [Symbol.toStringTag]: { value: "Module" }
137242
137285
  });
137243
137286
  require_chunk_Cek0wNdY();
137244
- var require_dist10 = require_dist_C89nqNnn();
137287
+ var require_dist10 = require_dist_BZQjLPiz();
137245
137288
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
137246
137289
  var require_prefix_range = require_prefix_range_D_KueXbQ();
137247
137290
  var require_prefix_walk = require_prefix_walk_Dv6MLZlM();
@@ -146315,7 +146358,7 @@ var require_hub_forwarder = __commonJS({
146315
146358
  [Symbol.toStringTag]: { value: "Module" }
146316
146359
  });
146317
146360
  require_chunk_Cek0wNdY();
146318
- var require_dist10 = require_dist_C89nqNnn();
146361
+ var require_dist10 = require_dist_BZQjLPiz();
146319
146362
  var require_formatter = require_formatter_DqAKDlvN();
146320
146363
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
146321
146364
  var HubForwarderDestination = class {
@@ -146449,7 +146492,7 @@ var require_liveness_monitor_addon = __commonJS({
146449
146492
  "use strict";
146450
146493
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
146451
146494
  require_chunk_Cek0wNdY();
146452
- var require_dist10 = require_dist_C89nqNnn();
146495
+ var require_dist10 = require_dist_BZQjLPiz();
146453
146496
  var NO_DEVICES = "liveness:no-devices";
146454
146497
  var ALL_OFFLINE = "liveness:all-devices-offline";
146455
146498
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -146812,12 +146855,12 @@ var require_local_auth_addon = __commonJS({
146812
146855
  [Symbol.toStringTag]: { value: "Module" }
146813
146856
  });
146814
146857
  var require_chunk = require_chunk_Cek0wNdY();
146815
- var require_dist10 = require_dist_C89nqNnn();
146858
+ var require_dist10 = require_dist_BZQjLPiz();
146816
146859
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
146817
146860
  var require_safe_buffer$1 = require_safe_buffer_D3aoa_7X();
146818
146861
  var require_ms$1 = require_ms_LB3giGoU();
146819
- var require_device_ca = require_device_ca_CVK3YcR();
146820
- var require_phase6_declare_gate = require_phase6_declare_gate_BO_jLh();
146862
+ var require_device_ca = require_device_ca_BrVK_5s3();
146863
+ var require_phase6_declare_gate = require_phase6_declare_gate_Dag1_WR2();
146821
146864
  var zod = require_zod();
146822
146865
  var node_crypto = __require("crypto");
146823
146866
  node_crypto = require_chunk.__toESM(node_crypto);
@@ -157499,7 +157542,7 @@ var require_loki_logging = __commonJS({
157499
157542
  [Symbol.toStringTag]: { value: "Module" }
157500
157543
  });
157501
157544
  require_chunk_Cek0wNdY();
157502
- var require_dist10 = require_dist_C89nqNnn();
157545
+ var require_dist10 = require_dist_BZQjLPiz();
157503
157546
  var require_log_read_filter = require_log_read_filter_Bi066jwU();
157504
157547
  var zod = require_zod();
157505
157548
  function sanitizeLabelName(raw) {
@@ -158460,7 +158503,7 @@ var require_native_metrics_addon = __commonJS({
158460
158503
  [Symbol.toStringTag]: { value: "Module" }
158461
158504
  });
158462
158505
  var require_chunk = require_chunk_Cek0wNdY();
158463
- var require_dist10 = require_dist_C89nqNnn();
158506
+ var require_dist10 = require_dist_BZQjLPiz();
158464
158507
  var node_fs_promises = __require("fs/promises");
158465
158508
  var node_util = __require("util");
158466
158509
  var node_os = __require("os");
@@ -161005,7 +161048,216 @@ var require_device_history_addon = __commonJS({
161005
161048
  [Symbol.toStringTag]: { value: "Module" }
161006
161049
  });
161007
161050
  require_chunk_Cek0wNdY();
161008
- var require_dist10 = require_dist_C89nqNnn();
161051
+ var require_dist10 = require_dist_BZQjLPiz();
161052
+ var FIVE_MINUTES_MS = 5 * 6e4;
161053
+ var HOUR_MS = 60 * 6e4;
161054
+ var DAY_MS = 24 * HOUR_MS;
161055
+ function floorTo(ts, widthMs) {
161056
+ return Math.floor(ts / widthMs) * widthMs;
161057
+ }
161058
+ function startOfLocalDay(ts) {
161059
+ const d = new Date(ts);
161060
+ d.setHours(0, 0, 0, 0);
161061
+ return d.getTime();
161062
+ }
161063
+ function nextLocalDayStart(dayStart) {
161064
+ const d = new Date(dayStart);
161065
+ d.setDate(d.getDate() + 1);
161066
+ d.setHours(0, 0, 0, 0);
161067
+ return d.getTime();
161068
+ }
161069
+ function bucketStartOf(tier, ts) {
161070
+ if (tier === "5m") return floorTo(ts, FIVE_MINUTES_MS);
161071
+ if (tier === "1h") return floorTo(ts, HOUR_MS);
161072
+ return startOfLocalDay(ts);
161073
+ }
161074
+ function bucketEndOf(tier, start) {
161075
+ if (tier === "5m") return start + FIVE_MINUTES_MS;
161076
+ if (tier === "1h") return start + HOUR_MS;
161077
+ return nextLocalDayStart(start);
161078
+ }
161079
+ var ROLLUP_GRACE_MS = {
161080
+ "5m": 3e4,
161081
+ "1h": 5 * 6e4,
161082
+ "1d": 15 * 6e4
161083
+ };
161084
+ var DEPARTED_ABSENCE_MS = 7 * DAY_MS;
161085
+ var DepartureTracker = class {
161086
+ store;
161087
+ registry;
161088
+ logger;
161089
+ missing = /* @__PURE__ */ new Map();
161090
+ constructor(store, registry, logger) {
161091
+ this.store = store;
161092
+ this.registry = registry;
161093
+ this.logger = logger;
161094
+ }
161095
+ async load() {
161096
+ this.missing = await this.store.loadDepartures();
161097
+ }
161098
+ missingSince(deviceId) {
161099
+ return this.missing.get(deviceId);
161100
+ }
161101
+ /** Forget a device's clock — its series were removed because it was DELETED (D865). */
161102
+ async forget(deviceId) {
161103
+ await this.store.clearMissing([deviceId]);
161104
+ const next = new Map(this.missing);
161105
+ next.delete(deviceId);
161106
+ this.missing = next;
161107
+ }
161108
+ /** Feed one SUCCESSFUL listing. A failed read never reaches here. */
161109
+ async observe(listed, now) {
161110
+ const withSeries = new Set(this.registry.all().flatMap((s) => s.deviceId === null ? [] : [s.deviceId]));
161111
+ const back = [...this.missing.keys()].filter((id) => listed.has(id));
161112
+ const gone = [...withSeries].filter((id) => !listed.has(id) && !this.missing.has(id));
161113
+ try {
161114
+ await this.store.clearMissing(back);
161115
+ await this.store.markMissing(gone, now);
161116
+ } catch (err) {
161117
+ this.logger.warn("device-history: departure clock not written", { meta: { error: err instanceof Error ? err.message : String(err) } });
161118
+ return;
161119
+ }
161120
+ const next = new Map(this.missing);
161121
+ for (const id of back) next.delete(id);
161122
+ for (const id of gone) next.set(id, now);
161123
+ this.missing = next;
161124
+ }
161125
+ };
161126
+ var DEFAULT_RETENTION = {
161127
+ rawDays: 7,
161128
+ fiveMinuteDays: 30,
161129
+ hourDays: 365,
161130
+ dayDays: null
161131
+ };
161132
+ function retentionCutoffs(policy, now) {
161133
+ return {
161134
+ raw: now - policy.rawDays * DAY_MS,
161135
+ "5m": now - policy.fiveMinuteDays * DAY_MS,
161136
+ "1h": now - policy.hourDays * DAY_MS,
161137
+ "1d": policy.dayDays === null || policy.dayDays <= 0 ? null : now - policy.dayDays * DAY_MS
161138
+ };
161139
+ }
161140
+ var TIERS = [
161141
+ "raw",
161142
+ "5m",
161143
+ "1h",
161144
+ "1d"
161145
+ ];
161146
+ var RETENTION_STEP_MS = {
161147
+ raw: HOUR_MS,
161148
+ "5m": HOUR_MS,
161149
+ "1h": DAY_MS,
161150
+ "1d": DAY_MS
161151
+ };
161152
+ var MAX_PURGES_PER_RUN = 20;
161153
+ var SLICE_MS = {
161154
+ raw: DAY_MS,
161155
+ "5m": DAY_MS,
161156
+ "1h": 30 * DAY_MS,
161157
+ "1d": 30 * DAY_MS
161158
+ };
161159
+ var BUCKET_LEAD_MS = 2 * DAY_MS;
161160
+ var SHORT_TIER_LOOKBACK_MS = 400 * DAY_MS;
161161
+ var yieldToEventLoop = () => new Promise((resolve) => setImmediate(resolve));
161162
+ var RetentionJob = class {
161163
+ deps;
161164
+ appliedUpTo = /* @__PURE__ */ new Map();
161165
+ running = null;
161166
+ constructor(deps) {
161167
+ this.deps = deps;
161168
+ }
161169
+ run(policy, now) {
161170
+ if (this.running !== null) return this.running;
161171
+ const run = this.doRun(policy, now).finally(() => {
161172
+ this.running = null;
161173
+ });
161174
+ this.running = run;
161175
+ return run;
161176
+ }
161177
+ async doRun(policy, now) {
161178
+ const { registry, counters, logger } = this.deps;
161179
+ const cutoffs = retentionCutoffs(policy, now);
161180
+ try {
161181
+ for (const tier of TIERS) {
161182
+ const cutoff = cutoffs[tier];
161183
+ if (cutoff === null) continue;
161184
+ for (const series of registry.all()) {
161185
+ if (series.firstTs - 864e5 >= cutoff) continue;
161186
+ if (tier === "raw" && registry.metric(series.key)?.ingest === "buckets") continue;
161187
+ const marker = `${tier}:${series.id}`;
161188
+ const applied = this.appliedUpTo.get(marker);
161189
+ if (applied !== void 0 && cutoff - applied < RETENTION_STEP_MS[tier]) continue;
161190
+ const lo = Math.max(0, applied === void 0 ? series.firstTs - BUCKET_LEAD_MS : applied - RETENTION_STEP_MS[tier]);
161191
+ counters.addDeleted(tier, await this.deleteSliced(tier, series.id, lo, cutoff - 1));
161192
+ this.appliedUpTo.set(marker, cutoff);
161193
+ }
161194
+ }
161195
+ await this.purgeDeparted(now);
161196
+ counters.retentionLastRunAt = now;
161197
+ } catch (err) {
161198
+ logger.warn("device-history: retention pass failed \u2014 retried at the next run", { meta: { error: err instanceof Error ? err.message : String(err) } });
161199
+ }
161200
+ }
161201
+ /** Delete `[lo, hiInclusive]` of one tier in time slices, yielding between them. */
161202
+ /** Drop the visit markers of a purged series. */
161203
+ forgetSeries(seriesId) {
161204
+ for (const tier of TIERS) this.appliedUpTo.delete(`${tier}:${seriesId}`);
161205
+ }
161206
+ async deleteSliced(tier, seriesId, lo, hiInclusive) {
161207
+ const yieldNow = this.deps.yieldNow ?? yieldToEventLoop;
161208
+ let deleted = 0;
161209
+ for (let from = lo; from <= hiInclusive; from += SLICE_MS[tier]) {
161210
+ const to = Math.min(from + SLICE_MS[tier] - 1, hiInclusive);
161211
+ deleted += await this.deps.store.deleteRange(tier, seriesId, from, to);
161212
+ await yieldNow();
161213
+ }
161214
+ return deleted;
161215
+ }
161216
+ /** Tier by tier in slices, then the series row (and whatever the slices missed). */
161217
+ async purgeSeries(series, now) {
161218
+ for (const tier of TIERS) {
161219
+ const lo = tier === "raw" || tier === "5m" ? Math.max(series.firstTs - BUCKET_LEAD_MS, now - SHORT_TIER_LOOKBACK_MS) : series.firstTs - BUCKET_LEAD_MS;
161220
+ await this.deleteSliced(tier, series.id, Math.max(0, lo), now + DAY_MS);
161221
+ }
161222
+ await this.deps.store.deleteSeries(series.id);
161223
+ }
161224
+ /**
161225
+ * Delete every series of a DELETED device now (D865). Driven by a tombstone
161226
+ * through the `device-removal-hook`, never by a listing: the week-long
161227
+ * absence clock above remains the backstop for a device removed before
161228
+ * tombstones existed.
161229
+ */
161230
+ async purgeDevice(deviceId, now) {
161231
+ const { registry, counters } = this.deps;
161232
+ let purged = 0;
161233
+ for (const series of registry.all()) {
161234
+ if (series.deviceId !== deviceId) continue;
161235
+ await this.purgeSeries(series, now);
161236
+ registry.remove(series.id);
161237
+ counters.purgedSeries += 1;
161238
+ purged += 1;
161239
+ }
161240
+ return purged;
161241
+ }
161242
+ async purgeDeparted(now) {
161243
+ const { registry, departures, counters, logger } = this.deps;
161244
+ let purged = 0;
161245
+ for (const series of registry.all()) {
161246
+ if (purged >= MAX_PURGES_PER_RUN) break;
161247
+ if (series.deviceId === null) continue;
161248
+ const since = departures.missingSince(series.deviceId);
161249
+ if (since === void 0 || now - since < DEPARTED_ABSENCE_MS) continue;
161250
+ await this.purgeSeries(series, now);
161251
+ registry.remove(series.id);
161252
+ counters.purgedSeries += 1;
161253
+ purged += 1;
161254
+ logger.info("device-history: purged the series of an unregistered device", {
161255
+ tags: { deviceId: series.deviceId },
161256
+ meta: { key: series.key }
161257
+ });
161258
+ }
161259
+ }
161260
+ };
161009
161261
  function subjectIdOf(subject) {
161010
161262
  return subject.kind === "device" ? `d:${subject.deviceId}` : `n:${subject.nodeId}`;
161011
161263
  }
@@ -161677,38 +161929,18 @@ var require_device_history_addon = __commonJS({
161677
161929
  this.deps.onDropped(dropped);
161678
161930
  }
161679
161931
  };
161680
- var FIVE_MINUTES_MS = 5 * 6e4;
161681
- var HOUR_MS = 60 * 6e4;
161682
- var DAY_MS = 24 * HOUR_MS;
161683
- function floorTo(ts, widthMs) {
161684
- return Math.floor(ts / widthMs) * widthMs;
161685
- }
161686
- function startOfLocalDay(ts) {
161687
- const d = new Date(ts);
161688
- d.setHours(0, 0, 0, 0);
161689
- return d.getTime();
161690
- }
161691
- function nextLocalDayStart(dayStart) {
161692
- const d = new Date(dayStart);
161693
- d.setDate(d.getDate() + 1);
161694
- d.setHours(0, 0, 0, 0);
161695
- return d.getTime();
161696
- }
161697
- function bucketStartOf(tier, ts) {
161698
- if (tier === "5m") return floorTo(ts, FIVE_MINUTES_MS);
161699
- if (tier === "1h") return floorTo(ts, HOUR_MS);
161700
- return startOfLocalDay(ts);
161701
- }
161702
- function bucketEndOf(tier, start) {
161703
- if (tier === "5m") return start + FIVE_MINUTES_MS;
161704
- if (tier === "1h") return start + HOUR_MS;
161705
- return nextLocalDayStart(start);
161932
+ var RECORD_MIN_INTERVAL_MS = 1e4;
161933
+ function nextSlot(slot, ts) {
161934
+ if (slot === void 0) return {
161935
+ lastTs: ts,
161936
+ nextDue: ts + RECORD_MIN_INTERVAL_MS
161937
+ };
161938
+ if (ts < slot.lastTs) return slot;
161939
+ return {
161940
+ lastTs: ts,
161941
+ nextDue: Math.max(slot.nextDue, ts) + RECORD_MIN_INTERVAL_MS
161942
+ };
161706
161943
  }
161707
- var ROLLUP_GRACE_MS = {
161708
- "5m": 3e4,
161709
- "1h": 5 * 6e4,
161710
- "1d": 15 * 6e4
161711
- };
161712
161944
  function addRefusal(refusals, key, reason) {
161713
161945
  const byReason = refusals.get(key) ?? /* @__PURE__ */ new Map();
161714
161946
  byReason.set(reason, (byReason.get(reason) ?? 0) + 1);
@@ -161726,7 +161958,7 @@ var require_device_history_addon = __commonJS({
161726
161958
  }
161727
161959
  var ProducerIngest = class {
161728
161960
  deps;
161729
- /** Last accepted point time per series, for the sustained-rate bound. */
161961
+ /** Rate state per series identity, for the sustained-rate bound. */
161730
161962
  lastAccepted = /* @__PURE__ */ new Map();
161731
161963
  constructor(deps) {
161732
161964
  this.deps = deps;
@@ -161785,13 +162017,13 @@ var require_device_history_addon = __commonJS({
161785
162017
  continue;
161786
162018
  }
161787
162019
  const identity = identityOf(point.key, subjectIdOf(point.subject), point.scope);
161788
- const last = this.lastAccepted.get(identity);
161789
- if (last !== void 0 && point.ts >= last && point.ts - last < 1e4) {
162020
+ const slot = this.lastAccepted.get(identity);
162021
+ if (slot !== void 0 && point.ts >= slot.lastTs && point.ts < slot.nextDue - 1e3) {
161790
162022
  addRefusal(refusals, point.key, "rate");
161791
162023
  counters.refuse("rate");
161792
162024
  continue;
161793
162025
  }
161794
- this.lastAccepted.set(identity, Math.max(last ?? point.ts, point.ts));
162026
+ this.lastAccepted.set(identity, nextSlot(slot, point.ts));
161795
162027
  this.deps.writer.enqueue({
161796
162028
  key: point.key,
161797
162029
  subject: point.subject,
@@ -162216,183 +162448,6 @@ var require_device_history_addon = __commonJS({
162216
162448
  const rollups = tiers.filter((t) => t !== "raw");
162217
162449
  return rollups.length > 0 ? rollups : ["5m"];
162218
162450
  }
162219
- var DEPARTED_ABSENCE_MS = 7 * DAY_MS;
162220
- var DepartureTracker = class {
162221
- store;
162222
- registry;
162223
- logger;
162224
- missing = /* @__PURE__ */ new Map();
162225
- constructor(store, registry, logger) {
162226
- this.store = store;
162227
- this.registry = registry;
162228
- this.logger = logger;
162229
- }
162230
- async load() {
162231
- this.missing = await this.store.loadDepartures();
162232
- }
162233
- missingSince(deviceId) {
162234
- return this.missing.get(deviceId);
162235
- }
162236
- /** Forget a device's clock — its series were removed because it was DELETED (D865). */
162237
- async forget(deviceId) {
162238
- await this.store.clearMissing([deviceId]);
162239
- const next = new Map(this.missing);
162240
- next.delete(deviceId);
162241
- this.missing = next;
162242
- }
162243
- /** Feed one SUCCESSFUL listing. A failed read never reaches here. */
162244
- async observe(listed, now) {
162245
- const withSeries = new Set(this.registry.all().flatMap((s) => s.deviceId === null ? [] : [s.deviceId]));
162246
- const back = [...this.missing.keys()].filter((id) => listed.has(id));
162247
- const gone = [...withSeries].filter((id) => !listed.has(id) && !this.missing.has(id));
162248
- try {
162249
- await this.store.clearMissing(back);
162250
- await this.store.markMissing(gone, now);
162251
- } catch (err) {
162252
- this.logger.warn("device-history: departure clock not written", { meta: { error: err instanceof Error ? err.message : String(err) } });
162253
- return;
162254
- }
162255
- const next = new Map(this.missing);
162256
- for (const id of back) next.delete(id);
162257
- for (const id of gone) next.set(id, now);
162258
- this.missing = next;
162259
- }
162260
- };
162261
- var DEFAULT_RETENTION = {
162262
- rawDays: 7,
162263
- fiveMinuteDays: 30,
162264
- hourDays: 365,
162265
- dayDays: null
162266
- };
162267
- function retentionCutoffs(policy, now) {
162268
- return {
162269
- raw: now - policy.rawDays * DAY_MS,
162270
- "5m": now - policy.fiveMinuteDays * DAY_MS,
162271
- "1h": now - policy.hourDays * DAY_MS,
162272
- "1d": policy.dayDays === null || policy.dayDays <= 0 ? null : now - policy.dayDays * DAY_MS
162273
- };
162274
- }
162275
- var TIERS = [
162276
- "raw",
162277
- "5m",
162278
- "1h",
162279
- "1d"
162280
- ];
162281
- var RETENTION_STEP_MS = {
162282
- raw: HOUR_MS,
162283
- "5m": HOUR_MS,
162284
- "1h": DAY_MS,
162285
- "1d": DAY_MS
162286
- };
162287
- var MAX_PURGES_PER_RUN = 20;
162288
- var SLICE_MS = {
162289
- raw: DAY_MS,
162290
- "5m": DAY_MS,
162291
- "1h": 30 * DAY_MS,
162292
- "1d": 30 * DAY_MS
162293
- };
162294
- var BUCKET_LEAD_MS = 2 * DAY_MS;
162295
- var SHORT_TIER_LOOKBACK_MS = 400 * DAY_MS;
162296
- var yieldToEventLoop = () => new Promise((resolve) => setImmediate(resolve));
162297
- var RetentionJob = class {
162298
- deps;
162299
- appliedUpTo = /* @__PURE__ */ new Map();
162300
- running = null;
162301
- constructor(deps) {
162302
- this.deps = deps;
162303
- }
162304
- run(policy, now) {
162305
- if (this.running !== null) return this.running;
162306
- const run = this.doRun(policy, now).finally(() => {
162307
- this.running = null;
162308
- });
162309
- this.running = run;
162310
- return run;
162311
- }
162312
- async doRun(policy, now) {
162313
- const { registry, counters, logger } = this.deps;
162314
- const cutoffs = retentionCutoffs(policy, now);
162315
- try {
162316
- for (const tier of TIERS) {
162317
- const cutoff = cutoffs[tier];
162318
- if (cutoff === null) continue;
162319
- for (const series of registry.all()) {
162320
- if (series.firstTs - 864e5 >= cutoff) continue;
162321
- if (tier === "raw" && registry.metric(series.key)?.ingest === "buckets") continue;
162322
- const marker = `${tier}:${series.id}`;
162323
- const applied = this.appliedUpTo.get(marker);
162324
- if (applied !== void 0 && cutoff - applied < RETENTION_STEP_MS[tier]) continue;
162325
- const lo = Math.max(0, applied === void 0 ? series.firstTs - BUCKET_LEAD_MS : applied - RETENTION_STEP_MS[tier]);
162326
- counters.addDeleted(tier, await this.deleteSliced(tier, series.id, lo, cutoff - 1));
162327
- this.appliedUpTo.set(marker, cutoff);
162328
- }
162329
- }
162330
- await this.purgeDeparted(now);
162331
- counters.retentionLastRunAt = now;
162332
- } catch (err) {
162333
- logger.warn("device-history: retention pass failed \u2014 retried at the next run", { meta: { error: err instanceof Error ? err.message : String(err) } });
162334
- }
162335
- }
162336
- /** Delete `[lo, hiInclusive]` of one tier in time slices, yielding between them. */
162337
- /** Drop the visit markers of a purged series. */
162338
- forgetSeries(seriesId) {
162339
- for (const tier of TIERS) this.appliedUpTo.delete(`${tier}:${seriesId}`);
162340
- }
162341
- async deleteSliced(tier, seriesId, lo, hiInclusive) {
162342
- const yieldNow = this.deps.yieldNow ?? yieldToEventLoop;
162343
- let deleted = 0;
162344
- for (let from = lo; from <= hiInclusive; from += SLICE_MS[tier]) {
162345
- const to = Math.min(from + SLICE_MS[tier] - 1, hiInclusive);
162346
- deleted += await this.deps.store.deleteRange(tier, seriesId, from, to);
162347
- await yieldNow();
162348
- }
162349
- return deleted;
162350
- }
162351
- /** Tier by tier in slices, then the series row (and whatever the slices missed). */
162352
- async purgeSeries(series, now) {
162353
- for (const tier of TIERS) {
162354
- const lo = tier === "raw" || tier === "5m" ? Math.max(series.firstTs - BUCKET_LEAD_MS, now - SHORT_TIER_LOOKBACK_MS) : series.firstTs - BUCKET_LEAD_MS;
162355
- await this.deleteSliced(tier, series.id, Math.max(0, lo), now + DAY_MS);
162356
- }
162357
- await this.deps.store.deleteSeries(series.id);
162358
- }
162359
- /**
162360
- * Delete every series of a DELETED device now (D865). Driven by a tombstone
162361
- * through the `device-removal-hook`, never by a listing: the week-long
162362
- * absence clock above remains the backstop for a device removed before
162363
- * tombstones existed.
162364
- */
162365
- async purgeDevice(deviceId, now) {
162366
- const { registry, counters } = this.deps;
162367
- let purged = 0;
162368
- for (const series of registry.all()) {
162369
- if (series.deviceId !== deviceId) continue;
162370
- await this.purgeSeries(series, now);
162371
- registry.remove(series.id);
162372
- counters.purgedSeries += 1;
162373
- purged += 1;
162374
- }
162375
- return purged;
162376
- }
162377
- async purgeDeparted(now) {
162378
- const { registry, departures, counters, logger } = this.deps;
162379
- let purged = 0;
162380
- for (const series of registry.all()) {
162381
- if (purged >= MAX_PURGES_PER_RUN) break;
162382
- if (series.deviceId === null) continue;
162383
- const since = departures.missingSince(series.deviceId);
162384
- if (since === void 0 || now - since < DEPARTED_ABSENCE_MS) continue;
162385
- await this.purgeSeries(series, now);
162386
- registry.remove(series.id);
162387
- counters.purgedSeries += 1;
162388
- purged += 1;
162389
- logger.info("device-history: purged the series of an unregistered device", {
162390
- tags: { deviceId: series.deviceId },
162391
- meta: { key: series.key }
162392
- });
162393
- }
162394
- }
162395
- };
162396
162451
  var HISTORY_NAMESPACE = "device-history";
162397
162452
  var COLLECTIONS = {
162398
162453
  metrics: "metrics",
@@ -163809,9 +163864,40 @@ var require_device_history_addon = __commonJS({
163809
163864
  runtime = null;
163810
163865
  unsubscribe = null;
163811
163866
  removalHook = null;
163867
+ /** This instance's readiness generation (the base class keeps its own private). */
163868
+ readinessGeneration = `device-history-${Date.now().toString(36)}`;
163812
163869
  constructor() {
163813
163870
  super({ ...DEFAULT_CONFIG });
163814
163871
  }
163872
+ /** `ready` is the store being open, emitted by {@link emitStoreReadiness}. */
163873
+ get autoEmitReadiness() {
163874
+ return false;
163875
+ }
163876
+ /** Readiness of both provided caps, on the bare node this runner belongs to. */
163877
+ emitStoreReadiness(state) {
163878
+ const ctx = this.ctxIfReady;
163879
+ if (ctx === null) return;
163880
+ const raw = ctx.kernel?.localNodeId ?? "hub";
163881
+ const nodeId = raw.includes("/") ? raw.split("/")[0] ?? raw : raw;
163882
+ for (const capName of [require_dist10.deviceHistoryCapability.name, require_dist10.deviceRemovalHookCapability.name]) try {
163883
+ require_dist10.emitReadiness(ctx.eventBus, {
163884
+ capName,
163885
+ scope: {
163886
+ type: "node",
163887
+ nodeId
163888
+ },
163889
+ state,
163890
+ generation: this.readinessGeneration,
163891
+ sourceNodeId: nodeId
163892
+ });
163893
+ } catch (err) {
163894
+ ctx.logger.warn("device-history: readiness not emitted", { meta: {
163895
+ capName,
163896
+ state,
163897
+ error: err instanceof Error ? err.message : String(err)
163898
+ } });
163899
+ }
163900
+ }
163815
163901
  retention() {
163816
163902
  const c = this.config;
163817
163903
  return {
@@ -163857,6 +163943,7 @@ var require_device_history_addon = __commonJS({
163857
163943
  setDeviceEnabled: async (input) => ({ enabled: await this.requireRuntime().setEnabled(input.deviceId, input.enabled) }),
163858
163944
  getStatus: async () => this.requireRuntime().status()
163859
163945
  };
163946
+ this.emitStoreReadiness("starting");
163860
163947
  this.ctx.logger.info("Initialized \u2014 device-history provider registered (store opens on hub link)");
163861
163948
  const removalHook = {
163862
163949
  onDeviceRemoved: async (input) => {
@@ -163933,6 +164020,7 @@ var require_device_history_addon = __commonJS({
163933
164020
  logger: this.ctx.logger,
163934
164021
  remove: (input) => removalHook.onDeviceRemoved(input)
163935
164022
  }));
164023
+ this.emitStoreReadiness("ready");
163936
164024
  this.ctx.logger.info("device-history: capturing", { meta: {
163937
164025
  series: runtime.status().series,
163938
164026
  metrics: runtime.status().metrics
@@ -163944,6 +164032,7 @@ var require_device_history_addon = __commonJS({
163944
164032
  await this.runtime?.stop();
163945
164033
  }
163946
164034
  async onShutdown() {
164035
+ this.emitStoreReadiness("down");
163947
164036
  await this.stopRuntime();
163948
164037
  this.runtime = null;
163949
164038
  }
@@ -164005,7 +164094,7 @@ var require_filesystem_storage_addon = __commonJS({
164005
164094
  [Symbol.toStringTag]: { value: "Module" }
164006
164095
  });
164007
164096
  var require_chunk = require_chunk_Cek0wNdY();
164008
- var require_dist10 = require_dist_C89nqNnn();
164097
+ var require_dist10 = require_dist_BZQjLPiz();
164009
164098
  var node_crypto = __require("crypto");
164010
164099
  var node_fs_promises = __require("fs/promises");
164011
164100
  var node_path = __require("path");
@@ -165115,12 +165204,12 @@ var require_lib = __commonJS({
165115
165204
  }
165116
165205
  });
165117
165206
 
165118
- // ../system/dist/wal-maintenance-DVN-DiVP.js
165119
- var require_wal_maintenance_DVN_DiVP = __commonJS({
165120
- "../system/dist/wal-maintenance-DVN-DiVP.js"(exports) {
165207
+ // ../system/dist/wal-maintenance-DfSIOj24.js
165208
+ var require_wal_maintenance_DfSIOj24 = __commonJS({
165209
+ "../system/dist/wal-maintenance-DfSIOj24.js"(exports) {
165121
165210
  "use strict";
165122
165211
  var require_chunk = require_chunk_Cek0wNdY();
165123
- var require_dist10 = require_dist_C89nqNnn();
165212
+ var require_dist10 = require_dist_BZQjLPiz();
165124
165213
  var require_prefix_range = require_prefix_range_D_KueXbQ();
165125
165214
  var node_crypto = __require("crypto");
165126
165215
  var node_module = __require("module");
@@ -169370,9 +169459,9 @@ var require_sqlite_settings_addon = __commonJS({
169370
169459
  [Symbol.toStringTag]: { value: "Module" }
169371
169460
  });
169372
169461
  var require_chunk = require_chunk_Cek0wNdY();
169373
- var require_dist10 = require_dist_C89nqNnn();
169462
+ var require_dist10 = require_dist_BZQjLPiz();
169374
169463
  var require_retired_settings_keys = require_retired_settings_keys_D_VwZiDt();
169375
- var require_wal_maintenance = require_wal_maintenance_DVN_DiVP();
169464
+ var require_wal_maintenance = require_wal_maintenance_DfSIOj24();
169376
169465
  var require_sqlite_snapshot_protocol = require_sqlite_snapshot_protocol_B9OndqZv();
169377
169466
  var require_wal_checkpoint_policy = require_wal_checkpoint_policy_d2z2qPqx();
169378
169467
  var node_fs_promises = __require("fs/promises");
@@ -171275,7 +171364,7 @@ var require_sqlite_storage = __commonJS({
171275
171364
  });
171276
171365
  require_chunk_Cek0wNdY();
171277
171366
  var require_builtins_sqlite_storage_filesystem_storage_addon = require_filesystem_storage_addon();
171278
- var require_wal_maintenance = require_wal_maintenance_DVN_DiVP();
171367
+ var require_wal_maintenance = require_wal_maintenance_DfSIOj24();
171279
171368
  var require_builtins_sqlite_storage_sqlite_settings_addon = require_sqlite_settings_addon();
171280
171369
  var ConfigStore = class {
171281
171370
  db;
@@ -171359,7 +171448,7 @@ var require_storage_orchestrator_addon = __commonJS({
171359
171448
  [Symbol.toStringTag]: { value: "Module" }
171360
171449
  });
171361
171450
  var require_chunk = require_chunk_Cek0wNdY();
171362
- var require_dist10 = require_dist_C89nqNnn();
171451
+ var require_dist10 = require_dist_BZQjLPiz();
171363
171452
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
171364
171453
  var zod = require_zod();
171365
171454
  var node_crypto = __require("crypto");
@@ -175948,11 +176037,11 @@ var require_storage_orchestrator = __commonJS({
175948
176037
  }
175949
176038
  });
175950
176039
 
175951
- // ../system/dist/constants-B_X9cWEK.js
175952
- var require_constants_B_X9cWEK = __commonJS({
175953
- "../system/dist/constants-B_X9cWEK.js"(exports) {
176040
+ // ../system/dist/constants-Njka8Cv6.js
176041
+ var require_constants_Njka8Cv6 = __commonJS({
176042
+ "../system/dist/constants-Njka8Cv6.js"(exports) {
175954
176043
  "use strict";
175955
- var MESH_CA_KEY_REF = require_dist_C89nqNnn().buildSecretRef({
176044
+ var MESH_CA_KEY_REF = require_dist_BZQjLPiz().buildSecretRef({
175956
176045
  owner: "system",
175957
176046
  scope: { kind: "global" },
175958
176047
  fieldPath: "meshCaKey"
@@ -176015,14 +176104,14 @@ var require_constants_B_X9cWEK = __commonJS({
176015
176104
  }
176016
176105
  });
176017
176106
 
176018
- // ../system/dist/agent-https-CoyOZ3pC.js
176019
- var require_agent_https_CoyOZ3pC = __commonJS({
176020
- "../system/dist/agent-https-CoyOZ3pC.js"(exports) {
176107
+ // ../system/dist/agent-https-DOELEug8.js
176108
+ var require_agent_https_DOELEug8 = __commonJS({
176109
+ "../system/dist/agent-https-DOELEug8.js"(exports) {
176021
176110
  "use strict";
176022
176111
  var require_chunk = require_chunk_Cek0wNdY();
176023
- var require_dist10 = require_dist_C89nqNnn();
176112
+ var require_dist10 = require_dist_BZQjLPiz();
176024
176113
  var require_x509_es = require_x509_es_C4cOo48M();
176025
- var require_constants15 = require_constants_B_X9cWEK();
176114
+ var require_constants15 = require_constants_Njka8Cv6();
176026
176115
  var zod = require_zod();
176027
176116
  var node_crypto = __require("crypto");
176028
176117
  var _camstack_types_node = require_node();
@@ -194783,11 +194872,11 @@ var require_system_config_addon = __commonJS({
194783
194872
  [Symbol.toStringTag]: { value: "Module" }
194784
194873
  });
194785
194874
  var require_chunk = require_chunk_Cek0wNdY();
194786
- var require_dist10 = require_dist_C89nqNnn();
194875
+ var require_dist10 = require_dist_BZQjLPiz();
194787
194876
  var require_safe_buffer$1 = require_safe_buffer_D3aoa_7X();
194788
194877
  var require_x509_es = require_x509_es_C4cOo48M();
194789
- var require_constants$8 = require_constants_B_X9cWEK();
194790
- var require_agent_https = require_agent_https_CoyOZ3pC();
194878
+ var require_constants$8 = require_constants_Njka8Cv6();
194879
+ var require_agent_https = require_agent_https_DOELEug8();
194791
194880
  var require_src$1 = require_src_CnAqG6EF();
194792
194881
  var zod = require_zod();
194793
194882
  var node_crypto = __require("crypto");
@@ -275262,7 +275351,7 @@ var require_winston_logging = __commonJS({
275262
275351
  [Symbol.toStringTag]: { value: "Module" }
275263
275352
  });
275264
275353
  var require_chunk = require_chunk_Cek0wNdY();
275265
- var require_dist10 = require_dist_C89nqNnn();
275354
+ var require_dist10 = require_dist_BZQjLPiz();
275266
275355
  var require_formatter = require_formatter_DqAKDlvN();
275267
275356
  var require_log_file_read_protocol = require_log_file_read_protocol_D0WcLbIV();
275268
275357
  var node_path = __require("path");
@@ -283063,14 +283152,14 @@ var require_lib_8oZrELLm = __commonJS({
283063
283152
  }
283064
283153
  });
283065
283154
 
283066
- // ../system/dist/hub-mdns-ciao-DB1Y9agt.js
283067
- var require_hub_mdns_ciao_DB1Y9agt = __commonJS({
283068
- "../system/dist/hub-mdns-ciao-DB1Y9agt.js"(exports) {
283155
+ // ../system/dist/hub-mdns-ciao-nce3TXs_.js
283156
+ var require_hub_mdns_ciao_nce3TXs = __commonJS({
283157
+ "../system/dist/hub-mdns-ciao-nce3TXs_.js"(exports) {
283069
283158
  "use strict";
283070
283159
  var require_chunk = require_chunk_Cek0wNdY();
283071
- var require_dist10 = require_dist_C89nqNnn();
283160
+ var require_dist10 = require_dist_BZQjLPiz();
283072
283161
  var require_x509_es = require_x509_es_C4cOo48M();
283073
- var require_agent_https = require_agent_https_CoyOZ3pC();
283162
+ var require_agent_https = require_agent_https_DOELEug8();
283074
283163
  var node_crypto = __require("crypto");
283075
283164
  var _camstack_types_node = require_node();
283076
283165
  var node_fs_promises = __require("fs/promises");
@@ -284082,12 +284171,12 @@ var require_platform_key_source_Di7HrlGR = __commonJS({
284082
284171
  }
284083
284172
  });
284084
284173
 
284085
- // ../system/dist/restore-archive-4DOUR5Gu.js
284086
- var require_restore_archive_4DOUR5Gu = __commonJS({
284087
- "../system/dist/restore-archive-4DOUR5Gu.js"(exports) {
284174
+ // ../system/dist/restore-archive-FyfZ8YMC.js
284175
+ var require_restore_archive_FyfZ8YMC = __commonJS({
284176
+ "../system/dist/restore-archive-FyfZ8YMC.js"(exports) {
284088
284177
  "use strict";
284089
284178
  var require_chunk = require_chunk_Cek0wNdY();
284090
- var require_dist10 = require_dist_C89nqNnn();
284179
+ var require_dist10 = require_dist_BZQjLPiz();
284091
284180
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
284092
284181
  var zod = require_zod();
284093
284182
  var node_crypto = __require("crypto");
@@ -288816,6 +288905,151 @@ var require_restore_archive_4DOUR5Gu = __commonJS({
288816
288905
  }
288817
288906
  });
288818
288907
 
288908
+ // ../system/dist/coral-accelerators-Bi_c3Rft.js
288909
+ var require_coral_accelerators_Bi_c3Rft = __commonJS({
288910
+ "../system/dist/coral-accelerators-Bi_c3Rft.js"(exports) {
288911
+ "use strict";
288912
+ var require_chunk = require_chunk_Cek0wNdY();
288913
+ var node_fs = __require("fs");
288914
+ node_fs = require_chunk.__toESM(node_fs);
288915
+ var CORAL_USB_IDS = [{
288916
+ vendor: "1a6e",
288917
+ product: "089a"
288918
+ }, {
288919
+ vendor: "18d1",
288920
+ product: "9302"
288921
+ }];
288922
+ var CORAL_PCI_VENDOR = "0x1ac1";
288923
+ var CORAL_PCI_DEVICE = "0x089a";
288924
+ var APEX_ENTRY = /^apex_(\d+)$/;
288925
+ var DEFAULT_EDGETPU_LIB = "/data/deps/edgetpu/lib/libedgetpu.so.1";
288926
+ function countUsbCorals(fsx) {
288927
+ let count = 0;
288928
+ for (const device of fsx.listUsbDevices()) {
288929
+ const vendor = fsx.readUsbAttr(device, "idVendor").toLowerCase();
288930
+ const product = fsx.readUsbAttr(device, "idProduct").toLowerCase();
288931
+ if (CORAL_USB_IDS.some((id) => id.vendor === vendor && id.product === product)) count++;
288932
+ }
288933
+ return count;
288934
+ }
288935
+ function countPciCorals(fsx) {
288936
+ let count = 0;
288937
+ for (const device of fsx.listPciDevices()) {
288938
+ const vendor = fsx.readPciAttr(device, "vendor").toLowerCase();
288939
+ const product = fsx.readPciAttr(device, "device").toLowerCase();
288940
+ if (vendor === CORAL_PCI_VENDOR && product === CORAL_PCI_DEVICE) count++;
288941
+ }
288942
+ return count;
288943
+ }
288944
+ function classifyPci(fsx) {
288945
+ let usable = 0;
288946
+ let notAccessible = 0;
288947
+ for (const entry of fsx.listApexClass()) {
288948
+ const match = APEX_ENTRY.exec(entry);
288949
+ if (match === null) continue;
288950
+ const node = `/dev/apex_${match[1]}`;
288951
+ if (fsx.exists(node) && fsx.canOpen(node)) usable++;
288952
+ else notAccessible++;
288953
+ }
288954
+ const driverMissing = Math.max(0, countPciCorals(fsx) - usable - notAccessible);
288955
+ return {
288956
+ usable,
288957
+ notAccessible,
288958
+ driverMissing
288959
+ };
288960
+ }
288961
+ function classifyCoralAccelerator(fsx) {
288962
+ const usb = countUsbCorals(fsx);
288963
+ const pci = classifyPci(fsx);
288964
+ const units = [];
288965
+ if (usb > 0) units.push({
288966
+ bus: "usb",
288967
+ count: usb
288968
+ });
288969
+ if (pci.usable > 0) units.push({
288970
+ bus: "pci",
288971
+ count: pci.usable
288972
+ });
288973
+ const unavailable = [];
288974
+ if (pci.driverMissing > 0) unavailable.push({
288975
+ bus: "pci",
288976
+ count: pci.driverMissing,
288977
+ reason: "driver-missing"
288978
+ });
288979
+ if (pci.notAccessible > 0) unavailable.push({
288980
+ bus: "pci",
288981
+ count: pci.notAccessible,
288982
+ reason: "device-not-accessible"
288983
+ });
288984
+ if (units.length > 0 || unavailable.length > 0) return unavailable.length > 0 ? {
288985
+ type: "coral-edgetpu",
288986
+ units,
288987
+ unavailable
288988
+ } : {
288989
+ type: "coral-edgetpu",
288990
+ units
288991
+ };
288992
+ const libPath = process.env["CAMSTACK_EDGETPU_LIB"] ?? DEFAULT_EDGETPU_LIB;
288993
+ if (fsx.exists(libPath)) return {
288994
+ type: "coral-edgetpu",
288995
+ units: [{
288996
+ bus: "usb",
288997
+ count: 1
288998
+ }]
288999
+ };
289000
+ return null;
289001
+ }
289002
+ function safeList(dir) {
289003
+ try {
289004
+ return node_fs.default.readdirSync(dir);
289005
+ } catch {
289006
+ return [];
289007
+ }
289008
+ }
289009
+ function safeRead(path) {
289010
+ try {
289011
+ return node_fs.default.readFileSync(path, "utf8").trim();
289012
+ } catch {
289013
+ return "";
289014
+ }
289015
+ }
289016
+ var nodeCoralFs = {
289017
+ listUsbDevices: () => safeList("/sys/bus/usb/devices"),
289018
+ readUsbAttr: (device, attr) => safeRead(`/sys/bus/usb/devices/${device}/${attr}`),
289019
+ listPciDevices: () => safeList("/sys/bus/pci/devices"),
289020
+ readPciAttr: (device, attr) => safeRead(`/sys/bus/pci/devices/${device}/${attr}`),
289021
+ listApexClass: () => safeList("/sys/class/apex"),
289022
+ canOpen: (path) => {
289023
+ try {
289024
+ node_fs.default.accessSync(path, node_fs.default.constants.R_OK | node_fs.default.constants.W_OK);
289025
+ return true;
289026
+ } catch {
289027
+ return false;
289028
+ }
289029
+ },
289030
+ exists: (path) => {
289031
+ try {
289032
+ return node_fs.default.existsSync(path);
289033
+ } catch {
289034
+ return false;
289035
+ }
289036
+ }
289037
+ };
289038
+ Object.defineProperty(exports, "classifyCoralAccelerator", {
289039
+ enumerable: true,
289040
+ get: function() {
289041
+ return classifyCoralAccelerator;
289042
+ }
289043
+ });
289044
+ Object.defineProperty(exports, "nodeCoralFs", {
289045
+ enumerable: true,
289046
+ get: function() {
289047
+ return nodeCoralFs;
289048
+ }
289049
+ });
289050
+ }
289051
+ });
289052
+
288819
289053
  // ../../node_modules/@trpc/client/dist/chunk-DWy1uDak.cjs
288820
289054
  var require_chunk_DWy1uDak = __commonJS({
288821
289055
  "../../node_modules/@trpc/client/dist/chunk-DWy1uDak.cjs"(exports) {
@@ -295408,9 +295642,9 @@ var require_dist3 = __commonJS({
295408
295642
  "use strict";
295409
295643
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
295410
295644
  var require_chunk = require_chunk_Cek0wNdY();
295411
- var require_dist10 = require_dist_C89nqNnn();
295645
+ var require_dist10 = require_dist_BZQjLPiz();
295412
295646
  var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
295413
- var require_device_ca = require_device_ca_CVK3YcR();
295647
+ var require_device_ca = require_device_ca_BrVK_5s3();
295414
295648
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
295415
295649
  require_alerts();
295416
295650
  var require_builtins_calendars_calendars_addon = require_calendars_addon();
@@ -295436,21 +295670,22 @@ var require_dist3 = __commonJS({
295436
295670
  var require_builtins_native_metrics_native_metrics_addon = require_native_metrics_addon();
295437
295671
  var require_builtins_device_history_device_history_addon = require_device_history_addon();
295438
295672
  var require_builtins_sqlite_storage_filesystem_storage_addon = require_filesystem_storage_addon();
295439
- var require_wal_maintenance = require_wal_maintenance_DVN_DiVP();
295673
+ var require_wal_maintenance = require_wal_maintenance_DfSIOj24();
295440
295674
  var require_builtins_sqlite_storage_sqlite_settings_addon = require_sqlite_settings_addon();
295441
295675
  var require_builtins_sqlite_storage_index = require_sqlite_storage();
295442
295676
  var require_builtins_storage_orchestrator_storage_orchestrator_addon = require_storage_orchestrator_addon();
295443
295677
  require_storage_orchestrator();
295444
- var require_constants15 = require_constants_B_X9cWEK();
295445
- var require_agent_https = require_agent_https_CoyOZ3pC();
295678
+ var require_constants15 = require_constants_Njka8Cv6();
295679
+ var require_agent_https = require_agent_https_DOELEug8();
295446
295680
  var require_builtins_system_config_system_config_addon = require_system_config_addon();
295447
295681
  require_system_config();
295448
295682
  var require_builtins_winston_logging_index = require_winston_logging();
295449
295683
  var require_custom_action_registry = require_custom_action_registry_COyb49zm();
295450
- var require_hub_mdns_ciao = require_hub_mdns_ciao_DB1Y9agt();
295684
+ var require_hub_mdns_ciao = require_hub_mdns_ciao_nce3TXs();
295451
295685
  var require_platform_key_source = require_platform_key_source_Di7HrlGR();
295452
295686
  var require_resource_monitor = require_resource_monitor_mio9dSCT();
295453
- var require_restore_archive = require_restore_archive_4DOUR5Gu();
295687
+ var require_restore_archive = require_restore_archive_FyfZ8YMC();
295688
+ var require_coral_accelerators = require_coral_accelerators_Bi_c3Rft();
295454
295689
  var zod = require_zod();
295455
295690
  var node_crypto = __require("crypto");
295456
295691
  node_crypto = require_chunk.__toESM(node_crypto);
@@ -313879,26 +314114,6 @@ var require_dist3 = __commonJS({
313879
314114
  return false;
313880
314115
  }
313881
314116
  }
313882
- function detectCoralUsb() {
313883
- const CORAL_IDS = [{
313884
- vendor: "1a6e",
313885
- product: "089a"
313886
- }, {
313887
- vendor: "18d1",
313888
- product: "9302"
313889
- }];
313890
- try {
313891
- for (const device of node_fs.readdirSync("/sys/bus/usb/devices")) try {
313892
- const base = `/sys/bus/usb/devices/${device}`;
313893
- const vendor = node_fs.readFileSync(`${base}/idVendor`, "utf8").trim().toLowerCase();
313894
- const product = node_fs.readFileSync(`${base}/idProduct`, "utf8").trim().toLowerCase();
313895
- if (CORAL_IDS.some((id) => id.vendor === vendor && id.product === product)) return true;
313896
- } catch {
313897
- }
313898
- } catch {
313899
- }
313900
- return safeExistsSync(process.env["CAMSTACK_EDGETPU_LIB"] ?? "/data/deps/edgetpu/lib/libedgetpu.so.1");
313901
- }
313902
314117
  function probeLinuxGpus() {
313903
314118
  const signals = {
313904
314119
  hasNvidiaGpu: false,
@@ -313906,7 +314121,7 @@ var require_dist3 = __commonJS({
313906
314121
  hasIntelGpu: false,
313907
314122
  hasRenderNode: false,
313908
314123
  hasIntelNpu: safeExistsSync("/dev/accel/accel0"),
313909
- hasCoral: detectCoralUsb()
314124
+ coral: require_coral_accelerators.classifyCoralAccelerator(require_coral_accelerators.nodeCoralFs)
313910
314125
  };
313911
314126
  signals.hasRenderNode = safeExistsSync("/dev/dri/renderD128");
313912
314127
  if (safeExistsSync("/dev/nvidia0") || safeExistsSync("/proc/driver/nvidia/version")) signals.hasNvidiaGpu = true;
@@ -313941,7 +314156,7 @@ var require_dist3 = __commonJS({
313941
314156
  hasIntelGpu: false,
313942
314157
  hasRenderNode: false,
313943
314158
  hasIntelNpu: false,
313944
- hasCoral: safeExistsSync(process.env["CAMSTACK_EDGETPU_LIB"] ?? "/data/deps/edgetpu/lib/libedgetpu.so.1")
314159
+ coral: require_coral_accelerators.classifyCoralAccelerator(require_coral_accelerators.nodeCoralFs)
313945
314160
  };
313946
314161
  }
313947
314162
  function pickBackendsForPlatform(signals) {
@@ -314003,7 +314218,7 @@ var require_dist3 = __commonJS({
314003
314218
  return {
314004
314219
  gpu: signals.hasNvidiaGpu ? { type: "nvidia" } : signals.hasAmdGpu ? { type: "amd" } : signals.hasIntelGpu ? { type: "intel" } : signals.hasRenderNode ? { type: "intel" } : null,
314005
314220
  npu: signals.platform === "darwin" && signals.arch === "arm64" ? { type: "apple-ane" } : signals.hasIntelNpu ? { type: "intel-npu" } : null,
314006
- coral: signals.hasCoral ? { type: "coral-edgetpu" } : null
314221
+ coral: signals.coral
314007
314222
  };
314008
314223
  }
314009
314224
  function createKernelInferenceEngine() {
@@ -315762,7 +315977,7 @@ var require_dist3 = __commonJS({
315762
315977
  name: gpuType
315763
315978
  } : null,
315764
315979
  npu: npuType !== null ? { type: npuType } : null,
315765
- coral: inference.coral != null ? { type: "coral-edgetpu" } : null
315980
+ coral: inference.coral ?? null
315766
315981
  };
315767
315982
  }
315768
315983
  function localSupportedPythonRuntimes() {
@@ -375416,9 +375631,24 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
375416
375631
  name: zod.z.string().optional(),
375417
375632
  generation: zod.z.enum(["xdna1", "xdna2"]).optional()
375418
375633
  });
375634
+ var CoralBusSchema = zod.z.enum(["usb", "pci"]);
375419
375635
  var CoralInfoSchema = zod.z.object({
375420
375636
  type: zod.z.literal("coral-edgetpu"),
375421
- bus: zod.z.string().optional()
375637
+ /** Legacy single-bus report (older nodes) — read via `coralUsableUnits`. */
375638
+ bus: zod.z.string().optional(),
375639
+ /** Legacy USB unit count (older nodes) — read via `coralUsableUnits`. */
375640
+ count: zod.z.number().int().nonnegative().optional(),
375641
+ /** Usable units per bus — each one is its own `edgetpu:<bus>[:N]` device. */
375642
+ units: zod.z.array(zod.z.object({
375643
+ bus: CoralBusSchema,
375644
+ count: zod.z.number().int().nonnegative()
375645
+ })).readonly().optional(),
375646
+ /** Present-but-unusable units, each with its typed reason (never "absent"). */
375647
+ unavailable: zod.z.array(zod.z.object({
375648
+ bus: CoralBusSchema,
375649
+ count: zod.z.number().int().nonnegative(),
375650
+ reason: zod.z.enum(["driver-missing", "device-not-accessible"])
375651
+ })).readonly().optional()
375422
375652
  });
375423
375653
  var HardwareInfoSchema = zod.z.object({
375424
375654
  platform: HardwarePlatformSchema,
@@ -406495,6 +406725,34 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
406495
406725
  });
406496
406726
  return out;
406497
406727
  }
406728
+ var BUS_ORDER = ["usb", "pci"];
406729
+ function unitDevice(bus, index) {
406730
+ return index === 0 ? bus : `${bus}:${index}`;
406731
+ }
406732
+ function countOn(coral, bus) {
406733
+ if (coral.units !== void 0) return coral.units.filter((u) => u.bus === bus).reduce((n, u) => n + Math.max(0, u.count), 0);
406734
+ return bus === (coral.bus === "pci" ? "pci" : "usb") ? Math.max(1, coral.count ?? 1) : 0;
406735
+ }
406736
+ function coralUsableUnits(coral) {
406737
+ if (coral == null) return [];
406738
+ const out = [];
406739
+ for (const bus of BUS_ORDER) {
406740
+ const count = countOn(coral, bus);
406741
+ for (let index = 0; index < count; index++) out.push({
406742
+ bus,
406743
+ index,
406744
+ device: unitDevice(bus, index)
406745
+ });
406746
+ }
406747
+ return out;
406748
+ }
406749
+ var KEY_DEVICE = /^(usb|pci)(?::(\d+))?$/;
406750
+ function edgetpuDelegateDevice(device2) {
406751
+ const match = KEY_DEVICE.exec(device2.trim());
406752
+ if (match === null) throw new Error(`edgetpu device "${device2}" is not usb[:N] or pci[:N]`);
406753
+ const [, bus, ordinal] = match;
406754
+ return `${bus}:${ordinal ?? "0"}`;
406755
+ }
406498
406756
  var AUTO = {
406499
406757
  value: "auto",
406500
406758
  label: "Auto"
@@ -406507,6 +406765,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
406507
406765
  value: "usb",
406508
406766
  label: "Coral USB"
406509
406767
  };
406768
+ function coralUnitOption(unit) {
406769
+ const bus = unit.bus === "pci" ? "PCIe" : "USB";
406770
+ const label = unit.index === 0 ? `Coral ${bus}` : `Coral ${bus} ${unit.index + 1}`;
406771
+ return {
406772
+ value: unit.device,
406773
+ label
406774
+ };
406775
+ }
406510
406776
  var RUNTIMES = [
406511
406777
  {
406512
406778
  id: "onnx",
@@ -406573,8 +406839,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
406573
406839
  },
406574
406840
  {
406575
406841
  id: "edgetpu",
406576
- supports: (hw) => hw?.coral != null,
406577
- devices: () => [USB],
406842
+ supports: (hw) => coralUsableUnits(hw?.coral).length > 0,
406843
+ devices: (hw) => {
406844
+ const units = coralUsableUnits(hw?.coral);
406845
+ return units.length > 0 ? units.map(coralUnitOption) : [USB];
406846
+ },
406578
406847
  defaultDevice: "usb"
406579
406848
  }
406580
406849
  ];
@@ -406643,7 +406912,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
406643
406912
  available: true
406644
406913
  });
406645
406914
  }
406646
- if (hw.coral != null) scores.push({
406915
+ if (coralUsableUnits(hw.coral).length > 0) scores.push({
406647
406916
  runtime: "python",
406648
406917
  backend: "edgetpu",
406649
406918
  format: "tflite",
@@ -406693,11 +406962,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
406693
406962
  continue;
406694
406963
  }
406695
406964
  if (s.backend === "edgetpu") {
406696
- const coralCount = Math.max(1, hw.coral?.count ?? 1);
406697
- for (let i = 0; i < coralCount; i++) {
406698
- const dev2 = i === 0 ? "usb" : `usb:${i}`;
406699
- out.push(device("edgetpu", dev2, s.format, s.score));
406700
- }
406965
+ for (const unit of coralUsableUnits(hw.coral)) out.push(device("edgetpu", unit.device, s.format, s.score));
406701
406966
  continue;
406702
406967
  }
406703
406968
  if (s.backend === "onnx" && s.reason.startsWith("ONNX WebGPU")) {
@@ -408866,6 +409131,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
408866
409131
  exports.controlCapability = controlCapability;
408867
409132
  exports.convertPresetFeature = convertPresetFeature;
408868
409133
  exports.convertUnit = convertUnit;
409134
+ exports.coralUsableUnits = coralUsableUnits;
408869
409135
  exports.coreBlockAddonId = coreBlockAddonId;
408870
409136
  exports.coreBlockComposition = coreBlockComposition;
408871
409137
  exports.coreBlockIdFromAddonId = coreBlockIdFromAddonId;
@@ -408958,6 +409224,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
408958
409224
  exports.doorbellCapability = doorbellCapability;
408959
409225
  exports.doorbellFeatureSources = doorbellFeatureSources;
408960
409226
  exports.droppedConditionsForKind = droppedConditionsForKind;
409227
+ exports.edgetpuDelegateDevice = edgetpuDelegateDevice;
408961
409228
  exports.effectiveStepSettings = effectiveStepSettings;
408962
409229
  exports.egressTranscodeSharingKey = egressTranscodeSharingKey;
408963
409230
  exports.egressTransportFromRequest = egressTransportFromRequest;
@@ -547086,6 +547353,7 @@ var require_agent_service = __commonJS({
547086
547353
  var os = __importStar(__require("os"));
547087
547354
  var path = __importStar(__require("path"));
547088
547355
  var system_1 = require_dist3();
547356
+ var types_1 = require_dist4();
547089
547357
  var moleculer_1 = require_moleculer();
547090
547358
  var agent_deploy_swap_js_1 = require_agent_deploy_swap();
547091
547359
  var agent_undeploy_js_1 = require_agent_undeploy();
@@ -547104,7 +547372,7 @@ var require_agent_service = __commonJS({
547104
547372
  detectionDevices.push(inference.gpu.type);
547105
547373
  if (inference.npu !== null)
547106
547374
  detectionDevices.push(inference.npu.type);
547107
- if (inference.coral != null)
547375
+ if (inference.coral != null && (0, types_1.coralUsableUnits)(inference.coral).length > 0)
547108
547376
  detectionDevices.push(inference.coral.type);
547109
547377
  return {
547110
547378
  decode: {