camstack 1.2.154 → 1.2.156

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-BEyvfshj.mjs
14525
+ // ../types/dist/sleep-BDR76Ykr.mjs
14526
14526
  var AUDIO_CHUNK_FORMATS = [
14527
14527
  "f32le",
14528
14528
  "pcmu",
@@ -18812,6 +18812,21 @@ var streamSignalsCapability = {
18812
18812
  mode: "singleton",
18813
18813
  deviceTypes: Object.values(DeviceType),
18814
18814
  runtimeState: StreamSignalsStatusSchema,
18815
+ /**
18816
+ * Runtime-state durability: **session** — mirrored in RAM, never written.
18817
+ *
18818
+ * The slice holds what the DEVICE says it can emit. That is a probed fact,
18819
+ * not an operator choice: the provider re-declares it on every registration,
18820
+ * so losing it loses nothing and persisting it would freeze an answer the
18821
+ * camera is entitled to change. Measured the same day on the sibling case —
18822
+ * `native-object-detection.supportedClasses` was persisted, and a firmware
18823
+ * class the camera really detected stayed missing for the life of the row
18824
+ * because the fix could not reach it.
18825
+ *
18826
+ * See `RuntimeStateDurability`. Enforced by
18827
+ * `scripts/check-runtime-state-durability.ts`.
18828
+ */
18829
+ durability: "session",
18815
18830
  methods: {
18816
18831
  /**
18817
18832
  * What this device can emit. Empty is a valid and common answer — most
@@ -25592,6 +25607,29 @@ var NcAlarmConfigSchema = external_exports.object({
25592
25607
  settings: NcAlarmSettingsSchema,
25593
25608
  coverage: external_exports.array(NcAlarmModeCoverageSchema)
25594
25609
  });
25610
+ var NcClipRetentionAskSchema = external_exports.object({
25611
+ /**
25612
+ * The camera this ask is about. **Absent = every camera**, which is what a
25613
+ * rule with no `conditions.devices` means: it can fire anywhere, so it is
25614
+ * asking everywhere.
25615
+ */
25616
+ deviceId: external_exports.number().int().nonnegative().optional(),
25617
+ /** Seconds of history the rule needs held for it. Never zero — a rule that
25618
+ * needs nothing produces no ask at all. */
25619
+ seconds: external_exports.number().min(0).max(60),
25620
+ /** The profile the rule cuts from, when it named one. Absent = the cheapest
25621
+ * assigned, which is what the cut defaults to. */
25622
+ profile: CamProfileSchema.optional(),
25623
+ /** Who is asking — so a retention the operator did not expect names a rule. */
25624
+ ruleId: external_exports.string(),
25625
+ ruleName: external_exports.string(),
25626
+ /** Why this many seconds: the rule's own window, or the occupancy ceiling. */
25627
+ reason: external_exports.enum(["window", "occupancy"])
25628
+ });
25629
+ var NcClipRetentionPlanSchema = external_exports.object({
25630
+ rulesLoaded: external_exports.boolean(),
25631
+ asks: external_exports.array(NcClipRetentionAskSchema).readonly()
25632
+ });
25595
25633
  var notificationRulesCapability = {
25596
25634
  name: "notification-rules",
25597
25635
  scope: "system",
@@ -25624,6 +25662,23 @@ var notificationRulesCapability = {
25624
25662
  auth: "admin"
25625
25663
  }),
25626
25664
  /**
25665
+ * WHAT THE RULES ACTUALLY ASK the stream broker to retain, per camera.
25666
+ *
25667
+ * The notification centre owns the rules, so it is the only thing that can
25668
+ * say how much history a camera's notifications will ever reach back for.
25669
+ * Before this the broker guessed — a flat minute on every camera — and
25670
+ * learned the PROFILE reactively, after the first clip had already been cut
25671
+ * from the wrong one. This is the same ask stated once, in front.
25672
+ *
25673
+ * A QUERY, pulled by each node's broker, not a push: brokers are per node
25674
+ * (a camera's ring lives wherever its stream is ingested) while this cap is
25675
+ * a singleton, so a push would have to enumerate the cluster. The pull also
25676
+ * makes the failure mode right — a broker that cannot reach the centre
25677
+ * keeps the plan it has, and a plan that has never arrived is UNKNOWN
25678
+ * rather than empty (D49: a read that fails changes nothing).
25679
+ */
25680
+ getClipRetentionAsks: method(external_exports.object({}), NcClipRetentionPlanSchema, { auth: "admin" }),
25681
+ /**
25627
25682
  * PERMANENT per-camera mute — the notifications half of the per-camera
25628
25683
  * function switch group ([D61](../../../../docs/decisions/adr-0067.md)).
25629
25684
  *
@@ -26783,6 +26838,7 @@ var TrackAudioLabelSchema = external_exports.object({
26783
26838
  });
26784
26839
  var TrackSourceSchema = external_exports.enum([
26785
26840
  "pipeline",
26841
+ "onboard",
26786
26842
  "sensor",
26787
26843
  "audio"
26788
26844
  ]);
@@ -27833,6 +27889,20 @@ var ReplayTrackSchema = external_exports.object({
27833
27889
  framesMatched: external_exports.number().int()
27834
27890
  });
27835
27891
  var RunReplayFrameProcessorResultSchema = external_exports.object({ tracks: external_exports.array(ReplayTrackSchema).readonly() });
27892
+ var AnalyticsLtsSeriesSchema = external_exports.enum([
27893
+ "motion",
27894
+ "audio-dbfs",
27895
+ "battery",
27896
+ "occupancy"
27897
+ ]);
27898
+ var LtsBucketSchema = external_exports.object({
27899
+ scope: external_exports.string(),
27900
+ bucketStart: external_exports.number().int(),
27901
+ samples: external_exports.number().int().nonnegative(),
27902
+ sum: external_exports.number(),
27903
+ min: external_exports.number(),
27904
+ max: external_exports.number()
27905
+ });
27836
27906
  var pipelineAnalyticsCapability = {
27837
27907
  name: "pipeline-analytics",
27838
27908
  scope: "device",
@@ -27976,6 +28046,30 @@ var pipelineAnalyticsCapability = {
27976
28046
  getKeyEventsBatch: method(KeyEventBatchQueryInput, external_exports.array(KeyEventsForDeviceSchema).readonly()),
27977
28047
  /** Server-side bucketed event counts for the 24-hour timeline.
27978
28048
  * Returns one entry per non-empty bucket; empty buckets are omitted. */
28049
+ /**
28050
+ * Read one camera's long-term series — 5-minute buckets, kept for a year.
28051
+ *
28052
+ * This is the history surface for every chart that used to be served from a
28053
+ * RAM ring: the ring dies with the process, cannot answer about last night,
28054
+ * and had a 60-minute horizon, while these rows are ~60 bytes and already
28055
+ * written. `scope` is the series' own dimension — for `occupancy`, spell it
28056
+ * with {@link occupancyScope} rather than by hand, and omit it to get every
28057
+ * scope back at once (the caller then groups with
28058
+ * {@link parseOccupancyScope}).
28059
+ *
28060
+ * Bounds are inclusive on the BUCKET START, so a range that ends mid-bucket
28061
+ * still returns the bucket it lands in — the alternative is a chart whose
28062
+ * last column silently disappears for five minutes out of every five.
28063
+ */
28064
+ readLongTermSeries: method(external_exports.object({
28065
+ deviceId: external_exports.number(),
28066
+ series: AnalyticsLtsSeriesSchema,
28067
+ /** Omit for EVERY scope of this series in the range. */
28068
+ scope: external_exports.string().optional(),
28069
+ from: external_exports.number(),
28070
+ to: external_exports.number(),
28071
+ limit: external_exports.number().int().positive().optional()
28072
+ }), external_exports.array(LtsBucketSchema).readonly()),
27979
28073
  getEventDensity: method(external_exports.object({
27980
28074
  deviceId: external_exports.number(),
27981
28075
  since: external_exports.number(),
@@ -28984,7 +29078,7 @@ var MotionSourceEnum = external_exports.enum([
28984
29078
  "device-activity"
28985
29079
  ]);
28986
29080
  var MotionSourcesSchema = external_exports.array(MotionSourceEnum);
28987
- var DetectionSourcesSchema = external_exports.array(DetectionSourceSchema);
29081
+ var DetectionSourcesSchema = external_exports.preprocess((value) => Array.isArray(value) && value.length > 1 ? value.slice(0, 1) : value, external_exports.array(DetectionSourceSchema).max(1));
28988
29082
  var ReportMotionInputSchema = external_exports.object({
28989
29083
  deviceId: external_exports.number(),
28990
29084
  detected: external_exports.boolean(),
@@ -29478,6 +29572,12 @@ var RunnerLocalMetricsSchema = external_exports.object({
29478
29572
  queueDepth: external_exports.number(),
29479
29573
  frameLazy: FrameLazyMetricsSchema.optional()
29480
29574
  });
29575
+ var OccupancyBurstRefusalSchema = external_exports.enum([
29576
+ "not-attached",
29577
+ "battery-asleep",
29578
+ "not-watching",
29579
+ "already-bursting"
29580
+ ]);
29481
29581
  var pipelineRunnerCapability = {
29482
29582
  name: "pipeline-runner",
29483
29583
  scope: "system",
@@ -29514,6 +29614,50 @@ var pipelineRunnerCapability = {
29514
29614
  /** List the deviceIds currently attached to this runner. */
29515
29615
  getLocalCameras: method(external_exports.void(), external_exports.array(external_exports.number()).readonly()),
29516
29616
  /**
29617
+ * Look at a camera NOW, out of band, because something just happened that
29618
+ * only a fresh look can settle.
29619
+ *
29620
+ * The periodic recheck (`occupancyRecheckSec`, 300 s) exists to watch a
29621
+ * still scene. It is the wrong instrument for a QUESTION that has just been
29622
+ * asked: on device 617 a parked car's departure was observed, a departure
29623
+ * strike was armed — and then the motion session ended, the strike decayed
29624
+ * after its 30 s TTL, and the next periodic look arrived up to five minutes
29625
+ * later with nothing left to confirm. Every one of those departures was
29626
+ * settled by the entry ageing out 6 to 10 minutes of observed time later,
29627
+ * and the notification's clip showed an empty space with nothing leaving
29628
+ * it.
29629
+ *
29630
+ * Two numbers make the ask specific, and a caller that ignores them wastes
29631
+ * the burst: a confirmation must land at least
29632
+ * `DEPARTURE_CONFIRM_MIN_GAP_MS` (3 s) after the read that armed the
29633
+ * strike — before that it is the same optical event and is refused — and
29634
+ * `DEPARTURE_ABSENCE_MIN_READS` (5) consecutive unassociated frames are
29635
+ * needed, while `occupancyRecheckFrames` defaults to FOUR. A burst of four
29636
+ * can never confirm an absence; that is why two periodic looks were always
29637
+ * required.
29638
+ *
29639
+ * The runner answers whether it actually started one. A refusal is NAMED,
29640
+ * never a silent `false`: a camera that is asleep on battery (D173 — this
29641
+ * must not become a self-initiated wake), detached, mid-session or already
29642
+ * bursting are four different facts, and a caller told only "no" cannot
29643
+ * tell a protection from a bug.
29644
+ */
29645
+ requestOccupancyBurst: method(external_exports.object({
29646
+ deviceId: external_exports.number(),
29647
+ /** How many frames to collect. The caller sizes this against what its
29648
+ * own confirmation needs; the runner clamps it to the field's range. */
29649
+ frames: external_exports.number().int().positive().optional(),
29650
+ /** Why, for the log. A burst nobody can attribute is a cost nobody can
29651
+ * defend — the periodic one at least has a timer to point at. */
29652
+ reason: external_exports.string()
29653
+ }), external_exports.object({
29654
+ started: external_exports.boolean(),
29655
+ refusedBecause: OccupancyBurstRefusalSchema.optional()
29656
+ }), {
29657
+ auth: "admin",
29658
+ kind: "mutation"
29659
+ }),
29660
+ /**
29517
29661
  * Best-effort NATIVE-resolution crop of a retention-ring frame. Given the
29518
29662
  * `FrameHandle` that rode an inference-result event and a normalized `bbox`,
29519
29663
  * the runner asks the decode worker still holding that frame's NATIVE
@@ -41041,7 +41185,28 @@ var PerScopeBreakdownSchema = external_exports.object({
41041
41185
  /** Total tracked objects in this scope (frame / zone / unzoned). */
41042
41186
  totalObjects: external_exports.number().int().nonnegative(),
41043
41187
  /** Per-class count. Keys are macro class names (e.g. `person`, `car`). */
41044
- byClass: external_exports.record(external_exports.string(), external_exports.number().int().nonnegative())
41188
+ byClass: external_exports.record(external_exports.string(), external_exports.number().int().nonnegative()),
41189
+ /**
41190
+ * Of `totalObjects`, how many are STANDING — objects the census holds,
41191
+ * present but not going anywhere (a parked car, a bin, a statue).
41192
+ *
41193
+ * The operator's question about a scene has two halves and they answer
41194
+ * different things: "what is parked here" is stable for hours and must not
41195
+ * flap, while "who is walking through" is the thing an alert is about. One
41196
+ * number could only serve one of them, and `totalObjects` served the first
41197
+ * badly — a passer-by moved it and every occupancy rule saw a change.
41198
+ *
41199
+ * `standing + transient === totalObjects`, always. The total keeps its old
41200
+ * meaning exactly, so no rule written against it changes behaviour.
41201
+ *
41202
+ * ABSENT means UNKNOWN, never zero (D393): a snapshot from a node older than
41203
+ * this field cannot say, and a reader that folds absence in as 0 reports "no
41204
+ * parked objects here" about a camera whose lot is full.
41205
+ */
41206
+ standingObjects: external_exports.number().int().nonnegative().optional(),
41207
+ /** Of `totalObjects`, how many are passing through. See `standingObjects` —
41208
+ * same absence rule. */
41209
+ transientObjects: external_exports.number().int().nonnegative().optional()
41045
41210
  });
41046
41211
  var ZoneScopeBreakdownSchema = PerScopeBreakdownSchema.extend({
41047
41212
  zoneId: external_exports.string(),
@@ -44362,6 +44527,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
44362
44527
  addonId: null,
44363
44528
  access: "view"
44364
44529
  },
44530
+ "notificationRules.getClipRetentionAsks": {
44531
+ capName: "notification-rules",
44532
+ capScope: "system",
44533
+ addonId: null,
44534
+ access: "view"
44535
+ },
44365
44536
  "notificationRules.getConditionCatalog": {
44366
44537
  capName: "notification-rules",
44367
44538
  capScope: "system",
@@ -44872,6 +45043,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
44872
45043
  addonId: null,
44873
45044
  access: "create"
44874
45045
  },
45046
+ "pipelineAnalytics.readLongTermSeries": {
45047
+ capName: "pipeline-analytics",
45048
+ capScope: "device",
45049
+ addonId: null,
45050
+ access: "view"
45051
+ },
44875
45052
  "pipelineAnalytics.rebuildObjectEmbeddings": {
44876
45053
  capName: "pipeline-analytics",
44877
45054
  capScope: "device",
@@ -45544,6 +45721,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
45544
45721
  addonId: null,
45545
45722
  access: "create"
45546
45723
  },
45724
+ "pipelineRunner.requestOccupancyBurst": {
45725
+ capName: "pipeline-runner",
45726
+ capScope: "system",
45727
+ addonId: null,
45728
+ access: "create"
45729
+ },
45547
45730
  "pipelineRunner.runDetailSubtree": {
45548
45731
  capName: "pipeline-runner",
45549
45732
  capScope: "system",
@@ -48688,6 +48871,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
48688
48871
  form: "single",
48689
48872
  optional: false
48690
48873
  }],
48874
+ "pipelineAnalytics.readLongTermSeries": [{
48875
+ name: "deviceId",
48876
+ form: "single",
48877
+ optional: false
48878
+ }],
48691
48879
  "pipelineAnalytics.rebuildObjectEmbeddings": [{
48692
48880
  name: "deviceId",
48693
48881
  form: "single",
@@ -48878,6 +49066,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
48878
49066
  form: "single",
48879
49067
  optional: false
48880
49068
  }],
49069
+ "pipelineRunner.requestOccupancyBurst": [{
49070
+ name: "deviceId",
49071
+ form: "single",
49072
+ optional: false
49073
+ }],
48881
49074
  "pipelineRunner.runDetailSubtree": [{
48882
49075
  name: "deviceId",
48883
49076
  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-G3ME646K.js";
4
+ } from "./chunk-VR72SEQZ.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-ZQZHWQ6F.js");
41
+ await import("./launcher-OPKFHSZH.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-ZQZHWQ6F.js");
86
+ await import("./launcher-OPKFHSZH.js");
87
87
  }
88
88
 
89
89
  // src/commands/setup.ts
@@ -1140,7 +1140,7 @@ function isUnknown(_value) {
1140
1140
  return true;
1141
1141
  }
1142
1142
  async function resolveServerInteractive(presetNamespace) {
1143
- const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-DFMZ7HZD.js");
1143
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-63TJXVH3.js");
1144
1144
  if (presetNamespace) {
1145
1145
  const spinner4 = clack.spinner();
1146
1146
  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-G3ME646K.js";
8
+ } from "./chunk-VR72SEQZ.js";
9
9
  import "./chunk-LMMQX4CK.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,