@camstack/addon-import-alexa 0.2.118 → 0.2.120

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.
Files changed (3) hide show
  1. package/dist/addon.js +999 -552
  2. package/dist/addon.mjs +999 -552
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -38,7 +38,7 @@ let node_os = require("node:os");
38
38
  let node_fs = require("node:fs");
39
39
  let node_path = require("node:path");
40
40
  node_path = __toESM(node_path);
41
- //#region ../types/dist/event-category-BGmz_oxW.mjs
41
+ //#region ../types/dist/event-category-B_0XEcLF.mjs
42
42
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
43
43
  EventCategory["SystemBoot"] = "system.boot";
44
44
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -539,15 +539,6 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
539
539
  EventCategory["AgentWsDisconnected"] = "agent.ws.disconnected";
540
540
  EventCategory["AgentBackupActivated"] = "agent.backup.activated";
541
541
  EventCategory["OrchestrationSettingsUpdated"] = "orchestration.settings-updated";
542
- /**
543
- * Per-agent hwaccel preference changed (user override set, cleared, or
544
- * re-probed). Observability event — decoders pull the current pref at
545
- * `createSession`, so running sessions keep their current backend until
546
- * they rotate naturally (camera add/remove, stream restart). Future
547
- * work can wire a listener in stream-broker that force-rotates live
548
- * sessions; for now this event powers logs + admin-UI toast feedback.
549
- */
550
- EventCategory["PipelineAgentHwaccelChanged"] = "pipeline.agent-hwaccel-changed";
551
542
  EventCategory["MotionAnalysis"] = "detection.motion-analysis";
552
543
  /** All raw motion zones from CCL before minArea filter — for UI debug overlay. */
553
544
  EventCategory["MotionZonesRaw"] = "detection.motion-zones-raw";
@@ -5418,7 +5409,7 @@ var ZodIssueCode = {
5418
5409
  var ZodFirstPartyTypeKind;
5419
5410
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5420
5411
  //#endregion
5421
- //#region ../types/dist/sleep-DXKLNFvA.mjs
5412
+ //#region ../types/dist/sleep-BNeXenvr.mjs
5422
5413
  /**
5423
5414
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5424
5415
  * window to float samples (D455).
@@ -6784,32 +6775,12 @@ object({
6784
6775
  audioCodec: string().optional(),
6785
6776
  metadata: record(string(), unknown()).readonly().optional()
6786
6777
  });
6787
- var EncodedPacketSchema = object({
6788
- type: _enum(["video", "audio"]),
6789
- data: _instanceof(Uint8Array),
6790
- pts: number(),
6791
- dts: number(),
6792
- keyframe: boolean(),
6793
- codec: string()
6794
- });
6795
- var DecodedFrameSchema = object({
6796
- data: _instanceof(Uint8Array),
6797
- width: number(),
6798
- height: number(),
6799
- format: _enum([
6800
- "jpeg",
6801
- "rgb",
6802
- "bgr",
6803
- "yuv420",
6804
- "gray"
6805
- ]),
6806
- timestamp: number()
6807
- });
6808
6778
  /**
6809
6779
  * Wire schema for `FrameHandle` — a zero-pixel, serialisable reference to a
6810
6780
  * frame in a shared-memory ring (Phase 5 / D9). Mirrors the `FrameHandle` TS
6811
- * interface in `interfaces/frame-handle.ts` field-for-field so a decoder cap
6812
- * method (`pullHandles`) can carry handles over tRPC / Moleculer.
6781
+ * interface in `interfaces/frame-handle.ts` field-for-field so a cap method
6782
+ * (the runner's native-crop and pipeline-executor inputs) can carry handles
6783
+ * over tRPC / Moleculer.
6813
6784
  *
6814
6785
  * The `satisfies` assertion below pins this schema to the interface: if a
6815
6786
  * field is added to / removed from `FrameHandle` without a matching schema
@@ -6835,50 +6806,6 @@ var FrameHandleSchema = object({
6835
6806
  slotCount: number().int().positive()
6836
6807
  });
6837
6808
  /**
6838
- * Pixel format a frame-handle subscriber can request from the broker
6839
- * (Phase 5 / D9). The packed, raster subset of `FrameFormat` — the formats a
6840
- * `frameSink: 'shm'` decoder session can write into a `FrameRing` slot.
6841
- * `jpeg` is excluded: a variable-length stream is not a fixed-stride ring
6842
- * payload, and no decoded-frame consumer requests it over the shm plane.
6843
- */
6844
- var FrameHandleFormatSchema = _enum([
6845
- "rgb",
6846
- "bgr",
6847
- "yuv420",
6848
- "gray"
6849
- ]);
6850
- /**
6851
- * Input for `stream-broker.subscribeFrames` (Phase 5 / D9). A consumer asks the
6852
- * broker for a `FrameHandle` stream of one `format`; the broker maintains one
6853
- * shared-memory ring per `(brokerId, format)` actually requested, so a `gray`
6854
- * subscriber (motion) and an `rgb` subscriber (detection) each read the format
6855
- * they asked for with no broker-side conversion.
6856
- */
6857
- var SubscribeFramesInputSchema = object({
6858
- brokerId: string(),
6859
- format: FrameHandleFormatSchema,
6860
- /**
6861
- * Optional reader-side cadence hint in frames per second. The broker does
6862
- * NOT throttle — latest-wins ring reads drop frames implicitly for a slow
6863
- * consumer. The value is echoed back in `SubscribeFramesResult.maxFps` so
6864
- * the consumer can pace its own `pullFrameHandles` polling.
6865
- */
6866
- maxFps: number().positive().optional(),
6867
- /** Short caller-identity tag (`motion`, `detection`, …) for diagnostics. */
6868
- tag: string().optional()
6869
- });
6870
- /**
6871
- * Result of `stream-broker.subscribeFrames`. The consumer then polls
6872
- * `pullFrameHandles({ subscriptionId, maxCount })` and feeds each returned
6873
- * `FrameHandle` to a `FrameRingReader`.
6874
- */
6875
- var SubscribeFramesResultSchema = object({
6876
- /** Opaque id the consumer passes to `pullFrameHandles` / `unsubscribeFrames`. */
6877
- subscriptionId: string(),
6878
- /** Reader-side cadence hint (frames/s) — echoes `SubscribeFramesInput.maxFps`. */
6879
- maxFps: number().nonnegative()
6880
- });
6881
- /**
6882
6809
  * Wire schema for a decoded audio chunk (Phase 5 / D9). Mirrors the
6883
6810
  * `DecodedAudioChunk` TS interface in `interfaces/stream-broker.ts`: PCM
6884
6811
  * sample bytes plus the track parameters a consumer needs to interpret them.
@@ -6886,8 +6813,8 @@ var SubscribeFramesResultSchema = object({
6886
6813
  * Audio chunks are tiny (a ~500ms AudioCodecSession window is a few KB of
6887
6814
  * Float32 PCM), so unlike video frames they ship their bytes INLINE over
6888
6815
  * tRPC / Moleculer — no shared-memory plane. `data` is typed `Uint8Array`
6889
- * (the wire-serialisable supertype of `Buffer`) to match `DecodedFrameSchema`
6890
- * / `EncodedPacketSchema`'s precedent; a `Buffer` is assignable to it.
6816
+ * (the wire-serialisable supertype of `Buffer`); a `Buffer` is assignable to
6817
+ * it.
6891
6818
  */
6892
6819
  var AudioChunkFormatSchema = _enum(AUDIO_CHUNK_FORMATS);
6893
6820
  var DecodedAudioChunkSchema = object({
@@ -6905,11 +6832,10 @@ var DecodedAudioChunkSchema = object({
6905
6832
  format: AudioChunkFormatSchema.optional()
6906
6833
  });
6907
6834
  /**
6908
- * Input for `stream-broker.subscribeAudioChunks` (Phase 5 / D9). The
6909
- * handle-free, ship-bytes-inline analogue of `subscribeFrames`: a consumer
6910
- * asks the broker for the decoded audio-chunk stream of one broker; the
6911
- * broker keeps a per-subscription bounded FIFO queue the consumer drains via
6912
- * `pullAudioChunks`.
6835
+ * Input for `stream-broker.subscribeAudioChunks` (Phase 5 / D9). Audio ships
6836
+ * its bytes inline: a consumer asks the broker for the decoded audio-chunk
6837
+ * stream of one broker; the broker keeps a per-subscription bounded FIFO queue
6838
+ * the consumer drains via `pullAudioChunks`.
6913
6839
  */
6914
6840
  var SubscribeAudioChunksInputSchema = object({
6915
6841
  brokerId: string(),
@@ -6940,9 +6866,7 @@ var BrokerStatsSchema = object({
6940
6866
  "stopped"
6941
6867
  ]),
6942
6868
  inputFps: number(),
6943
- decodeFps: number(),
6944
6869
  encodedSubscribers: number(),
6945
- decodedSubscribers: number(),
6946
6870
  uptimeMs: number(),
6947
6871
  bitrateKbps: number(),
6948
6872
  idrIntervalMs: number(),
@@ -6955,14 +6879,6 @@ var BrokerStatsSchema = object({
6955
6879
  preBufferMs: number(),
6956
6880
  preBufferPackets: number(),
6957
6881
  /**
6958
- * Moleculer node id of the decoder provider currently servicing this
6959
- * stream's decoded subscribers. `null` until the deferred decoder is
6960
- * created (no decoded clients yet, or codec not detected). Surfaces the
6961
- * runtime decoder placement so the UI can show "Decoder: <agent>" without
6962
- * a separate cap call per broker.
6963
- */
6964
- decoderNodeId: string().nullable(),
6965
- /**
6966
6882
  * Detected audio track parameters from the RTSP DESCRIBE / SDP. `null`
6967
6883
  * when the stream has no audio track or the broker is in cold start.
6968
6884
  * `supported = false` means the codec was detected but the local
@@ -10415,70 +10331,6 @@ var StorageLocationDeclarationSchema = object({
10415
10331
  "backup"
10416
10332
  ]).optional()
10417
10333
  });
10418
- var DecoderStatsSchema = object({
10419
- inputFps: number(),
10420
- outputFps: number(),
10421
- avgDecodeTimeMs: number(),
10422
- droppedFrames: number(),
10423
- /**
10424
- * Pull-mode adaptive-fps telemetry (optional — only pull sessions run the
10425
- * lag-driven controller; push sessions omit these). `lagMs` is the EWMA of
10426
- * the decoder's real-time drift (rising = falling behind live); `adaptiveFps`
10427
- * is the current lag-throttled emit rate (≤ `effectiveFps` ceiling).
10428
- */
10429
- lagMs: number().optional(),
10430
- effectiveFps: number().optional(),
10431
- adaptiveFps: number().optional()
10432
- });
10433
- var DecoderSessionConfigSchema = object({
10434
- codec: string(),
10435
- maxFps: number().default(0),
10436
- outputFormat: _enum([
10437
- "jpeg",
10438
- "rgb",
10439
- "bgr",
10440
- "yuv420",
10441
- "gray"
10442
- ]).default("jpeg"),
10443
- scale: number().default(1),
10444
- width: number().optional(),
10445
- height: number().optional(),
10446
- /**
10447
- * Identifier of the camera this decoder session serves. Optional
10448
- * because the cap is generic (any caller could request decode), but
10449
- * stream-broker passes it so decoder logs include `deviceId` for
10450
- * per-camera filtering when diagnosing failures (e.g. node-av
10451
- * sendPacket errors on a single hung camera).
10452
- */
10453
- deviceId: number().int().nonnegative().optional(),
10454
- /**
10455
- * Free-form tag for log scoping. Stream-broker uses
10456
- * `broker:<deviceId>/<profile>`. Decoder session logger surfaces it
10457
- * on every line so `grep tag=broker:5/high` filters one camera
10458
- * profile cleanly.
10459
- */
10460
- tag: string().optional(),
10461
- /**
10462
- * Where the session delivers decoded frames (Phase 5 / D9):
10463
- *
10464
- * - `'callback'` (default) — the legacy pixel path: decoded frames are
10465
- * buffered as `DecodedFrame`s and drained via `pullFrames`.
10466
- * - `'shm'` — the shared-memory frame plane: decoded frames are written
10467
- * into an OS shared-memory ring and drained as zero-pixel
10468
- * `FrameHandle`s via `pullHandles`. A session is one mode or the
10469
- * other — `pullFrames` returns nothing for an `'shm'` session and
10470
- * `pullHandles` returns nothing for a `'callback'` session.
10471
- */
10472
- frameSink: _enum(["callback", "shm"]).default("callback"),
10473
- /**
10474
- * Per-camera decoder DEBUG facility. When `true`, a pull-mode session emits
10475
- * a throttled (~1Hz) structured `decoder debug` line (effective/adaptive fps,
10476
- * real-time lag, dropped-frame delta, avg decode time, hwaccel). Mirrors the
10477
- * stream-broker's `streamingDebug` gate — off by default so production logs
10478
- * stay quiet and the emit path pays zero per-frame cost when disabled.
10479
- */
10480
- debug: boolean().optional()
10481
- });
10482
10334
  /**
10483
10335
  * Per-component log CHANNELS — the gate a hot path consults, and the registry
10484
10336
  * an addon declares its channels in.
@@ -10621,6 +10473,26 @@ var ClipSearchStrictnessSchema = _enum([
10621
10473
  "balanced",
10622
10474
  "strict"
10623
10475
  ]);
10476
+ /** Steps whose effect a root label can BE. */
10477
+ var LABEL_SUPPLY_STEP_IDS = [
10478
+ "animal-classifier",
10479
+ "vehicle-classifier",
10480
+ "package-detection"
10481
+ ];
10482
+ /** Steps whose box a root detection can BE. */
10483
+ var CROP_SUPPLY_STEP_IDS = ["plate-detection", "face-detection"];
10484
+ /**
10485
+ * Steps whose per-detection MASK a root detection can carry (D737). The live
10486
+ * mask step is `segmentation` — a frame-plane refiner that runs its own model
10487
+ * once per detection crop. (`instance-segmentation` is a dormant step id that
10488
+ * no camera tree carries.)
10489
+ */
10490
+ var MASK_SUPPLY_STEP_IDS = ["segmentation"];
10491
+ [
10492
+ ...LABEL_SUPPLY_STEP_IDS,
10493
+ ...CROP_SUPPLY_STEP_IDS,
10494
+ ...MASK_SUPPLY_STEP_IDS
10495
+ ];
10624
10496
  var MODEL_FORMATS = [
10625
10497
  "onnx",
10626
10498
  "coreml",
@@ -10649,7 +10521,53 @@ var ModelFormatEntrySchema = object({
10649
10521
  /** Multi-file payload (directory members or sibling files). */
10650
10522
  files: array(string()).readonly().optional(),
10651
10523
  /** Runtime(s) that can use this format. If omitted, inferred from ModelFormat key */
10652
- runtimes: array(_enum(["python"])).readonly().optional()
10524
+ runtimes: array(_enum(["python"])).readonly().optional(),
10525
+ /**
10526
+ * Content revision of the artefact, for one hosted OFF the CamStack mirror.
10527
+ * A format on the mirror leaves it unset: its revision (the sha256 of its
10528
+ * weight file) comes from the downloader's generated table, kept in step
10529
+ * with the mirror by `scripts/check-hosted-model-revisions.ts` (D744). A
10530
+ * node records the revision it downloaded next to the file
10531
+ * (`<file>.revision`); a copy with no record or a different one is stale
10532
+ * unless its weight file hashes to the revision, and a stale copy is
10533
+ * downloaded again, the old one serving until the new one is complete. No
10534
+ * revision at all ⇒ a file on disk is current, whatever it holds (D743).
10535
+ */
10536
+ revision: string().min(1).optional()
10537
+ });
10538
+ /**
10539
+ * What a node holds for one (model, format) (D746). `current` is a complete
10540
+ * copy at its catalog revision — exactly what `downloaded: true` means.
10541
+ * `stale` is bytes on disk that are not (yet) proven current under D743/D744:
10542
+ * no or a different revision record, or a missing sibling. `missing` is no
10543
+ * copy. `downloaded` alone folds `stale` into "not downloaded", which hid
10544
+ * reclaimable bytes and a copy about to be replaced.
10545
+ */
10546
+ var ModelOnDiskStateSchema = _enum([
10547
+ "current",
10548
+ "stale",
10549
+ "missing"
10550
+ ]);
10551
+ /**
10552
+ * The numeric precision of one format's BUILD (D746) — reported only when the
10553
+ * build states it (file-name token, an INT8 variant, an EdgeTPU compile, a
10554
+ * CamStack Core ML export). Absent means "not stated", never "fp32".
10555
+ */
10556
+ var ModelFormatPrecisionSchema = _enum([
10557
+ "fp32",
10558
+ "fp16",
10559
+ "int8"
10560
+ ]);
10561
+ /**
10562
+ * One format of one model as a node's `pipelineExecutor.getSchema` reports it.
10563
+ * `onDisk` / `precision` are optional for version skew: a runner that predates
10564
+ * them omits them, and a reader falls back to `downloaded`.
10565
+ */
10566
+ var PipelineModelFormatStatusSchema = object({
10567
+ downloaded: boolean(),
10568
+ sizeMB: number(),
10569
+ onDisk: ModelOnDiskStateSchema.optional(),
10570
+ precision: ModelFormatPrecisionSchema.optional()
10653
10571
  });
10654
10572
  /**
10655
10573
  * Extra file that must be downloaded alongside the model (e.g., labels JSON, dict.txt).
@@ -10690,11 +10608,11 @@ var ModelVariantGroupSchema = object({
10690
10608
  /** Quantization axis. Omit ⇒ the fp32 base build. */
10691
10609
  precision: _enum(["fp32", "int8"]).optional(),
10692
10610
  /**
10693
- * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
10694
- * latency-optimized export (e.g. ReLU-activation variant) — the slot the
10695
- * future performance variants plug into.
10611
+ * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
10612
+ * an alternate training of the same family (Scrypted `relu_test`); chip
10613
+ * label is "Test".
10696
10614
  */
10697
- optimization: _enum(["standard", "fast"]).optional(),
10615
+ optimization: _enum(["standard", "test"]).optional(),
10698
10616
  /**
10699
10617
  * Input-resolution axis (square input side, px). Omit ⇒ the family's native
10700
10618
  * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
@@ -10717,9 +10635,10 @@ var ModelProviderIdSchema = _enum([
10717
10635
  * are per upstream. A persisted custom-model row written when this field was a
10718
10636
  * string still parses — the string is lifted into `{ weights }`.
10719
10637
  *
10720
- * Every licence surface (the admin "Models and licenses" page,
10721
- * `THIRD_PARTY_MODELS.md`, the Hugging Face model table) is GENERATED from
10722
- * these records by `scripts/gen-model-licenses.ts` (D661).
10638
+ * Every machine licence surface (`THIRD_PARTY_MODELS.md`, the Hugging Face
10639
+ * model table) is GENERATED from these records by
10640
+ * `scripts/gen-model-licenses.ts` (D661). Operator-facing docs live in
10641
+ * `camstack/docs` → `/docs/detection/models`.
10723
10642
  */
10724
10643
  var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { weights: value } : value, object({
10725
10644
  /** SPDX id of the WEIGHTS' terms, a `LicenseRef-*` for non-SPDX terms, or `UNKNOWN`. */
@@ -10752,6 +10671,46 @@ var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { wei
10752
10671
  /** True when the weights or their data forbid commercial use. */
10753
10672
  nonCommercial: boolean().optional()
10754
10673
  }));
10674
+ /**
10675
+ * One step a ROOT detector can supply from its own output (D730) — see
10676
+ * `ModelCatalogEntry.suppliesSteps`.
10677
+ *
10678
+ * - `label`: the root's raw class IS the step's answer. `labelToEffect` maps
10679
+ * the root's label to the step's vocabulary; `uncovered` is the vocabulary
10680
+ * the root cannot produce (shown as unavailable, never a blocker).
10681
+ * - `crop`: the root draws the box the step would have found (`license_plate`
10682
+ * for plate-detection, `face` for face-detection). The box becomes a detail
10683
+ * child of the `parentMacro` detection that contains it — never a track.
10684
+ * - `mask`: the root's decode emits an instance mask with every detection (a
10685
+ * YOLO26-seg root, D737) — the `segmentation` step's result, carried on the
10686
+ * detection in the shape that step produces. Derived from the model's
10687
+ * postprocessor on read, never stored by an import.
10688
+ */
10689
+ var RootStepSupplySchema = discriminatedUnion("kind", [
10690
+ object({
10691
+ kind: literal("label"),
10692
+ stepId: _enum(LABEL_SUPPLY_STEP_IDS),
10693
+ labelToEffect: record(string(), string()),
10694
+ uncovered: array(string()).readonly()
10695
+ }),
10696
+ object({
10697
+ kind: literal("crop"),
10698
+ stepId: _enum(CROP_SUPPLY_STEP_IDS),
10699
+ rootLabels: array(string()).readonly(),
10700
+ parentMacro: _enum(["vehicle", "person"]),
10701
+ childClass: _enum(["plate", "face"]),
10702
+ /**
10703
+ * The root's smaller input side, stamped on read by `rootSuppliesOf` from
10704
+ * the model entry — what a step's `minRootInputPx` gate judges. Never
10705
+ * stored by an import.
10706
+ */
10707
+ rootInputPx: number().int().positive().optional()
10708
+ }),
10709
+ object({
10710
+ kind: literal("mask"),
10711
+ stepId: _enum(MASK_SUPPLY_STEP_IDS)
10712
+ })
10713
+ ]);
10755
10714
  var ModelCatalogEntrySchema = object({
10756
10715
  id: string(),
10757
10716
  name: string(),
@@ -10817,6 +10776,35 @@ var ModelCatalogEntrySchema = object({
10817
10776
  */
10818
10777
  defaultConfidence: number().min(0).max(1).optional(),
10819
10778
  /**
10779
+ * Per-MODEL default of the per-class confidence floors (`minConfidence<Macro>`
10780
+ * on a detector step), keyed by macro class: `{ person: 0.45 }`. A class
10781
+ * absent here runs at the step slider's global default. The same row shape
10782
+ * the floor measurement produces (`model-floors.json`: modelId → floors), so
10783
+ * a measured table is copied in as-is. An operator override is bound to the
10784
+ * model it was made for and does not survive a model change (D738). A custom
10785
+ * / imported model may declare it; without it, the global defaults apply.
10786
+ */
10787
+ defaultClassFloors: record(string(), number().min(0).max(1)).optional(),
10788
+ /**
10789
+ * The inference precision this model's OpenVINO IR needs on an Intel GPU.
10790
+ * Absent ⇒ the device default (f16 on a GPU). Set to `'f32'` for an FP32 IR
10791
+ * that produces invalid output at f16 — measured 2026-10-07 for YOLO26
10792
+ * base IRs (`yolo26s`: 0 true / 146 false positives; `yolo26m*`: NaN
10793
+ * scores) on the Core Ultra iGPU and the N100. Threaded to the pool as
10794
+ * `PoolModelConfig.gpuInferencePrecision`; the pool sets
10795
+ * INFERENCE_PRECISION_HINT on a GPU only. Costs ~60% latency on the GPU.
10796
+ */
10797
+ gpuInferencePrecision: _enum(["f32", "f16"]).optional(),
10798
+ /**
10799
+ * ROOT detectors only: per supplied step (`animal-classifier`, …), the
10800
+ * minimum DETECTION score from which this root's own fine label (species,
10801
+ * vehicle type — D736 root supply) is taken (D741). Below it the detection
10802
+ * keeps its macro class without the fine label. `1` = never take it from
10803
+ * this root. Absent ⇒ no floor beyond the macro floor. The supplied step's
10804
+ * `minConfidence` slider, bound to the ROOT model, overrides it.
10805
+ */
10806
+ suppliedLabelFloors: record(string(), number().min(0).max(1)).optional(),
10807
+ /**
10820
10808
  * When true, the executor produces a landmark-aligned crop (similarity warp
10821
10809
  * onto the canonical template) before this step runs, instead of a plain
10822
10810
  * axis-aligned bbox crop. Required for face-recognition embedders (ArcFace):
@@ -10878,6 +10866,16 @@ var ModelCatalogEntrySchema = object({
10878
10866
  */
10879
10867
  classMap: DetectionCatalogClassMapSchema.optional(),
10880
10868
  /**
10869
+ * The pipeline steps this ROOT detector can supply from its own output
10870
+ * (D730): its labels name a step's effect (`deer` for `animal-classifier`)
10871
+ * or draw a step's box (`license_plate` for `plate-detection`). Computed at
10872
+ * import from THIS model's labelmap by `deriveRootSupplies`, never written
10873
+ * by hand and never assumed per family; a row without it is derived on read
10874
+ * (`rootSuppliesOf`). Whether a camera uses it is the step's own
10875
+ * `useRootModel` flag (`resolveRootSupply`).
10876
+ */
10877
+ suppliesSteps: array(RootStepSupplySchema).readonly().optional(),
10878
+ /**
10881
10879
  * The model's CLIP feature-space contract (text encoder, dimension, vector
10882
10880
  * index, token window, search floor) — see `clip-model.ts`. Present ONLY on a
10883
10881
  * CLIP image encoder; its absence is what "not a CLIP model" means to the
@@ -12547,13 +12545,6 @@ var BrokerRtspClientSchema = object({
12547
12545
  lastRtpAt: number(),
12548
12546
  bytesSent: number()
12549
12547
  });
12550
- var BrokerDecodedClientSchema = object({
12551
- tag: string(),
12552
- subscribedAt: number(),
12553
- maxFps: number(),
12554
- framesDelivered: number(),
12555
- framesDropped: number()
12556
- });
12557
12548
  var BrokerAudioClientSchema = object({
12558
12549
  tag: string(),
12559
12550
  subscribedAt: number(),
@@ -12645,7 +12636,6 @@ var BrokerEncodedClientSchema = object({
12645
12636
  });
12646
12637
  var BrokerClientsSchema = object({
12647
12638
  rtsp: array(BrokerRtspClientSchema).readonly(),
12648
- decoded: array(BrokerDecodedClientSchema).readonly(),
12649
12639
  audio: array(BrokerAudioClientSchema).readonly(),
12650
12640
  encoded: array(BrokerEncodedClientSchema).readonly(),
12651
12641
  pipeClients: number(),
@@ -13014,11 +13004,7 @@ method(object({
13014
13004
  auth: "admin"
13015
13005
  }), method(object({ brokerId: string() }), BrokerClientsSchema), method(object({
13016
13006
  brokerId: string(),
13017
- channel: _enum([
13018
- "rtsp",
13019
- "decoded",
13020
- "audio"
13021
- ]),
13007
+ channel: _enum(["rtsp", "audio"]),
13022
13008
  handle: string()
13023
13009
  }), object({ killed: boolean() }), {
13024
13010
  kind: "mutation",
@@ -13053,10 +13039,7 @@ method(object({
13053
13039
  }), method(SubscribeAudioChunksInputSchema, SubscribeAudioChunksResultSchema, { kind: "mutation" }), method(object({
13054
13040
  subscriptionId: string(),
13055
13041
  maxCount: number().int().positive().default(8)
13056
- }), array(DecodedAudioChunkSchema).readonly()), method(object({ subscriptionId: string() }), object({ released: boolean() }), { kind: "mutation" }), method(SubscribeFramesInputSchema, SubscribeFramesResultSchema, { kind: "mutation" }), method(object({
13057
- subscriptionId: string(),
13058
- maxCount: number().int().positive().default(4)
13059
- }), array(FrameHandleSchema).readonly()), method(object({ subscriptionId: string() }), object({ released: boolean() }), { kind: "mutation" }), method(object({
13042
+ }), array(DecodedAudioChunkSchema).readonly()), method(object({ subscriptionId: string() }), object({ released: boolean() }), { kind: "mutation" }), method(object({
13060
13043
  brokerId: string(),
13061
13044
  seconds: number().min(0).max(30)
13062
13045
  }), _void(), {
@@ -14315,54 +14298,12 @@ id: union([string(), number()]) }), {
14315
14298
  kind: "mutation",
14316
14299
  auth: "admin"
14317
14300
  });
14318
- /**
14319
- * shm ring usage stats for a `frameSink: 'shm'` decoder session —
14320
- * exposed via `decoder.getShmStats` so downstream consumers can
14321
- * observe ring pressure (slot count, byte budget, hit/miss ratio).
14322
- */
14323
- var ShmRingStatsSchema = object({
14324
- sessionId: string(),
14325
- slotCount: number().int(),
14326
- slotByteLength: number().int(),
14327
- segmentBytes: number().int(),
14328
- budgetMb: number().int(),
14329
- framesWritten: number().int(),
14330
- getFrameHits: number().int(),
14331
- getFrameMisses: number().int()
14332
- });
14333
- method(object({ codec: string() }), boolean()), method(_void(), object({
14301
+ method(_void(), object({
14334
14302
  id: string(),
14335
14303
  name: string(),
14336
- isPullMode: boolean().optional(),
14337
- priority: number().optional(),
14338
14304
  hwaccel: string().optional(),
14339
14305
  probedBestHwaccel: string().optional()
14340
- })), method(DecoderSessionConfigSchema, object({
14341
- sessionId: string(),
14342
- nodeId: string()
14343
- })), method(object({ sessionId: string() }), _void()), method(object({
14344
- sessionId: string(),
14345
- packet: EncodedPacketSchema
14346
- }), _void()), method(object({
14347
- sessionId: string(),
14348
- url: string()
14349
- }), _void()), method(object({
14350
- sessionId: string(),
14351
- maxCount: number().default(1),
14352
- waitMs: number().optional()
14353
- }), array(DecodedFrameSchema)), method(object({
14354
- sessionId: string(),
14355
- maxCount: number().default(1),
14356
- waitMs: number().optional()
14357
- }), array(FrameHandleSchema)), method(object({ handle: FrameHandleSchema }), DecodedFrameSchema.nullable()), method(object({ sessionId: string() }), ShmRingStatsSchema.nullable()), method(object({
14358
- sessionId: string(),
14359
- config: DecoderSessionConfigSchema.partial()
14360
- }), _void()), method(object({ sessionId: string() }), DecoderStatsSchema), method(_void(), array(object({
14361
- sessionId: string(),
14362
- codec: string(),
14363
- outputFormat: string(),
14364
- createdAtMs: number()
14365
- })).readonly()), method(_void(), object({ backend: string() }), {
14306
+ })), method(_void(), object({ backend: string() }), {
14366
14307
  kind: "mutation",
14367
14308
  auth: "admin"
14368
14309
  });
@@ -14418,7 +14359,7 @@ DeviceType.Camera;
14418
14359
  * This matters here more than anywhere else in the repo, because every provider
14419
14360
  * that knows a device's host knows its PASSWORD too: `{ host, port, username,
14420
14361
  * password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
14421
- * and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
14362
+ * and `http://admin:hunter2@192.168.60.139/` is a URL a browser accepts. The
14422
14363
  * camera's own page will ask for its own login. That is correct, and pre-
14423
14364
  * filling it is the operator's business, not ours.
14424
14365
  *
@@ -16411,6 +16352,12 @@ method(_void(), array(string()).readonly(), { auth: "admin" }), method(object({
16411
16352
  kind: "mutation",
16412
16353
  auth: "admin"
16413
16354
  });
16355
+ var HUB_ADDRESS_ROLES = [
16356
+ "appConnections",
16357
+ "notificationTaps",
16358
+ "internal",
16359
+ "publicEndpoint"
16360
+ ];
16414
16361
  /**
16415
16362
  * Transport bounds for AI capability methods.
16416
16363
  *
@@ -17607,7 +17554,7 @@ method(object({
17607
17554
  timeoutMs: 6e5
17608
17555
  });
17609
17556
  method(object({
17610
- nodeId: string(),
17557
+ targetNodeId: string(),
17611
17558
  modelId: string(),
17612
17559
  format: _enum(MODEL_FORMATS),
17613
17560
  entry: ModelCatalogEntrySchema
@@ -19013,6 +18960,8 @@ var NcSystemEventKindSchema = _enum([
19013
18960
  "stream-offline",
19014
18961
  "node-online",
19015
18962
  "node-offline",
18963
+ "node-restarting",
18964
+ "node-updating",
19016
18965
  "node-inference-unavailable",
19017
18966
  "detection-blind",
19018
18967
  "addon-crash-loop",
@@ -20111,8 +20060,9 @@ var NcRuleSchema = NcRuleInputSchema.extend({
20111
20060
  disabledTargetIds: array(string()).default([])
20112
20061
  });
20113
20062
  /**
20114
- * The state-summary SECTIONS (D647 / D698): the D637 kind groups that report a
20115
- * still-true state. `backups-exports` and `alarm` are not sections — a completed
20063
+ * The state-summary SECTIONS (D647 / D698 / D708): the D637 kind groups that
20064
+ * report a still-true state. `addons` is the crash-looped addons only and
20065
+ * `addon-updates` the addons that are behind (D708 split them). `backups-exports` and `alarm` are not sections — a completed
20116
20066
  * job is not an open state, and the alarm stays instant.
20117
20067
  */
20118
20068
  var NcStateSummarySectionIdSchema = _enum([
@@ -20124,6 +20074,7 @@ var NcStateSummarySectionIdSchema = _enum([
20124
20074
  "detection-blind",
20125
20075
  "nodes",
20126
20076
  "addons",
20077
+ "addon-updates",
20127
20078
  "updates"
20128
20079
  ]);
20129
20080
  /** One section of a previewed state summary. `unavailable` = its state could not be read. */
@@ -20604,7 +20555,25 @@ var NcAlarmModeDelaysListSchema = array(object({
20604
20555
  * When this mode may be armed. Absent / null = always allowed (same as a
20605
20556
  * rule with no `schedule`). Evaluated with {@link isScheduleActive}.
20606
20557
  */
20607
- schedule: NcScheduleSchema.optional()
20558
+ schedule: NcScheduleSchema.optional(),
20559
+ /**
20560
+ * D706: while this mode's ENTRY DELAY runs, do the alarm rules' own pushes go out (as an
20561
+ * intrusion naming the locations)? Absent = false — the entry-delay notification is the
20562
+ * only one, and the matches ride the triggered notification's mosaic (D705).
20563
+ */
20564
+ notifyDuringEntryDelay: boolean().optional(),
20565
+ /**
20566
+ * D706: notify "watched again" when a sensor this arm bypassed closes and opens again.
20567
+ * Absent = false (logged, not sent). Even when true it is not sent when that same sensor
20568
+ * is the one that starts the entry delay — the entry-delay notification already names it.
20569
+ */
20570
+ notifySensorRewatched: boolean().optional(),
20571
+ /**
20572
+ * D735: notify "ignored" when a sensor this arm bypassed really MOVED while armed (its own
20573
+ * change time is after the arm) and set nothing off. Absent = false (logged, not sent). A
20574
+ * re-sync, a recovery from `unavailable` or a duplicate is never announced, switch or not.
20575
+ */
20576
+ notifySensorIgnored: boolean().optional()
20608
20577
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
20609
20578
  var NcAlarmModeDelaysEditListSchema = array(object({
20610
20579
  mode: AlarmArmModeSchema,
@@ -20613,7 +20582,13 @@ var NcAlarmModeDelaysEditListSchema = array(object({
20613
20582
  triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
20614
20583
  postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
20615
20584
  /** Set a schedule, or `null` to clear (mode always allowed again). */
20616
- schedule: NcScheduleSchema.nullable().optional()
20585
+ schedule: NcScheduleSchema.nullable().optional(),
20586
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20587
+ notifyDuringEntryDelay: boolean().nullable().optional(),
20588
+ /** D706: set the switch, or `null` to clear it (back to the default, false). */
20589
+ notifySensorRewatched: boolean().nullable().optional(),
20590
+ /** D735: set the switch, or `null` to clear it (back to the default, false). */
20591
+ notifySensorIgnored: boolean().nullable().optional()
20617
20592
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
20618
20593
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
20619
20594
  var NcAlarmNonBlockingEditSchema = object({
@@ -21574,45 +21549,25 @@ Object.freeze(Object.fromEntries([{
21574
21549
  label: "Face recognition model",
21575
21550
  defaultModelId: "auraface-r100",
21576
21551
  indexName: "the enrolled face gallery",
21577
- options: [
21578
- {
21579
- id: "auraface-r100",
21580
- label: "AuraFace R100"
21581
- },
21582
- {
21583
- id: "arcface-r100",
21584
- label: "ArcFace (ResNet34)"
21585
- },
21586
- {
21587
- id: "inception-resnet-v1",
21588
- label: "Inception ResNet V1"
21589
- }
21590
- ]
21552
+ options: [{
21553
+ id: "auraface-r100",
21554
+ label: "AuraFace R100"
21555
+ }]
21591
21556
  }, {
21592
21557
  stepId: "clip-embedding",
21593
21558
  label: "Semantic search model",
21594
- defaultModelId: "mobileclip-s1",
21559
+ defaultModelId: "siglip2-b16-224",
21595
21560
  indexName: "the object semantic-search index",
21596
- options: [
21597
- {
21598
- id: "mobileclip-s1",
21599
- label: "MobileCLIP S1"
21600
- },
21601
- {
21602
- id: "mobileclip-s2",
21603
- label: "MobileCLIP S2"
21604
- },
21605
- {
21606
- id: "siglip2-b16-224",
21607
- label: "SigLIP2 B/16 (Apache-2.0)"
21608
- }
21609
- ]
21561
+ options: [{
21562
+ id: "siglip2-b16-224",
21563
+ label: "SigLIP2 B/16 (Apache-2.0)"
21564
+ }]
21610
21565
  }].map((s) => [s.stepId, s.defaultModelId])));
21611
21566
  var CLUSTER_STEP_SETTING_FIELDS = [{
21612
21567
  stepId: "face-embedding",
21613
21568
  key: "minLandmarkFaceSize",
21614
- label: "Min face size for recognition (detection px)",
21615
- description: "Refuse to embed a face smaller than this IN THE DETECTION FRAME. Applies to every node — the enrolled gallery is one index, and two admission floors would fill it from two policies. 0 disables the gate.",
21569
+ label: "Min face size to embed (detection-frame px)",
21570
+ description: "Faces smaller than this in the small frame the detector sees are not embedded, so they can never be recognised. Below it the face cannot be aligned reliably and a bad embedding matches everyone. Same value on every node. 0 = no limit.",
21616
21571
  type: "slider",
21617
21572
  min: 0,
21618
21573
  max: 64,
@@ -23532,6 +23487,34 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
23532
23487
  timestamp: number()
23533
23488
  });
23534
23489
  /**
23490
+ * A root model's boxes standing in for one crop-kind step's own inference
23491
+ * (D730) — see `runPipeline.suppliedRoot`.
23492
+ */
23493
+ var SuppliedRootOutputSchema = object({
23494
+ stepId: string(),
23495
+ /** The root model that drew the boxes — stamped on the result. */
23496
+ modelId: string(),
23497
+ detections: array(object({
23498
+ /** `[x1, y1, x2, y2]` in the pixels of the call's image. */
23499
+ bbox: tuple([
23500
+ number(),
23501
+ number(),
23502
+ number(),
23503
+ number()
23504
+ ]),
23505
+ score: number(),
23506
+ /**
23507
+ * Five facial landmarks in the same pixels — a face the step's own
23508
+ * detector already re-found inside a root face box (D730), so its
23509
+ * embedder child aligns it exactly as it aligns any detected face.
23510
+ */
23511
+ landmarks: array(object({
23512
+ x: number(),
23513
+ y: number()
23514
+ })).optional()
23515
+ })).min(1)
23516
+ });
23517
+ /**
23535
23518
  * Reference to the frame's retained NATIVE surface + the parent crop's placement
23536
23519
  * within the frame, so the executor can re-cut a leaf child ROI at native
23537
23520
  * resolution on the detail plane. See the `runPipeline` `nativeCropRef` field.
@@ -23579,7 +23562,7 @@ var FrameRefSchema = object({
23579
23562
  timestamp: number(),
23580
23563
  capturedAt: number().optional()
23581
23564
  });
23582
- var ModelFormatSchema$1 = _enum([
23565
+ var ModelFormatSchema$2 = _enum([
23583
23566
  "onnx",
23584
23567
  "coreml",
23585
23568
  "openvino",
@@ -23597,7 +23580,7 @@ var PipelineSlotSchema = _enum([
23597
23580
  var PipelineEngineChoiceSchema = object({
23598
23581
  runtime: literal("python"),
23599
23582
  backend: string(),
23600
- format: ModelFormatSchema$1,
23583
+ format: ModelFormatSchema$2,
23601
23584
  device: string().optional()
23602
23585
  });
23603
23586
  /**
@@ -23636,32 +23619,15 @@ var PipelineDefaultStepSchema = lazy(() => object({
23636
23619
  group: string().optional(),
23637
23620
  settings: record(string(), unknown()).optional()
23638
23621
  }));
23639
- var PipelineTemplateStepSchema = lazy(() => object({
23640
- addonId: string(),
23641
- enabled: boolean(),
23642
- modelId: string(),
23643
- children: array(PipelineTemplateStepSchema).readonly(),
23644
- settings: record(string(), unknown()).optional()
23645
- }));
23646
- var PipelineTemplateSchema$1 = object({
23647
- id: string(),
23648
- name: string(),
23649
- createdAt: string(),
23650
- updatedAt: string(),
23651
- engine: PipelineEngineChoiceSchema,
23652
- steps: array(PipelineTemplateStepSchema).readonly()
23653
- });
23654
23622
  var PipelineModelOptionSchema = object({
23655
23623
  id: string(),
23656
23624
  name: string(),
23657
- formats: record(string(), object({
23658
- downloaded: boolean(),
23659
- sizeMB: number()
23660
- })),
23625
+ formats: record(string(), PipelineModelFormatStatusSchema),
23661
23626
  group: ModelVariantGroupSchema.optional(),
23662
23627
  legacy: boolean().optional(),
23663
23628
  provider: ModelProviderIdSchema.optional(),
23664
- defaultConfidence: number().optional()
23629
+ defaultConfidence: number().optional(),
23630
+ suppliesSteps: array(RootStepSupplySchema).readonly().optional()
23665
23631
  });
23666
23632
  var ConfigFieldBridge = custom();
23667
23633
  var PipelineAddonSchemaSchema = object({
@@ -23823,6 +23789,22 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
23823
23789
  }), {
23824
23790
  kind: "mutation",
23825
23791
  auth: "admin"
23792
+ }), method(object({
23793
+ nodeId: string(),
23794
+ deviceIds: array(number()).readonly().optional(),
23795
+ dryRun: boolean()
23796
+ }), object({
23797
+ entries: array(object({
23798
+ deviceId: number(),
23799
+ keys: array(string()).readonly()
23800
+ })).readonly(),
23801
+ refused: array(object({
23802
+ deviceId: number(),
23803
+ reason: string()
23804
+ })).readonly()
23805
+ }), {
23806
+ kind: "mutation",
23807
+ auth: "admin"
23826
23808
  }), method(object({ nodeId: string() }), object({ unhealthy: array(object({
23827
23809
  /** `<backend>:<device>`, e.g. `openvino:gpu`. */
23828
23810
  deviceKey: string(),
@@ -23848,22 +23830,14 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
23848
23830
  }), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({
23849
23831
  steps: array(PipelineStepInputSchema),
23850
23832
  deviceKey: string().optional()
23851
- }), PipelineValidationResultSchema), method(_void(), array(PipelineTemplateSchema$1).readonly()), method(object({
23852
- name: string(),
23853
- steps: array(PipelineTemplateStepSchema).readonly(),
23854
- engine: PipelineEngineChoiceSchema
23855
- }), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({
23856
- id: string(),
23857
- name: string().optional(),
23858
- steps: array(PipelineTemplateStepSchema).readonly().optional()
23859
- }), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({ id: string() }), _void(), { kind: "mutation" }), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
23833
+ }), PipelineValidationResultSchema), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
23860
23834
  addonId: string(),
23861
23835
  modelId: string(),
23862
- format: ModelFormatSchema$1
23836
+ format: ModelFormatSchema$2
23863
23837
  }), DownloadModelResultSchema, { kind: "mutation" }), method(object({
23864
23838
  addonId: string(),
23865
23839
  modelId: string(),
23866
- format: ModelFormatSchema$1
23840
+ format: ModelFormatSchema$2
23867
23841
  }), object({ success: literal(true) }), { kind: "mutation" }), method(object({
23868
23842
  steps: array(PipelineStepInputSchema).min(1),
23869
23843
  frame: FrameInputSchema.optional(),
@@ -23929,7 +23903,16 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
23929
23903
  * `device-not-servable`), and nothing reaches the camera's live
23930
23904
  * trace stream. Absent ⇒ unchanged behaviour.
23931
23905
  */
23932
- replay: literal(true).optional()
23906
+ replay: literal(true).optional(),
23907
+ /**
23908
+ * Root-supplied detections for the tree's ROOT step (D730). Set by
23909
+ * `runDetailSubtree` when the camera's root model supplies a crop-kind
23910
+ * step (a Frigate+ `license_plate` for `plate-detection`): the step is
23911
+ * NOT inferred, these boxes are its output, and its children (the plate
23912
+ * reader) run on them through their own crop policy. Boxes are in the
23913
+ * PIXELS of the image this call carries. Absent ⇒ the root step runs.
23914
+ */
23915
+ suppliedRoot: SuppliedRootOutputSchema.optional()
23933
23916
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
23934
23917
  steps: array(PipelineStepInputSchema).min(1),
23935
23918
  frames: array(FrameInputSchema).min(1).max(255),
@@ -24011,6 +23994,375 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
24011
23994
  filename: string().optional(),
24012
23995
  settings: record(string(), unknown()).optional()
24013
23996
  }), AudioTestResultSchema, { kind: "mutation" }), method(_void(), ConfigUISchemaNullableBridge);
23997
+ /**
23998
+ * The wire shapes of the Auto tune plan and apply (D745), used by the
23999
+ * `pipeline-orchestrator` cap. The recommender's own types
24000
+ * (`recommend.ts`) are the TS face of the same data; these
24001
+ * schemas are what crosses the cap boundary.
24002
+ */
24003
+ var ModelFormatSchema$1 = _enum(MODEL_FORMATS);
24004
+ /** The operator's range for it. */
24005
+ var MIN_SESSIONS_PER_DEVICE_RANGE = {
24006
+ min: 1,
24007
+ max: 8
24008
+ };
24009
+ var HardwareClassIdSchema = _enum([
24010
+ "intel-core-ultra",
24011
+ "intel-n-series",
24012
+ "apple-m-base",
24013
+ "apple-m-pro",
24014
+ "unknown"
24015
+ ]);
24016
+ var AcceleratorKindSchema = _enum([
24017
+ "intel-npu",
24018
+ "intel-igpu",
24019
+ "x86-cpu",
24020
+ "arm-cpu",
24021
+ "apple-ane",
24022
+ "coral"
24023
+ ]);
24024
+ var RecommendationReasonSchema = discriminatedUnion("kind", [
24025
+ object({
24026
+ kind: literal("capacity"),
24027
+ sessions: number(),
24028
+ minSessions: number()
24029
+ }),
24030
+ object({
24031
+ kind: literal("tie-faster"),
24032
+ over: string(),
24033
+ recallDelta: number()
24034
+ }),
24035
+ object({
24036
+ kind: literal("stepped-down"),
24037
+ from: string(),
24038
+ to: string(),
24039
+ limitedBy: string()
24040
+ }),
24041
+ object({
24042
+ kind: literal("no-fit-lightest"),
24043
+ sessions: number(),
24044
+ minSessions: number()
24045
+ }),
24046
+ object({
24047
+ kind: literal("derived-latency"),
24048
+ modelId: string()
24049
+ }),
24050
+ object({ kind: literal("cpu-device") }),
24051
+ object({ kind: literal("coral-untouched") }),
24052
+ object({ kind: literal("device-disabled") }),
24053
+ object({ kind: literal("device-unavailable") }),
24054
+ object({ kind: literal("node-offline") }),
24055
+ object({ kind: literal("no-hardware-facts") }),
24056
+ object({
24057
+ kind: literal("no-measured-data"),
24058
+ hardwareClass: HardwareClassIdSchema
24059
+ }),
24060
+ object({
24061
+ kind: literal("no-family-build"),
24062
+ format: ModelFormatSchema$1
24063
+ })
24064
+ ]);
24065
+ var DeviceModelChoiceSchema = object({
24066
+ modelId: string(),
24067
+ p50Ms: number(),
24068
+ fps: number(),
24069
+ measured: boolean(),
24070
+ /** Parallel sessions at the camera rate with the headroom kept free: ⌊fps × (1 − headroom) / camera fps⌋. */
24071
+ capacitySessions: number(),
24072
+ personRecall: number()
24073
+ });
24074
+ var DeviceRecommendationSchema = object({
24075
+ deviceKey: string(),
24076
+ accelerator: AcceleratorKindSchema.nullable(),
24077
+ enabled: boolean(),
24078
+ available: boolean(),
24079
+ chosen: DeviceModelChoiceSchema.nullable(),
24080
+ reasons: array(RecommendationReasonSchema).readonly()
24081
+ });
24082
+ var NodeRecommendationSchema = object({
24083
+ nodeId: string(),
24084
+ reachable: boolean(),
24085
+ hardwareClass: HardwareClassIdSchema.nullable(),
24086
+ cpuModel: string().nullable(),
24087
+ skipped: boolean(),
24088
+ acceleratorModelId: string().nullable(),
24089
+ devices: array(DeviceRecommendationSchema).readonly(),
24090
+ reasons: array(RecommendationReasonSchema).readonly()
24091
+ });
24092
+ var ModelPinChangeSchema = object({
24093
+ stepId: string(),
24094
+ before: string().nullable(),
24095
+ after: string().nullable()
24096
+ });
24097
+ var NodeDeviceChangeSchema = object({
24098
+ nodeId: string(),
24099
+ deviceKey: string(),
24100
+ madeExplicit: boolean(),
24101
+ modelPins: array(ModelPinChangeSchema).readonly(),
24102
+ thresholds: array(object({
24103
+ stepId: string(),
24104
+ keys: array(string()).readonly()
24105
+ })).readonly()
24106
+ });
24107
+ var CameraOverrideClearSchema = object({
24108
+ deviceId: number(),
24109
+ source: _enum(["step-override", "wholesale"]),
24110
+ nodeId: string(),
24111
+ deviceKey: string().nullable(),
24112
+ stepId: string(),
24113
+ modelIdBefore: string().nullable(),
24114
+ keys: array(string()).readonly()
24115
+ });
24116
+ var DetectorStoreClearSchema = object({
24117
+ deviceId: number(),
24118
+ keys: array(string()).readonly()
24119
+ });
24120
+ var AutoTuneWarningSchema = discriminatedUnion("kind", [
24121
+ object({
24122
+ kind: literal("detector-store-cluster-wide"),
24123
+ skippedNodes: array(string()).readonly()
24124
+ }),
24125
+ object({
24126
+ kind: literal("detector-store-unreadable"),
24127
+ error: string()
24128
+ }),
24129
+ object({
24130
+ kind: literal("coral-enabled"),
24131
+ nodeId: string(),
24132
+ deviceKey: string()
24133
+ })
24134
+ ]);
24135
+ var AutoTuneOptionsSchema = object({
24136
+ /** Share of each accelerator's throughput kept free (0.3–0.5). */
24137
+ headroom: number().min(.3).max(.5).default(.4),
24138
+ /**
24139
+ * The least number of parallel sessions every device must sustain at the
24140
+ * camera rate with the headroom kept free (D755). The most accurate model
24141
+ * that reaches it wins.
24142
+ */
24143
+ minSessionsPerDevice: number().int().min(MIN_SESSIONS_PER_DEVICE_RANGE.min).max(MIN_SESSIONS_PER_DEVICE_RANGE.max).default(2)
24144
+ });
24145
+ var AutoTunePlanSchema = object({
24146
+ /** Hash of everything the apply will write — the apply refuses a different one. */
24147
+ planHash: string(),
24148
+ family: literal("yolov9"),
24149
+ headroom: number(),
24150
+ minSessionsPerDevice: number(),
24151
+ /** The detection rate a session is counted at (the fastest camera running the pipeline root). */
24152
+ cameraFps: number(),
24153
+ generatedAt: number(),
24154
+ nodes: array(NodeRecommendationSchema).readonly(),
24155
+ nodeChanges: array(NodeDeviceChangeSchema).readonly(),
24156
+ cameraClears: array(CameraOverrideClearSchema).readonly(),
24157
+ detectorStoreClears: array(DetectorStoreClearSchema).readonly(),
24158
+ warnings: array(AutoTuneWarningSchema).readonly()
24159
+ });
24160
+ var AutoTuneApplyInputSchema = object({
24161
+ planHash: string(),
24162
+ headroom: number().min(.3).max(.5).default(.4),
24163
+ minSessionsPerDevice: number().int().min(MIN_SESSIONS_PER_DEVICE_RANGE.min).max(MIN_SESSIONS_PER_DEVICE_RANGE.max).default(2)
24164
+ });
24165
+ var AutoTunePhaseResultSchema = object({
24166
+ phase: _enum([
24167
+ "download",
24168
+ "camera-overrides",
24169
+ "detector-thresholds",
24170
+ "node-models",
24171
+ "redispatch"
24172
+ ]),
24173
+ ok: boolean(),
24174
+ detail: string()
24175
+ });
24176
+ var AutoTuneApplyResultSchema = discriminatedUnion("kind", [
24177
+ object({
24178
+ kind: literal("applied"),
24179
+ planHash: string(),
24180
+ phases: array(AutoTunePhaseResultSchema).readonly()
24181
+ }),
24182
+ object({
24183
+ kind: literal("aborted"),
24184
+ phases: array(AutoTunePhaseResultSchema).readonly()
24185
+ }),
24186
+ object({
24187
+ kind: literal("stale"),
24188
+ plan: AutoTunePlanSchema
24189
+ }),
24190
+ object({
24191
+ kind: literal("refused"),
24192
+ reason: _enum(["apply-in-progress"])
24193
+ })
24194
+ ]);
24195
+ /**
24196
+ * Wire shapes of the Load balancing surface (D748): the session placement
24197
+ * policy, the atomic share write, the observed placement statistics, the
24198
+ * hardware share suggestion and the stale device pins.
24199
+ */
24200
+ /**
24201
+ * How a new detection session picks its node and device.
24202
+ * - `least-loaded` — the historical rule: lowest `attached / weight`, a
24203
+ * constant node order at a tie (D37). An idle node always ties at 0, so a
24204
+ * weight only bites once a node already holds a session.
24205
+ * - `share` — the share of PARALLEL sessions is held to the weights, and a
24206
+ * full or drowning node yields to a free one (D748).
24207
+ */
24208
+ var SessionPlacementPolicySchema = _enum(["least-loaded", "share"]);
24209
+ var LoadBalancingSharesInputSchema = object({
24210
+ /** nodeId → share (> 0). A node left out keeps its weight. */
24211
+ nodes: record(string(), number().positive()).default({}),
24212
+ /** nodeId → deviceKey → share (> 0). A device left out keeps its weight. */
24213
+ devices: record(string(), record(string(), number().positive())).default({})
24214
+ });
24215
+ var PlacementStatsInputSchema = object({
24216
+ /** Window the observed shares are averaged over (default 1 h, max 24 h). */
24217
+ windowMs: number().int().min(6e4).max(1440 * 60 * 1e3).default(3600 * 1e3) });
24218
+ var PlacementDeviceStatsSchema = object({
24219
+ deviceKey: string(),
24220
+ /** Sessions running on this device now. */
24221
+ sessionsNow: number(),
24222
+ /** Sessions started on this device inside the window. */
24223
+ sessionsStarted: number(),
24224
+ /** Time-weighted share of the node's parallel sessions over the window (0–1); null = no session ran. */
24225
+ observedShare: number().nullable()
24226
+ });
24227
+ var PlacementNodeStatsSchema = object({
24228
+ nodeId: string(),
24229
+ sessionsNow: number(),
24230
+ sessionsStarted: number(),
24231
+ /** Time-weighted share of the cluster's parallel sessions over the window (0–1); null = none ran. */
24232
+ observedShare: number().nullable(),
24233
+ /** Most sessions this node ran at once inside the window. */
24234
+ peakSessions: number(),
24235
+ /** Sessions a share election handed elsewhere because this node was full or drowning. */
24236
+ yieldsAway: number(),
24237
+ devices: array(PlacementDeviceStatsSchema).readonly()
24238
+ });
24239
+ /** A camera's device pin that the session path cannot honour. */
24240
+ var StaleDevicePinSchema = object({
24241
+ deviceId: number(),
24242
+ deviceKey: string(),
24243
+ /** `disabled` — the key exists on some node but is not enabled anywhere; `absent` — no node has it. */
24244
+ reason: _enum(["disabled", "absent"])
24245
+ });
24246
+ var PlacementStatsSchema = object({
24247
+ policy: SessionPlacementPolicySchema,
24248
+ windowMs: number(),
24249
+ /** How much of the window was actually observed (the hub keeps it in memory). */
24250
+ observedForMs: number(),
24251
+ sessionsNow: number(),
24252
+ /** Most parallel sessions across the cluster inside the window. */
24253
+ clusterPeakSessions: number(),
24254
+ nodes: array(PlacementNodeStatsSchema).readonly(),
24255
+ stalePins: array(StaleDevicePinSchema).readonly()
24256
+ });
24257
+ /**
24258
+ * Where an automatic share's capacity comes from (D755).
24259
+ * - `hardware` — the static capacity of each device at its Auto tune model:
24260
+ * the measured latency table for the node's hardware class.
24261
+ * - `benchmark` — the node's own measured capacity (node benchmark results).
24262
+ * A node with no results falls back to `hardware`, and says so.
24263
+ */
24264
+ var CapacitySourceSchema = _enum(["hardware", "benchmark"]);
24265
+ /** Why a node under the `benchmark` source was sized from hardware instead. */
24266
+ var CapacityFallbackSchema = _enum(["no-benchmark-results", "partial-benchmark-results"]);
24267
+ var SuggestSharesInputSchema = object({
24268
+ headroom: number().min(.3).max(.5).default(.4),
24269
+ /** Default `hardware`. */
24270
+ source: CapacitySourceSchema.default("hardware")
24271
+ });
24272
+ var SuggestedDeviceShareSchema = object({
24273
+ deviceKey: string(),
24274
+ /** Share of the node (0–100, rounded). */
24275
+ share: number(),
24276
+ modelId: string().nullable(),
24277
+ /** Inferences per second at that model, from the measured table; null when sized by a benchmark. */
24278
+ fps: number().nullable(),
24279
+ /** False for a table cell derived from another chip; true for a measured cell or a benchmark. */
24280
+ measured: boolean(),
24281
+ /**
24282
+ * Advisory session cap: ⌊fps × (1 − headroom) / camera fps⌋ from the table,
24283
+ * or the benchmark's measured max sessions. Never enforced.
24284
+ */
24285
+ suggestedMaxSessions: number().nullable()
24286
+ });
24287
+ var SuggestedNodeShareSchema = object({
24288
+ nodeId: string(),
24289
+ /** Share of the cluster (0–100, rounded); null = node skipped (offline, unknown hardware). */
24290
+ share: number().nullable(),
24291
+ /** Parallel sessions the node sustains at the suggested models with the headroom kept free. */
24292
+ capacitySessions: number(),
24293
+ devices: array(SuggestedDeviceShareSchema).readonly(),
24294
+ skippedReason: string().nullable(),
24295
+ /** What this node's capacity was read from; null when the node is skipped. */
24296
+ capacitySource: CapacitySourceSchema.nullable(),
24297
+ /** Set when the `benchmark` source was asked for and this node used `hardware`. */
24298
+ capacityFallback: CapacityFallbackSchema.nullable()
24299
+ });
24300
+ var SuggestSharesResultSchema = object({
24301
+ headroom: number(),
24302
+ /** The source asked for; each node says what it actually used. */
24303
+ source: CapacitySourceSchema,
24304
+ /** Camera detection rate the capacity is counted in (the fastest camera's fps). */
24305
+ cameraFps: number(),
24306
+ /** The Auto tune capacity floor the models were picked at. */
24307
+ minSessionsPerDevice: number(),
24308
+ nodes: array(SuggestedNodeShareSchema).readonly()
24309
+ });
24310
+ /**
24311
+ * Where the node and device shares come from (D750, D755).
24312
+ * - `hardware` (default) — computed by the system from each node's static
24313
+ * capacity (its accelerators at their Auto tune models, from the measured
24314
+ * latency table), recomputed whenever a node or device joins, leaves, is
24315
+ * switched on or off, or changes model. No load input.
24316
+ * - `benchmark` — the same, from each node's measured capacity (node
24317
+ * benchmark results); a node without results falls back to `hardware`.
24318
+ * - `manual` — the operator's stored sliders.
24319
+ * Either way a node or device that cannot take sessions gives its share to
24320
+ * the others in proportion; the stored values are never rewritten for that.
24321
+ */
24322
+ var ShareSourceSchema = _enum([
24323
+ "hardware",
24324
+ "benchmark",
24325
+ "manual"
24326
+ ]);
24327
+ var SetShareSourceInputSchema = object({ source: ShareSourceSchema });
24328
+ object({
24329
+ nodes: record(string(), number()),
24330
+ devices: record(string(), record(string(), number()))
24331
+ });
24332
+ var EffectiveDeviceShareSchema = object({
24333
+ deviceKey: string(),
24334
+ /** Can take sessions now (enabled, available, can run the root). */
24335
+ eligible: boolean(),
24336
+ /** The share the source assigns, as a percentage of the node's devices. */
24337
+ configuredPct: number(),
24338
+ /** The share actually used, after an ineligible device's share went to the others. */
24339
+ effectivePct: number()
24340
+ });
24341
+ var EffectiveNodeShareSchema = object({
24342
+ nodeId: string(),
24343
+ eligible: boolean(),
24344
+ configuredPct: number(),
24345
+ effectivePct: number(),
24346
+ /** Automatic sources: what this node's share was computed from; null under `manual` or before the first answer. */
24347
+ capacitySource: CapacitySourceSchema.nullable(),
24348
+ /** Automatic `benchmark`: why this node used `hardware` instead. */
24349
+ capacityFallback: CapacityFallbackSchema.nullable(),
24350
+ devices: array(EffectiveDeviceShareSchema).readonly()
24351
+ });
24352
+ var EffectiveSharesSchema = object({
24353
+ source: ShareSourceSchema,
24354
+ policy: SessionPlacementPolicySchema,
24355
+ /** An automatic source with no computed answer yet: the stored sliders are used meanwhile. */
24356
+ autoPending: boolean(),
24357
+ /** When the automatic shares were last computed (ms epoch); null = never. */
24358
+ computedAt: number().nullable(),
24359
+ /** What made the system recompute them last. */
24360
+ trigger: string().nullable(),
24361
+ nodes: array(EffectiveNodeShareSchema).readonly(),
24362
+ /** The relative weights the election reads (before eligibility). */
24363
+ nodeWeights: record(string(), number()),
24364
+ deviceWeights: record(string(), record(string(), number()))
24365
+ });
24014
24366
  object({
24015
24367
  activeCameras: number(),
24016
24368
  throttledCameras: number(),
@@ -24494,6 +24846,22 @@ var MotionSourceEnum = _enum([
24494
24846
  "device-activity"
24495
24847
  ]);
24496
24848
  /**
24849
+ * What opened an on-motion detection SESSION: the motion source that passed the
24850
+ * camera's `motionSources` gate, and what raised it (the camera itself, or a
24851
+ * sensor the operator attached — D672). `sensorName` is the attached sensor's
24852
+ * device name as the orchestrator's camera-sensors resolution last read it;
24853
+ * absent when unknown or when the camera itself triggered.
24854
+ *
24855
+ * Carried on the session attach ONLY so the runner's `DetectionPhaseTransition`
24856
+ * can say what started the session (D672 rule 11, amended 2026-10-06). The
24857
+ * runner never decides anything on it.
24858
+ */
24859
+ var SessionTriggerSchema = object({
24860
+ source: MotionSourceEnum,
24861
+ triggeredBy: MotionTriggeredBySchema,
24862
+ sensorName: string().optional()
24863
+ });
24864
+ /**
24497
24865
  * List of motion sources active on a camera. Empty array is valid:
24498
24866
  * "no source" — happens for battery cams without firmware motion when
24499
24867
  * the operator hasn't opted into the SW analyzer (would hold the
@@ -24745,6 +25113,14 @@ var RunnerCameraConfigSchema = object({
24745
25113
  */
24746
25114
  motionSources: MotionSourcesSchema.default(["analyzer"]),
24747
25115
  /**
25116
+ * What opened this attach, on a SESSION attach only (see
25117
+ * {@link SessionTriggerSchema}). OPTIONAL with no default: absent on a
25118
+ * standing attach, an occupancy burst, a re-dispatch with no motion event
25119
+ * behind it, and every attach from an orchestrator older than the field — the
25120
+ * runner then names no source on the phase event.
25121
+ */
25122
+ sessionTrigger: SessionTriggerSchema.optional(),
25123
+ /**
24748
25124
  * WHICH root detector runs for this camera. The detection counterpart of
24749
25125
  * {@link motionSources}, same shape and same discipline: a per-camera list
24750
25126
  * of sources the system understands, vendor-agnostic, owned here.
@@ -24904,14 +25280,15 @@ var RunnerLocalLoadSchema = object({
24904
25280
  * Per-inference-device live load (multi-device C4). One entry per deviceKey
24905
25281
  * this runner currently has attached cameras on, so the orchestrator's second
24906
25282
  * `balance()` pass (over a node's devices) weights on real per-pool session
24907
- * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
24908
- * per device is 0 until the pool backlog gets a public accessor (follow-up).
25283
+ * counts. Empty on single-device / pre-multi-device runners. There is no
25284
+ * per-device queue depth: the inference pool's backlog has no accessor, and
25285
+ * a field that always read 0 was removed rather than shown as a measurement
25286
+ * (D762).
24909
25287
  */
24910
25288
  devices: array(object({
24911
25289
  deviceKey: string(),
24912
25290
  backend: string(),
24913
- attachedCameras: number(),
24914
- queueDepthTotal: number()
25291
+ attachedCameras: number()
24915
25292
  })).default([]),
24916
25293
  /** Hardware capability flags reported by this node. */
24917
25294
  hardware: object({
@@ -25047,7 +25424,22 @@ method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mu
25047
25424
  */
25048
25425
  cropJpeg: string().optional(),
25049
25426
  parent: DetailParentSchema,
25050
- steps: array(string()).optional()
25427
+ steps: array(string()).optional(),
25428
+ /**
25429
+ * The camera's root model already drew this step's boxes (D730): a
25430
+ * `license_plate` inside the parent vehicle. The named step is NOT
25431
+ * inferred — these FRAME-space boxes are its output — and its
25432
+ * requested children (the plate reader) run on them. Absent ⇒ every
25433
+ * requested step infers as before.
25434
+ */
25435
+ supplied: object({
25436
+ stepId: string(),
25437
+ modelId: string(),
25438
+ boxes: array(object({
25439
+ bbox: NativeCropBboxSchema,
25440
+ score: number()
25441
+ })).min(1)
25442
+ }).optional()
25051
25443
  }), object({ details: array(DetailResultSchema) }).nullable(), { kind: "mutation" }), method(object({
25052
25444
  /** Catalog step id, e.g. `clip-embedding`. */
25053
25445
  stepId: string(),
@@ -25110,14 +25502,6 @@ var CameraPipelineConfigSchema = object({
25110
25502
  settings: record(string(), unknown()).readonly().optional()
25111
25503
  }).nullable().optional()
25112
25504
  });
25113
- var PipelineTemplateSchema = object({
25114
- id: string(),
25115
- name: string(),
25116
- description: string().optional(),
25117
- config: CameraPipelineConfigSchema,
25118
- createdAt: string(),
25119
- updatedAt: string()
25120
- });
25121
25505
  var DeviceStepConfigSchema = object({
25122
25506
  modelId: string().optional(),
25123
25507
  settings: record(string(), unknown()).optional(),
@@ -25191,9 +25575,10 @@ var CameraStepOverridePatchSchema = object({
25191
25575
  modelId: string().optional(),
25192
25576
  settings: record(string(), unknown()).readonly().optional()
25193
25577
  });
25578
+ var CameraStepSettingsSchema = record(string(), record(string(), unknown()).readonly());
25194
25579
  var CameraPipelineSettingsSchema = object({
25195
- pinnedAgentNodeId: string().optional(),
25196
25580
  stepToggles: record(string(), boolean()).optional(),
25581
+ stepSettings: CameraStepSettingsSchema.optional(),
25197
25582
  stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
25198
25583
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
25199
25584
  });
@@ -25226,7 +25611,10 @@ var PipelineAssignmentSchema = object({
25226
25611
  });
25227
25612
  /**
25228
25613
  * Per-agent load summary surfaced to the load balancer + dashboards.
25229
- * Aggregated from each runner's `getLocalLoad` cap call.
25614
+ * Aggregated from each runner's `getLocalLoad` cap call. In the
25615
+ * `getAgentLoad` report, a single-device node's default-pool sessions (no
25616
+ * `deviceKey`) are credited to its one eligible device in `load.devices` —
25617
+ * the default pool IS that device (D745); the balancer's census stays raw.
25230
25618
  */
25231
25619
  var AgentLoadSummarySchema = object({
25232
25620
  nodeId: string(),
@@ -25315,26 +25703,27 @@ var CameraBrokerStatusSchema = object({
25315
25703
  width: number(),
25316
25704
  height: number(),
25317
25705
  subscribers: number(),
25318
- inFps: number(),
25319
- outFps: number()
25706
+ /**
25707
+ * Encoded packets/s the broker receives from the camera. null when the
25708
+ * broker's stats read failed — unknown, never 0 (a 0 here reads as a stall).
25709
+ * There is no output rate: decoding runs in the session decode workers, not
25710
+ * in the broker, so the broker's own decoded-frame rate is 0 on every live
25711
+ * camera and is not served (D758).
25712
+ */
25713
+ inFps: number().nullable()
25320
25714
  })).readonly(),
25321
25715
  webrtcSessions: number(),
25322
25716
  rtspRestream: boolean()
25323
25717
  });
25324
- /** Shared-memory ring statistics within the decoder block. */
25325
- var CameraDecoderShmSchema = object({
25326
- framesWritten: number(),
25327
- getFrameHits: number(),
25328
- getFrameMisses: number(),
25329
- budgetMb: number()
25330
- });
25331
- /** Decoder block — null when the decoder stage is unreachable or inactive. */
25332
- var CameraDecoderStatusSchema = object({
25333
- nodeId: string(),
25334
- formats: array(string()).readonly(),
25335
- sessionCount: number(),
25336
- shm: CameraDecoderShmSchema
25337
- });
25718
+ /**
25719
+ * Decoder block — WHERE decode runs (co-located with the detection node by
25720
+ * construction); null when the camera has no detection node. It carries no
25721
+ * frame counter: the shared-memory plane whose counters it used to serve is
25722
+ * gone, and those fields read 0 forever. Whether frames actually flow is read
25723
+ * from `detection.actualFps` (frames delivered to and processed by the
25724
+ * detector), never from a counter nothing feeds.
25725
+ */
25726
+ var CameraDecoderStatusSchema = object({ nodeId: string() });
25338
25727
  /** Motion block — null when motion detection is not active for this device. */
25339
25728
  var CameraMotionStatusSchema = object({
25340
25729
  enabled: boolean(),
@@ -25691,12 +26080,6 @@ method(object({
25691
26080
  }), object({ success: literal(true) }), {
25692
26081
  kind: "mutation",
25693
26082
  auth: "admin"
25694
- }), method(object({
25695
- agentNodeId: string(),
25696
- detectWeight: number().positive().nullable()
25697
- }), object({ success: literal(true) }), {
25698
- kind: "mutation",
25699
- auth: "admin"
25700
26083
  }), method(object({
25701
26084
  agentNodeId: string(),
25702
26085
  detect: boolean().nullable().optional(),
@@ -25738,6 +26121,15 @@ method(object({
25738
26121
  }), {
25739
26122
  kind: "mutation",
25740
26123
  auth: "admin"
26124
+ }), method(AutoTuneOptionsSchema, AutoTunePlanSchema, { auth: "admin" }), method(AutoTuneApplyInputSchema, AutoTuneApplyResultSchema, {
26125
+ kind: "mutation",
26126
+ auth: "admin"
26127
+ }), method(LoadBalancingSharesInputSchema, object({ success: literal(true) }), {
26128
+ kind: "mutation",
26129
+ auth: "admin"
26130
+ }), method(PlacementStatsInputSchema, PlacementStatsSchema, { auth: "admin" }), method(SuggestSharesInputSchema, SuggestSharesResultSchema, { auth: "admin" }), method(_void(), EffectiveSharesSchema, { auth: "admin" }), method(SetShareSourceInputSchema, object({ success: literal(true) }), {
26131
+ kind: "mutation",
26132
+ auth: "admin"
25741
26133
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
25742
26134
  deviceId: number(),
25743
26135
  addonId: string(),
@@ -25754,6 +26146,13 @@ method(object({
25754
26146
  }), object({ success: literal(true) }), {
25755
26147
  kind: "mutation",
25756
26148
  auth: "admin"
26149
+ }), method(object({
26150
+ deviceId: number(),
26151
+ addonId: string(),
26152
+ settings: record(string(), unknown()).nullable()
26153
+ }), object({ success: literal(true) }), {
26154
+ kind: "mutation",
26155
+ auth: "admin"
25757
26156
  }), method(object({
25758
26157
  deviceId: number(),
25759
26158
  agentNodeId: string(),
@@ -25777,25 +26176,7 @@ method(object({
25777
26176
  }), method(_void(), DiskReconcileJobSchema, {
25778
26177
  kind: "mutation",
25779
26178
  auth: "admin"
25780
- }), method(_void(), DiskReconcileJobSchema, { auth: "admin" }), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
25781
- name: string(),
25782
- description: string().optional(),
25783
- config: CameraPipelineConfigSchema
25784
- }), PipelineTemplateSchema, {
25785
- kind: "mutation",
25786
- auth: "admin"
25787
- }), method(object({
25788
- id: string(),
25789
- name: string().optional(),
25790
- description: string().optional(),
25791
- config: CameraPipelineConfigSchema.optional()
25792
- }), PipelineTemplateSchema, {
25793
- kind: "mutation",
25794
- auth: "admin"
25795
- }), method(object({ id: string() }), object({ success: literal(true) }), {
25796
- kind: "mutation",
25797
- auth: "admin"
25798
- });
26179
+ }), method(_void(), DiskReconcileJobSchema, { auth: "admin" });
25799
26180
  /**
25800
26181
  * Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
25801
26182
  * `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
@@ -28044,8 +28425,6 @@ var WebrtcStreamChoiceSchema = object({
28044
28425
  ]).nullable(),
28045
28426
  /** Input FPS from the camera (null for adaptive). */
28046
28427
  inputFps: number().nullable(),
28047
- /** Decoded FPS (null for adaptive). */
28048
- decodeFps: number().nullable(),
28049
28428
  /** Bitrate in kbps (null for adaptive). */
28050
28429
  bitrateKbps: number().nullable()
28051
28430
  });
@@ -28377,6 +28756,14 @@ DeviceType.Camera, method(object({ deviceId: number().int().nonnegative() }), ar
28377
28756
  */
28378
28757
  alive: boolean()
28379
28758
  })), method(object({
28759
+ deviceId: number().int().nonnegative(),
28760
+ sessionId: string(),
28761
+ downlinkMbps: number().nonnegative()
28762
+ }), object({
28763
+ outcome: _enum(["switching", "held"]),
28764
+ tier: CamProfileSchema.nullable(),
28765
+ reason: string()
28766
+ }), { kind: "mutation" }), method(object({
28380
28767
  deviceId: number().int().nonnegative(),
28381
28768
  sessionId: string()
28382
28769
  }), WebrtcSessionDebugSchema, { kind: "query" });
@@ -32150,7 +32537,7 @@ var LocalInterfaceSchema = object({
32150
32537
  name: string(),
32151
32538
  family: _enum(["IPv4", "IPv6"]),
32152
32539
  address: string(),
32153
- /** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
32540
+ /** CIDR shorthand (e.g. `192.168.10.10/24`). Empty when OS doesn't expose. */
32154
32541
  cidr: string(),
32155
32542
  /** OS netmask. Stable across calls so the SDK can hash on it. */
32156
32543
  netmask: string(),
@@ -32204,7 +32591,9 @@ var ConnectionEndpointSchema = object({
32204
32591
  "lan-ipv4",
32205
32592
  "lan-ipv6",
32206
32593
  "public",
32207
- "loopback"
32594
+ "loopback",
32595
+ "app-link",
32596
+ "custom"
32208
32597
  ]),
32209
32598
  /**
32210
32599
  * Originating-interface kind — `lan`/`wifi`/`docker`/`vpn`/`other`/
@@ -32273,15 +32662,27 @@ var GetConnectionEndpointsResultSchema = object({
32273
32662
  localPort: AdvertisedLocalPortSchema
32274
32663
  });
32275
32664
  /**
32276
- * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
32277
- * AUTO (resolved from the candidate ranking at send time); `resolved` reports
32278
- * what AUTO currently picks, so the UI can show the effective value either way.
32665
+ * The address flagged for notification taps (`notificationTaps`). `baseUrl: null` = AUTO, which
32666
+ * since D709 is the CamStack app link; `resolved` reports the effective value,
32667
+ * so the UI can show it either way.
32279
32668
  */
32280
32669
  var NotificationEndpointSchema = object({
32281
32670
  /** The operator's explicit choice, or null for AUTO. */
32282
32671
  baseUrl: string().nullable(),
32283
- /** What the ranking currently resolves to (null when nothing is reachable). */
32284
- resolved: string().nullable()
32672
+ /**
32673
+ * The effective flagged address: the explicit choice, else (AUTO) the
32674
+ * CamStack app link `https://camstack.zentik.app` (D709). A pre-D709 hub
32675
+ * answered the public tunnel / mesh here, or null.
32676
+ */
32677
+ resolved: string().nullable(),
32678
+ /**
32679
+ * The hub origin an app link carries as `hub=` (D709): the hub's best
32680
+ * public HTTPS address — the tunnel, then the mesh (Tailscale MagicDNS) —
32681
+ * picked from this cap's own palette by `pickAppLinkHub`. `null` when the
32682
+ * hub advertises neither; the app link is then minted without `hub=`.
32683
+ * Absent on a pre-D709 hub.
32684
+ */
32685
+ appLinkHub: string().nullable()
32285
32686
  });
32286
32687
  /**
32287
32688
  * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
@@ -32294,6 +32695,72 @@ var ViewerEndpointsSchema = object({
32294
32695
  /** What the ranking currently resolves to (may be empty if nothing is up). */
32295
32696
  resolved: array(string()).readonly()
32296
32697
  });
32698
+ /**
32699
+ * DEPRECATED compatibility shape of `getHubAddresses` (D729 amendment, kept
32700
+ * for addons built against it): `cluster` is the `internal` role, `browser`
32701
+ * the `publicEndpoint` role; `override` is the flagged address.
32702
+ */
32703
+ var HubAddressSnapshotSchema = object({
32704
+ override: string().nullable(),
32705
+ resolved: string().nullable(),
32706
+ source: _enum([
32707
+ "override",
32708
+ "auto",
32709
+ "none"
32710
+ ])
32711
+ });
32712
+ var HubAddressesSchema = object({
32713
+ cluster: HubAddressSnapshotSchema,
32714
+ browser: HubAddressSnapshotSchema
32715
+ });
32716
+ /**
32717
+ * What an address is used for (`hub-address.ts`, D734). `appConnections` is
32718
+ * many-valued; `notificationTaps`, `publicEndpoint` and `internal` are carried
32719
+ * by at most one address.
32720
+ */
32721
+ var HubAddressRoleSchema = _enum(HUB_ADDRESS_ROLES);
32722
+ var RoleSourceSchema = _enum([
32723
+ "flagged",
32724
+ "auto",
32725
+ "none"
32726
+ ]);
32727
+ /** One single-valued role: the flagged address, the one in use, and why. */
32728
+ var HubAddressRoleResolutionSchema = object({
32729
+ /** The address carrying the flag, or null = automatic. */
32730
+ flagged: string().nullable(),
32731
+ /** The address in use, or null when nothing qualifies (never loopback). */
32732
+ resolved: string().nullable(),
32733
+ source: RoleSourceSchema
32734
+ });
32735
+ var HubAppConnectionsResolutionSchema = object({
32736
+ /** The addresses flagged `appConnections`, or empty = automatic. */
32737
+ flagged: array(string()).readonly(),
32738
+ /** What the apps race right now. */
32739
+ resolved: array(string()).readonly(),
32740
+ source: RoleSourceSchema
32741
+ });
32742
+ var HubAddressBookSchema = object({
32743
+ rows: array(ConnectionEndpointSchema.extend({
32744
+ /** In the hub's detected palette right now. */
32745
+ detected: boolean(),
32746
+ /** Entered by the operator (removable). */
32747
+ custom: boolean(),
32748
+ /** The roles explicitly flagged on this address. */
32749
+ flags: array(HubAddressRoleSchema).readonly(),
32750
+ /** The roles this address serves right now — flagged or automatic. */
32751
+ inUse: array(HubAddressRoleSchema).readonly(),
32752
+ /** The roles this address may be flagged with. */
32753
+ eligible: array(HubAddressRoleSchema).readonly()
32754
+ })).readonly(),
32755
+ roles: object({
32756
+ appConnections: HubAppConnectionsResolutionSchema,
32757
+ notificationTaps: HubAddressRoleResolutionSchema,
32758
+ internal: HubAddressRoleResolutionSchema,
32759
+ publicEndpoint: HubAddressRoleResolutionSchema
32760
+ }),
32761
+ /** The `hub=` an app link carries (D709), or null. */
32762
+ appLinkHub: string().nullable()
32763
+ });
32297
32764
  var AllowedAddressesSchema = object({
32298
32765
  /**
32299
32766
  * Allowlist of interface addresses operators have explicitly opted
@@ -32335,8 +32802,29 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
32335
32802
  * Pass `'https'` when the caller is itself loaded over HTTPS
32336
32803
  * to avoid mixed-content blocks in the browser. The public
32337
32804
  * tunnel always emits `https://` regardless. */
32338
- scheme: _enum(["http", "https"]).optional()
32339
- }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
32805
+ scheme: _enum(["http", "https"]).optional(),
32806
+ /** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
32807
+ * an address notification taps can be flagged with, not a hub
32808
+ * route. Default `false`: racers and rankers never see it. */
32809
+ includeAppLink: boolean().optional()
32810
+ }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(object({ scheme: _enum(["http", "https"]).optional() }).optional(), HubAddressBookSchema), method(object({
32811
+ baseUrl: string(),
32812
+ label: string().max(80)
32813
+ }), HubAddressBookSchema, {
32814
+ kind: "mutation",
32815
+ auth: "admin"
32816
+ }), method(object({ baseUrl: string() }), HubAddressBookSchema, {
32817
+ kind: "mutation",
32818
+ auth: "admin"
32819
+ }), method(object({
32820
+ role: HubAddressRoleSchema,
32821
+ baseUrl: string().nullable(),
32822
+ enabled: boolean(),
32823
+ acceptInsecureHttp: boolean().optional()
32824
+ }), HubAddressBookSchema, {
32825
+ kind: "mutation",
32826
+ auth: "admin"
32827
+ }), method(_void(), HubAddressesSchema), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
32340
32828
  kind: "mutation",
32341
32829
  auth: "admin"
32342
32830
  }), method(object({
@@ -32664,7 +33152,7 @@ var MeshPeerSchema = object({
32664
33152
  tags: array(string()).readonly(),
32665
33153
  /** True when the peer advertises itself as an exit-node candidate. */
32666
33154
  exitNodeOption: boolean(),
32667
- /** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
33155
+ /** Subnet routes the peer advertises (e.g. `["192.168.10.0/24"]`). */
32668
33156
  advertisedRoutes: array(string()).readonly(),
32669
33157
  /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
32670
33158
  userLogin: string().nullable(),
@@ -32794,7 +33282,8 @@ var MotionStatusSchema = object({
32794
33282
  * writes this slice (not even a boot seed), and neither does the runner's
32795
33283
  * phase machine: its phase is "a session is attached" for every on-motion
32796
33284
  * session, not motion, and it now has its own `DetectionPhaseTransition`.
32797
- * A provider's `isDetected` answers from the hub's slice.
33285
+ * A provider's `isDetected` and `getStatus` answer from the hub's slice
33286
+ * (`hubMotionNativeProvider`).
32798
33287
  * - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
32799
33288
  * imports) — the provider pushes both edges itself, from the upstream
32800
33289
  * system's own state change. That is the sensor's own fact.
@@ -33992,7 +34481,13 @@ var OsdStatusSchema = object({ overlays: array(object({
33992
34481
  */
33993
34482
  availablePositions: array(OsdPositionEnum).readonly(),
33994
34483
  /** Firmware does not allow editing the `text` field (e.g. timestamp). */
33995
- readOnly: boolean().optional()
34484
+ readOnly: boolean().optional(),
34485
+ /**
34486
+ * Firmware text ceiling for this overlay. Absent = no known limit.
34487
+ * The OSD manager truncates here on every write — never stores its own
34488
+ * copy on the binding.
34489
+ */
34490
+ maxCharacters: number().int().positive().optional()
33996
34491
  })).readonly() });
33997
34492
  var OsdOverlayPatchSchema = object({
33998
34493
  enabled: boolean().optional(),
@@ -34043,7 +34538,9 @@ var OsdTemplateBindingSchema = object({
34043
34538
  valuePath: string().min(1).max(64),
34044
34539
  /** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
34045
34540
  displayUnit: string().max(16).optional(),
34046
- maxDecimals: number().int().min(0).max(4).default(1)
34541
+ maxDecimals: number().int().min(0).max(4).default(1),
34542
+ /** Raw value → display text (same shape as slot binding). Empty string hides. */
34543
+ valueMap: record(string(), string()).optional()
34047
34544
  });
34048
34545
  /**
34049
34546
  * A named template: bindings (alias → leaf field) + a parser that
@@ -34093,18 +34590,11 @@ var OsdSlotBindingSchema = object({
34093
34590
  source: OsdSourceSchema,
34094
34591
  /** `${value}` and `${unit}` are substituted; every occurrence. */
34095
34592
  template: string().max(96).default("${value}"),
34096
- /** Truncate with an ellipsis past this length. Absent = no limit. */
34097
- maxCharacters: number().int().min(4).max(64).optional(),
34098
34593
  /**
34099
34594
  * Decimal places for a numeric value. `0` yields an integer — the
34100
34595
  * documented workaround for firmwares that reject `.` in overlay text.
34101
34596
  */
34102
34597
  maxDecimals: number().int().min(0).max(4).default(1),
34103
- /**
34104
- * Appended via `${unit}` when no unit conversion produces a label.
34105
- * Prefer `source.displayUnit` for converted device-state values.
34106
- */
34107
- unitLabel: string().max(8).optional(),
34108
34598
  /** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
34109
34599
  valueMap: record(string(), string()).optional(),
34110
34600
  /** Time windows in which the slot is shown. Absent = always. */
@@ -34113,9 +34603,7 @@ var OsdSlotBindingSchema = object({
34113
34603
  * Display gate, in the notification centre's condition vocabulary.
34114
34604
  * Only the keys reported by `getConditionSupport` are accepted.
34115
34605
  */
34116
- conditions: NcConditionsSchema.optional(),
34117
- /** Rendered when the gate is closed or the value unreadable. Empty = hide. */
34118
- fallbackText: string().max(64).default("")
34606
+ conditions: NcConditionsSchema.optional()
34119
34607
  });
34120
34608
  /** One camera slot, as the operator sees it: firmware truth + our binding. */
34121
34609
  var OsdSlotViewSchema = object({
@@ -39342,6 +39830,16 @@ var zoneRulesCapability = {
39342
39830
  durability: "restored"
39343
39831
  };
39344
39832
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
39833
+ Object.freeze({
39834
+ person: .5,
39835
+ vehicle: .5,
39836
+ animal: .5
39837
+ });
39838
+ Object.freeze({
39839
+ person: .65,
39840
+ vehicle: .65,
39841
+ animal: .65
39842
+ });
39345
39843
  /**
39346
39844
  * Accessory device helpers — shared across drivers.
39347
39845
  *
@@ -42222,90 +42720,18 @@ Object.freeze({
42222
42720
  addonId: null,
42223
42721
  access: "create"
42224
42722
  },
42225
- "decoder.createSession": {
42226
- capName: "decoder",
42227
- capScope: "system",
42228
- addonId: null,
42229
- access: "view"
42230
- },
42231
- "decoder.destroySession": {
42232
- capName: "decoder",
42233
- capScope: "system",
42234
- addonId: null,
42235
- access: "delete"
42236
- },
42237
- "decoder.getFrame": {
42238
- capName: "decoder",
42239
- capScope: "system",
42240
- addonId: null,
42241
- access: "view"
42242
- },
42243
42723
  "decoder.getInfo": {
42244
42724
  capName: "decoder",
42245
42725
  capScope: "system",
42246
42726
  addonId: null,
42247
42727
  access: "view"
42248
42728
  },
42249
- "decoder.getShmStats": {
42250
- capName: "decoder",
42251
- capScope: "system",
42252
- addonId: null,
42253
- access: "view"
42254
- },
42255
- "decoder.getStats": {
42256
- capName: "decoder",
42257
- capScope: "system",
42258
- addonId: null,
42259
- access: "view"
42260
- },
42261
- "decoder.listActiveSessions": {
42262
- capName: "decoder",
42263
- capScope: "system",
42264
- addonId: null,
42265
- access: "view"
42266
- },
42267
- "decoder.openStream": {
42268
- capName: "decoder",
42269
- capScope: "system",
42270
- addonId: null,
42271
- access: "view"
42272
- },
42273
- "decoder.pullFrames": {
42274
- capName: "decoder",
42275
- capScope: "system",
42276
- addonId: null,
42277
- access: "view"
42278
- },
42279
- "decoder.pullHandles": {
42280
- capName: "decoder",
42281
- capScope: "system",
42282
- addonId: null,
42283
- access: "view"
42284
- },
42285
- "decoder.pushPacket": {
42286
- capName: "decoder",
42287
- capScope: "system",
42288
- addonId: null,
42289
- access: "view"
42290
- },
42291
42729
  "decoder.reprobeHwaccel": {
42292
42730
  capName: "decoder",
42293
42731
  capScope: "system",
42294
42732
  addonId: null,
42295
42733
  access: "create"
42296
42734
  },
42297
- "decoder.supportsCodec": {
42298
- capName: "decoder",
42299
- capScope: "system",
42300
- addonId: null,
42301
- access: "view"
42302
- },
42303
- "decoder.updateConfig": {
42304
- capName: "decoder",
42305
- capScope: "system",
42306
- addonId: null,
42307
- access: "view"
42308
- },
42309
42735
  "detectionPipeline.applyDeviceSettingsPatch": {
42310
42736
  capName: "detection-pipeline",
42311
42737
  capScope: "device",
@@ -43794,12 +44220,24 @@ Object.freeze({
43794
44220
  addonId: null,
43795
44221
  access: "view"
43796
44222
  },
44223
+ "localNetwork.addCustomAddress": {
44224
+ capName: "local-network",
44225
+ capScope: "system",
44226
+ addonId: null,
44227
+ access: "create"
44228
+ },
43797
44229
  "localNetwork.downloadCa": {
43798
44230
  capName: "local-network",
43799
44231
  capScope: "system",
43800
44232
  addonId: null,
43801
44233
  access: "view"
43802
44234
  },
44235
+ "localNetwork.getAddresses": {
44236
+ capName: "local-network",
44237
+ capScope: "system",
44238
+ addonId: null,
44239
+ access: "view"
44240
+ },
43803
44241
  "localNetwork.getAllowedAddresses": {
43804
44242
  capName: "local-network",
43805
44243
  capScope: "system",
@@ -43812,6 +44250,12 @@ Object.freeze({
43812
44250
  addonId: null,
43813
44251
  access: "view"
43814
44252
  },
44253
+ "localNetwork.getHubAddresses": {
44254
+ capName: "local-network",
44255
+ capScope: "system",
44256
+ addonId: null,
44257
+ access: "view"
44258
+ },
43815
44259
  "localNetwork.getNotificationEndpoint": {
43816
44260
  capName: "local-network",
43817
44261
  capScope: "system",
@@ -43848,6 +44292,12 @@ Object.freeze({
43848
44292
  addonId: null,
43849
44293
  access: "create"
43850
44294
  },
44295
+ "localNetwork.removeCustomAddress": {
44296
+ capName: "local-network",
44297
+ capScope: "system",
44298
+ addonId: null,
44299
+ access: "delete"
44300
+ },
43851
44301
  "localNetwork.resetAllowlistToBestMatch": {
43852
44302
  capName: "local-network",
43853
44303
  capScope: "system",
@@ -43860,6 +44310,12 @@ Object.freeze({
43860
44310
  addonId: null,
43861
44311
  access: "create"
43862
44312
  },
44313
+ "localNetwork.setAddressRole": {
44314
+ capName: "local-network",
44315
+ capScope: "system",
44316
+ addonId: null,
44317
+ access: "create"
44318
+ },
43863
44319
  "localNetwork.setAllowedAddresses": {
43864
44320
  capName: "local-network",
43865
44321
  capScope: "system",
@@ -45354,13 +45810,13 @@ Object.freeze({
45354
45810
  addonId: null,
45355
45811
  access: "delete"
45356
45812
  },
45357
- "pipelineExecutor.deleteModel": {
45813
+ "pipelineExecutor.clearModelBoundDeviceOverrides": {
45358
45814
  capName: "pipeline-executor",
45359
45815
  capScope: "system",
45360
45816
  addonId: null,
45361
45817
  access: "delete"
45362
45818
  },
45363
- "pipelineExecutor.deleteTemplate": {
45819
+ "pipelineExecutor.deleteModel": {
45364
45820
  capName: "pipeline-executor",
45365
45821
  capScope: "system",
45366
45822
  addonId: null,
@@ -45504,12 +45960,6 @@ Object.freeze({
45504
45960
  addonId: null,
45505
45961
  access: "view"
45506
45962
  },
45507
- "pipelineExecutor.listTemplates": {
45508
- capName: "pipeline-executor",
45509
- capScope: "system",
45510
- addonId: null,
45511
- access: "view"
45512
- },
45513
45963
  "pipelineExecutor.rearmInferenceDevice": {
45514
45964
  capName: "pipeline-executor",
45515
45965
  capScope: "system",
@@ -45534,12 +45984,6 @@ Object.freeze({
45534
45984
  addonId: null,
45535
45985
  access: "create"
45536
45986
  },
45537
- "pipelineExecutor.saveTemplate": {
45538
- capName: "pipeline-executor",
45539
- capScope: "system",
45540
- addonId: null,
45541
- access: "create"
45542
- },
45543
45987
  "pipelineExecutor.setVideoPipelineSteps": {
45544
45988
  capName: "pipeline-executor",
45545
45989
  capScope: "system",
@@ -45558,41 +46002,35 @@ Object.freeze({
45558
46002
  addonId: null,
45559
46003
  access: "create"
45560
46004
  },
45561
- "pipelineExecutor.updateTemplate": {
45562
- capName: "pipeline-executor",
45563
- capScope: "system",
45564
- addonId: null,
45565
- access: "create"
45566
- },
45567
46005
  "pipelineExecutor.validatePipeline": {
45568
46006
  capName: "pipeline-executor",
45569
46007
  capScope: "system",
45570
46008
  addonId: null,
45571
46009
  access: "view"
45572
46010
  },
45573
- "pipelineOrchestrator.applyDeviceSettingsPatch": {
46011
+ "pipelineOrchestrator.applyAutoTune": {
45574
46012
  capName: "pipeline-orchestrator",
45575
46013
  capScope: "system",
45576
46014
  addonId: null,
45577
46015
  access: "create"
45578
46016
  },
45579
- "pipelineOrchestrator.assignAudio": {
46017
+ "pipelineOrchestrator.applyDeviceSettingsPatch": {
45580
46018
  capName: "pipeline-orchestrator",
45581
46019
  capScope: "system",
45582
46020
  addonId: null,
45583
46021
  access: "create"
45584
46022
  },
45585
- "pipelineOrchestrator.assignPipeline": {
46023
+ "pipelineOrchestrator.assignAudio": {
45586
46024
  capName: "pipeline-orchestrator",
45587
46025
  capScope: "system",
45588
46026
  addonId: null,
45589
46027
  access: "create"
45590
46028
  },
45591
- "pipelineOrchestrator.deleteTemplate": {
46029
+ "pipelineOrchestrator.assignPipeline": {
45592
46030
  capName: "pipeline-orchestrator",
45593
46031
  capScope: "system",
45594
46032
  addonId: null,
45595
- access: "delete"
46033
+ access: "create"
45596
46034
  },
45597
46035
  "pipelineOrchestrator.getAgentLoad": {
45598
46036
  capName: "pipeline-orchestrator",
@@ -45684,6 +46122,12 @@ Object.freeze({
45684
46122
  addonId: null,
45685
46123
  access: "view"
45686
46124
  },
46125
+ "pipelineOrchestrator.getEffectiveShares": {
46126
+ capName: "pipeline-orchestrator",
46127
+ capScope: "system",
46128
+ addonId: null,
46129
+ access: "view"
46130
+ },
45687
46131
  "pipelineOrchestrator.getGlobalMetrics": {
45688
46132
  capName: "pipeline-orchestrator",
45689
46133
  capScope: "system",
@@ -45720,19 +46164,19 @@ Object.freeze({
45720
46164
  addonId: null,
45721
46165
  access: "view"
45722
46166
  },
45723
- "pipelineOrchestrator.getReconcileFromDiskStatus": {
46167
+ "pipelineOrchestrator.getPlacementStats": {
45724
46168
  capName: "pipeline-orchestrator",
45725
46169
  capScope: "system",
45726
46170
  addonId: null,
45727
46171
  access: "view"
45728
46172
  },
45729
- "pipelineOrchestrator.listAgentSettings": {
46173
+ "pipelineOrchestrator.getReconcileFromDiskStatus": {
45730
46174
  capName: "pipeline-orchestrator",
45731
46175
  capScope: "system",
45732
46176
  addonId: null,
45733
46177
  access: "view"
45734
46178
  },
45735
- "pipelineOrchestrator.listTemplates": {
46179
+ "pipelineOrchestrator.listAgentSettings": {
45736
46180
  capName: "pipeline-orchestrator",
45737
46181
  capScope: "system",
45738
46182
  addonId: null,
@@ -45744,6 +46188,12 @@ Object.freeze({
45744
46188
  addonId: null,
45745
46189
  access: "create"
45746
46190
  },
46191
+ "pipelineOrchestrator.planAutoTune": {
46192
+ capName: "pipeline-orchestrator",
46193
+ capScope: "system",
46194
+ addonId: null,
46195
+ access: "view"
46196
+ },
45747
46197
  "pipelineOrchestrator.rebalance": {
45748
46198
  capName: "pipeline-orchestrator",
45749
46199
  capScope: "system",
@@ -45786,12 +46236,6 @@ Object.freeze({
45786
46236
  addonId: null,
45787
46237
  access: "create"
45788
46238
  },
45789
- "pipelineOrchestrator.saveTemplate": {
45790
- capName: "pipeline-orchestrator",
45791
- capScope: "system",
45792
- addonId: null,
45793
- access: "create"
45794
- },
45795
46239
  "pipelineOrchestrator.setAgentCapabilities": {
45796
46240
  capName: "pipeline-orchestrator",
45797
46241
  capScope: "system",
@@ -45804,12 +46248,6 @@ Object.freeze({
45804
46248
  addonId: null,
45805
46249
  access: "create"
45806
46250
  },
45807
- "pipelineOrchestrator.setAgentDetectWeight": {
45808
- capName: "pipeline-orchestrator",
45809
- capScope: "system",
45810
- addonId: null,
45811
- access: "create"
45812
- },
45813
46251
  "pipelineOrchestrator.setAgentInferenceDevices": {
45814
46252
  capName: "pipeline-orchestrator",
45815
46253
  capScope: "system",
@@ -45846,6 +46284,12 @@ Object.freeze({
45846
46284
  addonId: null,
45847
46285
  access: "create"
45848
46286
  },
46287
+ "pipelineOrchestrator.setCameraStepSettings": {
46288
+ capName: "pipeline-orchestrator",
46289
+ capScope: "system",
46290
+ addonId: null,
46291
+ access: "create"
46292
+ },
45849
46293
  "pipelineOrchestrator.setCameraStepToggle": {
45850
46294
  capName: "pipeline-orchestrator",
45851
46295
  capScope: "system",
@@ -45864,25 +46308,37 @@ Object.freeze({
45864
46308
  addonId: null,
45865
46309
  access: "create"
45866
46310
  },
46311
+ "pipelineOrchestrator.setLoadBalancingShares": {
46312
+ capName: "pipeline-orchestrator",
46313
+ capScope: "system",
46314
+ addonId: null,
46315
+ access: "create"
46316
+ },
45867
46317
  "pipelineOrchestrator.setPipelineDevicePin": {
45868
46318
  capName: "pipeline-orchestrator",
45869
46319
  capScope: "system",
45870
46320
  addonId: null,
45871
46321
  access: "create"
45872
46322
  },
45873
- "pipelineOrchestrator.unassignAudio": {
46323
+ "pipelineOrchestrator.setShareSource": {
45874
46324
  capName: "pipeline-orchestrator",
45875
46325
  capScope: "system",
45876
46326
  addonId: null,
45877
46327
  access: "create"
45878
46328
  },
45879
- "pipelineOrchestrator.unassignPipeline": {
46329
+ "pipelineOrchestrator.suggestShares": {
46330
+ capName: "pipeline-orchestrator",
46331
+ capScope: "system",
46332
+ addonId: null,
46333
+ access: "view"
46334
+ },
46335
+ "pipelineOrchestrator.unassignAudio": {
45880
46336
  capName: "pipeline-orchestrator",
45881
46337
  capScope: "system",
45882
46338
  addonId: null,
45883
46339
  access: "create"
45884
46340
  },
45885
- "pipelineOrchestrator.updateTemplate": {
46341
+ "pipelineOrchestrator.unassignPipeline": {
45886
46342
  capName: "pipeline-orchestrator",
45887
46343
  capScope: "system",
45888
46344
  addonId: null,
@@ -47322,12 +47778,6 @@ Object.freeze({
47322
47778
  addonId: null,
47323
47779
  access: "view"
47324
47780
  },
47325
- "streamBroker.pullFrameHandles": {
47326
- capName: "stream-broker",
47327
- capScope: "system",
47328
- addonId: null,
47329
- access: "view"
47330
- },
47331
47781
  "streamBroker.regenerateRtspToken": {
47332
47782
  capName: "stream-broker",
47333
47783
  capScope: "system",
@@ -47394,12 +47844,6 @@ Object.freeze({
47394
47844
  addonId: null,
47395
47845
  access: "create"
47396
47846
  },
47397
- "streamBroker.subscribeFrames": {
47398
- capName: "stream-broker",
47399
- capScope: "system",
47400
- addonId: null,
47401
- access: "create"
47402
- },
47403
47847
  "streamBroker.unassignProfile": {
47404
47848
  capName: "stream-broker",
47405
47849
  capScope: "system",
@@ -47412,12 +47856,6 @@ Object.freeze({
47412
47856
  addonId: null,
47413
47857
  access: "create"
47414
47858
  },
47415
- "streamBroker.unsubscribeFrames": {
47416
- capName: "stream-broker",
47417
- capScope: "system",
47418
- addonId: null,
47419
- access: "create"
47420
- },
47421
47859
  "streamCatalog.getCatalog": {
47422
47860
  capName: "stream-catalog",
47423
47861
  capScope: "device",
@@ -48114,6 +48552,12 @@ Object.freeze({
48114
48552
  addonId: null,
48115
48553
  access: "create"
48116
48554
  },
48555
+ "webrtcSession.applyDownlinkProbe": {
48556
+ capName: "webrtc-session",
48557
+ capScope: "device",
48558
+ addonId: null,
48559
+ access: "create"
48560
+ },
48117
48561
  "webrtcSession.closeSession": {
48118
48562
  capName: "webrtc-session",
48119
48563
  capScope: "device",
@@ -49925,11 +50369,6 @@ Object.freeze({
49925
50369
  form: "single",
49926
50370
  optional: false
49927
50371
  }],
49928
- "decoder.createSession": [{
49929
- name: "deviceId",
49930
- form: "single",
49931
- optional: true
49932
- }],
49933
50372
  "detectionPipeline.applyDeviceSettingsPatch": [{
49934
50373
  name: "deviceId",
49935
50374
  form: "single",
@@ -51160,6 +51599,11 @@ Object.freeze({
51160
51599
  form: "single",
51161
51600
  optional: false
51162
51601
  }],
51602
+ "pipelineExecutor.clearModelBoundDeviceOverrides": [{
51603
+ name: "deviceIds",
51604
+ form: "array",
51605
+ optional: true
51606
+ }],
51163
51607
  "pipelineExecutor.runPipeline": [{
51164
51608
  name: "deviceId",
51165
51609
  form: "single",
@@ -51265,6 +51709,11 @@ Object.freeze({
51265
51709
  form: "single",
51266
51710
  optional: false
51267
51711
  }],
51712
+ "pipelineOrchestrator.setCameraStepSettings": [{
51713
+ name: "deviceId",
51714
+ form: "single",
51715
+ optional: false
51716
+ }],
51268
51717
  "pipelineOrchestrator.setCameraStepToggle": [{
51269
51718
  name: "deviceId",
51270
51719
  form: "single",
@@ -52036,6 +52485,11 @@ Object.freeze({
52036
52485
  form: "single",
52037
52486
  optional: false
52038
52487
  }],
52488
+ "webrtcSession.applyDownlinkProbe": [{
52489
+ name: "deviceId",
52490
+ form: "single",
52491
+ optional: false
52492
+ }],
52039
52493
  "webrtcSession.closeSession": [{
52040
52494
  name: "deviceId",
52041
52495
  form: "single",
@@ -52265,6 +52719,8 @@ new Map(Object.entries({
52265
52719
  "detection-blind": "device-events",
52266
52720
  "node-online": "system",
52267
52721
  "node-offline": "system",
52722
+ "node-restarting": "system",
52723
+ "node-updating": "system",
52268
52724
  "node-inference-unavailable": "system",
52269
52725
  "addon-crash-loop": "system",
52270
52726
  "addon-update-available": "system",
@@ -52342,18 +52798,21 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
52342
52798
  kinds: [
52343
52799
  "node-offline",
52344
52800
  "node-online",
52801
+ "node-restarting",
52345
52802
  "node-inference-unavailable"
52346
52803
  ]
52347
52804
  },
52348
52805
  {
52349
52806
  id: "addons",
52350
52807
  family: "system",
52351
- label: "Addons",
52352
- kinds: [
52353
- "addon-crash-loop",
52354
- "addon-update-available",
52355
- "addon-updated"
52356
- ]
52808
+ label: "Addons stopped",
52809
+ kinds: ["addon-crash-loop"]
52810
+ },
52811
+ {
52812
+ id: "addon-updates",
52813
+ family: "system",
52814
+ label: "Addon updates",
52815
+ kinds: ["addon-update-available", "addon-updated"]
52357
52816
  },
52358
52817
  {
52359
52818
  id: "updates",
@@ -52361,6 +52820,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
52361
52820
  label: "Server & container updates",
52362
52821
  kinds: [
52363
52822
  "server-update-available",
52823
+ "node-updating",
52364
52824
  "server-updated",
52365
52825
  "wrapper-update-available"
52366
52826
  ]
@@ -52508,18 +52968,21 @@ var STATE_SUMMARY_SECTION_VARS = [
52508
52968
  kinds: [
52509
52969
  "node-offline",
52510
52970
  "node-online",
52971
+ "node-restarting",
52511
52972
  "node-inference-unavailable"
52512
52973
  ]
52513
52974
  },
52514
52975
  {
52515
52976
  name: "summaryAddons",
52516
- label: "Summary: addons",
52517
- example: "@camstack/addon-recorder 1.2.3 → 1.2.4",
52518
- kinds: [
52519
- "addon-crash-loop",
52520
- "addon-update-available",
52521
- "addon-updated"
52522
- ]
52977
+ label: "Summary: addons stopped",
52978
+ example: "hub — recorder stopped after repeated crashes",
52979
+ kinds: ["addon-crash-loop"]
52980
+ },
52981
+ {
52982
+ name: "summaryAddonUpdates",
52983
+ label: "Summary: addon updates",
52984
+ example: "hub:\n• @camstack/addon-recorder 1.2.3 → 1.2.4",
52985
+ kinds: ["addon-update-available", "addon-updated"]
52523
52986
  },
52524
52987
  {
52525
52988
  name: "summaryUpdates",
@@ -52527,6 +52990,7 @@ var STATE_SUMMARY_SECTION_VARS = [
52527
52990
  example: "server 1.2.377 → 1.2.378",
52528
52991
  kinds: [
52529
52992
  "server-update-available",
52993
+ "node-updating",
52530
52994
  "server-updated",
52531
52995
  "wrapper-update-available"
52532
52996
  ]
@@ -52559,7 +53023,7 @@ var STATE_SUMMARY_VARS = [
52559
53023
  {
52560
53024
  name: "summarySection",
52561
53025
  label: "Summary: this section",
52562
- description: "The section a per-section summary row is about (D698); on a summary sent as one message, every section it reports, comma-separated.",
53026
+ description: "The section a per-section summary row is about; on a summary sent as one message, every section it reports, comma-separated.",
52563
53027
  example: "Batterie scariche",
52564
53028
  group: "system",
52565
53029
  families: ["rule"],
@@ -52603,6 +53067,7 @@ var STATE_SUMMARY_VARS = [
52603
53067
  [...RULE_BODY_ONLY],
52604
53068
  [...RULE_TEXT],
52605
53069
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
53070
+ ([...RULE_TEXT], [...COMBINED_ALARM]),
52606
53071
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
52607
53072
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
52608
53073
  ([...RULE_TEXT], [...CONSUMABLE]),
@@ -52643,6 +53108,8 @@ var STATE_SUMMARY_VARS = [
52643
53108
  [...RULE_TEXT],
52644
53109
  [...RULE_TEXT],
52645
53110
  [...RULE_TEXT],
53111
+ [...RULE_TEXT],
53112
+ [...RULE_TEXT],
52646
53113
  ...STATE_SUMMARY_VARS
52647
53114
  ];
52648
53115
  new Set([
@@ -96247,26 +96714,6 @@ function setBrokerDevicesOnline(devices, brokerId, online) {
96247
96714
  }
96248
96715
  //#endregion
96249
96716
  //#region src/alexa-state-to-cap.ts
96250
- /**
96251
- * Pure decoders translating a single polled Alexa property value (as stored on
96252
- * the {@link AlexaAccountResolver} by interface + property) into the CamStack cap
96253
- * status field it drives. The inverse of the exporter's report-state mapping.
96254
- *
96255
- * Each function takes the raw `unknown` value (provider-specific) and returns a
96256
- * narrowed primitive or `null` when the value is absent / unrecognised, so the
96257
- * device class can fall back to its cold-start/runtime default. No I/O, no
96258
- * alexa-remote2 import — unit-testable with fixtures.
96259
- *
96260
- * Alexa property reference (smart-home Phoenix state):
96261
- * - Alexa.PowerController.powerState → 'ON' | 'OFF'
96262
- * - Alexa.BrightnessController.brightness → 0..100
96263
- * - Alexa.LockController.lockState → 'LOCKED' | 'UNLOCKED' | 'JAMMED'
96264
- * - Alexa.ContactSensor.detectionState → 'DETECTED' | 'NOT_DETECTED'
96265
- * - Alexa.MotionSensor.detectionState → 'DETECTED' | 'NOT_DETECTED'
96266
- * - Alexa.TemperatureSensor.temperature → { value:number, scale:'CELSIUS'|'FAHRENHEIT' } | number
96267
- * - Alexa.PercentageController.percentage → 0..100
96268
- * - humidity → number (percent)
96269
- */
96270
96717
  /** Decode an Alexa `powerState` to a boolean on-state, or null. */
96271
96718
  function decodePowerState(value) {
96272
96719
  if (value === "ON") return true;