camstack 1.2.66 → 1.2.67

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.
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
23633
23633
  }
23634
23634
  });
23635
23635
 
23636
- // ../system/dist/dist-CcvXUhHK.js
23637
- var require_dist_CcvXUhHK = __commonJS({
23638
- "../system/dist/dist-CcvXUhHK.js"(exports) {
23636
+ // ../system/dist/dist-Keu5TDO7.js
23637
+ var require_dist_Keu5TDO7 = __commonJS({
23638
+ "../system/dist/dist-Keu5TDO7.js"(exports) {
23639
23639
  "use strict";
23640
23640
  var zod = require_zod();
23641
23641
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
@@ -31940,6 +31940,80 @@ var require_dist_CcvXUhHK = __commonJS({
31940
31940
  getInfo: method(zod.z.void(), EmbeddingInfoSchema, { auth: "admin" })
31941
31941
  }
31942
31942
  };
31943
+ var FailureReasonCountSchema = zod.z.object({
31944
+ /**
31945
+ * Why the attempt did not land, in the contributor's own vocabulary —
31946
+ * `worker-lease-gone`, `queue-overflow`, `timeout`, `empty-read`. The same
31947
+ * strings that already appear in this repo's logs and, where one exists, the
31948
+ * same string the per-track `previewMissReason` records (D276): a second
31949
+ * vocabulary for the same loss would make the row and the counter
31950
+ * un-joinable.
31951
+ */
31952
+ reason: zod.z.string(),
31953
+ count: zod.z.number().int().nonnegative()
31954
+ });
31955
+ var FailureContributionSchema = zod.z.object({
31956
+ /**
31957
+ * The failing path — `enrichment-crop`, `inference`, `plate-ocr`,
31958
+ * `person-over-vehicle`. Free text, for the reason `load-contribution` keeps
31959
+ * `unit` free: the families are owned by different addons and a shared enum
31960
+ * is a central list that rots invisibly.
31961
+ */
31962
+ family: zod.z.string(),
31963
+ /**
31964
+ * The NUMERIC device id — the same value every log line carries as
31965
+ * `tags.deviceId`. Never nullable and never absent: a contributor that
31966
+ * cannot name the camera must not emit the entry, because a fleet total
31967
+ * cannot answer the only question anybody asks of this surface.
31968
+ */
31969
+ deviceId: zod.z.number().int().positive(),
31970
+ /**
31971
+ * A second dimension inside the family: the model / step id for an inference
31972
+ * timeout, so "which camera AND which model" is one read. Absent when the
31973
+ * family has a single variant.
31974
+ */
31975
+ variant: zod.z.string().optional(),
31976
+ /**
31977
+ * Epoch ms this counter started — the INCARNATION MARKER. A consumer
31978
+ * differencing two reads must drop the interval when it changes, because the
31979
+ * counter restarted from zero in a respawned runner. Same discipline as
31980
+ * `LoadContribution.startedAtMs`.
31981
+ */
31982
+ sinceMs: zod.z.number(),
31983
+ /** Epoch ms it was read. `atMs - sinceMs` is the interval this covers. */
31984
+ atMs: zod.z.number(),
31985
+ /**
31986
+ * THE DENOMINATOR — every attempt on this path for this camera in the
31987
+ * window. A failure count published without it is the mistake this schema
31988
+ * exists to make impossible.
31989
+ */
31990
+ attempts: zod.z.number().int().nonnegative(),
31991
+ /** Attempts that landed. `attempts - succeeded` is the loss. */
31992
+ succeeded: zod.z.number().int().nonnegative(),
31993
+ /** The loss, partitioned. Sums to `attempts - succeeded`. */
31994
+ reasons: zod.z.array(FailureReasonCountSchema).readonly()
31995
+ });
31996
+ var failureContributionCapability = {
31997
+ name: "failure-contribution",
31998
+ scope: "system",
31999
+ mode: "collection",
32000
+ internal: true,
32001
+ methods: {
32002
+ /**
32003
+ * This addon's per-camera failure counters, read live from bounded in-RAM
32004
+ * state it already keeps. Inert: no persistence, no sampling, no timer.
32005
+ *
32006
+ * READING NEVER RESETS. The counters are CUMULATIVE since `sinceMs`, and a
32007
+ * consumer that wants a rate differences two reads. A draining read would
32008
+ * make two operators with the page open each destroy half of the other's
32009
+ * numbers, and `load-contribution` already settled the same question the
32010
+ * same way for `cpuSeconds`.
32011
+ */
32012
+ list: method(zod.z.void(), zod.z.array(FailureContributionSchema).readonly())
32013
+ },
32014
+ /** In-process only — enumerated through `addons.listCapabilityProviders`. */
32015
+ mount: { kind: "skip" }
32016
+ };
31943
32017
  var DirEntrySchema = zod.z.object({
31944
32018
  name: zod.z.string(),
31945
32019
  path: zod.z.string()
@@ -32477,145 +32551,6 @@ var require_dist_CcvXUhHK = __commonJS({
32477
32551
  })
32478
32552
  }
32479
32553
  };
32480
- var LogChannelApplyResultSchema = zod.z.object({
32481
- /** How many declared channels are armed in this process after the call. */
32482
- armed: zod.z.number().int().min(0),
32483
- /**
32484
- * Names the document armed that this process does not declare. Reported
32485
- * rather than swallowed: a name here is either a typo or an addon that has
32486
- * not booted, and both deserve a line instead of silence.
32487
- */
32488
- unknown: zod.z.array(zod.z.string()).readonly()
32489
- });
32490
- var logChannelsCapability = {
32491
- name: "log-channels",
32492
- scope: "system",
32493
- mode: "collection",
32494
- internal: true,
32495
- methods: {
32496
- /** The channels this addon declares. Inert: no value, no state. */
32497
- list: method(zod.z.void(), zod.z.array(LogChannelDescriptorSchema).readonly()),
32498
- /**
32499
- * Refresh this process's mirror from the document's FULL set of armed
32500
- * windows.
32501
- *
32502
- * Full and not incremental on purpose: the document is the authority, so a
32503
- * channel it does not name is disarmed here. An incremental apply would
32504
- * let a disarm get lost in transit and leave a channel running that
32505
- * nobody can see is running.
32506
- */
32507
- apply: method(zod.z.object({ windows: zod.z.array(LogChannelWindowSchema).readonly() }), LogChannelApplyResultSchema, { kind: "mutation" })
32508
- },
32509
- /** In-process only — enumerated through `addons.listCapabilityProviders`. */
32510
- mount: { kind: "skip" }
32511
- };
32512
- var LogLevelSchema = zod.z.enum([
32513
- "debug",
32514
- "info",
32515
- "warn",
32516
- "error"
32517
- ]);
32518
- var LogEntrySchema = zod.z.object({
32519
- timestamp: zod.z.date(),
32520
- level: LogLevelSchema,
32521
- scope: zod.z.array(zod.z.string()),
32522
- message: zod.z.string(),
32523
- meta: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
32524
- tags: zod.z.record(zod.z.string(), zod.z.string()).optional()
32525
- });
32526
- var logDestinationCapability = {
32527
- name: "log-destination",
32528
- scope: "system",
32529
- mode: "collection",
32530
- internal: true,
32531
- methods: {
32532
- write: method(LogEntrySchema, zod.z.void(), { kind: "mutation" }),
32533
- query: method(zod.z.object({
32534
- scope: zod.z.array(zod.z.string()).optional(),
32535
- level: LogLevelSchema.optional(),
32536
- since: zod.z.date().optional(),
32537
- until: zod.z.date().optional(),
32538
- limit: zod.z.number().optional(),
32539
- tags: zod.z.record(zod.z.string(), zod.z.string()).optional()
32540
- }), zod.z.array(LogEntrySchema).readonly())
32541
- },
32542
- /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
32543
- mount: { kind: "skip" }
32544
- };
32545
- var FailureReasonCountSchema = zod.z.object({
32546
- /**
32547
- * Why the attempt did not land, in the contributor's own vocabulary —
32548
- * `worker-lease-gone`, `queue-overflow`, `timeout`, `empty-read`. The same
32549
- * strings that already appear in this repo's logs and, where one exists, the
32550
- * same string the per-track `previewMissReason` records (D276): a second
32551
- * vocabulary for the same loss would make the row and the counter
32552
- * un-joinable.
32553
- */
32554
- reason: zod.z.string(),
32555
- count: zod.z.number().int().nonnegative()
32556
- });
32557
- var FailureContributionSchema = zod.z.object({
32558
- /**
32559
- * The failing path — `enrichment-crop`, `inference`, `plate-ocr`,
32560
- * `person-over-vehicle`. Free text, for the reason `load-contribution` keeps
32561
- * `unit` free: the families are owned by different addons and a shared enum
32562
- * is a central list that rots invisibly.
32563
- */
32564
- family: zod.z.string(),
32565
- /**
32566
- * The NUMERIC device id — the same value every log line carries as
32567
- * `tags.deviceId`. Never nullable and never absent: a contributor that
32568
- * cannot name the camera must not emit the entry, because a fleet total
32569
- * cannot answer the only question anybody asks of this surface.
32570
- */
32571
- deviceId: zod.z.number().int().positive(),
32572
- /**
32573
- * A second dimension inside the family: the model / step id for an inference
32574
- * timeout, so "which camera AND which model" is one read. Absent when the
32575
- * family has a single variant.
32576
- */
32577
- variant: zod.z.string().optional(),
32578
- /**
32579
- * Epoch ms this counter started — the INCARNATION MARKER. A consumer
32580
- * differencing two reads must drop the interval when it changes, because the
32581
- * counter restarted from zero in a respawned runner. Same discipline as
32582
- * `LoadContribution.startedAtMs`.
32583
- */
32584
- sinceMs: zod.z.number(),
32585
- /** Epoch ms it was read. `atMs - sinceMs` is the interval this covers. */
32586
- atMs: zod.z.number(),
32587
- /**
32588
- * THE DENOMINATOR — every attempt on this path for this camera in the
32589
- * window. A failure count published without it is the mistake this schema
32590
- * exists to make impossible.
32591
- */
32592
- attempts: zod.z.number().int().nonnegative(),
32593
- /** Attempts that landed. `attempts - succeeded` is the loss. */
32594
- succeeded: zod.z.number().int().nonnegative(),
32595
- /** The loss, partitioned. Sums to `attempts - succeeded`. */
32596
- reasons: zod.z.array(FailureReasonCountSchema).readonly()
32597
- });
32598
- var failureContributionCapability = {
32599
- name: "failure-contribution",
32600
- scope: "system",
32601
- mode: "collection",
32602
- internal: true,
32603
- methods: {
32604
- /**
32605
- * This addon's per-camera failure counters, read live from bounded in-RAM
32606
- * state it already keeps. Inert: no persistence, no sampling, no timer.
32607
- *
32608
- * READING NEVER RESETS. The counters are CUMULATIVE since `sinceMs`, and a
32609
- * consumer that wants a rate differences two reads. A draining read would
32610
- * make two operators with the page open each destroy half of the other's
32611
- * numbers, and `load-contribution` already settled the same question the
32612
- * same way for `cpuSeconds`.
32613
- */
32614
- list: method(zod.z.void(), zod.z.array(FailureContributionSchema).readonly())
32615
- },
32616
- /** In-process only — enumerated through `addons.listCapabilityProviders`. */
32617
- mount: { kind: "skip" }
32618
- };
32619
32554
  var LoadContributionSchema = zod.z.object({
32620
32555
  role: zod.z.enum([
32621
32556
  "decode",
@@ -32693,6 +32628,71 @@ var require_dist_CcvXUhHK = __commonJS({
32693
32628
  /** In-process only — enumerated through `addons.listCapabilityProviders`. */
32694
32629
  mount: { kind: "skip" }
32695
32630
  };
32631
+ var LogChannelApplyResultSchema = zod.z.object({
32632
+ /** How many declared channels are armed in this process after the call. */
32633
+ armed: zod.z.number().int().min(0),
32634
+ /**
32635
+ * Names the document armed that this process does not declare. Reported
32636
+ * rather than swallowed: a name here is either a typo or an addon that has
32637
+ * not booted, and both deserve a line instead of silence.
32638
+ */
32639
+ unknown: zod.z.array(zod.z.string()).readonly()
32640
+ });
32641
+ var logChannelsCapability = {
32642
+ name: "log-channels",
32643
+ scope: "system",
32644
+ mode: "collection",
32645
+ internal: true,
32646
+ methods: {
32647
+ /** The channels this addon declares. Inert: no value, no state. */
32648
+ list: method(zod.z.void(), zod.z.array(LogChannelDescriptorSchema).readonly()),
32649
+ /**
32650
+ * Refresh this process's mirror from the document's FULL set of armed
32651
+ * windows.
32652
+ *
32653
+ * Full and not incremental on purpose: the document is the authority, so a
32654
+ * channel it does not name is disarmed here. An incremental apply would
32655
+ * let a disarm get lost in transit and leave a channel running that
32656
+ * nobody can see is running.
32657
+ */
32658
+ apply: method(zod.z.object({ windows: zod.z.array(LogChannelWindowSchema).readonly() }), LogChannelApplyResultSchema, { kind: "mutation" })
32659
+ },
32660
+ /** In-process only — enumerated through `addons.listCapabilityProviders`. */
32661
+ mount: { kind: "skip" }
32662
+ };
32663
+ var LogLevelSchema = zod.z.enum([
32664
+ "debug",
32665
+ "info",
32666
+ "warn",
32667
+ "error"
32668
+ ]);
32669
+ var LogEntrySchema = zod.z.object({
32670
+ timestamp: zod.z.date(),
32671
+ level: LogLevelSchema,
32672
+ scope: zod.z.array(zod.z.string()),
32673
+ message: zod.z.string(),
32674
+ meta: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
32675
+ tags: zod.z.record(zod.z.string(), zod.z.string()).optional()
32676
+ });
32677
+ var logDestinationCapability = {
32678
+ name: "log-destination",
32679
+ scope: "system",
32680
+ mode: "collection",
32681
+ internal: true,
32682
+ methods: {
32683
+ write: method(LogEntrySchema, zod.z.void(), { kind: "mutation" }),
32684
+ query: method(zod.z.object({
32685
+ scope: zod.z.array(zod.z.string()).optional(),
32686
+ level: LogLevelSchema.optional(),
32687
+ since: zod.z.date().optional(),
32688
+ until: zod.z.date().optional(),
32689
+ limit: zod.z.number().optional(),
32690
+ tags: zod.z.record(zod.z.string(), zod.z.string()).optional()
32691
+ }), zod.z.array(LogEntrySchema).readonly())
32692
+ },
32693
+ /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
32694
+ mount: { kind: "skip" }
32695
+ };
32696
32696
  var LoginStageEnum = zod.z.enum(["primary", "second-factor"]);
32697
32697
  var RedirectLoginMethodSchema = zod.z.object({
32698
32698
  kind: zod.z.literal("redirect"),
@@ -36780,9 +36780,13 @@ var require_dist_CcvXUhHK = __commonJS({
36780
36780
  var MediaFileSchema = zod.z.object({
36781
36781
  key: zod.z.string(),
36782
36782
  kind: MediaFileKindEnum,
36783
- base64: zod.z.string(),
36784
36783
  sizeBytes: zod.z.number(),
36785
36784
  timestamp: zod.z.number()
36785
+ }).extend({
36786
+ /** `/addon/<addonId>/event-media/<encoded stored key>`. Always present. */
36787
+ url: zod.z.string(),
36788
+ /** @deprecated Transitional — see the schema docblock. Use {@link url}. */
36789
+ base64: zod.z.string()
36786
36790
  });
36787
36791
  var MediaFileInfoSchema = MediaFileSchema.omit({ base64: true });
36788
36792
  var RetrainMacroClassSchema = zod.z.enum([
@@ -37849,6 +37853,26 @@ var require_dist_CcvXUhHK = __commonJS({
37849
37853
  deviceId: zod.z.number()
37850
37854
  }), zod.z.array(MediaFileInfoSchema).readonly()),
37851
37855
  /**
37856
+ * What media an EVENT has, without any of it — the twin `getEventMedia`
37857
+ * never had.
37858
+ *
37859
+ * `listTrackMedia` above got this treatment because a track's media is
37860
+ * 5-8 MB. An event's is worse per row, not better: an old-style event owns
37861
+ * a `crop` AND a native-resolution `fullFrameBoxed`, and the track DETAIL
37862
+ * modal — the one surface that legitimately shows the big kinds — unions
37863
+ * both listings to build its filmstrip. It then renders every tile from
37864
+ * the `event-media` plane by key and throws the bytes away. Measured on
37865
+ * the live hub: one event's `fullFrameBoxed` is 2 824 077 B, base64'd to
37866
+ * ~3.8 MB, allocated whole in hub-main's heap, for a list of keys.
37867
+ *
37868
+ * Same `deviceId` authorization subject as `getEventMedia`, and the same
37869
+ * rows — this is a projection of that method, never a different question.
37870
+ */
37871
+ listEventMedia: method(zod.z.object({
37872
+ eventId: zod.z.string(),
37873
+ deviceId: zod.z.number()
37874
+ }), zod.z.array(MediaFileInfoSchema).readonly()),
37875
+ /**
37852
37876
  * Search object events by text query using CLIP cosine similarity.
37853
37877
  * Encodes `text` via the `embedding-encoder` cap, queries the
37854
37878
  * `ObjectEmbeddingStore` with optional prefilters, ranks all matching
@@ -43144,7 +43168,7 @@ var require_dist_CcvXUhHK = __commonJS({
43144
43168
  var MediaFileLiteSchema$1 = zod.z.object({
43145
43169
  key: zod.z.string(),
43146
43170
  kind: zod.z.string(),
43147
- base64: zod.z.string(),
43171
+ url: zod.z.string(),
43148
43172
  sizeBytes: zod.z.number(),
43149
43173
  timestamp: zod.z.number()
43150
43174
  });
@@ -46037,7 +46061,7 @@ var require_dist_CcvXUhHK = __commonJS({
46037
46061
  var MediaFileLiteSchema = zod.z.object({
46038
46062
  key: zod.z.string(),
46039
46063
  kind: zod.z.string(),
46040
- base64: zod.z.string(),
46064
+ url: zod.z.string(),
46041
46065
  sizeBytes: zod.z.number(),
46042
46066
  timestamp: zod.z.number()
46043
46067
  });
@@ -53345,6 +53369,12 @@ var require_dist_CcvXUhHK = __commonJS({
53345
53369
  addonId: null,
53346
53370
  access: "view"
53347
53371
  },
53372
+ "pipelineAnalytics.listEventMedia": {
53373
+ capName: "pipeline-analytics",
53374
+ capScope: "device",
53375
+ addonId: null,
53376
+ access: "view"
53377
+ },
53348
53378
  "pipelineAnalytics.listGroups": {
53349
53379
  capName: "pipeline-analytics",
53350
53380
  capScope: "device",
@@ -56968,6 +56998,11 @@ var require_dist_CcvXUhHK = __commonJS({
56968
56998
  form: "array",
56969
56999
  optional: false
56970
57000
  }],
57001
+ "pipelineAnalytics.listEventMedia": [{
57002
+ name: "deviceId",
57003
+ form: "single",
57004
+ optional: false
57005
+ }],
56971
57006
  "pipelineAnalytics.listGroups": [{
56972
57007
  name: "deviceIds",
56973
57008
  form: "array",
@@ -59112,7 +59147,7 @@ var require_alerts_addon = __commonJS({
59112
59147
  [Symbol.toStringTag]: { value: "Module" }
59113
59148
  });
59114
59149
  require_chunk_Cek0wNdY();
59115
- var require_dist10 = require_dist_CcvXUhHK();
59150
+ var require_dist10 = require_dist_Keu5TDO7();
59116
59151
  function selectExpired(alerts, cutoffMs) {
59117
59152
  return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
59118
59153
  }
@@ -59931,7 +59966,7 @@ var require_console_logging = __commonJS({
59931
59966
  [Symbol.toStringTag]: { value: "Module" }
59932
59967
  });
59933
59968
  require_chunk_Cek0wNdY();
59934
- var require_dist10 = require_dist_CcvXUhHK();
59969
+ var require_dist10 = require_dist_Keu5TDO7();
59935
59970
  var require_formatter = require_formatter_DqAKDlvN();
59936
59971
  var LEVEL_RANK = {
59937
59972
  debug: 0,
@@ -60025,7 +60060,7 @@ var require_core_blocks_addon = __commonJS({
60025
60060
  "use strict";
60026
60061
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
60027
60062
  var require_chunk = require_chunk_Cek0wNdY();
60028
- var require_dist10 = require_dist_CcvXUhHK();
60063
+ var require_dist10 = require_dist_Keu5TDO7();
60029
60064
  var node_crypto = __require("crypto");
60030
60065
  var node_fs_promises = __require("fs/promises");
60031
60066
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -60922,11 +60957,11 @@ var require_core_blocks = __commonJS({
60922
60957
  }
60923
60958
  });
60924
60959
 
60925
- // ../system/dist/retired-settings-keys-DXZ2xe7C.js
60926
- var require_retired_settings_keys_DXZ2xe7C = __commonJS({
60927
- "../system/dist/retired-settings-keys-DXZ2xe7C.js"(exports) {
60960
+ // ../system/dist/retired-settings-keys-BBohF-eC.js
60961
+ var require_retired_settings_keys_BBohF_eC = __commonJS({
60962
+ "../system/dist/retired-settings-keys-BBohF-eC.js"(exports) {
60928
60963
  "use strict";
60929
- var require_dist10 = require_dist_CcvXUhHK();
60964
+ var require_dist10 = require_dist_Keu5TDO7();
60930
60965
  function settingsStoreIsAuthoritativeHere(env) {
60931
60966
  const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
60932
60967
  return raw === "" || raw === "hub";
@@ -63140,8 +63175,8 @@ var require_device_manager_addon = __commonJS({
63140
63175
  [Symbol.toStringTag]: { value: "Module" }
63141
63176
  });
63142
63177
  require_chunk_Cek0wNdY();
63143
- var require_dist10 = require_dist_CcvXUhHK();
63144
- var require_retired_settings_keys = require_retired_settings_keys_DXZ2xe7C();
63178
+ var require_dist10 = require_dist_Keu5TDO7();
63179
+ var require_retired_settings_keys = require_retired_settings_keys_BBohF_eC();
63145
63180
  var node_crypto = __require("crypto");
63146
63181
  var _camstack_types_node = require_node();
63147
63182
  var JOB_HISTORY = 20;
@@ -67954,7 +67989,7 @@ var require_hub_forwarder = __commonJS({
67954
67989
  [Symbol.toStringTag]: { value: "Module" }
67955
67990
  });
67956
67991
  require_chunk_Cek0wNdY();
67957
- var require_dist10 = require_dist_CcvXUhHK();
67992
+ var require_dist10 = require_dist_Keu5TDO7();
67958
67993
  var require_formatter = require_formatter_DqAKDlvN();
67959
67994
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
67960
67995
  var HubForwarderDestination = class {
@@ -68091,7 +68126,7 @@ var require_liveness_monitor_addon = __commonJS({
68091
68126
  "use strict";
68092
68127
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
68093
68128
  require_chunk_Cek0wNdY();
68094
- var require_dist10 = require_dist_CcvXUhHK();
68129
+ var require_dist10 = require_dist_Keu5TDO7();
68095
68130
  var NO_DEVICES = "liveness:no-devices";
68096
68131
  var ALL_OFFLINE = "liveness:all-devices-offline";
68097
68132
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -68281,7 +68316,7 @@ var require_local_auth_addon = __commonJS({
68281
68316
  [Symbol.toStringTag]: { value: "Module" }
68282
68317
  });
68283
68318
  var require_chunk = require_chunk_Cek0wNdY();
68284
- var require_dist10 = require_dist_CcvXUhHK();
68319
+ var require_dist10 = require_dist_Keu5TDO7();
68285
68320
  var node_crypto = __require("crypto");
68286
68321
  node_crypto = require_chunk.__toESM(node_crypto);
68287
68322
  var crypto$1 = __require("crypto");
@@ -76094,7 +76129,7 @@ var require_loki_logging = __commonJS({
76094
76129
  [Symbol.toStringTag]: { value: "Module" }
76095
76130
  });
76096
76131
  require_chunk_Cek0wNdY();
76097
- var require_dist10 = require_dist_CcvXUhHK();
76132
+ var require_dist10 = require_dist_Keu5TDO7();
76098
76133
  function sanitizeLabelName(raw) {
76099
76134
  const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
76100
76135
  return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
@@ -76659,7 +76694,7 @@ var require_native_metrics_addon = __commonJS({
76659
76694
  [Symbol.toStringTag]: { value: "Module" }
76660
76695
  });
76661
76696
  var require_chunk = require_chunk_Cek0wNdY();
76662
- var require_dist10 = require_dist_CcvXUhHK();
76697
+ var require_dist10 = require_dist_Keu5TDO7();
76663
76698
  var node_fs_promises = __require("fs/promises");
76664
76699
  var node_child_process = __require("child_process");
76665
76700
  var node_util = __require("util");
@@ -79281,7 +79316,7 @@ var require_filesystem_storage_addon = __commonJS({
79281
79316
  [Symbol.toStringTag]: { value: "Module" }
79282
79317
  });
79283
79318
  var require_chunk = require_chunk_Cek0wNdY();
79284
- var require_dist10 = require_dist_CcvXUhHK();
79319
+ var require_dist10 = require_dist_Keu5TDO7();
79285
79320
  var node_crypto = __require("crypto");
79286
79321
  var node_fs_promises = __require("fs/promises");
79287
79322
  var node_path = __require("path");
@@ -80397,8 +80432,8 @@ var require_sqlite_settings_addon = __commonJS({
80397
80432
  [Symbol.toStringTag]: { value: "Module" }
80398
80433
  });
80399
80434
  var require_chunk = require_chunk_Cek0wNdY();
80400
- var require_dist10 = require_dist_CcvXUhHK();
80401
- var require_retired_settings_keys = require_retired_settings_keys_DXZ2xe7C();
80435
+ var require_dist10 = require_dist_Keu5TDO7();
80436
+ var require_retired_settings_keys = require_retired_settings_keys_BBohF_eC();
80402
80437
  var node_crypto = __require("crypto");
80403
80438
  var node_fs = __require("fs");
80404
80439
  var node_module = __require("module");
@@ -82777,7 +82812,7 @@ var require_storage_orchestrator_addon = __commonJS({
82777
82812
  [Symbol.toStringTag]: { value: "Module" }
82778
82813
  });
82779
82814
  var require_chunk = require_chunk_Cek0wNdY();
82780
- var require_dist10 = require_dist_CcvXUhHK();
82815
+ var require_dist10 = require_dist_Keu5TDO7();
82781
82816
  var node_crypto = __require("crypto");
82782
82817
  var node_fs_promises = __require("fs/promises");
82783
82818
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -85352,7 +85387,7 @@ var require_system_config_addon = __commonJS({
85352
85387
  [Symbol.toStringTag]: { value: "Module" }
85353
85388
  });
85354
85389
  require_chunk_Cek0wNdY();
85355
- var require_dist10 = require_dist_CcvXUhHK();
85390
+ var require_dist10 = require_dist_Keu5TDO7();
85356
85391
  var SECTION_TITLES = {
85357
85392
  server: "Server",
85358
85393
  auth: "Authentication"
@@ -103413,7 +103448,7 @@ var require_winston_logging = __commonJS({
103413
103448
  [Symbol.toStringTag]: { value: "Module" }
103414
103449
  });
103415
103450
  var require_chunk = require_chunk_Cek0wNdY();
103416
- var require_dist10 = require_dist_CcvXUhHK();
103451
+ var require_dist10 = require_dist_Keu5TDO7();
103417
103452
  var require_formatter = require_formatter_DqAKDlvN();
103418
103453
  var node_path = __require("path");
103419
103454
  node_path = require_chunk.__toESM(node_path);
@@ -105356,9 +105391,9 @@ var require_event_category_BaEgqJNv = __commonJS({
105356
105391
  }
105357
105392
  });
105358
105393
 
105359
- // ../types/dist/sleep-CWWLTM6W.js
105360
- var require_sleep_CWWLTM6W = __commonJS({
105361
- "../types/dist/sleep-CWWLTM6W.js"(exports) {
105394
+ // ../types/dist/sleep-C3AniWy-.js
105395
+ var require_sleep_C3AniWy = __commonJS({
105396
+ "../types/dist/sleep-C3AniWy-.js"(exports) {
105362
105397
  "use strict";
105363
105398
  var require_event_category = require_event_category_BaEgqJNv();
105364
105399
  var zod = require_zod();
@@ -108080,6 +108115,7 @@ var require_sleep_CWWLTM6W = __commonJS({
108080
108115
  getEventMedia: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getEventMedia", "query", input),
108081
108116
  getTrackMedia: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getTrackMedia", "query", input),
108082
108117
  listTrackMedia: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "listTrackMedia", "query", input),
108118
+ listEventMedia: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "listEventMedia", "query", input),
108083
108119
  searchObjectEvents: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "searchObjectEvents", "query", input),
108084
108120
  wipeObjectEmbeddings: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "wipeObjectEmbeddings", "mutation", input),
108085
108121
  rebuildObjectEmbeddings: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "rebuildObjectEmbeddings", "mutation", input),
@@ -109024,7 +109060,7 @@ var require_addon = __commonJS({
109024
109060
  "use strict";
109025
109061
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
109026
109062
  var require_event_category = require_event_category_BaEgqJNv();
109027
- var require_sleep = require_sleep_CWWLTM6W();
109063
+ var require_sleep = require_sleep_C3AniWy();
109028
109064
  var require_err_msg = require_err_msg_COpsHMw2();
109029
109065
  var CAP_INPUT_DEFAULTS = Object.freeze({
109030
109066
  "addons": { "getLogs": { "limit": 100 } },
@@ -115906,12 +115942,12 @@ var require_dist2 = __commonJS({
115906
115942
  }
115907
115943
  });
115908
115944
 
115909
- // ../system/dist/manifest-system-deps-oJMkWSX-.js
115910
- var require_manifest_system_deps_oJMkWSX = __commonJS({
115911
- "../system/dist/manifest-system-deps-oJMkWSX-.js"(exports) {
115945
+ // ../system/dist/manifest-system-deps-DYv4ZPo2.js
115946
+ var require_manifest_system_deps_DYv4ZPo2 = __commonJS({
115947
+ "../system/dist/manifest-system-deps-DYv4ZPo2.js"(exports) {
115912
115948
  "use strict";
115913
115949
  var require_chunk = require_chunk_Cek0wNdY();
115914
- require_dist_CcvXUhHK();
115950
+ require_dist_Keu5TDO7();
115915
115951
  var node_crypto = __require("crypto");
115916
115952
  node_crypto = require_chunk.__toESM(node_crypto);
115917
115953
  var _camstack_types_node = require_node();
@@ -127940,7 +127976,7 @@ var require_dist3 = __commonJS({
127940
127976
  "use strict";
127941
127977
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
127942
127978
  var require_chunk = require_chunk_Cek0wNdY();
127943
- var require_dist10 = require_dist_CcvXUhHK();
127979
+ var require_dist10 = require_dist_Keu5TDO7();
127944
127980
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
127945
127981
  require_alerts();
127946
127982
  var require_formatter = require_formatter_DqAKDlvN();
@@ -127966,7 +128002,7 @@ var require_dist3 = __commonJS({
127966
128002
  var require_builtins_winston_logging_index = require_winston_logging();
127967
128003
  var require_file_data_plane = require_file_data_plane_DO8KbxCe();
127968
128004
  var require_tls$1 = require_tls_BxQlomxd();
127969
- var require_manifest_system_deps = require_manifest_system_deps_oJMkWSX();
128005
+ var require_manifest_system_deps = require_manifest_system_deps_DYv4ZPo2();
127970
128006
  var require_resource_monitor = require_resource_monitor_CdnzxBLP();
127971
128007
  var require_custom_action_registry = require_custom_action_registry_jY0NOZK8();
127972
128008
  var zod = require_zod();
@@ -208178,6 +208214,19 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
208178
208214
  * per-task abort timeout. On success the resolved `stagedPath` is returned; on
208179
208215
  * failure the task is marked `failed` and `null` is returned (so the apply
208180
208216
  * phase skips it). Other tasks are unaffected.
208217
+ *
208218
+ * **`toVersion` is REWRITTEN here, to the version that was actually
208219
+ * fetched.** A task's `toVersion` starts as the REQUEST, and the request is
208220
+ * routinely a dist-tag: `addons.updatePackage` with no version resolves to
208221
+ * the literal `'latest'`. The staging area already resolves it — it reads
208222
+ * the version out of the unpacked tarball and returns `resolvedVersion` —
208223
+ * and dropping that answer sent the string `'latest'` onward as if it were a
208224
+ * version. It became the manifest's recorded version, the version the Addons
208225
+ * page displayed, and the `toVersion` on the `addon.updated` event, which an
208226
+ * operator read on his phone as "@camstack/addon-terminal 0.0.0 → latest"
208227
+ * (2026-08-30). Everything downstream of the apply reads a version; none of
208228
+ * it can resolve a tag, and none of it could tell that it had been handed
208229
+ * one.
208181
208230
  */
208182
208231
  async fetchAddonTask(job, task) {
208183
208232
  try {
@@ -208187,20 +208236,28 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
208187
208236
  });
208188
208237
  const ac = new AbortController();
208189
208238
  const timer = setTimeout(() => ac.abort(), this.deps.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS);
208190
- let stagedPath;
208239
+ let staged;
208191
208240
  try {
208192
- stagedPath = (await this.deps.staging.fetchAndStage({
208241
+ staged = await this.deps.staging.fetchAndStage({
208193
208242
  jobId: job.jobId,
208194
208243
  name: task.packageName,
208195
208244
  version: task.toVersion,
208196
208245
  signal: ac.signal
208197
- })).stagedPath;
208246
+ });
208198
208247
  } finally {
208199
208248
  clearTimeout(timer);
208200
208249
  }
208201
- this.advance(job.jobId, task, "staged", { stagedPath });
208250
+ const stagedPath = staged.stagedPath;
208251
+ const resolved = {
208252
+ ...task,
208253
+ toVersion: staged.resolvedVersion
208254
+ };
208255
+ this.advance(job.jobId, task, "staged", {
208256
+ stagedPath,
208257
+ toVersion: resolved.toVersion
208258
+ });
208202
208259
  return {
208203
- task,
208260
+ task: resolved,
208204
208261
  stagedPath
208205
208262
  };
208206
208263
  } catch (err) {
@@ -208769,7 +208826,7 @@ var require_dist4 = __commonJS({
208769
208826
  "use strict";
208770
208827
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
208771
208828
  var require_event_category = require_event_category_BaEgqJNv();
208772
- var require_sleep = require_sleep_CWWLTM6W();
208829
+ var require_sleep = require_sleep_C3AniWy();
208773
208830
  var require_canonical_hash = require_canonical_hash_DNV8S5ET();
208774
208831
  var require_enums2 = require_enums();
208775
208832
  var require_err_msg = require_err_msg_COpsHMw2();
@@ -216951,6 +217008,80 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
216951
217008
  getInfo: require_sleep.method(zod.z.void(), EmbeddingInfoSchema, { auth: "admin" })
216952
217009
  }
216953
217010
  };
217011
+ var FailureReasonCountSchema = zod.z.object({
217012
+ /**
217013
+ * Why the attempt did not land, in the contributor's own vocabulary —
217014
+ * `worker-lease-gone`, `queue-overflow`, `timeout`, `empty-read`. The same
217015
+ * strings that already appear in this repo's logs and, where one exists, the
217016
+ * same string the per-track `previewMissReason` records (D276): a second
217017
+ * vocabulary for the same loss would make the row and the counter
217018
+ * un-joinable.
217019
+ */
217020
+ reason: zod.z.string(),
217021
+ count: zod.z.number().int().nonnegative()
217022
+ });
217023
+ var FailureContributionSchema = zod.z.object({
217024
+ /**
217025
+ * The failing path — `enrichment-crop`, `inference`, `plate-ocr`,
217026
+ * `person-over-vehicle`. Free text, for the reason `load-contribution` keeps
217027
+ * `unit` free: the families are owned by different addons and a shared enum
217028
+ * is a central list that rots invisibly.
217029
+ */
217030
+ family: zod.z.string(),
217031
+ /**
217032
+ * The NUMERIC device id — the same value every log line carries as
217033
+ * `tags.deviceId`. Never nullable and never absent: a contributor that
217034
+ * cannot name the camera must not emit the entry, because a fleet total
217035
+ * cannot answer the only question anybody asks of this surface.
217036
+ */
217037
+ deviceId: zod.z.number().int().positive(),
217038
+ /**
217039
+ * A second dimension inside the family: the model / step id for an inference
217040
+ * timeout, so "which camera AND which model" is one read. Absent when the
217041
+ * family has a single variant.
217042
+ */
217043
+ variant: zod.z.string().optional(),
217044
+ /**
217045
+ * Epoch ms this counter started — the INCARNATION MARKER. A consumer
217046
+ * differencing two reads must drop the interval when it changes, because the
217047
+ * counter restarted from zero in a respawned runner. Same discipline as
217048
+ * `LoadContribution.startedAtMs`.
217049
+ */
217050
+ sinceMs: zod.z.number(),
217051
+ /** Epoch ms it was read. `atMs - sinceMs` is the interval this covers. */
217052
+ atMs: zod.z.number(),
217053
+ /**
217054
+ * THE DENOMINATOR — every attempt on this path for this camera in the
217055
+ * window. A failure count published without it is the mistake this schema
217056
+ * exists to make impossible.
217057
+ */
217058
+ attempts: zod.z.number().int().nonnegative(),
217059
+ /** Attempts that landed. `attempts - succeeded` is the loss. */
217060
+ succeeded: zod.z.number().int().nonnegative(),
217061
+ /** The loss, partitioned. Sums to `attempts - succeeded`. */
217062
+ reasons: zod.z.array(FailureReasonCountSchema).readonly()
217063
+ });
217064
+ var failureContributionCapability = {
217065
+ name: "failure-contribution",
217066
+ scope: "system",
217067
+ mode: "collection",
217068
+ internal: true,
217069
+ methods: {
217070
+ /**
217071
+ * This addon's per-camera failure counters, read live from bounded in-RAM
217072
+ * state it already keeps. Inert: no persistence, no sampling, no timer.
217073
+ *
217074
+ * READING NEVER RESETS. The counters are CUMULATIVE since `sinceMs`, and a
217075
+ * consumer that wants a rate differences two reads. A draining read would
217076
+ * make two operators with the page open each destroy half of the other's
217077
+ * numbers, and `load-contribution` already settled the same question the
217078
+ * same way for `cpuSeconds`.
217079
+ */
217080
+ list: require_sleep.method(zod.z.void(), zod.z.array(FailureContributionSchema).readonly())
217081
+ },
217082
+ /** In-process only — enumerated through `addons.listCapabilityProviders`. */
217083
+ mount: { kind: "skip" }
217084
+ };
216954
217085
  var DirEntrySchema = zod.z.object({
216955
217086
  name: zod.z.string(),
216956
217087
  path: zod.z.string()
@@ -217495,145 +217626,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
217495
217626
  })
217496
217627
  }
217497
217628
  };
217498
- var LogChannelApplyResultSchema = zod.z.object({
217499
- /** How many declared channels are armed in this process after the call. */
217500
- armed: zod.z.number().int().min(0),
217501
- /**
217502
- * Names the document armed that this process does not declare. Reported
217503
- * rather than swallowed: a name here is either a typo or an addon that has
217504
- * not booted, and both deserve a line instead of silence.
217505
- */
217506
- unknown: zod.z.array(zod.z.string()).readonly()
217507
- });
217508
- var logChannelsCapability = {
217509
- name: "log-channels",
217510
- scope: "system",
217511
- mode: "collection",
217512
- internal: true,
217513
- methods: {
217514
- /** The channels this addon declares. Inert: no value, no state. */
217515
- list: require_sleep.method(zod.z.void(), zod.z.array(LogChannelDescriptorSchema).readonly()),
217516
- /**
217517
- * Refresh this process's mirror from the document's FULL set of armed
217518
- * windows.
217519
- *
217520
- * Full and not incremental on purpose: the document is the authority, so a
217521
- * channel it does not name is disarmed here. An incremental apply would
217522
- * let a disarm get lost in transit and leave a channel running that
217523
- * nobody can see is running.
217524
- */
217525
- apply: require_sleep.method(zod.z.object({ windows: zod.z.array(LogChannelWindowSchema).readonly() }), LogChannelApplyResultSchema, { kind: "mutation" })
217526
- },
217527
- /** In-process only — enumerated through `addons.listCapabilityProviders`. */
217528
- mount: { kind: "skip" }
217529
- };
217530
- var LogLevelSchema = zod.z.enum([
217531
- "debug",
217532
- "info",
217533
- "warn",
217534
- "error"
217535
- ]);
217536
- var LogEntrySchema = zod.z.object({
217537
- timestamp: zod.z.date(),
217538
- level: LogLevelSchema,
217539
- scope: zod.z.array(zod.z.string()),
217540
- message: zod.z.string(),
217541
- meta: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
217542
- tags: zod.z.record(zod.z.string(), zod.z.string()).optional()
217543
- });
217544
- var logDestinationCapability = {
217545
- name: "log-destination",
217546
- scope: "system",
217547
- mode: "collection",
217548
- internal: true,
217549
- methods: {
217550
- write: require_sleep.method(LogEntrySchema, zod.z.void(), { kind: "mutation" }),
217551
- query: require_sleep.method(zod.z.object({
217552
- scope: zod.z.array(zod.z.string()).optional(),
217553
- level: LogLevelSchema.optional(),
217554
- since: zod.z.date().optional(),
217555
- until: zod.z.date().optional(),
217556
- limit: zod.z.number().optional(),
217557
- tags: zod.z.record(zod.z.string(), zod.z.string()).optional()
217558
- }), zod.z.array(LogEntrySchema).readonly())
217559
- },
217560
- /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
217561
- mount: { kind: "skip" }
217562
- };
217563
- var FailureReasonCountSchema = zod.z.object({
217564
- /**
217565
- * Why the attempt did not land, in the contributor's own vocabulary —
217566
- * `worker-lease-gone`, `queue-overflow`, `timeout`, `empty-read`. The same
217567
- * strings that already appear in this repo's logs and, where one exists, the
217568
- * same string the per-track `previewMissReason` records (D276): a second
217569
- * vocabulary for the same loss would make the row and the counter
217570
- * un-joinable.
217571
- */
217572
- reason: zod.z.string(),
217573
- count: zod.z.number().int().nonnegative()
217574
- });
217575
- var FailureContributionSchema = zod.z.object({
217576
- /**
217577
- * The failing path — `enrichment-crop`, `inference`, `plate-ocr`,
217578
- * `person-over-vehicle`. Free text, for the reason `load-contribution` keeps
217579
- * `unit` free: the families are owned by different addons and a shared enum
217580
- * is a central list that rots invisibly.
217581
- */
217582
- family: zod.z.string(),
217583
- /**
217584
- * The NUMERIC device id — the same value every log line carries as
217585
- * `tags.deviceId`. Never nullable and never absent: a contributor that
217586
- * cannot name the camera must not emit the entry, because a fleet total
217587
- * cannot answer the only question anybody asks of this surface.
217588
- */
217589
- deviceId: zod.z.number().int().positive(),
217590
- /**
217591
- * A second dimension inside the family: the model / step id for an inference
217592
- * timeout, so "which camera AND which model" is one read. Absent when the
217593
- * family has a single variant.
217594
- */
217595
- variant: zod.z.string().optional(),
217596
- /**
217597
- * Epoch ms this counter started — the INCARNATION MARKER. A consumer
217598
- * differencing two reads must drop the interval when it changes, because the
217599
- * counter restarted from zero in a respawned runner. Same discipline as
217600
- * `LoadContribution.startedAtMs`.
217601
- */
217602
- sinceMs: zod.z.number(),
217603
- /** Epoch ms it was read. `atMs - sinceMs` is the interval this covers. */
217604
- atMs: zod.z.number(),
217605
- /**
217606
- * THE DENOMINATOR — every attempt on this path for this camera in the
217607
- * window. A failure count published without it is the mistake this schema
217608
- * exists to make impossible.
217609
- */
217610
- attempts: zod.z.number().int().nonnegative(),
217611
- /** Attempts that landed. `attempts - succeeded` is the loss. */
217612
- succeeded: zod.z.number().int().nonnegative(),
217613
- /** The loss, partitioned. Sums to `attempts - succeeded`. */
217614
- reasons: zod.z.array(FailureReasonCountSchema).readonly()
217615
- });
217616
- var failureContributionCapability = {
217617
- name: "failure-contribution",
217618
- scope: "system",
217619
- mode: "collection",
217620
- internal: true,
217621
- methods: {
217622
- /**
217623
- * This addon's per-camera failure counters, read live from bounded in-RAM
217624
- * state it already keeps. Inert: no persistence, no sampling, no timer.
217625
- *
217626
- * READING NEVER RESETS. The counters are CUMULATIVE since `sinceMs`, and a
217627
- * consumer that wants a rate differences two reads. A draining read would
217628
- * make two operators with the page open each destroy half of the other's
217629
- * numbers, and `load-contribution` already settled the same question the
217630
- * same way for `cpuSeconds`.
217631
- */
217632
- list: require_sleep.method(zod.z.void(), zod.z.array(FailureContributionSchema).readonly())
217633
- },
217634
- /** In-process only — enumerated through `addons.listCapabilityProviders`. */
217635
- mount: { kind: "skip" }
217636
- };
217637
217629
  var LOAD_CONTRIBUTION_ROLES = [
217638
217630
  "decode",
217639
217631
  "transcode",
@@ -217713,6 +217705,71 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
217713
217705
  /** In-process only — enumerated through `addons.listCapabilityProviders`. */
217714
217706
  mount: { kind: "skip" }
217715
217707
  };
217708
+ var LogChannelApplyResultSchema = zod.z.object({
217709
+ /** How many declared channels are armed in this process after the call. */
217710
+ armed: zod.z.number().int().min(0),
217711
+ /**
217712
+ * Names the document armed that this process does not declare. Reported
217713
+ * rather than swallowed: a name here is either a typo or an addon that has
217714
+ * not booted, and both deserve a line instead of silence.
217715
+ */
217716
+ unknown: zod.z.array(zod.z.string()).readonly()
217717
+ });
217718
+ var logChannelsCapability = {
217719
+ name: "log-channels",
217720
+ scope: "system",
217721
+ mode: "collection",
217722
+ internal: true,
217723
+ methods: {
217724
+ /** The channels this addon declares. Inert: no value, no state. */
217725
+ list: require_sleep.method(zod.z.void(), zod.z.array(LogChannelDescriptorSchema).readonly()),
217726
+ /**
217727
+ * Refresh this process's mirror from the document's FULL set of armed
217728
+ * windows.
217729
+ *
217730
+ * Full and not incremental on purpose: the document is the authority, so a
217731
+ * channel it does not name is disarmed here. An incremental apply would
217732
+ * let a disarm get lost in transit and leave a channel running that
217733
+ * nobody can see is running.
217734
+ */
217735
+ apply: require_sleep.method(zod.z.object({ windows: zod.z.array(LogChannelWindowSchema).readonly() }), LogChannelApplyResultSchema, { kind: "mutation" })
217736
+ },
217737
+ /** In-process only — enumerated through `addons.listCapabilityProviders`. */
217738
+ mount: { kind: "skip" }
217739
+ };
217740
+ var LogLevelSchema = zod.z.enum([
217741
+ "debug",
217742
+ "info",
217743
+ "warn",
217744
+ "error"
217745
+ ]);
217746
+ var LogEntrySchema = zod.z.object({
217747
+ timestamp: zod.z.date(),
217748
+ level: LogLevelSchema,
217749
+ scope: zod.z.array(zod.z.string()),
217750
+ message: zod.z.string(),
217751
+ meta: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
217752
+ tags: zod.z.record(zod.z.string(), zod.z.string()).optional()
217753
+ });
217754
+ var logDestinationCapability = {
217755
+ name: "log-destination",
217756
+ scope: "system",
217757
+ mode: "collection",
217758
+ internal: true,
217759
+ methods: {
217760
+ write: require_sleep.method(LogEntrySchema, zod.z.void(), { kind: "mutation" }),
217761
+ query: require_sleep.method(zod.z.object({
217762
+ scope: zod.z.array(zod.z.string()).optional(),
217763
+ level: LogLevelSchema.optional(),
217764
+ since: zod.z.date().optional(),
217765
+ until: zod.z.date().optional(),
217766
+ limit: zod.z.number().optional(),
217767
+ tags: zod.z.record(zod.z.string(), zod.z.string()).optional()
217768
+ }), zod.z.array(LogEntrySchema).readonly())
217769
+ },
217770
+ /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
217771
+ mount: { kind: "skip" }
217772
+ };
217716
217773
  var LoginStageEnum = zod.z.enum(["primary", "second-factor"]);
217717
217774
  var RedirectLoginMethodSchema = zod.z.object({
217718
217775
  kind: zod.z.literal("redirect"),
@@ -222600,13 +222657,18 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
222600
222657
  "keyFrameSmall",
222601
222658
  "thumbnailSmall"
222602
222659
  ]);
222603
- var MediaFileSchema = zod.z.object({
222660
+ var MediaFileRefSchema = zod.z.object({
222604
222661
  key: zod.z.string(),
222605
222662
  kind: MediaFileKindEnum,
222606
- base64: zod.z.string(),
222607
222663
  sizeBytes: zod.z.number(),
222608
222664
  timestamp: zod.z.number()
222609
222665
  });
222666
+ var MediaFileSchema = MediaFileRefSchema.extend({
222667
+ /** `/addon/<addonId>/event-media/<encoded stored key>`. Always present. */
222668
+ url: zod.z.string(),
222669
+ /** @deprecated Transitional — see the schema docblock. Use {@link url}. */
222670
+ base64: zod.z.string()
222671
+ });
222610
222672
  var MediaFileInfoSchema = MediaFileSchema.omit({ base64: true });
222611
222673
  var RetrainMacroClassSchema = zod.z.enum([
222612
222674
  "person",
@@ -223672,6 +223734,26 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
223672
223734
  deviceId: zod.z.number()
223673
223735
  }), zod.z.array(MediaFileInfoSchema).readonly()),
223674
223736
  /**
223737
+ * What media an EVENT has, without any of it — the twin `getEventMedia`
223738
+ * never had.
223739
+ *
223740
+ * `listTrackMedia` above got this treatment because a track's media is
223741
+ * 5-8 MB. An event's is worse per row, not better: an old-style event owns
223742
+ * a `crop` AND a native-resolution `fullFrameBoxed`, and the track DETAIL
223743
+ * modal — the one surface that legitimately shows the big kinds — unions
223744
+ * both listings to build its filmstrip. It then renders every tile from
223745
+ * the `event-media` plane by key and throws the bytes away. Measured on
223746
+ * the live hub: one event's `fullFrameBoxed` is 2 824 077 B, base64'd to
223747
+ * ~3.8 MB, allocated whole in hub-main's heap, for a list of keys.
223748
+ *
223749
+ * Same `deviceId` authorization subject as `getEventMedia`, and the same
223750
+ * rows — this is a projection of that method, never a different question.
223751
+ */
223752
+ listEventMedia: require_sleep.method(zod.z.object({
223753
+ eventId: zod.z.string(),
223754
+ deviceId: zod.z.number()
223755
+ }), zod.z.array(MediaFileInfoSchema).readonly()),
223756
+ /**
223675
223757
  * Search object events by text query using CLIP cosine similarity.
223676
223758
  * Encodes `text` via the `embedding-encoder` cap, queries the
223677
223759
  * `ObjectEmbeddingStore` with optional prefilters, ranks all matching
@@ -229134,7 +229216,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
229134
229216
  var MediaFileLiteSchema$1 = zod.z.object({
229135
229217
  key: zod.z.string(),
229136
229218
  kind: zod.z.string(),
229137
- base64: zod.z.string(),
229219
+ url: zod.z.string(),
229138
229220
  sizeBytes: zod.z.number(),
229139
229221
  timestamp: zod.z.number()
229140
229222
  });
@@ -232029,7 +232111,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
232029
232111
  var MediaFileLiteSchema = zod.z.object({
232030
232112
  key: zod.z.string(),
232031
232113
  kind: zod.z.string(),
232032
- base64: zod.z.string(),
232114
+ url: zod.z.string(),
232033
232115
  sizeBytes: zod.z.number(),
232034
232116
  timestamp: zod.z.number()
232035
232117
  });
@@ -242277,6 +242359,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
242277
242359
  addonId: null,
242278
242360
  access: "view"
242279
242361
  },
242362
+ "pipelineAnalytics.listEventMedia": {
242363
+ capName: "pipeline-analytics",
242364
+ capScope: "device",
242365
+ addonId: null,
242366
+ access: "view"
242367
+ },
242280
242368
  "pipelineAnalytics.listGroups": {
242281
242369
  capName: "pipeline-analytics",
242282
242370
  capScope: "device",
@@ -246158,6 +246246,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
246158
246246
  form: "array",
246159
246247
  optional: false
246160
246248
  }],
246249
+ "pipelineAnalytics.listEventMedia": [{
246250
+ name: "deviceId",
246251
+ form: "single",
246252
+ optional: false
246253
+ }],
246161
246254
  "pipelineAnalytics.listGroups": [{
246162
246255
  name: "deviceIds",
246163
246256
  form: "array",
@@ -251198,6 +251291,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
251198
251291
  exports.MaskShapeKindSchema = MaskShapeKindSchema;
251199
251292
  exports.MaskShapeSchema = MaskShapeSchema;
251200
251293
  exports.MediaFileInfoSchema = MediaFileInfoSchema;
251294
+ exports.MediaFileRefSchema = MediaFileRefSchema;
251201
251295
  exports.MediaFileSchema = MediaFileSchema;
251202
251296
  exports.MediaPlayerRepeatSchema = MediaPlayerRepeatSchema;
251203
251297
  exports.MediaPlayerStateSchema = MediaPlayerStateSchema;
@@ -402904,7 +402998,7 @@ var require_addon_package_service = __commonJS({
402904
402998
  this.requireInstaller();
402905
402999
  const addonInstaller = this.installer;
402906
403000
  const previousVersion = this.getInstalledPackageVersion(name);
402907
- const isFirstInstall = !previousVersion;
403001
+ const isFirstInstall = previousVersion === null;
402908
403002
  let result;
402909
403003
  if (isFirstInstall) {
402910
403004
  const r = await addonInstaller.installFromNpm(name, version);
@@ -402930,12 +403024,13 @@ var require_addon_package_service = __commonJS({
402930
403024
  const targetDir = path.join(addonsDir, dirName);
402931
403025
  const packageSpec = version ? `${name}@${version}` : name;
402932
403026
  await installPackageFromNpm(packageSpec, targetDir);
402933
- updatedVersion = this.getInstalledPackageVersion(name);
403027
+ const installedVersion = this.getInstalledPackageVersion(name);
403028
+ updatedVersion = installedVersion ?? "";
402934
403029
  this.cachedUpdates = null;
402935
403030
  this.logger.info("Core package updated -- restart required", {
402936
- meta: { name, updatedVersion }
403031
+ meta: { name, updatedVersion: installedVersion }
402937
403032
  });
402938
- this.sendUpdateNotification(name, updatedVersion);
403033
+ this.sendUpdateNotification(name, installedVersion);
402939
403034
  return { success: true, version: updatedVersion, requiresRestart: true };
402940
403035
  } catch (error) {
402941
403036
  const msg = (0, types_1.errMsg)(error);
@@ -403622,36 +403717,39 @@ var require_addon_package_service = __commonJS({
403622
403717
  // Private: general helpers
403623
403718
  // =========================================================================
403624
403719
  /**
403625
- * Read the currently installed version of a package.
403626
- * Checks data/addons/ first, then falls back to Node module resolution.
403627
- * Returns '0.0.0' if not found.
403720
+ * The version of `packageName` INSTALLED RIGHT NOW, or `null` when the hub
403721
+ * has no readable copy.
403722
+ *
403723
+ * Delegates to the installer, which is the one place that knows the on-disk
403724
+ * layout (`<addonsDir>/@camstack/<pkg>/`, with the pre-scope flat form as a
403725
+ * fallback). This method used to restate that path and got it wrong —
403726
+ * `packageName.replace(/^@camstack\//, '')` looked ONLY in the flat form, so
403727
+ * every scoped install missed. It then fell back to
403728
+ * `require.resolve('<pkg>/package.json')`, which cannot succeed either: an
403729
+ * addon is installed under the data directory, not in the hub's own
403730
+ * node_modules. Both misses landed on the literal `'0.0.0'`, and that string
403731
+ * was published on the `addon.updated` event as the version the operator had
403732
+ * been running ("@camstack/addon-terminal 0.0.0 → latest", 2026-08-30).
403733
+ *
403734
+ * `null`, not `'0.0.0'`: a version nobody installed is indistinguishable
403735
+ * from one that was, and the caller must be forced to decide what to say
403736
+ * about "unknown" rather than inherit a number that looks like an answer.
403628
403737
  */
403629
403738
  getInstalledPackageVersion(packageName) {
403630
403739
  try {
403631
- const addonsDir = this.resolveAddonsDir();
403632
- const dirName = packageName.replace(/^@camstack\//, "");
403633
- const pkgJsonPath = path.join(addonsDir, dirName, "package.json");
403634
- if (fs.existsSync(pkgJsonPath)) {
403635
- const pkgJson = readJsonObject(pkgJsonPath);
403636
- const v = asString(pkgJson?.["version"]);
403637
- if (v)
403638
- return v;
403639
- }
403740
+ const installed = this.installer?.getInstalledPackage(packageName) ?? null;
403741
+ const version = installed === null ? "" : asString(installed.version);
403742
+ if (version)
403743
+ return version;
403640
403744
  } catch (err) {
403641
- this.logger.debug("Version lookup via fs failed, trying require.resolve", {
403745
+ this.logger.debug("Installed-version lookup failed", {
403642
403746
  meta: { packageName, error: (0, types_1.errMsg)(err) }
403643
403747
  });
403644
403748
  }
403645
- try {
403646
- const pkgJsonPath = __require.resolve(`${packageName}/package.json`);
403647
- const pkgJson = readJsonObject(pkgJsonPath);
403648
- return asString(pkgJson?.["version"], "0.0.0");
403649
- } catch (err) {
403650
- this.logger.debug("Could not resolve version, returning 0.0.0", {
403651
- meta: { packageName, error: (0, types_1.errMsg)(err) }
403652
- });
403653
- return "0.0.0";
403654
- }
403749
+ this.logger.debug("No readable installed copy \u2014 previous version is unknown", {
403750
+ meta: { packageName }
403751
+ });
403752
+ return null;
403655
403753
  }
403656
403754
  /** Only allow @camstack/* scoped packages */
403657
403755
  isAllowedPackage(name) {
@@ -403703,11 +403801,18 @@ var require_addon_package_service = __commonJS({
403703
403801
  throw new Error("AddonInstaller is not available -- @camstack/system may not be installed");
403704
403802
  }
403705
403803
  }
403706
- /** Send notification and toast for a successful package update */
403804
+ /**
403805
+ * Send notification and toast for a successful package update.
403806
+ *
403807
+ * `version === null` means the hub could not read back what it just
403808
+ * installed. The sentence then says the package was updated and stops —
403809
+ * never "updated to v0.0.0", which reads as a real version.
403810
+ */
403707
403811
  sendUpdateNotification(name, version) {
403812
+ const sentence = version === null ? `${name} updated` : `${name} updated to v${version}`;
403708
403813
  this.notificationService.notify({
403709
403814
  title: "Package Updated",
403710
- body: `${name} updated to v${version}`,
403815
+ body: sentence,
403711
403816
  format: "text",
403712
403817
  priority: 3,
403713
403818
  category: "system",
@@ -403718,7 +403823,7 @@ var require_addon_package_service = __commonJS({
403718
403823
  });
403719
403824
  this.toastService.broadcast({
403720
403825
  title: "Package Updated",
403721
- message: `${name} updated to v${version}`,
403826
+ message: sentence,
403722
403827
  severity: "info",
403723
403828
  duration: 5e3
403724
403829
  });
@@ -417257,6 +417362,7 @@ var require_addon_registry_service = __commonJS({
417257
417362
  Object.defineProperty(exports, "__esModule", { value: true });
417258
417363
  exports.AddonRegistryService = void 0;
417259
417364
  exports.shouldEvictMissingOnDisk = shouldEvictMissingOnDisk;
417365
+ exports.addonUpdatePayload = addonUpdatePayload;
417260
417366
  exports.shouldEmitProviderRegisteredReady = shouldEmitProviderRegisteredReady;
417261
417367
  var node_crypto_1 = __require("crypto");
417262
417368
  var fs = __importStar(__require("fs"));
@@ -417279,6 +417385,12 @@ var require_addon_registry_service = __commonJS({
417279
417385
  function shouldEvictMissingOnDisk(entry, id, onDiskIds) {
417280
417386
  return entry.source === "installed" && entry.packageName !== "@camstack/system" && !onDiskIds.has(id);
417281
417387
  }
417388
+ function addonUpdatePayload(fromVersion, toVersion) {
417389
+ return {
417390
+ ...fromVersion !== null ? { fromVersion } : {},
417391
+ toVersion
417392
+ };
417393
+ }
417282
417394
  function isSettingsStore(backend) {
417283
417395
  const required = [
417284
417396
  "getSystem",
@@ -418354,14 +418466,17 @@ var require_addon_registry_service = __commonJS({
418354
418466
  this.healthMonitor.forget(packageName);
418355
418467
  this.addonLoader.clearLoadFailures(packageName);
418356
418468
  }
418357
- /** Emit addon.updated lifecycle event for all addons belonging to a package */
418469
+ /**
418470
+ * Emit `addon.updated` for every addon belonging to a package.
418471
+ *
418472
+ * The payload shape is {@link addonUpdatePayload} — an unknown predecessor
418473
+ * is an ABSENT key, never a placeholder.
418474
+ */
418358
418475
  emitUpdateEvent(packageName, fromVersion, toVersion) {
418476
+ const payload = addonUpdatePayload(fromVersion, toVersion);
418359
418477
  for (const [id, entry] of this.addonEntries) {
418360
418478
  if (entry.packageName === packageName) {
418361
- this.emitAddonLifecycleEvent("addon.updated", id, {
418362
- fromVersion,
418363
- toVersion
418364
- });
418479
+ this.emitAddonLifecycleEvent("addon.updated", id, payload);
418365
418480
  }
418366
418481
  }
418367
418482
  }