camstack 1.2.68 → 1.2.69

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.
@@ -14522,7 +14522,7 @@ function date4(params) {
14522
14522
  // ../../node_modules/zod/v4/classic/external.js
14523
14523
  config(en_default());
14524
14524
 
14525
- // ../types/dist/sleep-BS40IUZZ.mjs
14525
+ // ../types/dist/sleep-DcA-CgqX.mjs
14526
14526
  var WELL_KNOWN_TABS = [
14527
14527
  {
14528
14528
  id: "overview",
@@ -15787,6 +15787,20 @@ var RelocateJobSchema = external_exports.object({
15787
15787
  * in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
15788
15788
  */
15789
15789
  rowsReconciled: external_exports.number().int().nonnegative().optional(),
15790
+ /**
15791
+ * Rows this run FORGOT because the file they name is not on disk.
15792
+ *
15793
+ * The mover derived the path from the row's own fields and `stat`ed it; an
15794
+ * ENOENT there is a per-path confirmation that the segment is gone (D296),
15795
+ * and the durable row is dropped through the same channel eviction uses. It
15796
+ * is reported for the same reason `rowsReconciled` is: this is a durable
15797
+ * mutation nobody asked for, and a migration that quietly erases hour rows is
15798
+ * the same failure as one that quietly skips them (D295).
15799
+ *
15800
+ * The production drain of 2026-08-30 would have reported 11 074 here — the
15801
+ * ledger claimed 5.65 GB of footage that no longer existed.
15802
+ */
15803
+ rowsForgotten: external_exports.number().int().nonnegative().optional(),
15790
15804
  startedAt: external_exports.number(),
15791
15805
  finishedAt: external_exports.number().nullable(),
15792
15806
  error: external_exports.string().nullable()
@@ -15994,6 +16008,71 @@ var RelocateResidueSchema = external_exports.object({
15994
16008
  segments: external_exports.number().int().nonnegative(),
15995
16009
  bytes: external_exports.number().int().nonnegative()
15996
16010
  }).nullable();
16011
+ var LedgerWalkInputSchema = external_exports.object({
16012
+ locationId: external_exports.string().min(1),
16013
+ /** Forget the confirmed-absent rows, rather than only counting them. */
16014
+ apply: external_exports.boolean().optional(),
16015
+ /** Narrow to one camera. */
16016
+ deviceId: external_exports.number().int().positive().optional(),
16017
+ /** Narrow to these recording profiles; empty/absent = every profile. */
16018
+ profiles: external_exports.array(external_exports.string().min(1)).optional()
16019
+ });
16020
+ var LedgerWalkRefusalSchema = external_exports.enum([
16021
+ "location-unknown",
16022
+ "source-writable",
16023
+ "no-ledger",
16024
+ "archive-unreadable",
16025
+ "anchor-absent",
16026
+ "anchor-unreadable",
16027
+ "anchor-moved"
16028
+ ]);
16029
+ var LedgerWalkSkipReasonSchema = external_exports.enum([
16030
+ "live-tail",
16031
+ "listing-error",
16032
+ "path-mismatch",
16033
+ "durable-refused"
16034
+ ]);
16035
+ var LedgerWalkSkipCountsSchema = external_exports.object({
16036
+ "live-tail": external_exports.number().int().nonnegative(),
16037
+ "listing-error": external_exports.number().int().nonnegative(),
16038
+ "path-mismatch": external_exports.number().int().nonnegative(),
16039
+ "durable-refused": external_exports.number().int().nonnegative()
16040
+ });
16041
+ var LedgerWalkDeviceReportSchema = external_exports.object({
16042
+ deviceId: external_exports.number().int(),
16043
+ hoursWalked: external_exports.number().int().nonnegative(),
16044
+ hoursMissing: external_exports.number().int().nonnegative(),
16045
+ ghostSegments: external_exports.number().int().nonnegative(),
16046
+ ghostBytes: external_exports.number().int().nonnegative(),
16047
+ forgottenSegments: external_exports.number().int().nonnegative(),
16048
+ orphanFiles: external_exports.number().int().nonnegative()
16049
+ });
16050
+ var LedgerWalkReportSchema = external_exports.object({
16051
+ locationId: external_exports.string(),
16052
+ applied: external_exports.boolean(),
16053
+ refused: LedgerWalkRefusalSchema.nullable(),
16054
+ archiveSegments: external_exports.number().int().nonnegative().nullable(),
16055
+ archiveBytes: external_exports.number().int().nonnegative().nullable(),
16056
+ hoursClaimed: external_exports.number().int().nonnegative(),
16057
+ hoursWalked: external_exports.number().int().nonnegative(),
16058
+ hoursMissing: external_exports.number().int().nonnegative(),
16059
+ /** `readdir` calls issued — the cost, stated in the unit that is paid. */
16060
+ listings: external_exports.number().int().nonnegative(),
16061
+ segmentsClaimed: external_exports.number().int().nonnegative(),
16062
+ ghostSegments: external_exports.number().int().nonnegative(),
16063
+ ghostBytes: external_exports.number().int().nonnegative(),
16064
+ ghostHoursWhole: external_exports.number().int().nonnegative(),
16065
+ forgottenSegments: external_exports.number().int().nonnegative(),
16066
+ forgottenBytes: external_exports.number().int().nonnegative(),
16067
+ /** Files under a claimed hour that no durable row names. Never deleted. */
16068
+ orphanFiles: external_exports.number().int().nonnegative(),
16069
+ orphanSample: external_exports.array(external_exports.string()).readonly(),
16070
+ hoursSkipped: external_exports.number().int().nonnegative(),
16071
+ skippedByReason: LedgerWalkSkipCountsSchema,
16072
+ /** The walk stopped at its per-pass hour bound with claims unwalked. */
16073
+ bounded: external_exports.boolean(),
16074
+ byDevice: external_exports.array(LedgerWalkDeviceReportSchema).readonly()
16075
+ });
15997
16076
  var RelocatableMediaCountSchema = external_exports.object({ rows: external_exports.number().int().nonnegative() }).nullable();
15998
16077
  var RelocatableMediaCountInputSchema = external_exports.object({
15999
16078
  toLocationId: external_exports.string().min(1),
@@ -26303,13 +26382,15 @@ var ListGroupsPageSchema = external_exports.object({
26303
26382
  groups: external_exports.array(AnalyticsGroupRecordSchema).readonly(),
26304
26383
  nextCursor: external_exports.string().nullable()
26305
26384
  });
26385
+ var KEY_EVENTS_DEFAULT_LIMIT = 50;
26386
+ var KEY_EVENTS_MAX_LIMIT = 200;
26306
26387
  var KeyEventQueryInput = external_exports.object({
26307
26388
  deviceId: external_exports.number(),
26308
26389
  /** Window lower bound (track firstSeen ≥ since). */
26309
26390
  since: external_exports.number(),
26310
26391
  /** Window upper bound (track firstSeen ≤ until). */
26311
26392
  until: external_exports.number(),
26312
- limit: external_exports.number().int().min(1).max(200).default(50),
26393
+ limit: external_exports.number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
26313
26394
  /** Drop tracks scoring below this importance. */
26314
26395
  minImportance: external_exports.number().min(0).max(1).optional(),
26315
26396
  /** Restrict to a single class (e.g. 'person'). */
@@ -26331,6 +26412,21 @@ var KeyEventSchema = external_exports.object({
26331
26412
  ...TrackFlagFields,
26332
26413
  ...TrackRetrainFields
26333
26414
  });
26415
+ var KeyEventBatchQueryInput = external_exports.object({
26416
+ deviceIds: external_exports.array(external_exports.number()).min(1).max(200),
26417
+ since: external_exports.number(),
26418
+ until: external_exports.number(),
26419
+ /** Applied PER CAMERA, exactly as `getKeyEvents.limit` is — never a total
26420
+ * across the set, which would let a busy camera starve a quiet one of its
26421
+ * rows and change what the merged feed contains. */
26422
+ limit: external_exports.number().int().min(1).max(KEY_EVENTS_MAX_LIMIT).default(KEY_EVENTS_DEFAULT_LIMIT),
26423
+ minImportance: external_exports.number().min(0).max(1).optional(),
26424
+ classFilter: external_exports.string().optional()
26425
+ });
26426
+ var KeyEventsForDeviceSchema = external_exports.object({
26427
+ deviceId: external_exports.number(),
26428
+ events: external_exports.array(KeyEventSchema).readonly()
26429
+ });
26334
26430
  var TrackedDetectionSchema = external_exports.object({
26335
26431
  trackId: external_exports.string(),
26336
26432
  className: external_exports.string(),
@@ -26625,6 +26721,21 @@ var pipelineAnalyticsCapability = {
26625
26721
  * scored on-read (no write). Degrades to `[]` on error.
26626
26722
  */
26627
26723
  getKeyEvents: method(KeyEventQueryInput, external_exports.array(KeyEventSchema).readonly()),
26724
+ /**
26725
+ * The same ranking, for a SET of cameras, in one round trip.
26726
+ *
26727
+ * The Detection Intelligence events feed asks this of every selected
26728
+ * camera and re-asks on a 30s timer. Fanned out client-side that is N
26729
+ * round trips — browser → hub → post-analysis — for N independent,
26730
+ * already-indexed store queries. Batched, the queries are unchanged and
26731
+ * run concurrently INSIDE the owner; only the transport collapses.
26732
+ *
26733
+ * Deliberately per-device rather than pre-merged: `limit` stays per
26734
+ * camera (a total would let a busy camera starve a quiet one), and a
26735
+ * caller that renders one camera's lane needs to know which camera a row
26736
+ * came from. `getKeyEvents` stays for single-device callers.
26737
+ */
26738
+ getKeyEventsBatch: method(KeyEventBatchQueryInput, external_exports.array(KeyEventsForDeviceSchema).readonly()),
26628
26739
  /** Server-side bucketed event counts for the 24-hour timeline.
26629
26740
  * Returns one entry per non-empty bucket; empty buckets are omitted. */
26630
26741
  getEventDensity: method(external_exports.object({
@@ -36714,6 +36825,23 @@ var recordingCapability = {
36714
36825
  kind: "query",
36715
36826
  auth: "admin"
36716
36827
  }),
36828
+ /**
36829
+ * Does this location's LEDGER tell the truth about its disk? (D319)
36830
+ *
36831
+ * One `readdir` per claimed hour, diffed both ways: durable rows whose file
36832
+ * is not there, and files no durable row names. `apply` defaults to FALSE —
36833
+ * the report is the product, and the dry run is how an operator
36834
+ * sanity-checks the destructive run before authorising it.
36835
+ *
36836
+ * REFUSES a source that is still a write target: a listing of a live
36837
+ * location is a lower bound, which is not the strong evidence that lets
36838
+ * this pass forget without a budget. A live location is reconciled by the
36839
+ * mover, under D318's bound.
36840
+ */
36841
+ reconcileLedgerAgainstDisk: method(LedgerWalkInputSchema, LedgerWalkReportSchema, {
36842
+ kind: "mutation",
36843
+ auth: "admin"
36844
+ }),
36717
36845
  /** Cancel a running or queued relocate job. A queued job never runs. */
36718
36846
  cancelRelocateJob: method(external_exports.object({ jobId: external_exports.string() }), external_exports.object({ cancelled: external_exports.boolean() }), {
36719
36847
  kind: "mutation",
@@ -37013,6 +37141,10 @@ var SceneMonitorStatusSchema = external_exports.object({
37013
37141
  monitors: external_exports.array(SceneMonitorSchema),
37014
37142
  lastFetchedAt: external_exports.number()
37015
37143
  });
37144
+ var SceneMonitorStatusForDeviceSchema = external_exports.object({
37145
+ deviceId: external_exports.number(),
37146
+ status: SceneMonitorStatusSchema.nullable()
37147
+ });
37016
37148
  var sceneMonitorCapability = {
37017
37149
  name: "scene-monitor",
37018
37150
  scope: "device",
@@ -37022,6 +37154,22 @@ var sceneMonitorCapability = {
37022
37154
  deviceTypes: [DeviceType.Camera],
37023
37155
  methods: {
37024
37156
  listScenes: method(external_exports.object({ deviceId: external_exports.number() }), SceneMonitorStatusSchema),
37157
+ /**
37158
+ * The same answer, for a SET of cameras, in one round trip.
37159
+ *
37160
+ * `/scenes` renders every camera and re-reads them on a 30s safety-net
37161
+ * poll behind the push slice. Fanned out client-side that was one query
37162
+ * per camera — 29 round trips through the browser, the hub and the
37163
+ * post-analysis runner every 30 seconds to read an in-memory map the
37164
+ * owner had already merged. The work is unchanged (`statusFor` per
37165
+ * device, all in-process at the owner); what collapses is the transport.
37166
+ *
37167
+ * A camera that cannot answer still gets a row, with `status: null` —
37168
+ * see {@link SceneMonitorStatusForDeviceSchema}. Never fewer rows than
37169
+ * ids: a caller that asked for twenty-nine and got twenty-seven cannot
37170
+ * tell which two are missing, or that any are.
37171
+ */
37172
+ listScenesBatch: method(external_exports.object({ deviceIds: external_exports.array(external_exports.number()).min(1).max(200) }), external_exports.array(SceneMonitorStatusForDeviceSchema).readonly()),
37025
37173
  createScene: method(external_exports.object({
37026
37174
  deviceId: external_exports.number(),
37027
37175
  label: external_exports.string(),
@@ -38591,6 +38739,11 @@ var CameraOccupancySnapshotSchema = external_exports.object({
38591
38739
  * than as repeated tracks/events. */
38592
38740
  stationaryObjects: external_exports.array(StationaryObjectSchema).readonly().optional()
38593
38741
  });
38742
+ var CameraOccupancySnapshotForDeviceSchema = external_exports.object({
38743
+ deviceId: external_exports.number(),
38744
+ read: external_exports.enum(["read", "unreadable"]),
38745
+ snapshot: CameraOccupancySnapshotSchema.nullable()
38746
+ });
38594
38747
  var HistoryResolutionEnum = external_exports.enum([
38595
38748
  "minute",
38596
38749
  "5min",
@@ -38620,6 +38773,20 @@ var zoneAnalyticsCapability = {
38620
38773
  * (no inference result emitted since boot or since binding was
38621
38774
  * activated). */
38622
38775
  getCurrentSnapshot: method(external_exports.object({ deviceId: external_exports.number() }), CameraOccupancySnapshotSchema.nullable()),
38776
+ /**
38777
+ * The same snapshot, for a SET of cameras, in one round trip.
38778
+ *
38779
+ * The Events page's Stationary section polls this every 15s for every
38780
+ * selected camera. Fanned out client-side that is one query per camera to
38781
+ * read a `Map.get` at the owner — the answer costs nothing, the round trip
38782
+ * costs everything. Batched, N transports become one and the per-device
38783
+ * work is unchanged.
38784
+ *
38785
+ * Every requested deviceId gets a row, tagged `read` — see
38786
+ * {@link CameraOccupancySnapshotForDeviceSchema}. A camera the owner could
38787
+ * not answer for is `'unreadable'`, never an empty reading.
38788
+ */
38789
+ getCurrentSnapshotBatch: method(external_exports.object({ deviceIds: external_exports.array(external_exports.number()).min(1).max(200) }), external_exports.array(CameraOccupancySnapshotForDeviceSchema).readonly()),
38623
38790
  /** Time-series object count inside one zone. `className` optional —
38624
38791
  * omit to count every class in the zone. */
38625
38792
  getZoneHistory: method(external_exports.object({
@@ -42030,6 +42197,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
42030
42197
  addonId: null,
42031
42198
  access: "view"
42032
42199
  },
42200
+ "pipelineAnalytics.getKeyEventsBatch": {
42201
+ capName: "pipeline-analytics",
42202
+ capScope: "device",
42203
+ addonId: null,
42204
+ access: "view"
42205
+ },
42033
42206
  "pipelineAnalytics.getMotionEvents": {
42034
42207
  capName: "pipeline-analytics",
42035
42208
  capScope: "device",
@@ -43206,6 +43379,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
43206
43379
  addonId: null,
43207
43380
  access: "view"
43208
43381
  },
43382
+ "recording.reconcileLedgerAgainstDisk": {
43383
+ capName: "recording",
43384
+ capScope: "system",
43385
+ addonId: null,
43386
+ access: "create"
43387
+ },
43209
43388
  "recording.refreshStorageLocationsForMigration": {
43210
43389
  capName: "recording",
43211
43390
  capScope: "system",
@@ -43332,6 +43511,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
43332
43511
  addonId: null,
43333
43512
  access: "view"
43334
43513
  },
43514
+ "sceneMonitor.listScenesBatch": {
43515
+ capName: "scene-monitor",
43516
+ capScope: "device",
43517
+ addonId: null,
43518
+ access: "view"
43519
+ },
43335
43520
  "sceneMonitor.recheckNow": {
43336
43521
  capName: "scene-monitor",
43337
43522
  capScope: "device",
@@ -44688,6 +44873,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
44688
44873
  addonId: null,
44689
44874
  access: "view"
44690
44875
  },
44876
+ "zoneAnalytics.getCurrentSnapshotBatch": {
44877
+ capName: "zone-analytics",
44878
+ capScope: "device",
44879
+ addonId: null,
44880
+ access: "view"
44881
+ },
44691
44882
  "zoneAnalytics.getUnzonedHistory": {
44692
44883
  capName: "zone-analytics",
44693
44884
  capScope: "device",
@@ -45692,6 +45883,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
45692
45883
  form: "single",
45693
45884
  optional: false
45694
45885
  }],
45886
+ "pipelineAnalytics.getKeyEventsBatch": [{
45887
+ name: "deviceIds",
45888
+ form: "array",
45889
+ optional: false
45890
+ }],
45695
45891
  "pipelineAnalytics.getMotionEvents": [{
45696
45892
  name: "deviceId",
45697
45893
  form: "single",
@@ -46132,6 +46328,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
46132
46328
  form: "single",
46133
46329
  optional: false
46134
46330
  }],
46331
+ "recording.reconcileLedgerAgainstDisk": [{
46332
+ name: "deviceId",
46333
+ form: "single",
46334
+ optional: true
46335
+ }],
46135
46336
  "recording.relocateFootage": [{
46136
46337
  name: "deviceId",
46137
46338
  form: "single",
@@ -46197,6 +46398,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
46197
46398
  form: "single",
46198
46399
  optional: false
46199
46400
  }],
46401
+ "sceneMonitor.listScenesBatch": [{
46402
+ name: "deviceIds",
46403
+ form: "array",
46404
+ optional: false
46405
+ }],
46200
46406
  "sceneMonitor.recheckNow": [{
46201
46407
  name: "deviceId",
46202
46408
  form: "single",
@@ -46458,6 +46664,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
46458
46664
  form: "single",
46459
46665
  optional: false
46460
46666
  }],
46667
+ "zoneAnalytics.getCurrentSnapshotBatch": [{
46668
+ name: "deviceIds",
46669
+ form: "array",
46670
+ optional: false
46671
+ }],
46461
46672
  "zoneAnalytics.getUnzonedHistory": [{
46462
46673
  name: "deviceId",
46463
46674
  form: "single",
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-6X7D7D4Y.js";
4
+ } from "./chunk-VBTD2AIS.js";
5
5
  import "./chunk-LMMQX4CK.js";
6
6
 
7
7
  // src/cli.ts
@@ -38,7 +38,7 @@ async function runServe(args) {
38
38
  ...typeof values.data === "string" ? { data: values.data } : {}
39
39
  };
40
40
  Object.assign(process.env, buildServeEnv(opts));
41
- await import("./launcher-H2LQYCEY.js");
41
+ await import("./launcher-INC5TETK.js");
42
42
  }
43
43
 
44
44
  // src/commands/agent.ts
@@ -83,7 +83,7 @@ async function runAgent(args) {
83
83
  ...typeof values.port === "string" ? { port: values.port } : {}
84
84
  };
85
85
  Object.assign(process.env, buildAgentEnv(opts));
86
- await import("./launcher-H2LQYCEY.js");
86
+ await import("./launcher-INC5TETK.js");
87
87
  }
88
88
 
89
89
  // src/commands/setup.ts
@@ -1130,7 +1130,7 @@ function isUnknown(_value) {
1130
1130
  return true;
1131
1131
  }
1132
1132
  async function resolveServerInteractive(presetNamespace) {
1133
- const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-ABTN33LN.js");
1133
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-4S4WTMPM.js");
1134
1134
  if (presetNamespace) {
1135
1135
  const spinner4 = clack.spinner();
1136
1136
  spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
@@ -5,7 +5,7 @@ import {
5
5
  filterHubNodes,
6
6
  resolveHubFromDiscovered,
7
7
  runDiscover
8
- } from "./chunk-6X7D7D4Y.js";
8
+ } from "./chunk-VBTD2AIS.js";
9
9
  import "./chunk-LMMQX4CK.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,