@camstack/addon-pipeline 1.2.190 → 1.2.192

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 (38) hide show
  1. package/dist/audio-analyzer/index.js +2 -2
  2. package/dist/audio-analyzer/index.mjs +2 -2
  3. package/dist/detection-pipeline/index.js +5 -5
  4. package/dist/detection-pipeline/index.mjs +4 -4
  5. package/dist/{dist-CZkzc0WB.mjs → dist-B8J7wrtY.mjs} +313 -0
  6. package/dist/{dist-C31OZkZP.js → dist-CXO_Fmx6.js} +313 -0
  7. package/dist/{lazy-sharp-DhHuLuQf.js → lazy-sharp-o-aNNXuz.js} +1 -1
  8. package/dist/{local-frame-registry-B8_L3v0O.mjs → local-frame-registry-BDeDpYQk.mjs} +1 -1
  9. package/dist/{local-frame-registry-CkIaPLcW.js → local-frame-registry-P7tSfvaY.js} +1 -1
  10. package/dist/motion-wasm/index.js +2 -2
  11. package/dist/motion-wasm/index.mjs +1 -1
  12. package/dist/{node-kSXNMrbg.mjs → node-BSbB0or0.mjs} +1 -1
  13. package/dist/{node-CIpenwbm.js → node-DF98pVP7.js} +1 -1
  14. package/dist/pipeline-runner/index.js +5 -5
  15. package/dist/pipeline-runner/index.mjs +4 -4
  16. package/dist/{process-memory-BQTHtzan.js → process-memory-BVMk3gfY.js} +1 -1
  17. package/dist/{process-memory-CphvVq1H.mjs → process-memory-BZTgJyE8.mjs} +1 -1
  18. package/dist/recorder/index.js +2 -2
  19. package/dist/recorder/index.mjs +2 -2
  20. package/dist/{segment-demux-js-AELUnBau.mjs → segment-demux-js-0L1EF4Fg.mjs} +1 -1
  21. package/dist/{segment-demux-js-CYjZAotp.js → segment-demux-js-CLaSHw0n.js} +1 -1
  22. package/dist/session-decode/decode-worker-child.js +79 -6
  23. package/dist/session-decode/decode-worker-child.mjs +78 -5
  24. package/dist/stream-broker/_stub.js +2 -2
  25. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BA9MaopY.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BmNfrv_U.mjs} +3 -3
  26. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D8AK-_F6.mjs +26 -0
  27. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CkCh5TvE.mjs +26 -0
  28. package/dist/stream-broker/demux-worker-child.js +1 -1
  29. package/dist/stream-broker/demux-worker-child.mjs +1 -1
  30. package/dist/stream-broker/{hostInit-0htGr-yV.mjs → hostInit-DQLtjntf.mjs} +3 -3
  31. package/dist/stream-broker/index.js +3 -3
  32. package/dist/stream-broker/index.mjs +3 -3
  33. package/dist/stream-broker/remoteEntry.js +1 -1
  34. package/dist/{worker-protocol-BSgTKhW7.js → worker-protocol-BJzhw3t0.js} +1 -1
  35. package/dist/{worker-protocol-Bcy8Ti5P.mjs → worker-protocol-WiXU2VuW.mjs} +1 -1
  36. package/package.json +1 -1
  37. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CDtnQr69.mjs +0 -26
  38. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BOR2heMq.mjs +0 -26
@@ -5429,6 +5429,12 @@ Object.fromEntries([
5429
5429
  icon: "move",
5430
5430
  order: 40
5431
5431
  },
5432
+ {
5433
+ id: "navigation",
5434
+ label: "Navigation",
5435
+ icon: "compass",
5436
+ order: 41
5437
+ },
5432
5438
  {
5433
5439
  id: "consumables",
5434
5440
  label: "Consumables",
@@ -29647,6 +29653,203 @@ DeviceType.Camera, method(object({ deviceId: number() }), PtzAutotrackStatusSche
29647
29653
  deviceId: number(),
29648
29654
  status: PtzAutotrackStatusSchema
29649
29655
  });
29656
+ /**
29657
+ * `navigation` — a device-scoped capability that natively expresses the FULL
29658
+ * navigation / action surface of a robot that DRIVES ITSELF and carries an
29659
+ * on-board camera (the Dreame robot-vacuum camera is the first provider).
29660
+ *
29661
+ * Why a NEW cap rather than overloading `ptz`:
29662
+ * - `ptz` moves a *gimbal* on a fixed camera (pan/tilt/zoom of the lens). A
29663
+ * robot vacuum has no gimbal — the whole chassis drives, turns and spins.
29664
+ * The two are different physical models: PTZ is absolute-position + presets,
29665
+ * navigation is momentary drive nudges + discrete robot ACTIONS
29666
+ * (dock / spot-clean / follow-pet / go-to-point / …).
29667
+ * - This cap is the SOURCE OF TRUTH. Two consumers adapt from it rather than
29668
+ * the reverse:
29669
+ * 1. a native CamStack navigation panel (data-driven from `listActions`
29670
+ * / `getOptions`), and
29671
+ * 2. the PTZ surface — a thin adapter mimics `ptz` from `navigation` so a
29672
+ * robot camera shows up in the existing PTZ control path without every
29673
+ * PTZ provider learning about robots. The mapping lives in the adapter,
29674
+ * not here (see the addon design note):
29675
+ * ptz.continuousMove({pan,tilt}) → navigation.move({pan,tilt})
29676
+ * ptz.stop() → navigation.stop()
29677
+ * ptz.goHome() → navigation.runAction('goHome')
29678
+ * ptz.getPresets() → navigation.listActions() (id→preset)
29679
+ * ptz.goToPreset(id) → navigation.runAction(id)
29680
+ *
29681
+ * ## Continuous drive
29682
+ *
29683
+ * `move` is MOMENTARY. Fluid navigation comes from the UI (or the PTZ adapter)
29684
+ * sending `move({pan,tilt})` REPEATEDLY at ~1 Hz while a direction is held, and
29685
+ * one `stop()` on release — exactly like the robot app's remote-drive joystick.
29686
+ * The provider forwards EACH `move` to one drive write; it must NOT debounce or
29687
+ * coalesce them. The UI owns the cadence.
29688
+ *
29689
+ * ## The action dictionary
29690
+ *
29691
+ * The discrete controls (dock / locate / spot-clean / follow / flash / sounds)
29692
+ * are a DATA-DRIVEN dictionary the cap exposes via `listActions()`. Each entry
29693
+ * carries `{ id, kind, label, icon }` (plus `soundId` for sound entries) so the
29694
+ * native panel AND the PTZ mimic render buttons WITHOUT hardcoding a
29695
+ * vendor-specific list. `kind: 'action'` entries are triggered with
29696
+ * `runAction({ actionId })`; `kind: 'sound'` entries with `playSound({ soundId })`
29697
+ * (the entry carries the `soundId` to pass). The general primitives — `move`,
29698
+ * `stop`, `goToPoint` — stay as first-class methods, not dictionary entries.
29699
+ *
29700
+ * NOTE (provider wiring): the first provider (Dreame) drives this with the RAW
29701
+ * `callAction(siid,aiid,in)` / `setProperty({siid,piid,value})` MIoT primitives
29702
+ * that the currently-published `@apocaliss92/nodedreame` already exposes on
29703
+ * every device handle. A future nodedreame publish adds a typed
29704
+ * `DreameCameraController` (drive / playPetSound / spotClean / findPet / …); the
29705
+ * provider can then swap the raw calls for the typed methods with no change to
29706
+ * THIS contract.
29707
+ */
29708
+ /**
29709
+ * A momentary drive nudge. The robot MOVES (no gimbal) for as long as the caller
29710
+ * keeps sending nudges (~1 Hz); an explicit `stop` (or letting the nudges lapse)
29711
+ * halts it.
29712
+ *
29713
+ * - `pan` — turn: negative = left, positive = right, 0 = straight.
29714
+ * - `tilt` — throttle: positive = forward, negative = spin / turn-around.
29715
+ * - `speed` — optional intensity hint [0, 1]; the provider may scale the drive
29716
+ * vector by it (drivers without proportional drive ignore it).
29717
+ *
29718
+ * `pan` / `tilt` are normalized [-1, 1]. Both optional so a caller can nudge one
29719
+ * axis alone; an all-undefined nudge is a no-op.
29720
+ */
29721
+ var NavigationMoveCommandSchema = object({
29722
+ pan: number().min(-1).max(1).optional(),
29723
+ tilt: number().min(-1).max(1).optional(),
29724
+ speed: number().min(0).max(1).optional()
29725
+ });
29726
+ /**
29727
+ * The enumerated discrete actions a navigation-capable robot can perform via
29728
+ * `runAction`. This is the CLOSED vocabulary; a given device advertises the
29729
+ * subset it supports through `listActions`. Sounds are NOT here — they go through
29730
+ * `playSound` (see the `sound` dictionary entries).
29731
+ */
29732
+ var NavigationActionIdSchema = _enum([
29733
+ "goHome",
29734
+ "locate",
29735
+ "spotClean",
29736
+ "findPet",
29737
+ "personFollow",
29738
+ "stop",
29739
+ "startClean",
29740
+ "pauseClean",
29741
+ "dockWash",
29742
+ "autoEmpty",
29743
+ "flashOn",
29744
+ "flashOff"
29745
+ ]);
29746
+ /** Whether a dictionary entry is a `runAction` action or a `playSound` sound. */
29747
+ var NavigationEntryKindSchema = _enum(["action", "sound"]);
29748
+ /**
29749
+ * One entry in the navigation action dictionary — the DATA-DRIVEN unit both the
29750
+ * native panel and the PTZ mimic render as a button.
29751
+ *
29752
+ * - `id` — stable id. For `kind:'action'` it is a {@link NavigationActionId}
29753
+ * (pass to `runAction`); for `kind:'sound'` it is a namespaced id
29754
+ * (`sound:meow`) whose `soundId` is passed to `playSound`.
29755
+ * - `icon` — icon HINT (lucide-style name; the UI maps it to its own set).
29756
+ * - `label` — operator-facing English label.
29757
+ * - `soundId` — wire sound id, present only on `kind:'sound'` entries.
29758
+ * - `enabled` — per-device FEATURE FLAG. `listActions` reports it so the UI /
29759
+ * PTZ render ONLY enabled entries. Data-driven: the provider
29760
+ * flips it from config, never by editing code.
29761
+ */
29762
+ var NavigationActionEntrySchema = object({
29763
+ id: string(),
29764
+ kind: NavigationEntryKindSchema,
29765
+ label: string(),
29766
+ icon: string(),
29767
+ /** Present only on `kind:'sound'` entries — the id to pass to `playSound`. */
29768
+ soundId: number().int().optional(),
29769
+ /** Per-device feature flag — render this entry only when true. */
29770
+ enabled: boolean()
29771
+ });
29772
+ /** Coordinates for `goToPoint` — a point on the robot's live map. */
29773
+ var NavigationPointSchema = object({
29774
+ x: number(),
29775
+ y: number()
29776
+ });
29777
+ /**
29778
+ * Per-device FEATURE-FLAG report for the general (non-dictionary) primitives.
29779
+ * The cap reports which are enabled so the UI / PTZ render only the controls
29780
+ * that are turned on for THIS device. Data-driven: the provider derives these
29781
+ * from config + probe, never hardcoded in the UI. The per-DICTIONARY-entry flags
29782
+ * live on {@link NavigationActionEntrySchema.enabled}; these gate the primitives
29783
+ * that are not dictionary entries.
29784
+ *
29785
+ * - `move` / `stop` — the momentary drive joystick.
29786
+ * - `goToPoint` — send-to-map-coordinate. Ships OFF on Dreame until the
29787
+ * map-coordinate plumbing is wired.
29788
+ * - `runAction` — the discrete action buttons (dictionary `kind:'action'`).
29789
+ * - `playSound` — the sound buttons (dictionary `kind:'sound'`).
29790
+ * - `light` — the on/off fill-light toggle (works anytime).
29791
+ * - `lightMode` — the auto/manual selector + manual level slider (a
29792
+ * camera-service control; needs an active stream).
29793
+ */
29794
+ var NavigationFeaturesSchema = object({
29795
+ move: boolean(),
29796
+ stop: boolean(),
29797
+ goToPoint: boolean(),
29798
+ runAction: boolean(),
29799
+ playSound: boolean(),
29800
+ light: boolean(),
29801
+ lightMode: boolean()
29802
+ });
29803
+ /** Light mode: `auto` lets the camera choose brightness; `manual` uses `level`. */
29804
+ var NavigationLightModeSchema = _enum(["auto", "manual"]);
29805
+ /**
29806
+ * Live navigation state so the UI can reflect what the robot is doing:
29807
+ * - `mode` — coarse activity (idle / cleaning / following / …).
29808
+ * - `following` — person/pet follow is currently armed.
29809
+ * - `flash` — the on-camera fill light is on.
29810
+ * - `lightMode` — auto vs manual fill-light mode.
29811
+ * - `lightLevel` — manual fill-light level (40..100); meaningful when
29812
+ * `lightMode === 'manual'`.
29813
+ */
29814
+ var NavigationStatusSchema = object({
29815
+ mode: _enum([
29816
+ "idle",
29817
+ "cleaning",
29818
+ "spot",
29819
+ "following",
29820
+ "goto",
29821
+ "returning",
29822
+ "paused",
29823
+ "unknown"
29824
+ ]),
29825
+ following: boolean(),
29826
+ flash: boolean(),
29827
+ lightMode: NavigationLightModeSchema,
29828
+ lightLevel: number().min(40).max(100),
29829
+ /** Ms epoch when the slice was last updated. */
29830
+ lastChangedAt: number()
29831
+ });
29832
+ NavigationStatusSchema.extend({ lastFetchedAt: number() });
29833
+ DeviceType.Camera, method(NavigationMoveCommandSchema.extend({ deviceId: number() }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), _void(), { kind: "mutation" }), method(NavigationPointSchema.extend({ deviceId: number() }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), array(NavigationActionEntrySchema)), method(object({
29834
+ deviceId: number(),
29835
+ actionId: NavigationActionIdSchema
29836
+ }), _void(), { kind: "mutation" }), method(object({
29837
+ deviceId: number(),
29838
+ soundId: number().int()
29839
+ }), _void(), { kind: "mutation" }), method(object({
29840
+ deviceId: number(),
29841
+ on: boolean()
29842
+ }), _void(), { kind: "mutation" }), method(object({
29843
+ deviceId: number(),
29844
+ mode: NavigationLightModeSchema,
29845
+ level: number().min(40).max(100).optional()
29846
+ }), _void(), { kind: "mutation" }), method(object({
29847
+ deviceId: number(),
29848
+ level: number().min(40).max(100)
29849
+ }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), NavigationFeaturesSchema), object({
29850
+ deviceId: number(),
29851
+ status: NavigationStatusSchema
29852
+ });
29650
29853
  DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
29651
29854
  kind: "mutation",
29652
29855
  auth: "admin"
@@ -35095,6 +35298,66 @@ Object.freeze({
35095
35298
  addonId: null,
35096
35299
  access: "create"
35097
35300
  },
35301
+ "navigation.getFeatures": {
35302
+ capName: "navigation",
35303
+ capScope: "device",
35304
+ addonId: null,
35305
+ access: "view"
35306
+ },
35307
+ "navigation.goToPoint": {
35308
+ capName: "navigation",
35309
+ capScope: "device",
35310
+ addonId: null,
35311
+ access: "create"
35312
+ },
35313
+ "navigation.listActions": {
35314
+ capName: "navigation",
35315
+ capScope: "device",
35316
+ addonId: null,
35317
+ access: "view"
35318
+ },
35319
+ "navigation.move": {
35320
+ capName: "navigation",
35321
+ capScope: "device",
35322
+ addonId: null,
35323
+ access: "create"
35324
+ },
35325
+ "navigation.playSound": {
35326
+ capName: "navigation",
35327
+ capScope: "device",
35328
+ addonId: null,
35329
+ access: "create"
35330
+ },
35331
+ "navigation.runAction": {
35332
+ capName: "navigation",
35333
+ capScope: "device",
35334
+ addonId: null,
35335
+ access: "create"
35336
+ },
35337
+ "navigation.setLightLevel": {
35338
+ capName: "navigation",
35339
+ capScope: "device",
35340
+ addonId: null,
35341
+ access: "create"
35342
+ },
35343
+ "navigation.setLightMode": {
35344
+ capName: "navigation",
35345
+ capScope: "device",
35346
+ addonId: null,
35347
+ access: "create"
35348
+ },
35349
+ "navigation.setLightOn": {
35350
+ capName: "navigation",
35351
+ capScope: "device",
35352
+ addonId: null,
35353
+ access: "create"
35354
+ },
35355
+ "navigation.stop": {
35356
+ capName: "navigation",
35357
+ capScope: "device",
35358
+ addonId: null,
35359
+ access: "create"
35360
+ },
35098
35361
  "networkAccess.getEndpoint": {
35099
35362
  capName: "network-access",
35100
35363
  capScope: "system",
@@ -39190,6 +39453,56 @@ Object.freeze({
39190
39453
  form: "single",
39191
39454
  optional: false
39192
39455
  }],
39456
+ "navigation.getFeatures": [{
39457
+ name: "deviceId",
39458
+ form: "single",
39459
+ optional: false
39460
+ }],
39461
+ "navigation.goToPoint": [{
39462
+ name: "deviceId",
39463
+ form: "single",
39464
+ optional: false
39465
+ }],
39466
+ "navigation.listActions": [{
39467
+ name: "deviceId",
39468
+ form: "single",
39469
+ optional: false
39470
+ }],
39471
+ "navigation.move": [{
39472
+ name: "deviceId",
39473
+ form: "single",
39474
+ optional: false
39475
+ }],
39476
+ "navigation.playSound": [{
39477
+ name: "deviceId",
39478
+ form: "single",
39479
+ optional: false
39480
+ }],
39481
+ "navigation.runAction": [{
39482
+ name: "deviceId",
39483
+ form: "single",
39484
+ optional: false
39485
+ }],
39486
+ "navigation.setLightLevel": [{
39487
+ name: "deviceId",
39488
+ form: "single",
39489
+ optional: false
39490
+ }],
39491
+ "navigation.setLightMode": [{
39492
+ name: "deviceId",
39493
+ form: "single",
39494
+ optional: false
39495
+ }],
39496
+ "navigation.setLightOn": [{
39497
+ name: "deviceId",
39498
+ form: "single",
39499
+ optional: false
39500
+ }],
39501
+ "navigation.stop": [{
39502
+ name: "deviceId",
39503
+ form: "single",
39504
+ optional: false
39505
+ }],
39193
39506
  "networkQuality.getDeviceStats": [{
39194
39507
  name: "deviceId",
39195
39508
  form: "single",
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-C31OZkZP.js");
1
+ const require_dist = require("./dist-CXO_Fmx6.js");
2
2
  let node_path = require("node:path");
3
3
  node_path = require_dist.__toESM(node_path);
4
4
  let node_url = require("node:url");
@@ -1,4 +1,4 @@
1
- import { M as audioKindId, Z as hfModelUrl, a as COCO_80_LABELS, o as COCO_TO_MACRO, r as AUDIO_MACRO_LABELS } from "./dist-CZkzc0WB.mjs";
1
+ import { M as audioKindId, Z as hfModelUrl, a as COCO_80_LABELS, o as COCO_TO_MACRO, r as AUDIO_MACRO_LABELS } from "./dist-B8J7wrtY.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  //#region src/detection-pipeline/registry/model-catalogs.ts
4
4
  var HF_REPO = "camstack/camstack-models";
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-C31OZkZP.js");
1
+ const require_dist = require("./dist-CXO_Fmx6.js");
2
2
  let node_crypto = require("node:crypto");
3
3
  //#region src/detection-pipeline/registry/model-catalogs.ts
4
4
  var HF_REPO = "camstack/camstack-models";
@@ -2,8 +2,8 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-C31OZkZP.js");
6
- const require_lazy_sharp = require("../lazy-sharp-DhHuLuQf.js");
5
+ const require_dist = require("../dist-CXO_Fmx6.js");
6
+ const require_lazy_sharp = require("../lazy-sharp-o-aNNXuz.js");
7
7
  let node_fs = require("node:fs");
8
8
  let node_path = require("node:path");
9
9
  //#region src/motion-wasm/wasm-motion-detector.ts
@@ -1,4 +1,4 @@
1
- import { It as hydrateSchema, Pt as DeviceType, Y as evaluateZoneRules, it as motionDetectionCapability, jt as BaseAddon } from "../dist-CZkzc0WB.mjs";
1
+ import { It as hydrateSchema, Pt as DeviceType, Y as evaluateZoneRules, it as motionDetectionCapability, jt as BaseAddon } from "../dist-B8J7wrtY.mjs";
2
2
  import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
3
3
  import { readFileSync } from "node:fs";
4
4
  import { join } from "node:path";
@@ -1,4 +1,4 @@
1
- import { Dt as buildFfmpegArgs, Et as Fmp4BoxSplitter, kt as isSoftwareDecode, wt as errMsg } from "./dist-CZkzc0WB.mjs";
1
+ import { Dt as buildFfmpegArgs, Et as Fmp4BoxSplitter, kt as isSoftwareDecode, wt as errMsg } from "./dist-B8J7wrtY.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import "node:fs";
4
4
  import "node:path";
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-C31OZkZP.js");
1
+ const require_dist = require("./dist-CXO_Fmx6.js");
2
2
  let node_crypto = require("node:crypto");
3
3
  let node_fs = require("node:fs");
4
4
  node_fs = require_dist.__toESM(node_fs, 1);
@@ -2,12 +2,12 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-C31OZkZP.js");
6
- const require_node = require("../node-CIpenwbm.js");
7
- const require_local_frame_registry = require("../local-frame-registry-CkIaPLcW.js");
8
- const require_worker_protocol = require("../worker-protocol-BSgTKhW7.js");
5
+ const require_dist = require("../dist-CXO_Fmx6.js");
6
+ const require_node = require("../node-DF98pVP7.js");
7
+ const require_local_frame_registry = require("../local-frame-registry-P7tSfvaY.js");
8
+ const require_worker_protocol = require("../worker-protocol-BJzhw3t0.js");
9
9
  const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
10
- const require_lazy_sharp = require("../lazy-sharp-DhHuLuQf.js");
10
+ const require_lazy_sharp = require("../lazy-sharp-o-aNNXuz.js");
11
11
  const require_restream_intent = require("../restream-intent-Cv9x3jmu.js");
12
12
  const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-DaUBcb13.js");
13
13
  const require_remote_restream = require("../remote-restream-CO36Sr30.js");
@@ -1,7 +1,7 @@
1
- import { B as defineCustomActions, Bt as nodePin, Ft as createEvent, Gt as _enum, H as deriveDetailCropRect, Kt as array, L as customAction, Qt as object, X as failureContributionCapability, Xt as literal, Yt as lazy, Zt as number, _ as FailureCounters, en as string, et as loadContributionCapability, ft as pipelineRunnerCapability, jt as BaseAddon, lt as pickDetailCropConvention, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, p as DEFAULT_NATIVE_LEASE_SETTINGS, qt as boolean, u as DEFAULT_DETAIL_CROP_CONVENTION, ut as pickNativeLeaseOverride, wt as errMsg } from "../dist-CZkzc0WB.mjs";
2
- import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-kSXNMrbg.mjs";
3
- import { c as getStepDefinition, n as resolveFrameViewGeometry, t as localFrameRegistry } from "../local-frame-registry-B8_L3v0O.mjs";
4
- import { a as nativeLeaseSettingEnv, t as isWorkerReply } from "../worker-protocol-Bcy8Ti5P.mjs";
1
+ import { B as defineCustomActions, Bt as nodePin, Ft as createEvent, Gt as _enum, H as deriveDetailCropRect, Kt as array, L as customAction, Qt as object, X as failureContributionCapability, Xt as literal, Yt as lazy, Zt as number, _ as FailureCounters, en as string, et as loadContributionCapability, ft as pipelineRunnerCapability, jt as BaseAddon, lt as pickDetailCropConvention, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, p as DEFAULT_NATIVE_LEASE_SETTINGS, qt as boolean, u as DEFAULT_DETAIL_CROP_CONVENTION, ut as pickNativeLeaseOverride, wt as errMsg } from "../dist-B8J7wrtY.mjs";
2
+ import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-BSbB0or0.mjs";
3
+ import { c as getStepDefinition, n as resolveFrameViewGeometry, t as localFrameRegistry } from "../local-frame-registry-BDeDpYQk.mjs";
4
+ import { a as nativeLeaseSettingEnv, t as isWorkerReply } from "../worker-protocol-WiXU2VuW.mjs";
5
5
  import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
6
6
  import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
7
7
  import { n as withDetectionIntent } from "../restream-intent-B4BXZra7.mjs";
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-C31OZkZP.js");
1
+ const require_dist = require("./dist-CXO_Fmx6.js");
2
2
  let node_fs = require("node:fs");
3
3
  node_fs = require_dist.__toESM(node_fs);
4
4
  let node_child_process = require("node:child_process");
@@ -1,4 +1,4 @@
1
- import { ot as parseProcStatus } from "./dist-CZkzc0WB.mjs";
1
+ import { ot as parseProcStatus } from "./dist-B8J7wrtY.mjs";
2
2
  import * as fs from "node:fs";
3
3
  import { execFile } from "node:child_process";
4
4
  //#region src/shared/node-topology-platform.ts
@@ -2,8 +2,8 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-C31OZkZP.js");
6
- const require_node = require("../node-CIpenwbm.js");
5
+ const require_dist = require("../dist-CXO_Fmx6.js");
6
+ const require_node = require("../node-DF98pVP7.js");
7
7
  const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
8
8
  const require_restream_intent = require("../restream-intent-Cv9x3jmu.js");
9
9
  const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-DaUBcb13.js");
@@ -1,5 +1,5 @@
1
- import { $ as isFirstLevelMacroClass, $t as record, B as defineCustomActions, Bt as nodePin, E as RecordingConfigSchema, Gt as _enum, It as hydrateSchema, J as evaluateSensorEdge, Kt as array, L as customAction, N as batteryCapability, Nt as DeviceFeature, Pt as DeviceType, Qt as object, T as RECORDING_EXPORT_MAX_READ_BYTES, U as deriveRecordingMode, Ut as selectAssignedProfileSlots, V as deriveBatteryPresence, Wt as sleep$1, Zt as number, bt as storageEvictableCapability, d as DEFAULT_EVENTS_BAND_BUFFER_SEC, en as string, et as loadContributionCapability, g as ExportRecordSchema, i as BatteryStatusSchema, jt as BaseAddon, mt as recordingExportCapability, nn as EventCategory, pt as recordingCapability, qt as boolean, vt as resolveRecordingProfiles, wt as errMsg, x as OpsLogEntrySchema } from "../dist-CZkzc0WB.mjs";
2
- import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-kSXNMrbg.mjs";
1
+ import { $ as isFirstLevelMacroClass, $t as record, B as defineCustomActions, Bt as nodePin, E as RecordingConfigSchema, Gt as _enum, It as hydrateSchema, J as evaluateSensorEdge, Kt as array, L as customAction, N as batteryCapability, Nt as DeviceFeature, Pt as DeviceType, Qt as object, T as RECORDING_EXPORT_MAX_READ_BYTES, U as deriveRecordingMode, Ut as selectAssignedProfileSlots, V as deriveBatteryPresence, Wt as sleep$1, Zt as number, bt as storageEvictableCapability, d as DEFAULT_EVENTS_BAND_BUFFER_SEC, en as string, et as loadContributionCapability, g as ExportRecordSchema, i as BatteryStatusSchema, jt as BaseAddon, mt as recordingExportCapability, nn as EventCategory, pt as recordingCapability, qt as boolean, vt as resolveRecordingProfiles, wt as errMsg, x as OpsLogEntrySchema } from "../dist-B8J7wrtY.mjs";
2
+ import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-BSbB0or0.mjs";
3
3
  import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
4
4
  import { r as withRecordingIntent } from "../restream-intent-B4BXZra7.mjs";
5
5
  import { n as startEventLoopStallMonitor } from "../event-loop-stall-monitor-DXLNBMkY.mjs";
@@ -1,5 +1,5 @@
1
1
  import { r as __toESM, t as __commonJSMin } from "./chunk-DnnnRqeS.mjs";
2
- import { wt as errMsg } from "./dist-CZkzc0WB.mjs";
2
+ import { wt as errMsg } from "./dist-B8J7wrtY.mjs";
3
3
  import { spawn } from "node:child_process";
4
4
  //#region ../../node_modules/mp4box/dist/mp4box.all.js
5
5
  var require_mp4box_all = /* @__PURE__ */ __commonJSMin(((exports) => {
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-C31OZkZP.js");
1
+ const require_dist = require("./dist-CXO_Fmx6.js");
2
2
  let node_child_process = require("node:child_process");
3
3
  //#region ../../node_modules/mp4box/dist/mp4box.all.js
4
4
  var require_mp4box_all = /* @__PURE__ */ require_dist.__commonJSMin(((exports) => {
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_worker_protocol = require("../worker-protocol-BSgTKhW7.js");
3
- const require_lazy_sharp = require("../lazy-sharp-DhHuLuQf.js");
2
+ const require_worker_protocol = require("../worker-protocol-BJzhw3t0.js");
3
+ const require_lazy_sharp = require("../lazy-sharp-o-aNNXuz.js");
4
4
  //#region src/session-decode/color-conversion.ts
5
5
  /**
6
6
  * Explicit YUV→RGB colorspace/range resolution for the session-decode worker.
@@ -289,6 +289,10 @@ var FrameSlot = class {
289
289
  markPendingPull() {
290
290
  this.pendingPull = true;
291
291
  }
292
+ /** The id of the frame the last `pull` delivered (the reserved one), or `null`. */
293
+ get reservedFrameId() {
294
+ return this.reserved?.frameId ?? null;
295
+ }
292
296
  /** The reserved frame for `frameId`, or `null` if unknown/stale. */
293
297
  toBuffer(frameId) {
294
298
  if (!this.reserved || this.reserved.frameId !== frameId) return null;
@@ -446,6 +450,21 @@ var LeaseAdmissionLedger = class {
446
450
  get markedSize() {
447
451
  return this.marked.size;
448
452
  }
453
+ /**
454
+ * The runner is DONE with `frameId` before the worker ever leased it — its
455
+ * result came back (or it was dropped) before the next pull superseded it.
456
+ * Withdrawing the mark makes the supersede decline the frame, so it is
457
+ * freed at once instead of leased after its own release and pinned until
458
+ * the bound evicts it. Measured 2026-09-06: on every busy worker
459
+ * `leaseReleaseMisses ≈ leaseAdmitted` and `holdOverflow ≈ admitted − 8`.
460
+ */
461
+ unmark(frameId) {
462
+ this.marked.delete(frameId);
463
+ }
464
+ /** Whether `frameId` is inside the remembered marked window. */
465
+ isMarked(frameId) {
466
+ return this.marked.has(frameId);
467
+ }
449
468
  /** The runner admitted `frameId` to its detection queue. */
450
469
  mark(frameId) {
451
470
  this.markedTotal++;
@@ -617,7 +636,9 @@ var NativeLeaseStore = class {
617
636
  * has taken what it wanted. Idempotent, and the ORDINARY exit.
618
637
  */
619
638
  release(frameId) {
639
+ const held = this.entries.has(frameId);
620
640
  this.drop(frameId);
641
+ return held;
621
642
  }
622
643
  /** Free + drop every held frame. Idempotent (re-dial + teardown call it). */
623
644
  clear() {
@@ -635,6 +656,20 @@ var NativeLeaseStore = class {
635
656
  }
636
657
  };
637
658
  //#endregion
659
+ //#region src/session-decode/to-buffer-miss.ts
660
+ /** Which rung lost the frame, from what the worker knows at the miss. */
661
+ function toBufferMissRung(facts) {
662
+ if (facts.reservedFrameId !== null && facts.frameId > facts.reservedFrameId) return "not-yet-delivered";
663
+ if (!facts.marked) return "never-leased";
664
+ if (facts.leaseFrames >= facts.holdFrames) return "hold-full";
665
+ return "released";
666
+ }
667
+ /** The error line the runner sees: the rung first, the numbers after it. */
668
+ function describeToBufferMiss(facts) {
669
+ const rung = toBufferMissRung(facts);
670
+ return `decode-worker-child: toBuffer miss for frameId ${facts.frameId} — ${rung} {reserved=${facts.reservedFrameId ?? "none"} marked=${facts.marked} leaseFrames=${facts.leaseFrames}/${facts.holdFrames} holdOverflow=${facts.holdOverflow}${facts.unmarkedBy !== void 0 ? ` unmarkedBy=${facts.unmarkedBy}` : ""}}`;
671
+ }
672
+ //#endregion
638
673
  //#region src/session-decode/native-tile-geometry.ts
639
674
  /**
640
675
  * Pure geometry for the **native subject tile** — the compressed, subject-sized
@@ -1429,6 +1464,8 @@ var NATIVE_TILE_JPEG_QUALITY = 90;
1429
1464
  * eager capture) — it does not disable retention. Default 15000.
1430
1465
  */
1431
1466
  var NATIVE_LEASE_ACTIVITY_WINDOW_MS = NATIVE_LEASE_KNOBS.values.activityMs;
1467
+ /** How many early-withdrawn frame ids the worker remembers for the miss line. */
1468
+ var UNMARKED_MEMORY = 256;
1432
1469
  /**
1433
1470
  * How long lease capture stays off after the download path proves broken, and
1434
1471
  * the ceiling that backoff climbs to. Doubling from the base, so the Nth
@@ -1859,6 +1896,13 @@ var DecodeWorkerChild = class {
1859
1896
  colorDebug = process.env["CAMSTACK_DECODE_COLOR_DEBUG"] === "1";
1860
1897
  /** Scrypted-style throughput counters (plain integers, no per-frame allocation). */
1861
1898
  framesDecoded = 0;
1899
+ /** Releases that found a held frame / that found nothing to release. */
1900
+ leaseReleased = 0;
1901
+ leaseReleaseMisses = 0;
1902
+ /** Releases that beat the supersede and withdrew the mark instead. */
1903
+ leaseReleasedEarly = 0;
1904
+ /** Frame ids withdrawn early → by whom (insertion-ordered, bounded). */
1905
+ unmarkedBy = /* @__PURE__ */ new Map();
1862
1906
  /** Child-side skips only (HW-guard drops + probe/degrade frees); slot drops add {@link FrameSlot.droppedCount}. */
1863
1907
  framesSkipped = 0;
1864
1908
  /** Frames actually handed to the parent as a `frame` reply. */
@@ -1943,7 +1987,7 @@ var DecodeWorkerChild = class {
1943
1987
  this.handleCutTiles(message.frameId, message.bboxes);
1944
1988
  return;
1945
1989
  case "releaseNativeLease":
1946
- this.leaseStore.release(message.frameId);
1990
+ this.noteLeaseRelease(message.frameId, this.leaseStore.release(message.frameId), "release");
1947
1991
  return;
1948
1992
  case "markInferred":
1949
1993
  this.admission.mark(message.frameId);
@@ -2007,7 +2051,7 @@ var DecodeWorkerChild = class {
2007
2051
  const skipped = this.framesSkipped + this.frames.droppedCount;
2008
2052
  const rssMb = Math.round(process.memoryUsage().rss / 1048576);
2009
2053
  const ageS = Math.round((now - this.startedAt) / 1e3);
2010
- this.emitStderr(`session-decode metrics {framesDecoded:${this.framesDecoded}, framesSkipped:${skipped}, deliveredFps:${deliveredFps}, nativeCropHits:${this.nativeCropHits}, nativeCropMisses:${this.nativeCropMisses}, leaseOffered:${this.admission.offered}, leaseAdmitted:${this.admission.admitted}, leaseMarks:${this.admission.marks}, leaseUnmarkedCrops:${this.admission.unmarkedCrops}, leaseAdmission:${NATIVE_LEASE_KNOBS.values.admission}, leaseMb:${Math.round(this.leaseStore.totalBytes / 1048576)}, leaseFrames:${this.leaseStore.size}, holdOverflow:${this.leaseStore.overflowCount}, tilesCut:${this.tilesCut}, tileHits:${this.tileHits}, tileMisses:${this.tileMisses}, tileCutFailures:${this.tileCutFailures}, tileMb:${Math.round(this.tileStore.totalBytes / 1048576)}, tileFrames:${this.tileStore.frameCount}, scenesCut:${this.scenesCut}, sceneHits:${this.sceneHits}, sceneRefused:${this.sceneRefused}, sceneUnclassified:${this.sceneUnclassified}, sceneEvicted:${this.sceneStore.evictedCount}, sceneMb:${Math.round(this.sceneStore.totalBytes / 1048576)}, sceneFrames:${this.sceneStore.frameCount}, rssMb:${rssMb}, ageS:${ageS}}${final ? " (final)" : ""}\n`);
2054
+ this.emitStderr(`session-decode metrics {framesDecoded:${this.framesDecoded}, framesSkipped:${skipped}, deliveredFps:${deliveredFps}, nativeCropHits:${this.nativeCropHits}, nativeCropMisses:${this.nativeCropMisses}, leaseOffered:${this.admission.offered}, leaseAdmitted:${this.admission.admitted}, leaseMarks:${this.admission.marks}, leaseUnmarkedCrops:${this.admission.unmarkedCrops}, leaseAdmission:${NATIVE_LEASE_KNOBS.values.admission}, leaseMb:${Math.round(this.leaseStore.totalBytes / 1048576)}, leaseFrames:${this.leaseStore.size}, holdOverflow:${this.leaseStore.overflowCount}, leaseReleased:${this.leaseReleased}, leaseReleaseMisses:${this.leaseReleaseMisses}, leaseReleasedEarly:${this.leaseReleasedEarly}, tilesCut:${this.tilesCut}, tileHits:${this.tileHits}, tileMisses:${this.tileMisses}, tileCutFailures:${this.tileCutFailures}, tileMb:${Math.round(this.tileStore.totalBytes / 1048576)}, tileFrames:${this.tileStore.frameCount}, scenesCut:${this.scenesCut}, sceneHits:${this.sceneHits}, sceneRefused:${this.sceneRefused}, sceneUnclassified:${this.sceneUnclassified}, sceneEvicted:${this.sceneStore.evictedCount}, sceneMb:${Math.round(this.sceneStore.totalBytes / 1048576)}, sceneFrames:${this.sceneStore.frameCount}, rssMb:${rssMb}, ageS:${ageS}}${final ? " (final)" : ""}\n`);
2011
2055
  this.lastMetricsAt = now;
2012
2056
  this.lastDeliveredSnapshot = this.framesDelivered;
2013
2057
  if (!this.warnedLarge && rssMb >= WORKER_RSS_WARN_MB) {
@@ -2045,10 +2089,39 @@ var DecodeWorkerChild = class {
2045
2089
  this.pendingPull = true;
2046
2090
  this.frames.markPendingPull();
2047
2091
  }
2092
+ /**
2093
+ * Account for a release. A release that found no lease is the runner being
2094
+ * done BEFORE the supersede leased the frame: withdraw its mark so the
2095
+ * supersede declines it (`LeaseAdmissionLedger.unmark`), and count it.
2096
+ */
2097
+ noteLeaseRelease(frameId, held, by) {
2098
+ if (held) {
2099
+ this.leaseReleased += 1;
2100
+ return;
2101
+ }
2102
+ this.leaseReleaseMisses += 1;
2103
+ if (this.admission.isMarked(frameId)) {
2104
+ this.admission.unmark(frameId);
2105
+ this.leaseReleasedEarly += 1;
2106
+ this.unmarkedBy.set(frameId, by);
2107
+ if (this.unmarkedBy.size > UNMARKED_MEMORY) {
2108
+ const oldest = this.unmarkedBy.keys().next().value;
2109
+ if (oldest !== void 0) this.unmarkedBy.delete(oldest);
2110
+ }
2111
+ }
2112
+ }
2048
2113
  async handleToBuffer(frameId, opts) {
2049
2114
  const frame = this.leaseStore.get(frameId)?.frame ?? this.frames.toBuffer(frameId);
2050
2115
  if (!frame) {
2051
- this.sendError(`decode-worker-child: toBuffer for unknown or stale frameId ${frameId}`, frameId);
2116
+ this.sendError(describeToBufferMiss({
2117
+ frameId,
2118
+ reservedFrameId: this.frames.reservedFrameId,
2119
+ marked: this.admission.isMarked(frameId),
2120
+ leaseFrames: this.leaseStore.size,
2121
+ holdFrames: NATIVE_LEASE_HOLD_FRAMES,
2122
+ holdOverflow: this.leaseStore.overflowCount,
2123
+ ...this.unmarkedBy.has(frameId) ? { unmarkedBy: this.unmarkedBy.get(frameId) } : {}
2124
+ }), frameId);
2052
2125
  return;
2053
2126
  }
2054
2127
  try {
@@ -2282,7 +2355,7 @@ var DecodeWorkerChild = class {
2282
2355
  this.sceneStore.put(frameId, [scene]);
2283
2356
  }
2284
2357
  } finally {
2285
- this.leaseStore.release(frameId);
2358
+ this.noteLeaseRelease(frameId, this.leaseStore.release(frameId), "cut");
2286
2359
  }
2287
2360
  }
2288
2361
  /**