@camstack/addon-pipeline 1.1.51 → 1.1.53

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 (31) hide show
  1. package/dist/audio-analyzer/index.js +1 -1
  2. package/dist/audio-analyzer/index.mjs +1 -1
  3. package/dist/detection-pipeline/index.js +48 -7
  4. package/dist/detection-pipeline/index.mjs +48 -7
  5. package/dist/{dist-gWOMlIyx.mjs → dist-BalxNwOt.mjs} +54 -2
  6. package/dist/{dist-gJgSPFxd.js → dist-DWb62H5U.js} +54 -2
  7. package/dist/motion-wasm/index.js +1 -1
  8. package/dist/motion-wasm/index.mjs +1 -1
  9. package/dist/pipeline-runner/index.js +2 -2
  10. package/dist/pipeline-runner/index.mjs +2 -2
  11. package/dist/recorder/index.js +1 -1
  12. package/dist/recorder/index.mjs +1 -1
  13. package/dist/{remote-source-plane-CaN4WP3E.mjs → remote-source-plane-BCJW5CvF.mjs} +1 -1
  14. package/dist/{remote-source-plane-CBPLC_6k.js → remote-source-plane-CZpzIVro.js} +1 -1
  15. package/dist/stream-broker/_stub.js +73 -73
  16. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BACsijAd.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DIN3CcRP.mjs} +3 -3
  17. package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CK4BmiTK.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-C9fwKMfg.mjs} +2 -2
  18. package/dist/stream-broker/{hostInit-Cyg0YeOF.mjs → hostInit-CGUEq--X.mjs} +3 -3
  19. package/dist/stream-broker/index.js +2 -2
  20. package/dist/stream-broker/index.mjs +2 -2
  21. package/dist/stream-broker/remoteEntry.js +1 -1
  22. package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-BA-WsO08.js → MaskShapeCanvas-DI4BY7W2-CqOe8eYa.js} +1 -1
  23. package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-BB6jZ0nZ.js → MotionZonesSettings-NcxxQN8r-CZyLeUnd.js} +1 -1
  24. package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-CZZ9Yx7Y.js → PrivacyMaskSettings-APgPLF7p-Cn0hGZnu.js} +1 -1
  25. package/embed-dist/assets/index-CC06JBcl.css +2 -0
  26. package/embed-dist/assets/{index-3wAsTkJs.js → index-DRl4XYjA.js} +11 -11
  27. package/embed-dist/index.html +2 -2
  28. package/package.json +1 -1
  29. package/python/inference_pool.py +42 -1
  30. package/python/test_inference_pool_layout.py +44 -0
  31. package/embed-dist/assets/index-JqUY2p33.css +0 -2
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../chunk-D6vf50IK.js");
6
- const require_dist = require("../dist-gJgSPFxd.js");
6
+ const require_dist = require("../dist-DWb62H5U.js");
7
7
  const require_node_topology_platform = require("../node-topology-platform-CFZ7F4xW.js");
8
8
  const require_model_download_service_C_IHWnXx = require("../model-download-service-C-IHWnXx-BLXzxpRB.js");
9
9
  let node_fs = require("node:fs");
@@ -1,5 +1,5 @@
1
1
  import { t as __require } from "../chunk-BdkLduGY.mjs";
2
- import { C as mapAudioLabelToMacro, I as errMsg, L as BaseAddon, U as hydrateSchema, h as audioAnalyzerCapability, l as HF_BASE_URL, m as audioAnalysisCapability, n as AUDIO_BACKEND_CHOICES, o as DEFAULT_AUDIO_ANALYZER_CONFIG } from "../dist-gWOMlIyx.mjs";
2
+ import { C as mapAudioLabelToMacro, I as errMsg, L as BaseAddon, U as hydrateSchema, h as audioAnalyzerCapability, l as HF_BASE_URL, m as audioAnalysisCapability, n as AUDIO_BACKEND_CHOICES, o as DEFAULT_AUDIO_ANALYZER_CONFIG } from "../dist-BalxNwOt.mjs";
3
3
  import { t as pickNodePlatformArch } from "../node-topology-platform-BkR_k6WT.mjs";
4
4
  import { r as downloadFile } from "../model-download-service-C-IHWnXx-BPy6aoAx.mjs";
5
5
  import * as fs from "node:fs";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../chunk-D6vf50IK.js");
6
- const require_dist = require("../dist-gJgSPFxd.js");
6
+ const require_dist = require("../dist-DWb62H5U.js");
7
7
  const require_node_topology_platform = require("../node-topology-platform-CFZ7F4xW.js");
8
8
  const require_model_download_service_C_IHWnXx = require("../model-download-service-C-IHWnXx-BLXzxpRB.js");
9
9
  let _camstack_shm_ring = require("@camstack/shm-ring");
@@ -1543,11 +1543,16 @@ var STEP_CLIP_EMBEDDING = new PipelineStepBase({
1543
1543
  slot: "classifier",
1544
1544
  postprocessor: "clip",
1545
1545
  extractMode: "crop-roi",
1546
- inputClasses: null,
1546
+ inputClasses: [
1547
+ "person",
1548
+ "vehicle",
1549
+ "animal"
1550
+ ],
1547
1551
  outputClasses: ["embedding"],
1548
1552
  models: [...CLIP_EMBEDDING_MODELS],
1549
1553
  defaultModelId: "mobileclip-s1",
1550
- enabledByDefault: false,
1554
+ enabledByDefault: true,
1555
+ backfillIntoExistingOverrides: true,
1551
1556
  defaultConfidence: 0,
1552
1557
  defaultMinParentScore: .4,
1553
1558
  group: "CLIP"
@@ -4132,15 +4137,34 @@ function formatTopResult(output) {
4132
4137
  /**
4133
4138
  * Default minimum short-side (px, source-frame resolution) of a face bbox for
4134
4139
  * which a recognition embedding is attempted. Faces smaller than this upscale
4135
- * into garbage embeddings; we skip them rather than pollute clustering. Override
4140
+ * into weaker embeddings; we skip them rather than pollute clustering. Override
4136
4141
  * per-step via `settings.minFaceSize`.
4142
+ *
4143
+ * Lowered 40 → 28 (2026-07-14): detection runs on a downscaled frame (e.g.
4144
+ * 640×360), so an indoor person's face is often 28-38px there and was being
4145
+ * skipped entirely — no faces collected. 28px still warps acceptably onto the
4146
+ * 112×112 ArcFace input; the honest below-threshold count is surfaced by the
4147
+ * throttled "too small to embed" diagnostic (with the actual `faceShortSidePx`).
4148
+ * The quality-preserving alternative is to run face-detection at a higher input
4149
+ * resolution — a deeper change tracked separately.
4137
4150
  */
4138
- var DEFAULT_MIN_FACE_SIZE_PX = 40;
4151
+ var DEFAULT_MIN_FACE_SIZE_PX = 28;
4139
4152
  var PipelineExecutor = class {
4140
4153
  opts;
4141
4154
  constructor(opts) {
4142
4155
  this.opts = opts;
4143
4156
  }
4157
+ /** Per-key last-warn timestamps, so a persistently-failing/skipping child
4158
+ * step surfaces a diagnostic without spamming the log every frame. */
4159
+ warnThrottleAt = /* @__PURE__ */ new Map();
4160
+ throttledWarn(key, everyMs, message, meta) {
4161
+ const logger = this.opts.logger;
4162
+ if (!logger) return;
4163
+ const now = Date.now();
4164
+ if (now - (this.warnThrottleAt.get(key) ?? 0) < everyMs) return;
4165
+ this.warnThrottleAt.set(key, now);
4166
+ logger.warn(message, { meta });
4167
+ }
4144
4168
  /**
4145
4169
  * Execute the full pipeline tree against a frame.
4146
4170
  *
@@ -4309,7 +4333,16 @@ var PipelineExecutor = class {
4309
4333
  let cropH;
4310
4334
  if (modelEntry?.faceAlignment) {
4311
4335
  const minFaceSize = typeof child.settings?.["minFaceSize"] === "number" ? child.settings["minFaceSize"] : DEFAULT_MIN_FACE_SIZE_PX;
4312
- if (bboxShortSide(parentDetection.bbox) < minFaceSize) continue;
4336
+ const faceShortSide = bboxShortSide(parentDetection.bbox);
4337
+ if (faceShortSide < minFaceSize) {
4338
+ this.throttledWarn(`face-small:${child.stepId}`, 3e4, "face detected but too small to embed — skipping", {
4339
+ step: child.stepId,
4340
+ model: child.modelId,
4341
+ faceShortSidePx: Math.round(faceShortSide),
4342
+ minFaceSizePx: minFaceSize
4343
+ });
4344
+ continue;
4345
+ }
4313
4346
  const lms = parentDetection.landmarks;
4314
4347
  if (lms && lms.length >= 5) {
4315
4348
  const aligned = await alignFaceCrop(fullFrameJpeg, parentDetection.bbox, lms, imageWidth, imageHeight, { outSize: modelEntry.inputSize.width });
@@ -4349,7 +4382,13 @@ var PipelineExecutor = class {
4349
4382
  await this.executeChildren(child.children, detail, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg);
4350
4383
  }
4351
4384
  }
4352
- } catch {}
4385
+ } catch (err) {
4386
+ this.throttledWarn(`child-fail:${child.stepId}`, 15e3, "pipeline child step failed", {
4387
+ step: child.stepId,
4388
+ model: child.modelId,
4389
+ error: require_dist.errMsg(err)
4390
+ });
4391
+ }
4353
4392
  }
4354
4393
  }
4355
4394
  matchesInputClasses(className, inputClasses) {
@@ -7173,6 +7212,7 @@ function buildSchemaSlots(format, modelsDir, customByStep) {
7173
7212
  defaultModelId: step.defaultModelId,
7174
7213
  ...step.defaultModelIdByFormat ? { defaultModelIdByFormat: { ...step.defaultModelIdByFormat } } : {},
7175
7214
  ...step.enabledByDefault !== void 0 ? { enabledByDefault: step.enabledByDefault } : {},
7215
+ ...step.backfillIntoExistingOverrides !== void 0 ? { backfillIntoExistingOverrides: step.backfillIntoExistingOverrides } : {},
7176
7216
  defaultConfidence: step.defaultConfidence,
7177
7217
  ...step.group ? { group: step.group } : {},
7178
7218
  ...configSchema.length > 0 ? { configSchema: [...configSchema] } : {}
@@ -7252,6 +7292,7 @@ function buildDefaultStepTree(format, objectDetectionModelId) {
7252
7292
  const root = makeStep("object-detection", [
7253
7293
  faceDetection,
7254
7294
  makeStep("plate-detection", plateOcr ? [plateOcr] : []),
7295
+ makeStep("clip-embedding", []),
7255
7296
  makeStep("animal-classifier", [], { enabled: false }),
7256
7297
  makeStep("bird-classifier", [], { enabled: false }),
7257
7298
  makeStep("vehicle-classifier", [], { enabled: false }),
@@ -1,5 +1,5 @@
1
1
  import { t as __require } from "../chunk-BdkLduGY.mjs";
2
- import { H as createEvent, I as errMsg, L as BaseAddon, O as pipelineExecutorCapability, P as supportedRuntimes$1, S as hfModelUrl, U as hydrateSchema, V as EventCategory, X as sleep, a as COCO_TO_MACRO, b as detectionPipelineCapability, f as YAMNET_TO_MACRO, i as COCO_80_LABELS, j as runtimeDevices$1, q as parseJsonUnknown, r as AUDIO_MACRO_LABELS, t as APPLE_SA_TO_MACRO, v as defaultDeviceFor$1, x as evaluateZoneRules } from "../dist-gWOMlIyx.mjs";
2
+ import { H as createEvent, I as errMsg, L as BaseAddon, O as pipelineExecutorCapability, P as supportedRuntimes$1, S as hfModelUrl, U as hydrateSchema, V as EventCategory, X as sleep, a as COCO_TO_MACRO, b as detectionPipelineCapability, f as YAMNET_TO_MACRO, i as COCO_80_LABELS, j as runtimeDevices$1, q as parseJsonUnknown, r as AUDIO_MACRO_LABELS, t as APPLE_SA_TO_MACRO, v as defaultDeviceFor$1, x as evaluateZoneRules } from "../dist-BalxNwOt.mjs";
3
3
  import { t as pickNodePlatformArch } from "../node-topology-platform-BkR_k6WT.mjs";
4
4
  import { a as isModelDownloaded, i as ensureModel, n as deleteModelFromDisk } from "../model-download-service-C-IHWnXx-BPy6aoAx.mjs";
5
5
  import { FrameRingReaderCache } from "@camstack/shm-ring";
@@ -1535,11 +1535,16 @@ var STEP_CLIP_EMBEDDING = new PipelineStepBase({
1535
1535
  slot: "classifier",
1536
1536
  postprocessor: "clip",
1537
1537
  extractMode: "crop-roi",
1538
- inputClasses: null,
1538
+ inputClasses: [
1539
+ "person",
1540
+ "vehicle",
1541
+ "animal"
1542
+ ],
1539
1543
  outputClasses: ["embedding"],
1540
1544
  models: [...CLIP_EMBEDDING_MODELS],
1541
1545
  defaultModelId: "mobileclip-s1",
1542
- enabledByDefault: false,
1546
+ enabledByDefault: true,
1547
+ backfillIntoExistingOverrides: true,
1543
1548
  defaultConfidence: 0,
1544
1549
  defaultMinParentScore: .4,
1545
1550
  group: "CLIP"
@@ -4124,15 +4129,34 @@ function formatTopResult(output) {
4124
4129
  /**
4125
4130
  * Default minimum short-side (px, source-frame resolution) of a face bbox for
4126
4131
  * which a recognition embedding is attempted. Faces smaller than this upscale
4127
- * into garbage embeddings; we skip them rather than pollute clustering. Override
4132
+ * into weaker embeddings; we skip them rather than pollute clustering. Override
4128
4133
  * per-step via `settings.minFaceSize`.
4134
+ *
4135
+ * Lowered 40 → 28 (2026-07-14): detection runs on a downscaled frame (e.g.
4136
+ * 640×360), so an indoor person's face is often 28-38px there and was being
4137
+ * skipped entirely — no faces collected. 28px still warps acceptably onto the
4138
+ * 112×112 ArcFace input; the honest below-threshold count is surfaced by the
4139
+ * throttled "too small to embed" diagnostic (with the actual `faceShortSidePx`).
4140
+ * The quality-preserving alternative is to run face-detection at a higher input
4141
+ * resolution — a deeper change tracked separately.
4129
4142
  */
4130
- var DEFAULT_MIN_FACE_SIZE_PX = 40;
4143
+ var DEFAULT_MIN_FACE_SIZE_PX = 28;
4131
4144
  var PipelineExecutor = class {
4132
4145
  opts;
4133
4146
  constructor(opts) {
4134
4147
  this.opts = opts;
4135
4148
  }
4149
+ /** Per-key last-warn timestamps, so a persistently-failing/skipping child
4150
+ * step surfaces a diagnostic without spamming the log every frame. */
4151
+ warnThrottleAt = /* @__PURE__ */ new Map();
4152
+ throttledWarn(key, everyMs, message, meta) {
4153
+ const logger = this.opts.logger;
4154
+ if (!logger) return;
4155
+ const now = Date.now();
4156
+ if (now - (this.warnThrottleAt.get(key) ?? 0) < everyMs) return;
4157
+ this.warnThrottleAt.set(key, now);
4158
+ logger.warn(message, { meta });
4159
+ }
4136
4160
  /**
4137
4161
  * Execute the full pipeline tree against a frame.
4138
4162
  *
@@ -4301,7 +4325,16 @@ var PipelineExecutor = class {
4301
4325
  let cropH;
4302
4326
  if (modelEntry?.faceAlignment) {
4303
4327
  const minFaceSize = typeof child.settings?.["minFaceSize"] === "number" ? child.settings["minFaceSize"] : DEFAULT_MIN_FACE_SIZE_PX;
4304
- if (bboxShortSide(parentDetection.bbox) < minFaceSize) continue;
4328
+ const faceShortSide = bboxShortSide(parentDetection.bbox);
4329
+ if (faceShortSide < minFaceSize) {
4330
+ this.throttledWarn(`face-small:${child.stepId}`, 3e4, "face detected but too small to embed — skipping", {
4331
+ step: child.stepId,
4332
+ model: child.modelId,
4333
+ faceShortSidePx: Math.round(faceShortSide),
4334
+ minFaceSizePx: minFaceSize
4335
+ });
4336
+ continue;
4337
+ }
4305
4338
  const lms = parentDetection.landmarks;
4306
4339
  if (lms && lms.length >= 5) {
4307
4340
  const aligned = await alignFaceCrop(fullFrameJpeg, parentDetection.bbox, lms, imageWidth, imageHeight, { outSize: modelEntry.inputSize.width });
@@ -4341,7 +4374,13 @@ var PipelineExecutor = class {
4341
4374
  await this.executeChildren(child.children, detail, fullFrameJpegProvider, imageWidth, imageHeight, traceBuilder, stepTimings, ctx, poolAgg);
4342
4375
  }
4343
4376
  }
4344
- } catch {}
4377
+ } catch (err) {
4378
+ this.throttledWarn(`child-fail:${child.stepId}`, 15e3, "pipeline child step failed", {
4379
+ step: child.stepId,
4380
+ model: child.modelId,
4381
+ error: errMsg(err)
4382
+ });
4383
+ }
4345
4384
  }
4346
4385
  }
4347
4386
  matchesInputClasses(className, inputClasses) {
@@ -7165,6 +7204,7 @@ function buildSchemaSlots(format, modelsDir, customByStep) {
7165
7204
  defaultModelId: step.defaultModelId,
7166
7205
  ...step.defaultModelIdByFormat ? { defaultModelIdByFormat: { ...step.defaultModelIdByFormat } } : {},
7167
7206
  ...step.enabledByDefault !== void 0 ? { enabledByDefault: step.enabledByDefault } : {},
7207
+ ...step.backfillIntoExistingOverrides !== void 0 ? { backfillIntoExistingOverrides: step.backfillIntoExistingOverrides } : {},
7168
7208
  defaultConfidence: step.defaultConfidence,
7169
7209
  ...step.group ? { group: step.group } : {},
7170
7210
  ...configSchema.length > 0 ? { configSchema: [...configSchema] } : {}
@@ -7244,6 +7284,7 @@ function buildDefaultStepTree(format, objectDetectionModelId) {
7244
7284
  const root = makeStep("object-detection", [
7245
7285
  faceDetection,
7246
7286
  makeStep("plate-detection", plateOcr ? [plateOcr] : []),
7287
+ makeStep("clip-embedding", []),
7247
7288
  makeStep("animal-classifier", [], { enabled: false }),
7248
7289
  makeStep("bird-classifier", [], { enabled: false }),
7249
7290
  makeStep("vehicle-classifier", [], { enabled: false }),
@@ -4627,7 +4627,7 @@ function _instanceof(cls, params = {}) {
4627
4627
  return inst;
4628
4628
  }
4629
4629
  //#endregion
4630
- //#region ../types/dist/sleep-DJaTV2D7.mjs
4630
+ //#region ../types/dist/sleep-b4Jf2n33.mjs
4631
4631
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4632
4632
  EventCategory["SystemBoot"] = "system.boot";
4633
4633
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -6831,6 +6831,18 @@ function method(input, output, options) {
6831
6831
  timeoutMs: options?.timeoutMs
6832
6832
  };
6833
6833
  }
6834
+ /**
6835
+ * A wrapper/system-only method: served exclusively by the cap's system-level
6836
+ * provider (`InferProvider`), and OPTIONAL on `InferNativeProvider` so per-device
6837
+ * driver natives don't stub out a wrapper concern (e.g. a cross-device cache
6838
+ * overview). The `systemOnly: true` literal is what `InferNativeProvider` keys on.
6839
+ */
6840
+ function systemMethod(input, output, options) {
6841
+ return {
6842
+ ...method(input, output, options),
6843
+ systemOnly: true
6844
+ };
6845
+ }
6834
6846
  /** Shorthand to define an event schema */
6835
6847
  function event(data) {
6836
6848
  return { data };
@@ -11408,6 +11420,7 @@ var PipelineAddonSchemaSchema = object({
11408
11420
  defaultModelId: string(),
11409
11421
  defaultModelIdByFormat: record(string(), string()).optional(),
11410
11422
  enabledByDefault: boolean().optional(),
11423
+ backfillIntoExistingOverrides: boolean().optional(),
11411
11424
  defaultConfidence: number(),
11412
11425
  group: string().optional(),
11413
11426
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -17337,7 +17350,12 @@ DeviceType.Camera, method(object({
17337
17350
  }), SnapshotImageSchema.nullable()), method(object({ deviceId: number() }), _void(), {
17338
17351
  kind: "mutation",
17339
17352
  auth: "admin"
17340
- });
17353
+ }), systemMethod(object({ deviceIds: array(number()).min(1).max(200) }), array(object({
17354
+ deviceId: number(),
17355
+ lastCapturedAt: number().nullable(),
17356
+ cacheAgeMs: number().nullable(),
17357
+ etag: string().nullable()
17358
+ })));
17341
17359
  /**
17342
17360
  * `sso-bridge` — internal hub-only cap that lets SSO-style auth
17343
17361
  * providers (OIDC, SAML, magic-link, …) mint an HMAC-signed token
@@ -17620,6 +17638,15 @@ method(_void(), array(TurnServerSchema).readonly());
17620
17638
  * - `listPasskeys({userId})` — enumerate user's enrolled credentials.
17621
17639
  * - `removePasskey({userId, credentialId})` — revoke one credential.
17622
17640
  *
17641
+ * 4. Second-factor preference (opt-in, default OFF):
17642
+ * Enrolling a passkey only enables passkey-FIRST sign-in. It is
17643
+ * demanded as a second factor after a password login ONLY when the
17644
+ * user explicitly opts in via `setSecondFactorPreference`.
17645
+ * - `getSecondFactorPreference({userId})` → `{ enabled }` (missing
17646
+ * row ⇒ `enabled: false`).
17647
+ * - `setSecondFactorPreference({userId, enabled})` — persisted by
17648
+ * the providing addon beside its credentials.
17649
+ *
17623
17650
  * Challenges are short-lived (5 min, in-memory). The cap is internal —
17624
17651
  * the admin-ui composes the begin/finish round-trip and never exposes
17625
17652
  * the cap to non-admins.
@@ -17680,6 +17707,13 @@ response: record(string(), unknown()) }), object({
17680
17707
  kind: "mutation",
17681
17708
  auth: "admin",
17682
17709
  access: "delete"
17710
+ }), method(object({ userId: string() }), object({ enabled: boolean() }), { auth: "admin" }), method(object({
17711
+ userId: string(),
17712
+ enabled: boolean()
17713
+ }), object({ success: literal(true) }), {
17714
+ kind: "mutation",
17715
+ auth: "admin",
17716
+ access: "create"
17683
17717
  });
17684
17718
  /**
17685
17719
  * `videoclips` — the unified, navigable-clip surface for a camera.
@@ -23607,6 +23641,12 @@ Object.freeze({
23607
23641
  addonId: null,
23608
23642
  access: "view"
23609
23643
  },
23644
+ "snapshot.getSnapshotOverview": {
23645
+ capName: "snapshot",
23646
+ capScope: "device",
23647
+ addonId: null,
23648
+ access: "view"
23649
+ },
23610
23650
  "snapshot.invalidateCache": {
23611
23651
  capName: "snapshot",
23612
23652
  capScope: "device",
@@ -24315,6 +24355,12 @@ Object.freeze({
24315
24355
  addonId: null,
24316
24356
  access: "create"
24317
24357
  },
24358
+ "userPasskeys.getSecondFactorPreference": {
24359
+ capName: "user-passkeys",
24360
+ capScope: "system",
24361
+ addonId: null,
24362
+ access: "view"
24363
+ },
24318
24364
  "userPasskeys.listPasskeys": {
24319
24365
  capName: "user-passkeys",
24320
24366
  capScope: "system",
@@ -24327,6 +24373,12 @@ Object.freeze({
24327
24373
  addonId: null,
24328
24374
  access: "delete"
24329
24375
  },
24376
+ "userPasskeys.setSecondFactorPreference": {
24377
+ capName: "user-passkeys",
24378
+ capScope: "system",
24379
+ addonId: null,
24380
+ access: "create"
24381
+ },
24330
24382
  "vacuumControl.locate": {
24331
24383
  capName: "vacuum-control",
24332
24384
  capScope: "device",
@@ -4627,7 +4627,7 @@ function _instanceof(cls, params = {}) {
4627
4627
  return inst;
4628
4628
  }
4629
4629
  //#endregion
4630
- //#region ../types/dist/sleep-DJaTV2D7.mjs
4630
+ //#region ../types/dist/sleep-b4Jf2n33.mjs
4631
4631
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4632
4632
  EventCategory["SystemBoot"] = "system.boot";
4633
4633
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -6831,6 +6831,18 @@ function method(input, output, options) {
6831
6831
  timeoutMs: options?.timeoutMs
6832
6832
  };
6833
6833
  }
6834
+ /**
6835
+ * A wrapper/system-only method: served exclusively by the cap's system-level
6836
+ * provider (`InferProvider`), and OPTIONAL on `InferNativeProvider` so per-device
6837
+ * driver natives don't stub out a wrapper concern (e.g. a cross-device cache
6838
+ * overview). The `systemOnly: true` literal is what `InferNativeProvider` keys on.
6839
+ */
6840
+ function systemMethod(input, output, options) {
6841
+ return {
6842
+ ...method(input, output, options),
6843
+ systemOnly: true
6844
+ };
6845
+ }
6834
6846
  /** Shorthand to define an event schema */
6835
6847
  function event(data) {
6836
6848
  return { data };
@@ -11408,6 +11420,7 @@ var PipelineAddonSchemaSchema = object({
11408
11420
  defaultModelId: string(),
11409
11421
  defaultModelIdByFormat: record(string(), string()).optional(),
11410
11422
  enabledByDefault: boolean().optional(),
11423
+ backfillIntoExistingOverrides: boolean().optional(),
11411
11424
  defaultConfidence: number(),
11412
11425
  group: string().optional(),
11413
11426
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -17337,7 +17350,12 @@ DeviceType.Camera, method(object({
17337
17350
  }), SnapshotImageSchema.nullable()), method(object({ deviceId: number() }), _void(), {
17338
17351
  kind: "mutation",
17339
17352
  auth: "admin"
17340
- });
17353
+ }), systemMethod(object({ deviceIds: array(number()).min(1).max(200) }), array(object({
17354
+ deviceId: number(),
17355
+ lastCapturedAt: number().nullable(),
17356
+ cacheAgeMs: number().nullable(),
17357
+ etag: string().nullable()
17358
+ })));
17341
17359
  /**
17342
17360
  * `sso-bridge` — internal hub-only cap that lets SSO-style auth
17343
17361
  * providers (OIDC, SAML, magic-link, …) mint an HMAC-signed token
@@ -17620,6 +17638,15 @@ method(_void(), array(TurnServerSchema).readonly());
17620
17638
  * - `listPasskeys({userId})` — enumerate user's enrolled credentials.
17621
17639
  * - `removePasskey({userId, credentialId})` — revoke one credential.
17622
17640
  *
17641
+ * 4. Second-factor preference (opt-in, default OFF):
17642
+ * Enrolling a passkey only enables passkey-FIRST sign-in. It is
17643
+ * demanded as a second factor after a password login ONLY when the
17644
+ * user explicitly opts in via `setSecondFactorPreference`.
17645
+ * - `getSecondFactorPreference({userId})` → `{ enabled }` (missing
17646
+ * row ⇒ `enabled: false`).
17647
+ * - `setSecondFactorPreference({userId, enabled})` — persisted by
17648
+ * the providing addon beside its credentials.
17649
+ *
17623
17650
  * Challenges are short-lived (5 min, in-memory). The cap is internal —
17624
17651
  * the admin-ui composes the begin/finish round-trip and never exposes
17625
17652
  * the cap to non-admins.
@@ -17680,6 +17707,13 @@ response: record(string(), unknown()) }), object({
17680
17707
  kind: "mutation",
17681
17708
  auth: "admin",
17682
17709
  access: "delete"
17710
+ }), method(object({ userId: string() }), object({ enabled: boolean() }), { auth: "admin" }), method(object({
17711
+ userId: string(),
17712
+ enabled: boolean()
17713
+ }), object({ success: literal(true) }), {
17714
+ kind: "mutation",
17715
+ auth: "admin",
17716
+ access: "create"
17683
17717
  });
17684
17718
  /**
17685
17719
  * `videoclips` — the unified, navigable-clip surface for a camera.
@@ -23607,6 +23641,12 @@ Object.freeze({
23607
23641
  addonId: null,
23608
23642
  access: "view"
23609
23643
  },
23644
+ "snapshot.getSnapshotOverview": {
23645
+ capName: "snapshot",
23646
+ capScope: "device",
23647
+ addonId: null,
23648
+ access: "view"
23649
+ },
23610
23650
  "snapshot.invalidateCache": {
23611
23651
  capName: "snapshot",
23612
23652
  capScope: "device",
@@ -24315,6 +24355,12 @@ Object.freeze({
24315
24355
  addonId: null,
24316
24356
  access: "create"
24317
24357
  },
24358
+ "userPasskeys.getSecondFactorPreference": {
24359
+ capName: "user-passkeys",
24360
+ capScope: "system",
24361
+ addonId: null,
24362
+ access: "view"
24363
+ },
24318
24364
  "userPasskeys.listPasskeys": {
24319
24365
  capName: "user-passkeys",
24320
24366
  capScope: "system",
@@ -24327,6 +24373,12 @@ Object.freeze({
24327
24373
  addonId: null,
24328
24374
  access: "delete"
24329
24375
  },
24376
+ "userPasskeys.setSecondFactorPreference": {
24377
+ capName: "user-passkeys",
24378
+ capScope: "system",
24379
+ addonId: null,
24380
+ access: "create"
24381
+ },
24330
24382
  "vacuumControl.locate": {
24331
24383
  capName: "vacuum-control",
24332
24384
  capScope: "device",
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-gJgSPFxd.js");
5
+ const require_dist = require("../dist-DWb62H5U.js");
6
6
  let _camstack_shm_ring = require("@camstack/shm-ring");
7
7
  let node_fs = require("node:fs");
8
8
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { B as DeviceType, E as motionDetectionCapability, L as BaseAddon, U as hydrateSchema, x as evaluateZoneRules } from "../dist-gWOMlIyx.mjs";
1
+ import { B as DeviceType, E as motionDetectionCapability, L as BaseAddon, U as hydrateSchema, x as evaluateZoneRules } from "../dist-BalxNwOt.mjs";
2
2
  import { FrameRingReaderCache } from "@camstack/shm-ring";
3
3
  import { readFileSync } from "node:fs";
4
4
  import { join } from "node:path";
@@ -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-gJgSPFxd.js");
6
- const require_remote_source_plane = require("../remote-source-plane-CBPLC_6k.js");
5
+ const require_dist = require("../dist-DWb62H5U.js");
6
+ const require_remote_source_plane = require("../remote-source-plane-CZpzIVro.js");
7
7
  const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
8
8
  const require_worker_protocol = require("../worker-protocol-BCfO8gUF.js");
9
9
  let _camstack_shm_ring = require("@camstack/shm-ring");
@@ -1,5 +1,5 @@
1
- import { $ as boolean, D as nodePin, H as createEvent, I as errMsg, K as makeSourceBrokerId, L as BaseAddon, Q as array, V as EventCategory, Z as _enum, _ as customAction, it as object, k as pipelineRunnerCapability, ot as string, rt as number, tt as lazy, y as defineCustomActions } from "../dist-gWOMlIyx.mjs";
2
- import { n as isRemoteRestream, r as profileForStreamId, t as RemoteSourcePlane } from "../remote-source-plane-CaN4WP3E.mjs";
1
+ import { $ as boolean, D as nodePin, H as createEvent, I as errMsg, K as makeSourceBrokerId, L as BaseAddon, Q as array, V as EventCategory, Z as _enum, _ as customAction, it as object, k as pipelineRunnerCapability, ot as string, rt as number, tt as lazy, y as defineCustomActions } from "../dist-BalxNwOt.mjs";
2
+ import { n as isRemoteRestream, r as profileForStreamId, t as RemoteSourcePlane } from "../remote-source-plane-BCJW5CvF.mjs";
3
3
  import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
4
4
  import { t as isWorkerReply } from "../worker-protocol-pk7qdYXt.mjs";
5
5
  import { DecoderFrameRingSink, FrameRingReaderCache, unlinkSegment } from "@camstack/shm-ring";
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("../chunk-D6vf50IK.js");
2
- const require_dist = require("../dist-gJgSPFxd.js");
2
+ const require_dist = require("../dist-DWb62H5U.js");
3
3
  const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
4
4
  const require_model_download_service_C_IHWnXx = require("../model-download-service-C-IHWnXx-BLXzxpRB.js");
5
5
  let node_child_process = require("node:child_process");
@@ -1,4 +1,4 @@
1
- import { A as recordingCapability, B as DeviceType, D as nodePin, I as errMsg, L as BaseAddon, M as storageEvictableCapability, T as migrateConfigToBands, U as hydrateSchema, V as EventCategory, Y as selectAssignedProfileSlots, at as record, ot as string, s as EVENT_PAD_MS, u as RecordingConfigSchema } from "../dist-gWOMlIyx.mjs";
1
+ import { A as recordingCapability, B as DeviceType, D as nodePin, I as errMsg, L as BaseAddon, M as storageEvictableCapability, T as migrateConfigToBands, U as hydrateSchema, V as EventCategory, Y as selectAssignedProfileSlots, at as record, ot as string, s as EVENT_PAD_MS, u as RecordingConfigSchema } from "../dist-BalxNwOt.mjs";
2
2
  import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
3
3
  import { t as createFileDataPlaneHandler } from "../model-download-service-C-IHWnXx-BPy6aoAx.mjs";
4
4
  import { spawn } from "node:child_process";
@@ -1,4 +1,4 @@
1
- import { D as nodePin, I as errMsg, d as RingBuffer } from "./dist-gWOMlIyx.mjs";
1
+ import { D as nodePin, I as errMsg, d as RingBuffer } from "./dist-BalxNwOt.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  //#region src/stream-broker/stream-broker/decoder-session-proxy.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-gJgSPFxd.js");
1
+ const require_dist = require("./dist-DWb62H5U.js");
2
2
  let node_crypto = require("node:crypto");
3
3
  //#region src/stream-broker/stream-broker/decoder-session-proxy.ts
4
4
  /**