@camstack/addon-pipeline 1.1.26 → 1.1.28

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/audio-analyzer/index.js +7 -6
  2. package/dist/audio-analyzer/index.mjs +7 -6
  3. package/dist/audio-codec-ffmpeg/index.js +1 -1
  4. package/dist/audio-codec-ffmpeg/index.mjs +1 -1
  5. package/dist/constants-CAqYVigN.js +6615 -0
  6. package/dist/constants-oYgW36Ty.mjs +3587 -0
  7. package/dist/decoder-ffmpeg/index.js +74 -281
  8. package/dist/decoder-ffmpeg/index.mjs +73 -280
  9. package/dist/decoder-nodeav/index.js +1218 -0
  10. package/dist/decoder-nodeav/index.mjs +1210 -0
  11. package/dist/detection-pipeline/index.js +157 -219
  12. package/dist/detection-pipeline/index.mjs +157 -219
  13. package/dist/{dist-DAIlCdAx.js → dist-Biq62zt4.js} +372 -35
  14. package/dist/{dist-CgEP_0OL.mjs → dist-C6_wgXqF.mjs} +373 -24
  15. package/dist/dist-D3Ytt-_Y.js +41111 -0
  16. package/dist/dist-DluJuxV5.mjs +37976 -0
  17. package/dist/{frame-handle-plane-Dq20KtKL.mjs → frame-handle-plane-BIoY6nRV.mjs} +13 -5
  18. package/dist/{frame-handle-plane-DtTRX_0n.js → frame-handle-plane-D6BzyEgy.js} +13 -5
  19. package/dist/frame-ring-sink-9J0wCdLF.js +444 -0
  20. package/dist/frame-ring-sink-Cs9vby6v.mjs +409 -0
  21. package/dist/motion-wasm/index.js +55 -3
  22. package/dist/motion-wasm/index.mjs +55 -3
  23. package/dist/node-topology-platform-BkR_k6WT.mjs +15 -0
  24. package/dist/node-topology-platform-CFZ7F4xW.js +20 -0
  25. package/dist/pipeline-runner/index.js +50 -16
  26. package/dist/pipeline-runner/index.mjs +50 -16
  27. package/dist/recorder/index.js +36 -40
  28. package/dist/recorder/index.mjs +36 -40
  29. package/dist/stream-broker/_stub.js +2 -2
  30. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-5tQlh9h4.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DoReAb4y.mjs} +3 -3
  31. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DhY3MZ2C.mjs +26 -0
  32. package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BJK0-svt.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DtoYGpTp.mjs} +1 -1
  33. package/dist/stream-broker/{hostInit-DyLqyJaS.mjs → hostInit-C0SuwQhL.mjs} +3 -3
  34. package/dist/stream-broker/index.js +81 -40
  35. package/dist/stream-broker/index.mjs +81 -40
  36. package/dist/stream-broker/remoteEntry.js +1 -1
  37. package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-BDLNwJ_F.js → MaskShapeCanvas-DI4BY7W2-Br2yi8ah.js} +1 -1
  38. package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-CoLjNiUN.js → MotionZonesSettings-NcxxQN8r-BSCcPdPf.js} +1 -1
  39. package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-DJE3OU-q.js → PrivacyMaskSettings-APgPLF7p-ztxvxSjS.js} +1 -1
  40. package/embed-dist/assets/index-C5UpuPr8.css +2 -0
  41. package/embed-dist/assets/{index-C-pL8ETk.js → index-CeZV1B-2.js} +10 -10
  42. package/embed-dist/index.html +2 -2
  43. package/package.json +31 -3
  44. package/python/inference_pool.py +108 -121
  45. package/python/test_inference_pool_device_selection.py +47 -43
  46. package/python/yamnet_audio.py +1 -1
  47. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CkOPfV8r.mjs +0 -26
  48. package/embed-dist/assets/index-DrJ0ee3f.css +0 -2
@@ -4627,7 +4627,7 @@ function _instanceof(cls, params = {}) {
4627
4627
  return inst;
4628
4628
  }
4629
4629
  //#endregion
4630
- //#region ../types/dist/sleep-BO1nweKv.mjs
4630
+ //#region ../types/dist/sleep-BiDFW0E7.mjs
4631
4631
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4632
4632
  EventCategory["SystemBoot"] = "system.boot";
4633
4633
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -5440,6 +5440,100 @@ function createDurableState(deps) {
5440
5440
  };
5441
5441
  }
5442
5442
  /**
5443
+ * Per-node scoping for the shared addon-settings blob.
5444
+ *
5445
+ * An addon's settings store is hub-central (the `addon-settings` cap is
5446
+ * hub-routed — the hub instance answers for every node), so fields whose
5447
+ * value is a NODE fact (decoder backend, engine pick, probed hardware
5448
+ * capabilities) persist under the node-scoped key `<key>@<nodeId>` inside
5449
+ * the single shared blob. The SCHEMA field key stays bare: the write path
5450
+ * ({@link scopePatch}) maps the bare field onto the target node's scoped
5451
+ * key; the read/hydrate path ({@link projectStore}) maps THIS node's value
5452
+ * back, so UI forms and `resolveConfig` only ever see the bare key.
5453
+ *
5454
+ * Fields opt in via the `perNode: true` schema marker on `ConfigFieldBase`
5455
+ * (`interfaces/config-ui.ts`); `BaseAddon` derives the key set from the
5456
+ * schema and routes reads/writes through these helpers.
5457
+ *
5458
+ * ## No bare-key fallback — deliberate
5459
+ *
5460
+ * {@link readNodeValue} reads the node-scoped key ONLY. A node with no
5461
+ * scoped key resolves to `undefined` so the field's schema `default` wins —
5462
+ * NEVER `store[base]` and never another node's value. A bare legacy key in
5463
+ * the store is invisible to every node, hub included, so one node's
5464
+ * selection can never leak onto another. (This generalizes the
5465
+ * `decoder-backend-keys.ts` semantics — the no-fallback variant — over an
5466
+ * arbitrary set of per-node field keys.)
5467
+ *
5468
+ * Pure functions only — no I/O, no imports beyond the language. This is a
5469
+ * LEAF module: import it via its deep path, never from the root barrel.
5470
+ */
5471
+ /**
5472
+ * Normalize a raw kernel node id to the bare node id used for scoping.
5473
+ * `localNodeId` can carry a `<node>/<addon>` suffix on forked child
5474
+ * processes; per-node settings are per-NODE, so strip the addon segment.
5475
+ * `undefined` / `null` / empty falls back to `'hub'`.
5476
+ */
5477
+ function normalizeNodeId(raw) {
5478
+ if (raw === void 0 || raw === null || raw === "") return "hub";
5479
+ const slashIdx = raw.indexOf("/");
5480
+ if (slashIdx < 0) return raw;
5481
+ const bare = raw.slice(0, slashIdx);
5482
+ return bare === "" ? "hub" : bare;
5483
+ }
5484
+ /** The node-scoped store key for a per-node field: `<base>@<nodeId>`. */
5485
+ function nodeScopedKey(base, nodeId) {
5486
+ return `${base}@${normalizeNodeId(nodeId)}`;
5487
+ }
5488
+ /**
5489
+ * Read a node's value for a per-node field from the raw shared store:
5490
+ * the node-scoped key when present, otherwise `undefined`.
5491
+ * Deliberately NO bare-key fallback (see module doc) — the caller lets the
5492
+ * schema `default` win on `undefined`.
5493
+ */
5494
+ function readNodeValue(store, base, nodeId) {
5495
+ return store[nodeScopedKey(base, nodeId)];
5496
+ }
5497
+ /**
5498
+ * Re-map a UI/settings patch so every bare perNode field persists under the
5499
+ * TARGET node's scoped key; all other keys pass through unchanged. Used on
5500
+ * the write path so a save for one node never clobbers another node's value
5501
+ * (and the bare key is never written). Returns a new object — the input
5502
+ * patch is not mutated.
5503
+ */
5504
+ function scopePatch(patch, perNodeKeys, nodeId) {
5505
+ const out = {};
5506
+ for (const [key, value] of Object.entries(patch)) out[perNodeKeys.has(key) ? nodeScopedKey(key, nodeId) : key] = value;
5507
+ return out;
5508
+ }
5509
+ /**
5510
+ * Project the raw shared store onto the bare schema keys for ONE node so a
5511
+ * UI schema (whose field keys are bare) hydrates from that node's own
5512
+ * values:
5513
+ *
5514
+ * - EVERY `@`-scoped key (any node's) is dropped from the pass-through.
5515
+ * - Every bare perNode key is dropped from the pass-through (a stray bare
5516
+ * legacy key must never hydrate any node — no bare fallback).
5517
+ * - THIS node's effective value ({@link readNodeValue}) is then laid onto
5518
+ * each bare perNode key; when the node has no scoped key the bare key is
5519
+ * left ABSENT so the field's schema `default` wins.
5520
+ *
5521
+ * Returns a new object — the input store is not mutated.
5522
+ */
5523
+ function projectStore(store, perNodeKeys, nodeId) {
5524
+ const out = {};
5525
+ for (const [key, value] of Object.entries(store)) {
5526
+ if (key.includes("@")) continue;
5527
+ if (perNodeKeys.has(key)) continue;
5528
+ out[key] = value;
5529
+ }
5530
+ for (const base of perNodeKeys) {
5531
+ const value = readNodeValue(store, base, nodeId);
5532
+ if (value !== void 0) out[base] = value;
5533
+ }
5534
+ return out;
5535
+ }
5536
+ /**
5443
5537
  * Base class for CamStack addons. Eliminates settings boilerplate:
5444
5538
  *
5445
5539
  * - Typed `config` property with automatic resolution from store + defaults
@@ -5607,23 +5701,63 @@ var BaseAddon = class {
5607
5701
  deviceSettingsSchema() {
5608
5702
  return null;
5609
5703
  }
5610
- async getGlobalSettings(overlay, cap, _nodeId) {
5704
+ async getGlobalSettings(overlay, cap, nodeId) {
5611
5705
  const schema = this.globalSettingsSchema(cap);
5612
5706
  if (!schema) return { sections: [] };
5613
- const raw = await this._ctx?.settings?.readAddonStore() ?? {};
5707
+ const projected = await this.resolveGlobalStore(nodeId, cap);
5614
5708
  return hydrateSchema(schema, overlay ? {
5615
- ...raw,
5709
+ ...projected,
5616
5710
  ...overlay
5617
- } : raw);
5711
+ } : projected);
5712
+ }
5713
+ /**
5714
+ * The raw addon store PROJECTED onto the target node's bare per-node keys:
5715
+ * every `perNode: true` field carries THAT node's scoped value on its bare
5716
+ * key (absent scoped key ⇒ key absent, so the schema `default` wins — no
5717
+ * bare fallback), all `@`-scoped and stray bare per-node keys are dropped.
5718
+ * A no-op passthrough when the schema declares no `perNode` field.
5719
+ *
5720
+ * This is the sanctioned way for a `getGlobalSettings` OVERRIDE that needs
5721
+ * the store for custom option logic (option narrowing, value snapping) to
5722
+ * read it per-node — never `ctx.settings.readAddonStore()` directly.
5723
+ * `nodeId` omitted ⇒ the local node (node-blind injection from ctx).
5724
+ */
5725
+ async resolveGlobalStore(nodeId, cap) {
5726
+ const raw = await this._ctx?.settings?.readAddonStore() ?? {};
5727
+ const keys = this.perNodeKeys(cap);
5728
+ const node = normalizeNodeId(nodeId ?? this._ctx?.kernel?.localNodeId);
5729
+ return keys.size > 0 ? projectStore(raw, keys, node) : raw;
5618
5730
  }
5619
- async updateGlobalSettings(patch, _nodeId) {
5620
- await this._ctx?.settings?.writeAddonStore(patch);
5731
+ async updateGlobalSettings(patch, nodeId) {
5732
+ const keys = this.perNodeKeys();
5733
+ const localNode = normalizeNodeId(this._ctx?.kernel?.localNodeId);
5734
+ const target = normalizeNodeId(nodeId ?? this._ctx?.kernel?.localNodeId);
5735
+ const barePatch = patch;
5736
+ const scoped = keys.size > 0 ? scopePatch(barePatch, keys, target) : barePatch;
5737
+ await this._ctx?.settings?.writeAddonStore(scoped);
5738
+ if (target !== localNode) return;
5621
5739
  await this.resolveConfig();
5622
5740
  await this.onConfigChanged();
5623
5741
  this.emitLifecycle(EventCategory.AddonUpdated, { level: "global" });
5624
5742
  this.maybeAutoRestart(patch, this.globalSettingsSchema());
5625
5743
  }
5626
5744
  /**
5745
+ * The set of field keys the global settings schema declares `perNode: true`
5746
+ * — derived once per `cap` argument and memoized (schemas are static
5747
+ * declarations). Empty set ⇒ every per-node code path is bypassed and the
5748
+ * settings API behaves exactly like the legacy node-agnostic one.
5749
+ */
5750
+ _perNodeKeysCache = /* @__PURE__ */ new Map();
5751
+ perNodeKeys(cap) {
5752
+ const cacheKey = cap ?? "";
5753
+ const cached = this._perNodeKeysCache.get(cacheKey);
5754
+ if (cached) return cached;
5755
+ const schema = this.globalSettingsSchema(cap);
5756
+ const keys = new Set(schema ? schema.sections.flatMap((section) => collectPerNodeFieldKeys(section.fields)) : []);
5757
+ this._perNodeKeysCache.set(cacheKey, keys);
5758
+ return keys;
5759
+ }
5760
+ /**
5627
5761
  * If any field in `patch` is marked `requiresRestart` in `schema`,
5628
5762
  * schedule an addon restart for the next tick. Deferred via
5629
5763
  * `setImmediate` so the tRPC mutation that triggered the write has
@@ -5776,12 +5910,19 @@ var BaseAddon = class {
5776
5910
  * The merge is shallow: each key in `defaults` is checked against the store.
5777
5911
  * Only keys present in defaults are read — the store can contain extra keys
5778
5912
  * (e.g. from older versions) without polluting the typed config.
5913
+ *
5914
+ * Keys the global settings schema declares `perNode: true` resolve from
5915
+ * THIS node's scoped key (`<key>@<localNode>`) via `readNodeValue` — never
5916
+ * from the bare key — so a per-node field resolves to this node's own
5917
+ * selection at boot (absent scoped key ⇒ the constructor default wins).
5779
5918
  */
5780
5919
  async resolveConfig() {
5781
5920
  const stored = await this.readAddonStoreWithRetry();
5921
+ const perNode = this.perNodeKeys();
5922
+ const localNode = normalizeNodeId(this._ctx?.kernel?.localNodeId);
5782
5923
  const resolved = { ...this.defaults };
5783
5924
  for (const key of Object.keys(this.defaults)) {
5784
- const storedValue = stored[key];
5925
+ const storedValue = perNode.has(key) ? readNodeValue(stored, key, localNode) : stored[key];
5785
5926
  if (storedValue !== void 0 && storedValue !== null) {
5786
5927
  const defaultType = typeof this.defaults[key];
5787
5928
  if (typeof storedValue === defaultType) resolved[key] = storedValue;
@@ -5865,6 +6006,27 @@ var BaseAddon = class {
5865
6006
  }
5866
6007
  };
5867
6008
  /**
6009
+ * Collect the keys of every field marked `perNode: true`, recursing into
6010
+ * layout containers (`group` fields and `sub-tabs` tabs) the same way
6011
+ * `hydrateSchema` does. Valueless structural fields (separator/info/…)
6012
+ * don't declare `perNode` and are excluded by the `in` narrowing.
6013
+ */
6014
+ function collectPerNodeFieldKeys(fields) {
6015
+ const collected = [];
6016
+ for (const field of fields) {
6017
+ if (field.type === "group") {
6018
+ collected.push(...collectPerNodeFieldKeys(field.fields));
6019
+ continue;
6020
+ }
6021
+ if (field.type === "sub-tabs") {
6022
+ for (const tab of field.tabs) collected.push(...collectPerNodeFieldKeys(tab.fields));
6023
+ continue;
6024
+ }
6025
+ if ("perNode" in field && field.perNode === true) collected.push(field.key);
6026
+ }
6027
+ return collected;
6028
+ }
6029
+ /**
5868
6030
  * Normalize an `ICamstackAddon.initialize()` return value into the
5869
6031
  * `AddonInitResult` envelope. Arrays are wrapped into `{ providers }`;
5870
6032
  * envelopes pass through; void stays void.
@@ -6272,11 +6434,6 @@ var ProfileRtspEntrySchema = object({
6272
6434
  function parseJsonUnknown(text) {
6273
6435
  return JSON.parse(text);
6274
6436
  }
6275
- /** Narrow an unknown value to a plain `Record<string, unknown>` or return null. */
6276
- function asJsonObject(value) {
6277
- if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
6278
- return { ...value };
6279
- }
6280
6437
  var DeviceType = /* @__PURE__ */ function(DeviceType) {
6281
6438
  DeviceType["Camera"] = "camera";
6282
6439
  DeviceType["Hub"] = "hub";
@@ -6361,6 +6518,13 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
6361
6518
  /** Single still-image entity (HA `image.*`). Read-only display of an
6362
6519
  * `entity_picture` signed URL the browser loads directly. `image` cap. */
6363
6520
  DeviceType["Image"] = "image";
6521
+ /** Smart pet feeder — cloud-connected food dispenser with a bowl food
6522
+ * level, battery, desiccant life, feeding state and manual-feed /
6523
+ * call-pet / maintenance actions. Installed with the `pet-feeder` cap;
6524
+ * dual-hopper models (D4S/D4SH) expose per-hopper portions. Sources:
6525
+ * native PetKit (`nodepetkit` `FeederDevice`), reusable by other feeder
6526
+ * integrations sharing the same food/desiccant/hopper surface. */
6527
+ DeviceType["PetFeeder"] = "pet-feeder";
6364
6528
  return DeviceType;
6365
6529
  }({});
6366
6530
  var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
@@ -10840,7 +11004,8 @@ var motionDetectionCapability = {
10840
11004
  methods: {
10841
11005
  analyze: method(object({
10842
11006
  deviceId: number(),
10843
- frame: FrameInputSchema
11007
+ frame: FrameInputSchema.optional(),
11008
+ frameHandle: FrameHandleSchema.optional()
10844
11009
  }), MotionAnalysisResultSchema, { kind: "mutation" }),
10845
11010
  removeCamera: method(object({ deviceId: number() }), _void(), { kind: "mutation" }),
10846
11011
  reset: method(_void(), _void(), { kind: "mutation" })
@@ -11152,11 +11317,20 @@ var pipelineExecutorCapability = {
11152
11317
  * legacy call shape used by existing benchmark code; once all
11153
11318
  * callers pass it explicitly we make it required.
11154
11319
  *
11155
- * Exactly one of `frame`, `imageBase64`, `referenceImage` must be
11156
- * provided:
11320
+ * Exactly one of `frame`, `frameHandle`, `imageBase64`,
11321
+ * `referenceImage` must be provided:
11157
11322
  * - `frame`: runtime dispatch path (runner → decoded broker frame).
11158
11323
  * Carries the raw buffer, dimensions, and format; the executor
11159
11324
  * uses it directly without base64 round-tripping.
11325
+ * - `frameHandle` (CB5): a zero-pixel shm `FrameHandle` for the SAME
11326
+ * decoded frame. Both runner and executor are hub-local processes
11327
+ * sharing `/dev/shm`, so the executor maps the named segment and
11328
+ * reads the pixels back zero-copy — eliminating the ~1.2MB
11329
+ * re-serialisation over UDS/MsgPack the `frame` path pays per call.
11330
+ * High-risk: the FrameRing is a latest-wins seqlock with no
11331
+ * refcount, so a recycled slot yields a null read; the executor
11332
+ * then degrades to an empty result and the runner ships pixels via
11333
+ * `frame` as the fallback (queue-depth gated on the runner side).
11160
11334
  * - `imageBase64`: one-shot test path (benchmark ImageTab).
11161
11335
  * - `referenceImage`: named file from the reference-image store.
11162
11336
  */
@@ -11164,6 +11338,12 @@ var pipelineExecutorCapability = {
11164
11338
  engine: PipelineEngineChoiceSchema.optional(),
11165
11339
  steps: array(PipelineStepInputSchema).min(1),
11166
11340
  frame: FrameInputSchema.optional(),
11341
+ /**
11342
+ * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
11343
+ * the decoded pixels live in. One more member of the one-of
11344
+ * frame/frameHandle/image/imageBase64/referenceImage group.
11345
+ */
11346
+ frameHandle: FrameHandleSchema.optional(),
11167
11347
  imageBase64: string().optional(),
11168
11348
  /**
11169
11349
  * Binary JPEG bytes — preferred over `imageBase64` on internal
@@ -11972,6 +12152,113 @@ object({
11972
12152
  lastFetchedAt: number()
11973
12153
  });
11974
12154
  DeviceType.Sensor;
12155
+ /**
12156
+ * Feeder connectivity / power status — mirrors the HA petkit device-status
12157
+ * enum: `normal` (online, mains), `offline` (not reaching PetKit cloud),
12158
+ * `on_batteries` (running on battery backup). `null` until first reported.
12159
+ */
12160
+ var PetFeederDeviceStatusSchema = _enum([
12161
+ "normal",
12162
+ "offline",
12163
+ "on_batteries"
12164
+ ]);
12165
+ var gramsPortion = number().int().min(4).max(200);
12166
+ object({
12167
+ /** Food currently in the bowl (grams). Null when the device has not
12168
+ * reported a reading yet. On dual-hopper models this is the combined
12169
+ * bowl reading; per-hopper levels live in `food1`/`food2`. */
12170
+ foodLevel: number().nullable(),
12171
+ /** Hopper-1 food level (grams) on dual-hopper feeders; null on
12172
+ * single-hopper models. */
12173
+ food1: number().nullable(),
12174
+ /** Hopper-2 food level (grams) on dual-hopper feeders; null on
12175
+ * single-hopper models. */
12176
+ food2: number().nullable(),
12177
+ /** Derived low-food flag — mirrors the HA `food_level` binary_sensor
12178
+ * (`device_class: problem`, on = low). True when the bowl is empty /
12179
+ * below the feeder's low threshold. */
12180
+ lowFood: boolean(),
12181
+ /** Battery charge 0..100 (%). Null on mains-powered models or when the
12182
+ * device has no battery reading. */
12183
+ batteryPower: number().min(0).max(100).nullable(),
12184
+ /** Days of desiccant life remaining. Null when the model has no
12185
+ * desiccant sensor. */
12186
+ desiccantLeftDays: number().nullable(),
12187
+ /** True while a feed is in progress. */
12188
+ feeding: boolean(),
12189
+ /** Decoded connectivity / power status (HA petkit device-status enum).
12190
+ * Null until the device has reported a status. */
12191
+ status: PetFeederDeviceStatusSchema.nullable(),
12192
+ /** Decoded human-readable fault message. Null (or the device's `no_error`
12193
+ * sentinel) means healthy; a non-null string is an active fault. Pairs
12194
+ * with `errorCode` for consumers that want the raw integer. */
12195
+ error: string().nullable(),
12196
+ /** Raw device error code (0 / null = no error). */
12197
+ errorCode: number().nullable(),
12198
+ /** True for D4S/D4SH dual-hopper hardware — gates the per-hopper UI. */
12199
+ isDualHopper: boolean(),
12200
+ /** Child-lock (manual-lock) setting — buttons on the unit are disabled. */
12201
+ childLock: boolean(),
12202
+ /** Front indicator-light setting. */
12203
+ indicatorLight: boolean(),
12204
+ /** Play a chime when dispensing. */
12205
+ feedSound: boolean(),
12206
+ /** Speaker / prompt volume level (device-scaled integer). */
12207
+ volume: number(),
12208
+ /** Ms epoch when the slice was last refreshed from the cloud. */
12209
+ lastFetchedAt: number()
12210
+ });
12211
+ DeviceType.PetFeeder, method(object({
12212
+ deviceId: number().int().nonnegative(),
12213
+ grams: gramsPortion.optional(),
12214
+ hopper1: gramsPortion.optional(),
12215
+ hopper2: gramsPortion.optional()
12216
+ }), _void(), {
12217
+ kind: "mutation",
12218
+ auth: "admin"
12219
+ }), method(object({ deviceId: number().int().nonnegative() }), _void(), {
12220
+ kind: "mutation",
12221
+ auth: "admin"
12222
+ }), method(object({ deviceId: number().int().nonnegative() }), _void(), {
12223
+ kind: "mutation",
12224
+ auth: "admin"
12225
+ }), method(object({ deviceId: number().int().nonnegative() }), _void(), {
12226
+ kind: "mutation",
12227
+ auth: "admin"
12228
+ }), method(object({ deviceId: number().int().nonnegative() }), _void(), {
12229
+ kind: "mutation",
12230
+ auth: "admin"
12231
+ }), method(object({
12232
+ deviceId: number().int().nonnegative(),
12233
+ soundId: number().int().nonnegative()
12234
+ }), _void(), {
12235
+ kind: "mutation",
12236
+ auth: "admin"
12237
+ }), method(object({
12238
+ deviceId: number().int().nonnegative(),
12239
+ on: boolean()
12240
+ }), _void(), {
12241
+ kind: "mutation",
12242
+ auth: "admin"
12243
+ }), method(object({
12244
+ deviceId: number().int().nonnegative(),
12245
+ on: boolean()
12246
+ }), _void(), {
12247
+ kind: "mutation",
12248
+ auth: "admin"
12249
+ }), method(object({
12250
+ deviceId: number().int().nonnegative(),
12251
+ on: boolean()
12252
+ }), _void(), {
12253
+ kind: "mutation",
12254
+ auth: "admin"
12255
+ }), method(object({
12256
+ deviceId: number().int().nonnegative(),
12257
+ level: number().int().nonnegative()
12258
+ }), _void(), {
12259
+ kind: "mutation",
12260
+ auth: "admin"
12261
+ });
11975
12262
  object({
11976
12263
  /** Instantaneous power draw in watts. */
11977
12264
  watts: number().optional(),
@@ -14087,11 +14374,13 @@ var decoderCapability = {
14087
14374
  }), _void()),
14088
14375
  pullFrames: method(object({
14089
14376
  sessionId: string(),
14090
- maxCount: number().default(1)
14377
+ maxCount: number().default(1),
14378
+ waitMs: number().optional()
14091
14379
  }), array(DecodedFrameSchema)),
14092
14380
  pullHandles: method(object({
14093
14381
  sessionId: string(),
14094
- maxCount: number().default(1)
14382
+ maxCount: number().default(1),
14383
+ waitMs: number().optional()
14095
14384
  }), array(FrameHandleSchema)),
14096
14385
  getFrame: method(object({ handle: FrameHandleSchema }), DecodedFrameSchema.nullable()),
14097
14386
  getShmStats: method(object({ sessionId: string() }), ShmRingStatsSchema.nullable()),
@@ -18727,7 +19016,10 @@ var HwAccelBackendInputSchema = _enum([
18727
19016
  "webgpu",
18728
19017
  "none"
18729
19018
  ]).nullable().optional();
18730
- var HwAccelResolutionSchema = object({ preferred: array(string()).readonly() });
19019
+ var HwAccelResolutionSchema = object({
19020
+ preferred: array(string()).readonly(),
19021
+ rationale: string()
19022
+ });
18731
19023
  var HardwareEncoderIdSchema = _enum([
18732
19024
  "h264_videotoolbox",
18733
19025
  "hevc_videotoolbox",
@@ -18832,10 +19124,7 @@ var ResolvedInferenceConfigSchema = object({
18832
19124
  format: ModelFormatSchema,
18833
19125
  reason: string()
18834
19126
  });
18835
- method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema), method(object({ requirements: array(ModelRequirementSchema).readonly() }), ResolvedInferenceConfigSchema), method(object({
18836
- prefer: HwAccelBackendInputSchema,
18837
- nodeId: string().optional()
18838
- }), HwAccelResolutionSchema), method(_void(), HardwareEncodersSchema), method(_void(), HardwareEncodersSchema, {
19127
+ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema), method(object({ requirements: array(ModelRequirementSchema).readonly() }), ResolvedInferenceConfigSchema), method(object({ prefer: HwAccelBackendInputSchema }), HwAccelResolutionSchema), method(_void(), HardwareEncodersSchema), method(_void(), HardwareEncodersSchema, {
18839
19128
  kind: "mutation",
18840
19129
  auth: "admin"
18841
19130
  }), method(_void(), HardwareDecodeAccelsSchema), method(_void(), HardwareDecodeAccelsSchema, {
@@ -21833,6 +22122,66 @@ Object.freeze({
21833
22122
  addonId: null,
21834
22123
  access: "create"
21835
22124
  },
22125
+ "petFeeder.callPet": {
22126
+ capName: "pet-feeder",
22127
+ capScope: "device",
22128
+ addonId: null,
22129
+ access: "create"
22130
+ },
22131
+ "petFeeder.cancelFeed": {
22132
+ capName: "pet-feeder",
22133
+ capScope: "device",
22134
+ addonId: null,
22135
+ access: "create"
22136
+ },
22137
+ "petFeeder.feed": {
22138
+ capName: "pet-feeder",
22139
+ capScope: "device",
22140
+ addonId: null,
22141
+ access: "create"
22142
+ },
22143
+ "petFeeder.markFoodReplenished": {
22144
+ capName: "pet-feeder",
22145
+ capScope: "device",
22146
+ addonId: null,
22147
+ access: "create"
22148
+ },
22149
+ "petFeeder.playSound": {
22150
+ capName: "pet-feeder",
22151
+ capScope: "device",
22152
+ addonId: null,
22153
+ access: "create"
22154
+ },
22155
+ "petFeeder.resetDesiccant": {
22156
+ capName: "pet-feeder",
22157
+ capScope: "device",
22158
+ addonId: null,
22159
+ access: "delete"
22160
+ },
22161
+ "petFeeder.setChildLock": {
22162
+ capName: "pet-feeder",
22163
+ capScope: "device",
22164
+ addonId: null,
22165
+ access: "create"
22166
+ },
22167
+ "petFeeder.setFeedSound": {
22168
+ capName: "pet-feeder",
22169
+ capScope: "device",
22170
+ addonId: null,
22171
+ access: "create"
22172
+ },
22173
+ "petFeeder.setIndicatorLight": {
22174
+ capName: "pet-feeder",
22175
+ capScope: "device",
22176
+ addonId: null,
22177
+ access: "create"
22178
+ },
22179
+ "petFeeder.setVolume": {
22180
+ capName: "pet-feeder",
22181
+ capScope: "device",
22182
+ addonId: null,
22183
+ access: "create"
22184
+ },
21836
22185
  "pipelineAnalytics.clearTracks": {
21837
22186
  capName: "pipeline-analytics",
21838
22187
  capScope: "device",
@@ -23981,4 +24330,4 @@ function defaultDeviceFor(id) {
23981
24330
  return def(id).defaultDevice;
23982
24331
  }
23983
24332
  //#endregion
23984
- export { parseProfileBrokerId as $, motionDetectionCapability as A, errMsg as B, defineCustomActions as C, mapAudioLabelToMacro as D, hfModelUrl as E, runtimeDevices as F, EventCategory as G, CAM_PROFILE_ORDER as H, storageEvictableCapability as I, createEvent as J, asJsonObject as K, streamBrokerCapability as L, pipelineExecutorCapability as M, pipelineRunnerCapability as N, maskUrlCredentials as O, recordingCapability as P, parseJsonUnknown as Q, supportedRuntimes as R, defaultDeviceFor as S, evaluateZoneRules as T, DeviceFeature as U, BaseAddon as V, DeviceType as W, makeProfileBrokerId as X, hydrateSchema as Y, makeSourceBrokerId as Z, audioAnalyzerCapability as _, COCO_TO_MACRO as a, discriminatedUnion as at, customAction as b, EVENT_PAD_MS as c, number as ct, HWACCEL_OPTIONS as d, string as dt, selectAssignedProfileSlots as et, RecordingConfigSchema as f, union as ft, audioAnalysisCapability as g, addonWidgetsSourceCapability as h, COCO_80_LABELS as i, boolean as it, nodePin as j, migrateConfigToBands as k, EncodeProfileSchema as l, object as lt, YAMNET_TO_MACRO as m, AUDIO_BACKEND_CHOICES as n, _enum as nt, DEFAULT_AUDIO_ANALYZER_CONFIG as o, lazy as ot, RingBuffer as p, createDurableState as q, AUDIO_MACRO_LABELS as r, array as rt, DEFAULT_DECODER_HWACCEL_CONFIG as s, literal as st, APPLE_SA_TO_MACRO as t, sleep as tt, HF_BASE_URL as u, record as ut, audioCodecCapability as v, detectionPipelineCapability as w, decoderCapability as x, cameraStreamsCapability as y, webrtcSessionCapability as z };
24333
+ export { sleep as $, motionDetectionCapability as A, errMsg as B, defineCustomActions as C, mapAudioLabelToMacro as D, hfModelUrl as E, runtimeDevices as F, EventCategory as G, CAM_PROFILE_ORDER as H, storageEvictableCapability as I, makeProfileBrokerId as J, createEvent as K, streamBrokerCapability as L, pipelineExecutorCapability as M, pipelineRunnerCapability as N, maskUrlCredentials as O, recordingCapability as P, selectAssignedProfileSlots as Q, supportedRuntimes as R, defaultDeviceFor as S, evaluateZoneRules as T, DeviceFeature as U, BaseAddon as V, DeviceType as W, parseJsonUnknown as X, makeSourceBrokerId as Y, parseProfileBrokerId as Z, audioAnalyzerCapability as _, COCO_TO_MACRO as a, literal as at, customAction as b, EVENT_PAD_MS as c, record as ct, HWACCEL_OPTIONS as d, _enum as et, RecordingConfigSchema as f, audioAnalysisCapability as g, addonWidgetsSourceCapability as h, COCO_80_LABELS as i, lazy as it, nodePin as j, migrateConfigToBands as k, EncodeProfileSchema as l, string as lt, YAMNET_TO_MACRO as m, AUDIO_BACKEND_CHOICES as n, boolean as nt, DEFAULT_AUDIO_ANALYZER_CONFIG as o, number as ot, RingBuffer as p, hydrateSchema as q, AUDIO_MACRO_LABELS as r, discriminatedUnion as rt, DEFAULT_DECODER_HWACCEL_CONFIG as s, object as st, APPLE_SA_TO_MACRO as t, array as tt, HF_BASE_URL as u, union as ut, audioCodecCapability as v, detectionPipelineCapability as w, decoderCapability as x, cameraStreamsCapability as y, webrtcSessionCapability as z };