@camstack/types 1.2.42 → 1.2.44

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 (48) hide show
  1. package/dist/addon.js +8 -2
  2. package/dist/addon.mjs +8 -2
  3. package/dist/cap-call-context.d.ts +26 -0
  4. package/dist/capabilities/index.d.ts +8 -5
  5. package/dist/capabilities/osd-manager.cap.d.ts +900 -0
  6. package/dist/capabilities/pipeline-analytics.cap.d.ts +171 -4
  7. package/dist/capabilities/pipeline-orchestrator.cap.d.ts +36 -0
  8. package/dist/capabilities/privacy-mask.cap.d.ts +69 -9
  9. package/dist/capabilities/recording.cap.d.ts +27 -0
  10. package/dist/capabilities/schemas/streaming-shared.d.ts +2 -0
  11. package/dist/capabilities/server-management.cap.d.ts +3 -3
  12. package/dist/capabilities/snapshot.cap.d.ts +1 -1
  13. package/dist/capabilities/stream-broker.cap.d.ts +36 -0
  14. package/dist/capabilities/stream-params.cap.d.ts +8 -4
  15. package/dist/device/device-profile.d.ts +12 -4
  16. package/dist/device/system-mirror.d.ts +11 -0
  17. package/dist/ffmpeg/encode-defaults.d.ts +18 -0
  18. package/dist/ffmpeg/fmp4-box-splitter.d.ts +113 -0
  19. package/dist/ffmpeg/fmp4-fragment-child.d.ts +85 -0
  20. package/dist/ffmpeg/fmp4-fragment-plane.d.ts +142 -0
  21. package/dist/ffmpeg/invocation.d.ts +102 -2
  22. package/dist/ffmpeg/sharing-key.d.ts +54 -2
  23. package/dist/fmp4-box-splitter-B53u9-Nu.mjs +615 -0
  24. package/dist/fmp4-box-splitter-BkWH7O3L.js +686 -0
  25. package/dist/generated/addon-api.d.ts +117 -0
  26. package/dist/generated/cap-input-defaults.d.ts +1 -1
  27. package/dist/generated/capability-router-map.d.ts +5 -2
  28. package/dist/generated/device-proxy.d.ts +4 -2
  29. package/dist/generated/method-access-map.d.ts +1 -1
  30. package/dist/generated/system-proxy.d.ts +2 -0
  31. package/dist/index.d.ts +4 -0
  32. package/dist/index.js +1264 -394
  33. package/dist/index.mjs +1217 -385
  34. package/dist/interfaces/camera-switches.d.ts +211 -5
  35. package/dist/interfaces/inference-engine.d.ts +24 -3
  36. package/dist/interfaces/stream-broker.d.ts +18 -0
  37. package/dist/node.d.ts +4 -0
  38. package/dist/node.js +509 -3
  39. package/dist/node.mjs +507 -3
  40. package/dist/notification/schedule.d.ts +20 -0
  41. package/dist/pipeline/native-lease.d.ts +150 -0
  42. package/dist/{sleep-BmNKsY7v.mjs → sleep-cC4Fuup8.mjs} +59 -3
  43. package/dist/{sleep-Cvi1JxZp.js → sleep-eiC10_cX.js} +64 -2
  44. package/dist/types/pipeline-step.d.ts +1 -1
  45. package/dist/utils/addon-id.d.ts +30 -0
  46. package/package.json +1 -1
  47. package/dist/canonical-hash-7nfBbEqR.mjs +0 -35
  48. package/dist/canonical-hash-BcZHRHIx.js +0 -40
@@ -1445,7 +1445,20 @@ var BrokerStatsSchema = z.object({
1445
1445
  sampleRate: z.number(),
1446
1446
  channels: z.number(),
1447
1447
  supported: z.boolean()
1448
- }).nullable().optional()
1448
+ }).nullable().optional(),
1449
+ /**
1450
+ * BROKER-SIDE AUDIO MUTE (D83). `true` = this broker is deliberately
1451
+ * distributing none of the device's audio, on live or recording.
1452
+ *
1453
+ * Present so a silent camera can be told apart from a broken one on the
1454
+ * stream panel itself, without cross-referencing the switch group: a
1455
+ * broker holding an `audio` track descriptor while `audioMuted` is true is
1456
+ * working exactly as asked. `audioMutedDropped` counts the audio units
1457
+ * thrown away since the current dial — it is how you confirm from stats
1458
+ * alone that the mute is on the packet path and not merely persisted.
1459
+ */
1460
+ audioMuted: z.boolean().optional(),
1461
+ audioMutedDropped: z.number().optional()
1449
1462
  });
1450
1463
  /**
1451
1464
  * Exporter-facing "profile restream" entry. Returned by
@@ -1934,9 +1947,38 @@ var CAP_NODE_PIN_CONTEXT_KEY = "__camstackNodePin";
1934
1947
  /**
1935
1948
  * Build the tRPC request options that pin a single capability call to `nodeId`.
1936
1949
  * Pass as the second argument to `.query(input, …)` / `.mutate(input, …)`.
1950
+ *
1951
+ * ## The id is normalised here, and it has to be
1952
+ *
1953
+ * A forked addon reads its own node from `ctx.kernel.localNodeId`, and inside a
1954
+ * worker that value is a RUNNER id — `hub/export-hap`, not `hub`. Routing
1955
+ * compares a pin against real node ids, so such a pin matches nothing and the
1956
+ * call fails with `no provider registered for cap "…"`. The local-first
1957
+ * resolver already guarded against this (`localNodeId.split('/')[0]`), which
1958
+ * made the hazard invisible: unpinned calls worked, and only an explicit pin —
1959
+ * the thing you reach for when you specifically need THIS node — silently
1960
+ * addressed a node that does not exist.
1961
+ *
1962
+ * Cost of it being missing: `addon-export-hap` pinned `decoder.getInfo` to its
1963
+ * own node to read the host's hardware-decode backend. It never once answered,
1964
+ * so every HomeKit egress transcode decoded in SOFTWARE — including 4K H.265 —
1965
+ * while D67's whole premise was that the decoder addon is the authority on
1966
+ * hardware. The warn said `decoding in SOFTWARE` and read as "this node has no
1967
+ * hardware", which was false.
1968
+ *
1969
+ * Normalising in the ONE constructor fixes every caller at once, which is why
1970
+ * it is here and not at the call sites.
1937
1971
  */
1938
1972
  function nodePin(nodeId) {
1939
- return { context: { [CAP_NODE_PIN_CONTEXT_KEY]: nodeId } };
1973
+ return { context: { [CAP_NODE_PIN_CONTEXT_KEY]: toNodeId(nodeId) } };
1974
+ }
1975
+ /**
1976
+ * A runner id is `<nodeId>/<addonId>`; a node id has no slash. Taking the head
1977
+ * is idempotent, so passing an already-clean id costs nothing.
1978
+ */
1979
+ function toNodeId(idOrRunnerId) {
1980
+ const head = idOrRunnerId.split("/")[0];
1981
+ return head === void 0 || head.length === 0 ? idOrRunnerId : head;
1940
1982
  }
1941
1983
  /**
1942
1984
  * Read a per-call node pin out of a tRPC `op.context` (transport side).
@@ -3163,6 +3205,8 @@ function createDeviceProxy(api, binding, opts) {
3163
3205
  getMediaRelocateStatus: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getMediaRelocateStatus", "query", input),
3164
3206
  cancelMediaRelocate: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "cancelMediaRelocate", "mutation", input),
3165
3207
  listOpsLog: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "listOpsLog", "query", input),
3208
+ getTrainingExportSummary: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getTrainingExportSummary", "query", input),
3209
+ getTrainingExportUrl: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getTrainingExportUrl", "query", input),
3166
3210
  getEventMedia: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getEventMedia", "query", input),
3167
3211
  getTrackMedia: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getTrackMedia", "query", input),
3168
3212
  listTrackMedia: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "listTrackMedia", "query", input),
@@ -3180,6 +3224,7 @@ function createDeviceProxy(api, binding, opts) {
3180
3224
  privacyMask: {
3181
3225
  getOptions: (input) => dispatch("privacy-mask", "privacyMask", "getOptions", "query", input),
3182
3226
  setMask: (input) => dispatch("privacy-mask", "privacyMask", "setMask", "mutation", input),
3227
+ setAudioEnabled: (input) => dispatch("privacy-mask", "privacyMask", "setAudioEnabled", "mutation", input),
3183
3228
  getStatus: (input) => dispatch("privacy-mask", "privacyMask", "getStatus", "query", input)
3184
3229
  },
3185
3230
  ptz: {
@@ -3370,6 +3415,14 @@ function createDeviceProxy(api, binding, opts) {
3370
3415
  getDeviceStats: (input) => dispatchSystem("networkQuality", "getDeviceStats", "query", input),
3371
3416
  reportClientStats: (input) => dispatchSystem("networkQuality", "reportClientStats", "mutation", input)
3372
3417
  },
3418
+ osdManager: {
3419
+ getDeviceOsd: (input) => dispatchSystem("osdManager", "getDeviceOsd", "query", input),
3420
+ getSourceCatalog: (input) => dispatchSystem("osdManager", "getSourceCatalog", "query", input),
3421
+ setSlotBinding: (input) => dispatchSystem("osdManager", "setSlotBinding", "mutation", input),
3422
+ clearSlotBinding: (input) => dispatchSystem("osdManager", "clearSlotBinding", "mutation", input),
3423
+ previewSlot: (input) => dispatchSystem("osdManager", "previewSlot", "mutation", input),
3424
+ renderDevice: (input) => dispatchSystem("osdManager", "renderDevice", "mutation", input)
3425
+ },
3373
3426
  pipelineExecutor: {
3374
3427
  runPipeline: (input) => dispatchSystem("pipelineExecutor", "runPipeline", "mutation", input),
3375
3428
  runPipelineBatch: (input) => dispatchSystem("pipelineExecutor", "runPipelineBatch", "mutation", input)
@@ -3414,6 +3467,7 @@ function createDeviceProxy(api, binding, opts) {
3414
3467
  getDeviceConfig: (input) => dispatchSystem("recording", "getDeviceConfig", "query", input),
3415
3468
  locateSegment: (input) => dispatchSystem("recording", "locateSegment", "query", input),
3416
3469
  readSegmentBytes: (input) => dispatchSystem("recording", "readSegmentBytes", "query", input),
3470
+ readGopBytes: (input) => dispatchSystem("recording", "readGopBytes", "query", input),
3417
3471
  setDeviceConfig: (input) => dispatchSystem("recording", "setDeviceConfig", "mutation", input),
3418
3472
  rescanStorage: (input) => dispatchSystem("recording", "rescanStorage", "mutation", input),
3419
3473
  pruneFootage: (input) => dispatchSystem("recording", "pruneFootage", "mutation", input),
@@ -3436,6 +3490,8 @@ function createDeviceProxy(api, binding, opts) {
3436
3490
  unassignProfile: (input) => dispatchSystem("streamBroker", "unassignProfile", "mutation", input),
3437
3491
  renderPreBufferClip: (input) => dispatchSystem("streamBroker", "renderPreBufferClip", "mutation", input),
3438
3492
  restartProfile: (input) => dispatchSystem("streamBroker", "restartProfile", "mutation", input),
3493
+ getDeviceAudioMute: (input) => dispatchSystem("streamBroker", "getDeviceAudioMute", "query", input),
3494
+ setDeviceAudioMute: (input) => dispatchSystem("streamBroker", "setDeviceAudioMute", "mutation", input),
3439
3495
  getDeviceSettingsContribution: (input) => dispatchSystem("streamBroker", "getDeviceSettingsContribution", "query", input),
3440
3496
  getDeviceLiveContribution: (input) => dispatchSystem("streamBroker", "getDeviceLiveContribution", "query", input),
3441
3497
  applyDeviceSettingsPatch: (input) => dispatchSystem("streamBroker", "applyDeviceSettingsPatch", "mutation", input)
@@ -3661,4 +3717,4 @@ function sleepCancellable(ms, signal) {
3661
3717
  });
3662
3718
  }
3663
3719
  //#endregion
3664
- export { ProfileRtspEntrySchema as $, method as A, scopeKey as B, DeviceType as C, collectHydratedFieldValues as Ct, event as D, DEVICE_STATUS_METHOD as E, readNodePin as F, CamStreamKindSchema as G, BrokerStatusSchema as H, ReadinessRegistry as I, DecodedAudioChunkSchema as J, CamStreamResolutionSchema as K, ReadinessTimeoutError as L, systemMethod as M, CAP_NODE_PIN_CONTEXT_KEY as N, expandCapMethods as O, nodePin as P, FrameHandleSchema as Q, emitDownForOwnedCaps as R, DeviceRole as S, collectHydratedFieldEntries as St, DEVICE_SETTINGS_CONTRIBUTION_METHODS as T, resolveHydratedFieldValue as Tt, CAM_PROFILE_ORDER as U, BrokerStatsSchema as V, CamProfileSchema as W, EncodedPacketSchema as X, DecodedFrameSchema as Y, FrameHandleFormatSchema as Z, RawStateResultSchema as _, createEvent as _t, asJsonObject as a, SubscribeAudioChunksResultSchema as at, ChargingStatus as b, WELL_KNOWN_TABS as bt, parseJsonArray as c, makeProfileBrokerId as ct, DEVICE_SCOPED_CAPS as d, selectAssignedProfileSlots as dt, ProfileSlotSchema as et, isDeviceScopedCap as f, DATAPLANE_SECRET_HEADER as ft, createSliceHandle as g, createDurableState as gt, createMirrorSource as h, normalizeAddonInitResult as ht, asJsonArray as i, SubscribeAudioChunksInputSchema as it, resolveCapMount as j, isDeviceConfigCap as k, parseJsonObject as l, makeSourceBrokerId as lt, createLazyTrpcSource as m, BaseAddon as mt, sleepCancellable as n, StreamSourceEntrySchema$1 as nt, asNumber as o, SubscribeFramesInputSchema as ot, createDeviceProxy as p, DisposerChain as pt, CameraStreamSchema as q, asBoolean as r, StreamSourceSchema as rt, asString as s, SubscribeFramesResultSchema as st, sleep as t, ProfileSlotStatusSchema as tt, parseJsonUnknown as u, parseProfileBrokerId as ut, deviceOpsCapability as v, emitReadiness as vt, adminUiCapability as w, hydrateSchema as wt, DeviceFeature as x, WELL_KNOWN_TAB_MAP as xt, viewerUiCapability as y, isEvent as yt, readinessKey as z };
3720
+ export { FrameHandleSchema as $, method as A, readinessKey as B, DeviceType as C, collectHydratedFieldEntries as Ct, event as D, DEVICE_STATUS_METHOD as E, resolveHydratedFieldValue as Et, readNodePin as F, CamProfileSchema as G, BrokerStatsSchema as H, toNodeId as I, CameraStreamSchema as J, CamStreamKindSchema as K, ReadinessRegistry as L, systemMethod as M, CAP_NODE_PIN_CONTEXT_KEY as N, expandCapMethods as O, nodePin as P, FrameHandleFormatSchema as Q, ReadinessTimeoutError as R, DeviceRole as S, WELL_KNOWN_TAB_MAP as St, DEVICE_SETTINGS_CONTRIBUTION_METHODS as T, hydrateSchema as Tt, BrokerStatusSchema as U, scopeKey as V, CAM_PROFILE_ORDER as W, DecodedFrameSchema as X, DecodedAudioChunkSchema as Y, EncodedPacketSchema as Z, RawStateResultSchema as _, createDurableState as _t, asJsonObject as a, SubscribeAudioChunksInputSchema as at, ChargingStatus as b, isEvent as bt, parseJsonArray as c, SubscribeFramesResultSchema as ct, DEVICE_SCOPED_CAPS as d, parseProfileBrokerId as dt, ProfileRtspEntrySchema as et, isDeviceScopedCap as f, selectAssignedProfileSlots as ft, createSliceHandle as g, normalizeAddonInitResult as gt, createMirrorSource as h, BaseAddon as ht, asJsonArray as i, StreamSourceSchema as it, resolveCapMount as j, isDeviceConfigCap as k, parseJsonObject as l, makeProfileBrokerId as lt, createLazyTrpcSource as m, DisposerChain as mt, sleepCancellable as n, ProfileSlotStatusSchema as nt, asNumber as o, SubscribeAudioChunksResultSchema as ot, createDeviceProxy as p, DATAPLANE_SECRET_HEADER as pt, CamStreamResolutionSchema as q, asBoolean as r, StreamSourceEntrySchema$1 as rt, asString as s, SubscribeFramesInputSchema as st, sleep as t, ProfileSlotSchema as tt, parseJsonUnknown as u, makeSourceBrokerId as ut, deviceOpsCapability as v, createEvent as vt, adminUiCapability as w, collectHydratedFieldValues as wt, DeviceFeature as x, WELL_KNOWN_TABS as xt, viewerUiCapability as y, emitReadiness as yt, emitDownForOwnedCaps as z };
@@ -1445,7 +1445,20 @@ var BrokerStatsSchema = zod.z.object({
1445
1445
  sampleRate: zod.z.number(),
1446
1446
  channels: zod.z.number(),
1447
1447
  supported: zod.z.boolean()
1448
- }).nullable().optional()
1448
+ }).nullable().optional(),
1449
+ /**
1450
+ * BROKER-SIDE AUDIO MUTE (D83). `true` = this broker is deliberately
1451
+ * distributing none of the device's audio, on live or recording.
1452
+ *
1453
+ * Present so a silent camera can be told apart from a broken one on the
1454
+ * stream panel itself, without cross-referencing the switch group: a
1455
+ * broker holding an `audio` track descriptor while `audioMuted` is true is
1456
+ * working exactly as asked. `audioMutedDropped` counts the audio units
1457
+ * thrown away since the current dial — it is how you confirm from stats
1458
+ * alone that the mute is on the packet path and not merely persisted.
1459
+ */
1460
+ audioMuted: zod.z.boolean().optional(),
1461
+ audioMutedDropped: zod.z.number().optional()
1449
1462
  });
1450
1463
  /**
1451
1464
  * Exporter-facing "profile restream" entry. Returned by
@@ -1934,9 +1947,38 @@ var CAP_NODE_PIN_CONTEXT_KEY = "__camstackNodePin";
1934
1947
  /**
1935
1948
  * Build the tRPC request options that pin a single capability call to `nodeId`.
1936
1949
  * Pass as the second argument to `.query(input, …)` / `.mutate(input, …)`.
1950
+ *
1951
+ * ## The id is normalised here, and it has to be
1952
+ *
1953
+ * A forked addon reads its own node from `ctx.kernel.localNodeId`, and inside a
1954
+ * worker that value is a RUNNER id — `hub/export-hap`, not `hub`. Routing
1955
+ * compares a pin against real node ids, so such a pin matches nothing and the
1956
+ * call fails with `no provider registered for cap "…"`. The local-first
1957
+ * resolver already guarded against this (`localNodeId.split('/')[0]`), which
1958
+ * made the hazard invisible: unpinned calls worked, and only an explicit pin —
1959
+ * the thing you reach for when you specifically need THIS node — silently
1960
+ * addressed a node that does not exist.
1961
+ *
1962
+ * Cost of it being missing: `addon-export-hap` pinned `decoder.getInfo` to its
1963
+ * own node to read the host's hardware-decode backend. It never once answered,
1964
+ * so every HomeKit egress transcode decoded in SOFTWARE — including 4K H.265 —
1965
+ * while D67's whole premise was that the decoder addon is the authority on
1966
+ * hardware. The warn said `decoding in SOFTWARE` and read as "this node has no
1967
+ * hardware", which was false.
1968
+ *
1969
+ * Normalising in the ONE constructor fixes every caller at once, which is why
1970
+ * it is here and not at the call sites.
1937
1971
  */
1938
1972
  function nodePin(nodeId) {
1939
- return { context: { [CAP_NODE_PIN_CONTEXT_KEY]: nodeId } };
1973
+ return { context: { [CAP_NODE_PIN_CONTEXT_KEY]: toNodeId(nodeId) } };
1974
+ }
1975
+ /**
1976
+ * A runner id is `<nodeId>/<addonId>`; a node id has no slash. Taking the head
1977
+ * is idempotent, so passing an already-clean id costs nothing.
1978
+ */
1979
+ function toNodeId(idOrRunnerId) {
1980
+ const head = idOrRunnerId.split("/")[0];
1981
+ return head === void 0 || head.length === 0 ? idOrRunnerId : head;
1940
1982
  }
1941
1983
  /**
1942
1984
  * Read a per-call node pin out of a tRPC `op.context` (transport side).
@@ -3163,6 +3205,8 @@ function createDeviceProxy(api, binding, opts) {
3163
3205
  getMediaRelocateStatus: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getMediaRelocateStatus", "query", input),
3164
3206
  cancelMediaRelocate: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "cancelMediaRelocate", "mutation", input),
3165
3207
  listOpsLog: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "listOpsLog", "query", input),
3208
+ getTrainingExportSummary: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getTrainingExportSummary", "query", input),
3209
+ getTrainingExportUrl: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getTrainingExportUrl", "query", input),
3166
3210
  getEventMedia: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getEventMedia", "query", input),
3167
3211
  getTrackMedia: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getTrackMedia", "query", input),
3168
3212
  listTrackMedia: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "listTrackMedia", "query", input),
@@ -3180,6 +3224,7 @@ function createDeviceProxy(api, binding, opts) {
3180
3224
  privacyMask: {
3181
3225
  getOptions: (input) => dispatch("privacy-mask", "privacyMask", "getOptions", "query", input),
3182
3226
  setMask: (input) => dispatch("privacy-mask", "privacyMask", "setMask", "mutation", input),
3227
+ setAudioEnabled: (input) => dispatch("privacy-mask", "privacyMask", "setAudioEnabled", "mutation", input),
3183
3228
  getStatus: (input) => dispatch("privacy-mask", "privacyMask", "getStatus", "query", input)
3184
3229
  },
3185
3230
  ptz: {
@@ -3370,6 +3415,14 @@ function createDeviceProxy(api, binding, opts) {
3370
3415
  getDeviceStats: (input) => dispatchSystem("networkQuality", "getDeviceStats", "query", input),
3371
3416
  reportClientStats: (input) => dispatchSystem("networkQuality", "reportClientStats", "mutation", input)
3372
3417
  },
3418
+ osdManager: {
3419
+ getDeviceOsd: (input) => dispatchSystem("osdManager", "getDeviceOsd", "query", input),
3420
+ getSourceCatalog: (input) => dispatchSystem("osdManager", "getSourceCatalog", "query", input),
3421
+ setSlotBinding: (input) => dispatchSystem("osdManager", "setSlotBinding", "mutation", input),
3422
+ clearSlotBinding: (input) => dispatchSystem("osdManager", "clearSlotBinding", "mutation", input),
3423
+ previewSlot: (input) => dispatchSystem("osdManager", "previewSlot", "mutation", input),
3424
+ renderDevice: (input) => dispatchSystem("osdManager", "renderDevice", "mutation", input)
3425
+ },
3373
3426
  pipelineExecutor: {
3374
3427
  runPipeline: (input) => dispatchSystem("pipelineExecutor", "runPipeline", "mutation", input),
3375
3428
  runPipelineBatch: (input) => dispatchSystem("pipelineExecutor", "runPipelineBatch", "mutation", input)
@@ -3414,6 +3467,7 @@ function createDeviceProxy(api, binding, opts) {
3414
3467
  getDeviceConfig: (input) => dispatchSystem("recording", "getDeviceConfig", "query", input),
3415
3468
  locateSegment: (input) => dispatchSystem("recording", "locateSegment", "query", input),
3416
3469
  readSegmentBytes: (input) => dispatchSystem("recording", "readSegmentBytes", "query", input),
3470
+ readGopBytes: (input) => dispatchSystem("recording", "readGopBytes", "query", input),
3417
3471
  setDeviceConfig: (input) => dispatchSystem("recording", "setDeviceConfig", "mutation", input),
3418
3472
  rescanStorage: (input) => dispatchSystem("recording", "rescanStorage", "mutation", input),
3419
3473
  pruneFootage: (input) => dispatchSystem("recording", "pruneFootage", "mutation", input),
@@ -3436,6 +3490,8 @@ function createDeviceProxy(api, binding, opts) {
3436
3490
  unassignProfile: (input) => dispatchSystem("streamBroker", "unassignProfile", "mutation", input),
3437
3491
  renderPreBufferClip: (input) => dispatchSystem("streamBroker", "renderPreBufferClip", "mutation", input),
3438
3492
  restartProfile: (input) => dispatchSystem("streamBroker", "restartProfile", "mutation", input),
3493
+ getDeviceAudioMute: (input) => dispatchSystem("streamBroker", "getDeviceAudioMute", "query", input),
3494
+ setDeviceAudioMute: (input) => dispatchSystem("streamBroker", "setDeviceAudioMute", "mutation", input),
3439
3495
  getDeviceSettingsContribution: (input) => dispatchSystem("streamBroker", "getDeviceSettingsContribution", "query", input),
3440
3496
  getDeviceLiveContribution: (input) => dispatchSystem("streamBroker", "getDeviceLiveContribution", "query", input),
3441
3497
  applyDeviceSettingsPatch: (input) => dispatchSystem("streamBroker", "applyDeviceSettingsPatch", "mutation", input)
@@ -4129,6 +4185,12 @@ Object.defineProperty(exports, "systemMethod", {
4129
4185
  return systemMethod;
4130
4186
  }
4131
4187
  });
4188
+ Object.defineProperty(exports, "toNodeId", {
4189
+ enumerable: true,
4190
+ get: function() {
4191
+ return toNodeId;
4192
+ }
4193
+ });
4132
4194
  Object.defineProperty(exports, "viewerUiCapability", {
4133
4195
  enumerable: true,
4134
4196
  get: function() {
@@ -12,7 +12,7 @@ export interface IPipelineStep {
12
12
  readonly definition: StepDefinition;
13
13
  getConfigSchema(): readonly ConfigField[];
14
14
  }
15
- export type PostprocessorType = 'yolo' | 'ssd' | 'yolo-seg' | 'scrfd' | 'arcface' | 'clip' | 'softmax' | 'ctc' | 'saliency' | 'yamnet';
15
+ export type PostprocessorType = 'yolo' | 'ssd' | 'rfdetr' | 'yolo-seg' | 'scrfd' | 'arcface' | 'clip' | 'softmax' | 'ctc' | 'saliency' | 'yamnet';
16
16
  export interface StepDefinition {
17
17
  /** Unique step identifier (e.g., 'object-detection', 'face-detection') */
18
18
  readonly id: string;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The addon id as the REGISTRY, the wire and the durable stores spell it.
3
+ *
4
+ * `AddonContext.id` does not agree with itself across the two context
5
+ * factories:
6
+ *
7
+ * - a FORKED addon gets the bare manifest id
8
+ * (`kernel/moleculer/addon-context-factory.ts` → `id: addonId`);
9
+ * - an addon co-located in hub-main gets it PREFIXED
10
+ * (`server/backend/src/core/addon/addon-registry.service.ts` →
11
+ * ``id: `addon:${addonId}` ``).
12
+ *
13
+ * Everything an addon might compare `ctx.id` AGAINST carries the bare form:
14
+ * `DeviceBindingEntry.providerAddonId`, the `device-manager` bindings store's
15
+ * `wrapperAddonId`, `CapabilityRegistry` provider keys, manifest ids.
16
+ *
17
+ * So `entry.providerAddonId === this.ctx.id` is silently, permanently false
18
+ * for a builtin — and only for a builtin, which is why it survives a green
19
+ * suite whose fake supplies the bare id. That is exactly how camera 615's
20
+ * virtual doorbell latched `unbound` for twelve hours on 2026-08-07 while its
21
+ * binding was intact ([D72](../../../../docs/decisions/adr-0072.md)).
22
+ *
23
+ * Route every comparison between `ctx.id` and a registry/store addon id
24
+ * through {@link isSameAddonId}. `scripts/check-addon-id-comparison.ts`
25
+ * enforces it in the processes where the prefix exists.
26
+ */
27
+ /** The manifest id, whichever spelling of `ctx.id` you were handed. */
28
+ export declare function bareAddonId(id: string): string;
29
+ /** True when both ids name the same addon, prefixed or not. */
30
+ export declare function isSameAddonId(a: string, b: string): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/types",
3
- "version": "1.2.42",
3
+ "version": "1.2.44",
4
4
  "description": "Shared types, interfaces, and model catalogs for the CamStack detection ecosystem",
5
5
  "keywords": [
6
6
  "camstack",
@@ -1,35 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- //#region src/utils/canonical-hash.ts
3
- /**
4
- * Deterministic SHA-256 hash of an arbitrary serialisable value. The
5
- * canonical form sorts object keys alphabetically at every depth so two
6
- * structurally-equal inputs with different key insertion orders produce
7
- * the same hash. Returns a 64-char lowercase hex digest.
8
- *
9
- * Used by export adapters (Alexa, HAP) to short-circuit re-discovery /
10
- * accessory-rebuild work when the upstream shape is byte-identical to
11
- * the last applied state — preventing user-visible "re-discovery"
12
- * notifications on every addon-runner respawn. Each respawn re-fires
13
- * `DeviceBindingsChanged` for every cap registration, which without
14
- * this guard would propagate redundant pushes.
15
- *
16
- * Note: this is a SYMPTOMATIC fix layered on top of the binding-change
17
- * subscription. The proper fix is a single "device ready" lifecycle
18
- * barrier so exports react only when the full cap set has landed —
19
- * tracked separately for post-HA-integration work.
20
- */
21
- function canonicalHash(value) {
22
- const canonical = JSON.stringify(value, replaceWithSortedKeys);
23
- return createHash("sha256").update(canonical ?? "").digest("hex");
24
- }
25
- function replaceWithSortedKeys(_key, value) {
26
- if (value && typeof value === "object" && !Array.isArray(value)) {
27
- const obj = value;
28
- const out = {};
29
- for (const k of Object.keys(obj).toSorted()) out[k] = obj[k];
30
- return out;
31
- }
32
- return value;
33
- }
34
- //#endregion
35
- export { canonicalHash as t };
@@ -1,40 +0,0 @@
1
- let node_crypto = require("node:crypto");
2
- //#region src/utils/canonical-hash.ts
3
- /**
4
- * Deterministic SHA-256 hash of an arbitrary serialisable value. The
5
- * canonical form sorts object keys alphabetically at every depth so two
6
- * structurally-equal inputs with different key insertion orders produce
7
- * the same hash. Returns a 64-char lowercase hex digest.
8
- *
9
- * Used by export adapters (Alexa, HAP) to short-circuit re-discovery /
10
- * accessory-rebuild work when the upstream shape is byte-identical to
11
- * the last applied state — preventing user-visible "re-discovery"
12
- * notifications on every addon-runner respawn. Each respawn re-fires
13
- * `DeviceBindingsChanged` for every cap registration, which without
14
- * this guard would propagate redundant pushes.
15
- *
16
- * Note: this is a SYMPTOMATIC fix layered on top of the binding-change
17
- * subscription. The proper fix is a single "device ready" lifecycle
18
- * barrier so exports react only when the full cap set has landed —
19
- * tracked separately for post-HA-integration work.
20
- */
21
- function canonicalHash(value) {
22
- const canonical = JSON.stringify(value, replaceWithSortedKeys);
23
- return (0, node_crypto.createHash)("sha256").update(canonical ?? "").digest("hex");
24
- }
25
- function replaceWithSortedKeys(_key, value) {
26
- if (value && typeof value === "object" && !Array.isArray(value)) {
27
- const obj = value;
28
- const out = {};
29
- for (const k of Object.keys(obj).toSorted()) out[k] = obj[k];
30
- return out;
31
- }
32
- return value;
33
- }
34
- //#endregion
35
- Object.defineProperty(exports, "canonicalHash", {
36
- enumerable: true,
37
- get: function() {
38
- return canonicalHash;
39
- }
40
- });