@camstack/addon-smtp-nodemailer 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/smtp.addon.js +1289 -1064
  2. package/dist/smtp.addon.mjs +1289 -1064
  3. package/package.json +1 -1
@@ -4665,63 +4665,7 @@ function _instanceof(cls, params = {}) {
4665
4665
  return inst;
4666
4666
  }
4667
4667
  //#endregion
4668
- //#region ../types/dist/index.mjs
4669
- /**
4670
- * Deep wiring healthcheck — snapshot of active reachability probes across
4671
- * every declared capability + widget of every installed plugin, on every
4672
- * node. Produced by the backend `WiringHealthService` and surfaced via
4673
- * `GET /health/wiring`, the tRPC `health.wiring` query, and the boot-gate.
4674
- *
4675
- * Unlike `/health` (process liveness), this reflects whether each cap/widget
4676
- * is actually *reachable* over the real cap-dispatch path. See spec
4677
- * `docs/superpowers/specs/2026-05-23-deep-healthcheck-design.md`.
4678
- */
4679
- /** What kind of target a probe addressed. */
4680
- var wiringProbeKindSchema = _enum([
4681
- "singleton",
4682
- "device",
4683
- "widget"
4684
- ]);
4685
- /** Result of probing a single (cap|widget [, device]) target. */
4686
- var wiringProbeResultSchema = object({
4687
- capName: string(),
4688
- kind: wiringProbeKindSchema,
4689
- deviceId: number().optional(),
4690
- reachable: boolean(),
4691
- latencyMs: number(),
4692
- error: string().optional()
4693
- });
4694
- /** Per-addon roll-up of cap + widget probe results. */
4695
- var wiringAddonHealthSchema = object({
4696
- addonId: string(),
4697
- caps: array(wiringProbeResultSchema).readonly(),
4698
- widgets: array(wiringProbeResultSchema).readonly()
4699
- });
4700
- /** Per-node roll-up. */
4701
- var wiringNodeHealthSchema = object({
4702
- nodeId: string(),
4703
- addons: array(wiringAddonHealthSchema).readonly()
4704
- });
4705
- object({
4706
- /** True only when every probed target is reachable. */
4707
- ok: boolean(),
4708
- /** True when at least one target is unreachable. */
4709
- degraded: boolean(),
4710
- checkedAt: string(),
4711
- nodes: array(wiringNodeHealthSchema).readonly(),
4712
- summary: object({
4713
- total: number(),
4714
- reachable: number(),
4715
- unreachable: number()
4716
- })
4717
- });
4718
- var MODEL_FORMATS = [
4719
- "onnx",
4720
- "coreml",
4721
- "openvino",
4722
- "tflite",
4723
- "pt"
4724
- ];
4668
+ //#region ../types/dist/sleep-D7JeS58T.mjs
4725
4669
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4726
4670
  EventCategory["SystemBoot"] = "system.boot";
4727
4671
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -5019,6 +4963,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5019
4963
  */
5020
4964
  EventCategory["PipelineEngineMetricsSnapshot"] = "pipeline.engine-metrics-snapshot";
5021
4965
  /**
4966
+ * Per-node detection-engine runtime-provisioning transition. Emitted by
4967
+ * the detection-pipeline provider on every state change of its lazy
4968
+ * engine-provisioning machine (idle → installing → verifying → ready,
4969
+ * or → failed with a `nextRetryAt`). Payload is the
4970
+ * `EngineProvisioningState` snapshot; `event.source.nodeId` carries the
4971
+ * node. The Pipeline page subscribes to drive a live "installing
4972
+ * OpenVINO… / ready" indicator per node without polling
4973
+ * `pipelineExecutor.getEngineProvisioning`. Telemetry-grade (D8): the UI
4974
+ * also reads the cap snapshot on mount / reconnect. Phase 2.
4975
+ */
4976
+ EventCategory["PipelineEngineProvisioning"] = "pipeline.engine-provisioning";
4977
+ /**
5022
4978
  * Cluster topology snapshot. Carries the same payload returned by
5023
4979
  * `nodes.topology` (every reachable node + addons + processes).
5024
4980
  * Emitted by the hub on any agent / addon lifecycle change
@@ -6032,7 +5988,7 @@ var ProfileSlotSchema = object({
6032
5988
  * Zod schema for StreamSourceEntry — the canonical stream descriptor
6033
5989
  * exposed by ICameraDevice.getStreamSources() and consumed by the broker.
6034
5990
  */
6035
- var StreamSourceEntrySchema = object({
5991
+ var StreamSourceEntrySchema$1 = object({
6036
5992
  id: string(),
6037
5993
  label: string(),
6038
5994
  protocol: _enum([
@@ -6254,894 +6210,1080 @@ var ProfileRtspEntrySchema = object({
6254
6210
  codec: string().optional(),
6255
6211
  resolution: CamStreamResolutionSchema.optional()
6256
6212
  });
6257
- /**
6258
- * Numeric day-of-week: 0 = Sunday … 6 = Saturday (matches `Date.getDay`).
6259
- * Named `RecordingWeekday` to avoid collision with the string-union
6260
- * `Weekday` exported from `interfaces/timezones.ts`.
6261
- */
6262
- var RecordingWeekdaySchema = number().int().min(0).max(6);
6263
- var HHMM = /^([01]\d|2[0-3]):[0-5]\d$/;
6264
- var RecordingScheduleSchema = discriminatedUnion("kind", [object({ kind: literal("always") }), object({
6265
- kind: literal("timeOfDay"),
6266
- start: string().regex(HHMM),
6267
- end: string().regex(HHMM),
6268
- /** Restrict to these weekdays; omit = every day. */
6269
- days: array(RecordingWeekdaySchema).optional()
6270
- })]);
6271
- var RecordingModeSchema = _enum([
6272
- "continuous",
6273
- "onMotion",
6274
- "onAudioThreshold"
6275
- ]);
6276
- /**
6277
- * First-class, authoritative per-camera storage mode the netta choice the UI
6278
- * reads directly (never inferred from `rules`):
6279
- * - `off` not recording.
6280
- * - `events` — record only around triggers (motion / audio threshold),
6281
- * with pre/post-buffer.
6282
- * - `continuous` record 24/7 within the schedule.
6283
- *
6284
- * `mode` compiles one-way to the internal `rules[]` consumed by the policy
6285
- * engine (see `compileRules`); `rules[]` is never authored directly anymore.
6286
- */
6287
- var RecordingStorageModeSchema = _enum([
6288
- "off",
6289
- "events",
6290
- "continuous"
6291
- ]);
6292
- /** Which detectors trigger an `events`-mode recording. */
6293
- var RecordingTriggersSchema = object({
6294
- motion: boolean().optional(),
6295
- audioThresholdDbfs: number().optional()
6296
- });
6297
- /**
6298
- * Mode of a single recording band the recorder per-band vocabulary.
6299
- *
6300
- * Distinct from `RecordingStorageModeSchema` (which carries `off`): a band is
6301
- * only ever `continuous` or `events`; "off" is expressed by the absence of a
6302
- * covering band, not by a band value.
6303
- */
6304
- var RecordingBandModeSchema = _enum(["continuous", "events"]);
6305
- /**
6306
- * Triggers for an `events`-mode band. Identical shape to
6307
- * `RecordingTriggersSchema`reuse that schema as the band trigger type so the
6308
- * two never drift.
6309
- */
6310
- var RecordingBandTriggersSchema = RecordingTriggersSchema;
6311
- /**
6312
- * A single mode-per-band window the canonical recorder band shape, the
6313
- * single source of truth re-used by `addon-pipeline/recorder`.
6314
- *
6315
- * `days` lists the weekdays the band covers (empty = every day, matching the
6316
- * band engine's `applies` rule). `start`/`end` are `HH:MM`; an `end <= start`
6317
- * span wraps past midnight (handled by the band engine).
6318
- */
6319
- var RecordingBandSchema = object({
6320
- days: array(RecordingWeekdaySchema),
6321
- start: string().regex(HHMM),
6322
- end: string().regex(HHMM),
6323
- mode: RecordingBandModeSchema,
6324
- triggers: RecordingBandTriggersSchema.optional(),
6325
- preBufferSec: number().min(0).optional(),
6326
- postBufferSec: number().min(0).optional()
6327
- });
6328
- var RecordingRuleSchema = object({
6329
- schedule: RecordingScheduleSchema,
6330
- mode: RecordingModeSchema,
6331
- /** Seconds of footage to retain BEFORE a trigger (applied at keep/discard). */
6332
- preBufferSec: number().min(0).default(0),
6333
- /** Keep recording until this many seconds after the last trigger. */
6334
- postBufferSec: number().min(0).default(0),
6335
- /** Each new trigger restarts the post-buffer window. */
6336
- resetTimeoutOnNewEvent: boolean().default(true),
6337
- /** onAudioThreshold only dBFS level that counts as a trigger. */
6338
- thresholdDbfs: number().optional()
6339
- });
6340
- /**
6341
- * Per-device retention overrides. Every field is optional; an unset or `0`
6342
- * value inherits the node-wide recorder default. Only footage-lifetime limits
6343
- * live per-camera: `maxAgeDays` and `maxSizeGb`. The disk-occupancy threshold
6344
- * (when the volume is too full to keep recording) is NOT a per-camera concern —
6345
- * it belongs to the StorageLocation (`StorageLocation.config.minFreePercent`),
6346
- * shared by every camera writing to that volume.
6347
- */
6348
- var RecordingRetentionSchema = object({
6349
- maxAgeDays: number().min(0).optional(),
6350
- maxSizeGb: number().min(0).optional()
6351
- });
6352
- /**
6353
- * The full per-camera recording intent — the wire shape of a RecordingTarget.
6354
- *
6355
- * `mode` is the authoritative storage choice; `schedule`/`triggers`/`pre`/`post`
6356
- * are its mode-specific parameters. `rules` is a DEPRECATED authoring input kept
6357
- * only for transition + migration (`migrateRulesToMode`); the policy engine
6358
- * consumes the compiled output of `compileRules(config)`, never `rules` directly.
6359
- */
6360
- var RecordingConfigSchema = object({
6361
- enabled: boolean(),
6362
- /** Authoritative storage mode. Absent on legacy targets → derived once via
6363
- * `migrateRulesToMode`, then persisted. */
6364
- mode: RecordingStorageModeSchema.optional(),
6365
- profiles: array(CamProfileSchema).optional(),
6366
- segmentSeconds: number().int().positive().optional(),
6367
- /** Shared recording time-bands for `events` & `continuous` — record only when
6368
- * the wall-clock falls inside one of these windows. Omit or empty = always.
6369
- * `continuous` compiles to one rule per band; `events` to band × trigger. */
6370
- schedules: array(RecordingScheduleSchema).optional(),
6371
- /** Legacy single-band predecessor of `schedules`. Read-compat only — it is
6372
- * normalized into `schedules` on read and never written going forward. (Not
6373
- * tagged `@deprecated`: the normalization paths must read it cast-free.) */
6374
- schedule: RecordingScheduleSchema.optional(),
6375
- /** `events`-mode only — which detectors trigger a recording. */
6376
- triggers: RecordingTriggersSchema.optional(),
6377
- /** `events`-mode only — seconds retained before / after a trigger. */
6378
- preBufferSec: number().min(0).optional(),
6379
- postBufferSec: number().min(0).optional(),
6380
- /** DEPRECATED authoring input; retained for migration/transition. */
6381
- rules: array(RecordingRuleSchema).optional(),
6382
- /**
6383
- * AUTHORITATIVE mode-per-band recording model (recorder). When present it
6384
- * is the single source of truth; the legacy `mode`/`schedules`/`schedule`/
6385
- * `triggers`/`rules` fields above are kept for READ-COMPAT only and are
6386
- * derived into bands once via `migrateConfigToBands`.
6387
- */
6388
- bands: array(RecordingBandSchema).optional(),
6389
- retention: RecordingRetentionSchema.optional()
6390
- });
6391
- /**
6392
- * `StorageLocationType` — an addon-declared id that identifies the *kind* of
6393
- * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
6394
- * so the persisted record schema and the consumer-facing cap can both consume it
6395
- * without forming a circular import. The `storage` cap re-exports it
6396
- * verbatim for back-compat.
6397
- *
6398
- * This Zod schema is the **authoritative source** for `StorageLocationType`.
6399
- * The TS alias in `./storage.ts` re-exports `z.infer<typeof
6400
- * StorageLocationTypeSchema>` so the wire surface (cap) and the legacy
6401
- * `IStorageProvider` interface stay in lockstep.
6402
- *
6403
- * The type is now an **open string** (not a closed enum) — addons declare
6404
- * their own location kinds via `StorageLocationDeclaration.id`. The regex
6405
- * enforces a safe id format: lowercase-start, alphanumeric + hyphens.
6406
- */
6407
- var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
6408
- /**
6409
- * Persisted record for a storage location instance. Operators can register
6410
- * multiple instances for multi-cardinality types (e.g. two `backups`
6411
- * locations with different `providerId`s). Cardinality is now declared per
6412
- * location via `StorageLocationDeclaration.cardinality` — the static
6413
- * `STORAGE_LOCATION_CARDINALITY` map has been removed.
6414
- *
6415
- * `id` is a stable namespaced string of the form `<type>:<slug>`.
6416
- * The default location for a type uses `id === <type>:default` by
6417
- * convention (the bare type ref like `'backups'` resolves to it).
6418
- *
6419
- * `isSystem: true` marks a location as orchestrator-seeded and
6420
- * undeletable. The bootstrap-installed defaults (one per type) carry
6421
- * this flag; operator-added locations don't. Editing the config of
6422
- * a system location is allowed (path migration, provider swap) but
6423
- * deleting it is rejected at the cap level.
6424
- */
6425
- var StorageLocationSchema = object({
6426
- id: string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
6427
- type: string(),
6428
- displayName: string().min(1),
6429
- providerId: string().min(1),
6430
- config: record(string(), unknown()),
6431
- /**
6432
- * Cluster node this location physically lives on. REQUIRED for node-local
6433
- * providers (filesystem — the path exists on one node's disk), null/absent
6434
- * for node-agnostic providers (S3/SFTP/WebDAV, reachable from any node).
6435
- * `'hub'` is the hub node. Validated against the provider's `nodeLocal`
6436
- * flag at upsert time, not here (the schema is provider-agnostic).
6437
- */
6438
- nodeId: string().optional(),
6439
- isDefault: boolean().default(false),
6440
- isSystem: boolean().default(false),
6441
- createdAt: number(),
6442
- updatedAt: number()
6443
- });
6444
- /**
6445
- * Reference accepted by consumer-facing `api.storage.*` calls.
6446
- * Either:
6447
- * - a `StorageLocationType` (e.g. `'backups'`) → orchestrator resolves to the default of that type
6448
- * - a fully-qualified id (e.g. `'backups:nas-01'`) → addresses a specific instance
6449
- *
6450
- * The orchestrator's `resolveRef(ref)` handles both cases.
6451
- */
6452
- var StorageLocationRefSchema = union([StorageLocationTypeSchema, string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/)]);
6453
- /**
6454
- * `StorageLocationDeclaration` — a single storage-location entry declared by
6455
- * an addon in its `package.json` under `camstack.storageLocations`.
6456
- *
6457
- * Design intent:
6458
- * - **Addon declares its needs** — each addon describes the logical storage
6459
- * slots it requires (e.g. `recordings`, `recordingsLow`) without caring
6460
- * about the physical path.
6461
- * - **Kernel aggregates** — at boot the kernel collects declarations from all
6462
- * installed addons, deduplicates by `id`, and exposes the union via the
6463
- * storage-locations settings surface.
6464
- * - **Orchestrator seeds** — for every declared `id` the orchestrator ensures
6465
- * at least one instance named `<id>:default` is present, using
6466
- * `defaultsTo` to inherit the resolved root from another location when the
6467
- * declaration is a derivative slot (e.g. `recordingsLow` defaults to
6468
- * `recordings`).
6469
- * - **ids are global** — `id` values are shared across the entire deployment;
6470
- * two addons declaring the same `id` must agree on `cardinality` (validated
6471
- * at kernel aggregation time, not here).
6472
- */
6473
- var StorageLocationDeclarationSchema = object({
6474
- /**
6475
- * Global location identifier, e.g. `recordings` or `recordingsLow`.
6476
- * Must start with a lowercase letter and may contain letters, digits, and
6477
- * hyphens.
6478
- */
6479
- id: string().regex(/^[a-z][a-zA-Z0-9-]*$/, { message: "id must start with a lowercase letter and contain only letters, digits, or hyphens" }),
6480
- /** Human-readable name shown in the admin UI. */
6481
- displayName: string().min(1, { message: "displayName must not be empty" }),
6482
- /** Optional longer explanation of what data this location stores. */
6483
- description: string().optional(),
6484
- /**
6485
- * `single` — exactly one instance of this location is allowed system-wide
6486
- * (e.g. `logs`, `models`). The operator can edit it but not add more.
6487
- * `multi` — the operator may register several instances (e.g. a second
6488
- * `recordings` on a NAS for disk tiering); one is the default at any time.
6489
- */
6490
- cardinality: _enum(["single", "multi"]),
6491
- /**
6492
- * When set, the default instance for this location inherits its resolved
6493
- * root from the named location's default instance. Useful for derivative
6494
- * slots (e.g. `recordingsLow` → `recordings`) so operators only need to
6495
- * configure the primary location.
6496
- */
6497
- defaultsTo: string().optional()
6498
- });
6499
- var DecoderStatsSchema = object({
6500
- inputFps: number(),
6501
- outputFps: number(),
6502
- avgDecodeTimeMs: number(),
6503
- droppedFrames: number()
6504
- });
6505
- var DecoderSessionConfigSchema = object({
6506
- codec: string(),
6507
- maxFps: number().default(0),
6508
- outputFormat: _enum([
6509
- "jpeg",
6510
- "rgb",
6511
- "bgr",
6512
- "yuv420",
6513
- "gray"
6514
- ]).default("jpeg"),
6515
- scale: number().default(1),
6516
- width: number().optional(),
6517
- height: number().optional(),
6213
+ var DeviceType = /* @__PURE__ */ function(DeviceType) {
6214
+ DeviceType["Camera"] = "camera";
6215
+ DeviceType["Hub"] = "hub";
6216
+ DeviceType["Light"] = "light";
6217
+ DeviceType["Siren"] = "siren";
6218
+ DeviceType["Switch"] = "switch";
6219
+ DeviceType["Sensor"] = "sensor";
6220
+ DeviceType["Thermostat"] = "thermostat";
6221
+ DeviceType["Button"] = "button";
6222
+ /** Generic stateless event emitter — carries a device's EXACT declared
6223
+ * event vocabulary verbatim (no normalization). Installed with the
6224
+ * `event-emitter` cap. Sources: HA `event.*` entities (structured) and
6225
+ * HA bus events (e.g. `zha_event`, generic). */
6226
+ DeviceType["EventEmitter"] = "event-emitter";
6227
+ /** Firmware/software update entity — current vs available version,
6228
+ * updatable flag, update state, and an install action. Installed with
6229
+ * the `update` cap. Sources: Homematic firmware-update channels (and
6230
+ * reusable by other providers, e.g. HA `update.*` entities). */
6231
+ DeviceType["Update"] = "update";
6232
+ DeviceType["Generic"] = "generic";
6233
+ /** Generic notification delivery target (HA `notify.<service>`, future
6234
+ * Telegram / Discord / ntfy / SMTP, …). One device per delivery
6235
+ * endpoint; the `notifier` cap defines the send surface. */
6236
+ DeviceType["Notifier"] = "notifier";
6237
+ /** Pre-recorded action sequence with optional parameters
6238
+ * (HA `script.*`). Runnable via `script-runner` cap. */
6239
+ DeviceType["Script"] = "script";
6240
+ /** Automation rule (HA `automation.*`) enable/disable + manual
6241
+ * trigger surface exposed via `automation-control` cap. */
6242
+ DeviceType["Automation"] = "automation";
6243
+ /** Door / smart lock device (HA `lock.*`). `lock-control` cap. */
6244
+ DeviceType["Lock"] = "lock";
6245
+ /** Window covering, blinds, garage door, valve, etc. (HA `cover.*`,
6246
+ * `valve.*`). `cover` cap with sub-roles for variant. */
6247
+ DeviceType["Cover"] = "cover";
6248
+ /** Pipe / water / gas valve with open/close/stop and optional
6249
+ * position (HA `valve.*`). `valve` cap — a cover-sibling actuator
6250
+ * modelled on the same open/closed lifecycle. */
6251
+ DeviceType["Valve"] = "valve";
6252
+ /** Humidifier / dehumidifier with on/off + target humidity + mode
6253
+ * (HA `humidifier.*`). `humidifier` cap — a climate-family actuator
6254
+ * modelled on the same target / mode lifecycle. */
6255
+ DeviceType["Humidifier"] = "humidifier";
6256
+ /** Water heater / boiler with target temperature + operation mode +
6257
+ * away mode (HA `water_heater.*`). `water-heater` cap a
6258
+ * climate-family actuator. */
6259
+ DeviceType["WaterHeater"] = "water-heater";
6260
+ /** Ceiling / standing / exhaust fan (HA `fan.*`). `fan-control` cap. */
6261
+ DeviceType["Fan"] = "fan";
6262
+ /** Audio / video playback endpoint (HA `media_player.*`). Disjoint from
6263
+ * the camera surface those use `Camera`. `media-player` cap. */
6264
+ DeviceType["MediaPlayer"] = "media-player";
6265
+ /** Security panel / alarm system (HA `alarm_control_panel.*`).
6266
+ * `alarm-panel` cap. */
6267
+ DeviceType["AlarmPanel"] = "alarm-panel";
6268
+ /** Generic user-settable input (HA `number` / `input_number` / `select`
6269
+ * / `input_select` / `text` / `input_text` / `input_datetime`).
6270
+ * Sub-type via `DeviceRole`: NumericControl / SelectControl /
6271
+ * TextControl / DateTimeControl. */
6272
+ DeviceType["Control"] = "control";
6273
+ /** Person / device-tracker presence (HA `person.*`, `device_tracker.*`).
6274
+ * `presence` cap. */
6275
+ DeviceType["Presence"] = "presence";
6276
+ /** Weather provider (HA `weather.*`). Tier-3, low MVP priority.
6277
+ * `weather` cap. */
6278
+ DeviceType["Weather"] = "weather";
6279
+ /** Robot vacuum (HA `vacuum.*`). Tier-3. `vacuum-control` cap. */
6280
+ DeviceType["Vacuum"] = "vacuum";
6281
+ /** Robotic lawn mower (HA `lawn_mower.*`). Tier-3.
6282
+ * `lawn-mower-control` cap. */
6283
+ DeviceType["LawnMower"] = "lawn-mower";
6284
+ /** Physical HA device group — parent container for entity-children
6285
+ * adopted from a single HA device entry. Not renderable as a
6286
+ * standalone device; exists only to anchor child entities. */
6287
+ DeviceType["Container"] = "container";
6288
+ /** Single still-image entity (HA `image.*`). Read-only display of an
6289
+ * `entity_picture` signed URL the browser loads directly. `image` cap. */
6290
+ DeviceType["Image"] = "image";
6291
+ return DeviceType;
6292
+ }({});
6293
+ var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
6294
+ DeviceFeature["BatteryOperated"] = "battery-operated";
6295
+ DeviceFeature["Rebootable"] = "rebootable";
6518
6296
  /**
6519
- * Identifier of the camera this decoder session serves. Optional
6520
- * because the cap is generic (any caller could request decode), but
6521
- * stream-broker passes it so decoder logs include `deviceId` for
6522
- * per-camera filtering when diagnosing failures (e.g. node-av
6523
- * sendPacket errors on a single hung camera).
6297
+ * Device supports an on-demand re-sync of its derived spec with its
6298
+ * upstream source drives the generic Re-sync button. The owning
6299
+ * provider implements the action via the `device-adoption.resync` cap.
6524
6300
  */
6525
- deviceId: number().int().nonnegative().optional(),
6301
+ DeviceFeature["Resyncable"] = "resyncable";
6302
+ DeviceFeature["NativeSnapshot"] = "native-snapshot";
6303
+ DeviceFeature["DoorbellButton"] = "doorbell-button";
6304
+ DeviceFeature["TwoWayAudio"] = "two-way-audio";
6305
+ DeviceFeature["PanTiltZoom"] = "pan-tilt-zoom";
6526
6306
  /**
6527
- * Free-form tag for log scoping. Stream-broker uses
6528
- * `broker:<deviceId>/<profile>`. Decoder session logger surfaces it
6529
- * on every line so `grep tag=broker:5/high` filters one camera
6530
- * profile cleanly.
6307
+ * Camera supports the on-firmware autotrack subsystem (subject-
6308
+ * following). Distinct from `PanTiltZoom` because not every PTZ
6309
+ * camera ships autotrack the admin UI uses this flag to gate
6310
+ * the autotrack toggle / settings card without re-deriving from
6311
+ * the cap registry. Mirrors `ptz-autotrack` cap registration:
6312
+ * driver sets this feature when probe confirms the firmware
6313
+ * surface, and registers the cap in the same code path.
6531
6314
  */
6532
- tag: string().optional(),
6315
+ DeviceFeature["PtzAutotrack"] = "ptz-autotrack";
6533
6316
  /**
6534
- * Where the session delivers decoded frames (Phase 5 / D9):
6317
+ * Accessory exposes a "trigger on motion" toggle the parent camera's
6318
+ * motion detection automatically activates this device. Mirrors
6319
+ * `motion-trigger` cap registration: drivers set this feature in the
6320
+ * same code path that calls `ctx.registerNativeCap(motionTriggerCapability, ...)`.
6535
6321
  *
6536
- * - `'callback'` (default) the legacy pixel path: decoded frames are
6537
- * buffered as `DecodedFrame`s and drained via `pullFrames`.
6538
- * - `'shm'` the shared-memory frame plane: decoded frames are written
6539
- * into an OS shared-memory ring and drained as zero-pixel
6540
- * `FrameHandle`s via `pullHandles`. A session is one mode or the
6541
- * other — `pullFrames` returns nothing for an `'shm'` session and
6542
- * `pullHandles` returns nothing for a `'callback'` session.
6543
- */
6544
- frameSink: _enum(["callback", "shm"]).default("callback")
6545
- });
6546
- var EncodeProfileSchema = object({
6547
- video: object({
6548
- codec: _enum([
6549
- "h264",
6550
- "h265",
6551
- "copy"
6552
- ]),
6553
- profile: _enum([
6554
- "baseline",
6555
- "main",
6556
- "high"
6557
- ]).optional(),
6558
- width: number().int().positive().optional(),
6559
- height: number().int().positive().optional(),
6560
- fps: number().positive().optional(),
6561
- bitrateKbps: number().int().positive().optional(),
6562
- gopFrames: number().int().positive().optional(),
6563
- bf: number().int().min(0).optional(),
6564
- preset: _enum([
6565
- "ultrafast",
6566
- "superfast",
6567
- "veryfast",
6568
- "faster",
6569
- "fast",
6570
- "medium"
6571
- ]).optional(),
6572
- tune: _enum([
6573
- "zerolatency",
6574
- "film",
6575
- "animation"
6576
- ]).optional()
6577
- }),
6578
- audio: union([literal("passthrough"), object({
6579
- codec: _enum([
6580
- "opus",
6581
- "aac",
6582
- "pcmu",
6583
- "pcma",
6584
- "copy"
6585
- ]),
6586
- bitrateKbps: number().int().positive().optional(),
6587
- sampleRateHz: number().int().positive().optional(),
6588
- channels: union([literal(1), literal(2)]).optional()
6589
- })]),
6590
- /**
6591
- * ffmpeg input-side args, inserted between the fixed global flags
6592
- * (`-hide_banner -loglevel error`) and `-i pipe:0`. Free-text array
6593
- * — the widget surfaces a textarea + suggestion chips for the most-
6594
- * used demuxer/format options.
6595
- */
6596
- inputArgs: array(string()).optional(),
6597
- /**
6598
- * ffmpeg output-side args, inserted between the encode block and
6599
- * the final `-f <muxer> pipe:1`. Use for muxer options, bitstream
6600
- * filters, codec-specific overrides. Free-text array.
6322
+ * Used by admin UI (gate the in-hero `MotionTriggerToggle` against a
6323
+ * fast scalar without binding fetch), notifier rules, and `listAll`
6324
+ * filters that want "all devices with on-motion behaviour".
6601
6325
  */
6602
- outputArgs: array(string()).optional()
6603
- });
6604
- var YAMNET_TO_MACRO = {
6605
- mapping: {
6606
- Speech: "speech",
6607
- "Child speech, kid speaking": "speech",
6608
- Conversation: "speech",
6609
- "Narration, monologue": "speech",
6610
- Babbling: "speech",
6611
- Whispering: "speech",
6612
- "Speech synthesizer": "speech",
6613
- Humming: "speech",
6614
- Rapping: "speech",
6615
- Singing: "speech",
6616
- Choir: "speech",
6617
- "Child singing": "speech",
6618
- Shout: "scream",
6619
- Bellow: "scream",
6620
- Yell: "scream",
6621
- Screaming: "scream",
6622
- "Children shouting": "scream",
6623
- Whoop: "scream",
6624
- "Crying, sobbing": "crying",
6625
- "Baby cry, infant cry": "crying",
6626
- Whimper: "crying",
6627
- "Wail, moan": "crying",
6628
- Groan: "crying",
6629
- Laughter: "laughter",
6630
- "Baby laughter": "laughter",
6631
- Giggle: "laughter",
6632
- Snicker: "laughter",
6633
- "Belly laugh": "laughter",
6634
- "Chuckle, chortle": "laughter",
6635
- Music: "music",
6636
- "Musical instrument": "music",
6637
- Guitar: "music",
6638
- Piano: "music",
6639
- Drum: "music",
6640
- "Drum kit": "music",
6641
- "Violin, fiddle": "music",
6642
- Flute: "music",
6643
- Saxophone: "music",
6644
- Trumpet: "music",
6645
- Synthesizer: "music",
6646
- "Pop music": "music",
6647
- "Rock music": "music",
6648
- "Hip hop music": "music",
6649
- "Classical music": "music",
6650
- Jazz: "music",
6651
- "Electronic music": "music",
6652
- "Background music": "music",
6653
- Dog: "dog",
6654
- Bark: "dog",
6655
- Yip: "dog",
6656
- Howl: "dog",
6657
- "Bow-wow": "dog",
6658
- Growling: "dog",
6659
- "Whimper (dog)": "dog",
6660
- Cat: "cat",
6661
- Purr: "cat",
6662
- Meow: "cat",
6663
- Hiss: "cat",
6664
- Caterwaul: "cat",
6665
- Bird: "bird",
6666
- "Bird vocalization, bird call, bird song": "bird",
6667
- "Chirp, tweet": "bird",
6668
- Squawk: "bird",
6669
- Crow: "bird",
6670
- Owl: "bird",
6671
- "Pigeon, dove": "bird",
6672
- Animal: "animal",
6673
- "Domestic animals, pets": "animal",
6674
- "Livestock, farm animals, working animals": "animal",
6675
- Horse: "animal",
6676
- "Cattle, bovinae": "animal",
6677
- Pig: "animal",
6678
- Sheep: "animal",
6679
- Goat: "animal",
6680
- Frog: "animal",
6681
- Insect: "animal",
6682
- Cricket: "animal",
6683
- Alarm: "alarm",
6684
- "Alarm clock": "alarm",
6685
- "Smoke detector, smoke alarm": "alarm",
6686
- "Fire alarm": "alarm",
6687
- Buzzer: "alarm",
6688
- "Civil defense siren": "alarm",
6689
- "Car alarm": "alarm",
6690
- Siren: "siren",
6691
- "Police car (siren)": "siren",
6692
- "Ambulance (siren)": "siren",
6693
- "Fire engine, fire truck (siren)": "siren",
6694
- "Emergency vehicle": "siren",
6695
- Foghorn: "siren",
6696
- Doorbell: "doorbell",
6697
- "Ding-dong": "doorbell",
6698
- Knock: "doorbell",
6699
- Tap: "doorbell",
6700
- Glass: "glass_breaking",
6701
- Shatter: "glass_breaking",
6702
- "Chink, clink": "glass_breaking",
6703
- "Gunshot, gunfire": "gunshot",
6704
- "Machine gun": "gunshot",
6705
- Explosion: "gunshot",
6706
- Fireworks: "gunshot",
6707
- Firecracker: "gunshot",
6708
- "Artillery fire": "gunshot",
6709
- "Cap gun": "gunshot",
6710
- Boom: "gunshot",
6711
- Vehicle: "vehicle",
6712
- Car: "vehicle",
6713
- Truck: "vehicle",
6714
- Bus: "vehicle",
6715
- Motorcycle: "vehicle",
6716
- "Car passing by": "vehicle",
6717
- "Vehicle horn, car horn, honking": "vehicle",
6718
- "Traffic noise, roadway noise": "vehicle",
6719
- Train: "vehicle",
6720
- Aircraft: "vehicle",
6721
- Helicopter: "vehicle",
6722
- Bicycle: "vehicle",
6723
- Skateboard: "vehicle",
6724
- Fire: "fire",
6725
- Crackle: "fire",
6726
- Water: "water",
6727
- Rain: "water",
6728
- Raindrop: "water",
6729
- "Rain on surface": "water",
6730
- Stream: "water",
6731
- Waterfall: "water",
6732
- Ocean: "water",
6733
- "Waves, surf": "water",
6734
- "Splash, splatter": "water",
6735
- Wind: "wind",
6736
- Thunderstorm: "wind",
6737
- Thunder: "wind",
6738
- "Wind noise (microphone)": "wind",
6739
- "Rustling leaves": "wind",
6740
- Door: "door",
6741
- "Sliding door": "door",
6742
- Slam: "door",
6743
- "Cupboard open or close": "door",
6744
- "Walk, footsteps": "footsteps",
6745
- Run: "footsteps",
6746
- Shuffle: "footsteps",
6747
- Crowd: "crowd",
6748
- Chatter: "crowd",
6749
- Cheering: "crowd",
6750
- Applause: "crowd",
6751
- "Children playing": "crowd",
6752
- "Hubbub, speech noise, speech babble": "crowd",
6753
- Telephone: "telephone",
6754
- "Telephone bell ringing": "telephone",
6755
- Ringtone: "telephone",
6756
- "Telephone dialing, DTMF": "telephone",
6757
- "Busy signal": "telephone",
6758
- Engine: "engine",
6759
- "Engine starting": "engine",
6760
- Idling: "engine",
6761
- "Accelerating, revving, vroom": "engine",
6762
- "Light engine (high frequency)": "engine",
6763
- "Medium engine (mid frequency)": "engine",
6764
- "Heavy engine (low frequency)": "engine",
6765
- "Lawn mower": "engine",
6766
- Chainsaw: "engine",
6767
- Hammer: "tools",
6768
- Jackhammer: "tools",
6769
- Sawing: "tools",
6770
- "Power tool": "tools",
6771
- Drill: "tools",
6772
- Sanding: "tools",
6773
- Silence: "silence"
6774
- },
6775
- preserveOriginal: false
6776
- };
6777
- var APPLE_SA_TO_MACRO = {
6778
- mapping: {
6779
- speech: "speech",
6780
- child_speech: "speech",
6781
- conversation: "speech",
6782
- whispering: "speech",
6783
- singing: "speech",
6784
- humming: "speech",
6785
- shout: "scream",
6786
- yell: "scream",
6787
- screaming: "scream",
6788
- crying: "crying",
6789
- baby_crying: "crying",
6790
- sobbing: "crying",
6791
- laughter: "laughter",
6792
- baby_laughter: "laughter",
6793
- giggling: "laughter",
6794
- music: "music",
6795
- guitar: "music",
6796
- piano: "music",
6797
- drums: "music",
6798
- dog_bark: "dog",
6799
- dog_bow_wow: "dog",
6800
- dog_growling: "dog",
6801
- dog_howl: "dog",
6802
- cat_meow: "cat",
6803
- cat_purr: "cat",
6804
- cat_hiss: "cat",
6805
- bird: "bird",
6806
- bird_chirp: "bird",
6807
- bird_squawk: "bird",
6808
- animal: "animal",
6809
- horse: "animal",
6810
- cow_moo: "animal",
6811
- insect: "animal",
6812
- alarm: "alarm",
6813
- smoke_alarm: "alarm",
6814
- fire_alarm: "alarm",
6815
- car_alarm: "alarm",
6816
- siren: "siren",
6817
- police_siren: "siren",
6818
- ambulance_siren: "siren",
6819
- doorbell: "doorbell",
6820
- door_knock: "doorbell",
6821
- knocking: "doorbell",
6822
- glass_breaking: "glass_breaking",
6823
- glass_shatter: "glass_breaking",
6824
- gunshot: "gunshot",
6825
- explosion: "gunshot",
6826
- fireworks: "gunshot",
6827
- car: "vehicle",
6828
- truck: "vehicle",
6829
- motorcycle: "vehicle",
6830
- car_horn: "vehicle",
6831
- vehicle_horn: "vehicle",
6832
- traffic: "vehicle",
6833
- fire: "fire",
6834
- fire_crackle: "fire",
6835
- water: "water",
6836
- rain: "water",
6837
- ocean: "water",
6838
- splash: "water",
6839
- wind: "wind",
6840
- thunder: "wind",
6841
- thunderstorm: "wind",
6842
- door: "door",
6843
- door_slam: "door",
6844
- sliding_door: "door",
6845
- footsteps: "footsteps",
6846
- walking: "footsteps",
6847
- running: "footsteps",
6848
- crowd: "crowd",
6849
- chatter: "crowd",
6850
- cheering: "crowd",
6851
- applause: "crowd",
6852
- telephone_ring: "telephone",
6853
- ringtone: "telephone",
6854
- engine: "engine",
6855
- engine_starting: "engine",
6856
- lawn_mower: "engine",
6857
- chainsaw: "engine",
6858
- hammer: "tools",
6859
- jackhammer: "tools",
6860
- drill: "tools",
6861
- power_tool: "tools",
6862
- silence: "silence"
6863
- },
6864
- preserveOriginal: false
6865
- };
6866
- var _macroLookup = /* @__PURE__ */ new Map();
6867
- for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
6868
- for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
6869
- var DeviceType = /* @__PURE__ */ function(DeviceType) {
6870
- DeviceType["Camera"] = "camera";
6871
- DeviceType["Hub"] = "hub";
6872
- DeviceType["Light"] = "light";
6873
- DeviceType["Siren"] = "siren";
6874
- DeviceType["Switch"] = "switch";
6875
- DeviceType["Sensor"] = "sensor";
6876
- DeviceType["Thermostat"] = "thermostat";
6877
- DeviceType["Button"] = "button";
6878
- /** Generic stateless event emitter — carries a device's EXACT declared
6879
- * event vocabulary verbatim (no normalization). Installed with the
6880
- * `event-emitter` cap. Sources: HA `event.*` entities (structured) and
6881
- * HA bus events (e.g. `zha_event`, generic). */
6882
- DeviceType["EventEmitter"] = "event-emitter";
6883
- /** Firmware/software update entity — current vs available version,
6884
- * updatable flag, update state, and an install action. Installed with
6885
- * the `update` cap. Sources: Homematic firmware-update channels (and
6886
- * reusable by other providers, e.g. HA `update.*` entities). */
6887
- DeviceType["Update"] = "update";
6888
- DeviceType["Generic"] = "generic";
6889
- /** Generic notification delivery target (HA `notify.<service>`, future
6890
- * Telegram / Discord / ntfy / SMTP, …). One device per delivery
6891
- * endpoint; the `notifier` cap defines the send surface. */
6892
- DeviceType["Notifier"] = "notifier";
6893
- /** Pre-recorded action sequence with optional parameters
6894
- * (HA `script.*`). Runnable via `script-runner` cap. */
6895
- DeviceType["Script"] = "script";
6896
- /** Automation rule (HA `automation.*`) — enable/disable + manual
6897
- * trigger surface exposed via `automation-control` cap. */
6898
- DeviceType["Automation"] = "automation";
6899
- /** Door / smart lock device (HA `lock.*`). `lock-control` cap. */
6900
- DeviceType["Lock"] = "lock";
6901
- /** Window covering, blinds, garage door, valve, etc. (HA `cover.*`,
6902
- * `valve.*`). `cover` cap with sub-roles for variant. */
6903
- DeviceType["Cover"] = "cover";
6904
- /** Pipe / water / gas valve with open/close/stop and optional
6905
- * position (HA `valve.*`). `valve` cap — a cover-sibling actuator
6906
- * modelled on the same open/closed lifecycle. */
6907
- DeviceType["Valve"] = "valve";
6908
- /** Humidifier / dehumidifier with on/off + target humidity + mode
6909
- * (HA `humidifier.*`). `humidifier` cap — a climate-family actuator
6910
- * modelled on the same target / mode lifecycle. */
6911
- DeviceType["Humidifier"] = "humidifier";
6912
- /** Water heater / boiler with target temperature + operation mode +
6913
- * away mode (HA `water_heater.*`). `water-heater` cap — a
6914
- * climate-family actuator. */
6915
- DeviceType["WaterHeater"] = "water-heater";
6916
- /** Ceiling / standing / exhaust fan (HA `fan.*`). `fan-control` cap. */
6917
- DeviceType["Fan"] = "fan";
6918
- /** Audio / video playback endpoint (HA `media_player.*`). Disjoint from
6919
- * the camera surface — those use `Camera`. `media-player` cap. */
6920
- DeviceType["MediaPlayer"] = "media-player";
6921
- /** Security panel / alarm system (HA `alarm_control_panel.*`).
6922
- * `alarm-panel` cap. */
6923
- DeviceType["AlarmPanel"] = "alarm-panel";
6924
- /** Generic user-settable input (HA `number` / `input_number` / `select`
6925
- * / `input_select` / `text` / `input_text` / `input_datetime`).
6926
- * Sub-type via `DeviceRole`: NumericControl / SelectControl /
6927
- * TextControl / DateTimeControl. */
6928
- DeviceType["Control"] = "control";
6929
- /** Person / device-tracker presence (HA `person.*`, `device_tracker.*`).
6930
- * `presence` cap. */
6931
- DeviceType["Presence"] = "presence";
6932
- /** Weather provider (HA `weather.*`). Tier-3, low MVP priority.
6933
- * `weather` cap. */
6934
- DeviceType["Weather"] = "weather";
6935
- /** Robot vacuum (HA `vacuum.*`). Tier-3. `vacuum-control` cap. */
6936
- DeviceType["Vacuum"] = "vacuum";
6937
- /** Robotic lawn mower (HA `lawn_mower.*`). Tier-3.
6938
- * `lawn-mower-control` cap. */
6939
- DeviceType["LawnMower"] = "lawn-mower";
6940
- /** Physical HA device group — parent container for entity-children
6941
- * adopted from a single HA device entry. Not renderable as a
6942
- * standalone device; exists only to anchor child entities. */
6943
- DeviceType["Container"] = "container";
6944
- /** Single still-image entity (HA `image.*`). Read-only display of an
6945
- * `entity_picture` signed URL the browser loads directly. `image` cap. */
6946
- DeviceType["Image"] = "image";
6947
- return DeviceType;
6326
+ DeviceFeature["MotionTrigger"] = "motion-trigger";
6327
+ /** Light supports rgb-triplet color via `color` cap. */
6328
+ DeviceFeature["LightColorRgb"] = "light-color-rgb";
6329
+ /** Light supports HSV color via `color` cap. */
6330
+ DeviceFeature["LightColorHsv"] = "light-color-hsv";
6331
+ /** Light supports color-temperature (mired) via `color` cap. */
6332
+ DeviceFeature["LightColorMired"] = "light-color-mired";
6333
+ /** Thermostat supports a `heat_cool` dual setpoint (targetLow +
6334
+ * targetHigh). Gates the range slider UI. */
6335
+ DeviceFeature["ClimateDualSetpoint"] = "climate-dual-setpoint";
6336
+ /** Thermostat exposes target humidity and/or current humidity
6337
+ * readings. Gates the humidity controls. */
6338
+ DeviceFeature["ClimateHumidity"] = "climate-humidity";
6339
+ /** Thermostat exposes a fan-mode selector. */
6340
+ DeviceFeature["ClimateFanMode"] = "climate-fan-mode";
6341
+ /** Thermostat exposes preset modes (eco / away / sleep / vendor). */
6342
+ DeviceFeature["ClimatePreset"] = "climate-preset";
6343
+ /** Cover exposes intermediate position control (0..100). Gates the
6344
+ * position slider UI. */
6345
+ DeviceFeature["CoverPositionable"] = "cover-positionable";
6346
+ /** Cover exposes slat-tilt control. Gates the tilt slider UI. */
6347
+ DeviceFeature["CoverTilt"] = "cover-tilt";
6348
+ /** Valve exposes intermediate position control (0..100). Gates the
6349
+ * position slider / drag surface UI. */
6350
+ DeviceFeature["ValvePositionable"] = "valve-positionable";
6351
+ /** Fan exposes a speed-percentage setter. Gates the speed slider UI. */
6352
+ DeviceFeature["FanSpeed"] = "fan-speed";
6353
+ /** Fan exposes a preset mode selector. */
6354
+ DeviceFeature["FanPreset"] = "fan-preset";
6355
+ /** Fan exposes blade direction (forward/reverse) — typical of
6356
+ * ceiling fans. */
6357
+ DeviceFeature["FanDirection"] = "fan-direction";
6358
+ /** Fan exposes an oscillation toggle. */
6359
+ DeviceFeature["FanOscillating"] = "fan-oscillating";
6360
+ /** Lock requires a PIN code on lock/unlock. Gates the code-entry
6361
+ * field on the UI lock-controls panel. */
6362
+ DeviceFeature["LockPinRequired"] = "lock-pin-required";
6363
+ /** Lock supports a latch-release ("open door") action distinct from
6364
+ * unlock. Mirrors HA `LockEntityFeature.OPEN` (bit 1) in
6365
+ * `supported_features`. Gates the Open Door button in the UI. */
6366
+ DeviceFeature["LockOpen"] = "lock-open";
6367
+ /** Media player exposes a seek-to-position surface. */
6368
+ DeviceFeature["MediaPlayerSeek"] = "media-player-seek";
6369
+ /** Media player exposes a volume-level setter. */
6370
+ DeviceFeature["MediaPlayerVolume"] = "media-player-volume";
6371
+ /** Media player exposes a mute toggle distinct from volume=0. */
6372
+ DeviceFeature["MediaPlayerMute"] = "media-player-mute";
6373
+ /** Media player exposes a shuffle toggle. */
6374
+ DeviceFeature["MediaPlayerShuffle"] = "media-player-shuffle";
6375
+ /** Media player exposes a repeat mode (off / all / one). */
6376
+ DeviceFeature["MediaPlayerRepeat"] = "media-player-repeat";
6377
+ /** Media player exposes a source / input selector. */
6378
+ DeviceFeature["MediaPlayerSelectSource"] = "media-player-select-source";
6379
+ /** Media player exposes a play-arbitrary-media surface (URL / id). */
6380
+ DeviceFeature["MediaPlayerPlayMedia"] = "media-player-play-media";
6381
+ /** Media player exposes next-track. */
6382
+ DeviceFeature["MediaPlayerNext"] = "media-player-next";
6383
+ /** Media player exposes previous-track. */
6384
+ DeviceFeature["MediaPlayerPrevious"] = "media-player-previous";
6385
+ /** Media player exposes stop distinct from pause. */
6386
+ DeviceFeature["MediaPlayerStop"] = "media-player-stop";
6387
+ /** Alarm panel requires a PIN code on arm/disarm. */
6388
+ DeviceFeature["AlarmPinRequired"] = "alarm-pin-required";
6389
+ /** Presence device carries GPS coordinates (lat/lng/accuracy) in
6390
+ * addition to a textual location. */
6391
+ DeviceFeature["PresenceGps"] = "presence-gps";
6392
+ /** Notifier accepts an inline / URL image attachment. */
6393
+ DeviceFeature["NotifierImage"] = "notifier-image";
6394
+ /** Notifier accepts a priority hint (high/normal/low). */
6395
+ DeviceFeature["NotifierPriority"] = "notifier-priority";
6396
+ /** Notifier accepts a free-form `data` payload for platform-specific
6397
+ * fields. */
6398
+ DeviceFeature["NotifierData"] = "notifier-data";
6399
+ /** Notifier supports interactive action buttons / callbacks. */
6400
+ DeviceFeature["NotifierActions"] = "notifier-actions";
6401
+ /** Notifier supports per-call recipient targeting (multi-user). */
6402
+ DeviceFeature["NotifierRecipients"] = "notifier-recipients";
6403
+ /** Script runner accepts a variables map on each run invocation. */
6404
+ DeviceFeature["ScriptVariables"] = "script-variables";
6405
+ /** Automation `trigger` accepts a skipCondition flag — fires the
6406
+ * automation's actions while bypassing its condition block. */
6407
+ DeviceFeature["AutomationSkipCondition"] = "automation-skip-condition";
6408
+ return DeviceFeature;
6409
+ }({});
6410
+ /**
6411
+ * Semantic role a device plays within its parent. Populated by driver
6412
+ * addons when creating accessory devices (Reolink siren/floodlight/
6413
+ * PIR/chime/autotrack/doorbell, ONVIF relay outputs, …). Used by the
6414
+ * admin UI to pick icons, labels, and widgets — a `Switch` with
6415
+ * `role: Floodlight` renders as a bulb with a brightness slider,
6416
+ * whereas a `Switch` with `role: Siren` renders as a klaxon.
6417
+ *
6418
+ * Undefined for top-level devices (cameras, NVRs, hubs). Persisted in
6419
+ * sqlite as a nullable TEXT column — old rows keep working unchanged.
6420
+ */
6421
+ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
6422
+ DeviceRole["Siren"] = "siren";
6423
+ DeviceRole["Floodlight"] = "floodlight";
6424
+ DeviceRole["Spotlight"] = "spotlight";
6425
+ DeviceRole["PirSensor"] = "pir-sensor";
6426
+ DeviceRole["Chime"] = "chime";
6427
+ DeviceRole["Autotrack"] = "autotrack";
6428
+ DeviceRole["Nightvision"] = "nightvision";
6429
+ DeviceRole["PrivacyMask"] = "privacy-mask";
6430
+ DeviceRole["Doorbell"] = "doorbell";
6431
+ /** Virtual HA toggle (input_boolean.*) — distinguishable from a
6432
+ * real Switch device for UI rendering / export adapters. */
6433
+ DeviceRole["BinaryHelper"] = "binary-helper";
6434
+ /** Generic motion / occupancy / moving event source. Distinct from
6435
+ * the camera accessory PirSensor role: that one is a camera child;
6436
+ * this is a standalone HA / 3rd-party motion sensor. */
6437
+ DeviceRole["MotionSensor"] = "motion-sensor";
6438
+ DeviceRole["ContactSensor"] = "contact-sensor";
6439
+ DeviceRole["LeakSensor"] = "leak-sensor";
6440
+ DeviceRole["SmokeSensor"] = "smoke-sensor";
6441
+ DeviceRole["COSensor"] = "co-sensor";
6442
+ DeviceRole["GasSensor"] = "gas-sensor";
6443
+ DeviceRole["TamperSensor"] = "tamper-sensor";
6444
+ DeviceRole["VibrationSensor"] = "vibration-sensor";
6445
+ DeviceRole["ConnectivitySensor"] = "connectivity-sensor";
6446
+ DeviceRole["SoundSensor"] = "sound-sensor";
6447
+ /** Fallback for `binary_sensor` without a known `device_class`. */
6448
+ DeviceRole["BinarySensor"] = "binary-sensor";
6449
+ DeviceRole["TemperatureSensor"] = "temperature-sensor";
6450
+ DeviceRole["HumiditySensor"] = "humidity-sensor";
6451
+ DeviceRole["AmbientLightSensor"] = "ambient-light-sensor";
6452
+ DeviceRole["PressureSensor"] = "pressure-sensor";
6453
+ DeviceRole["PowerSensor"] = "power-sensor";
6454
+ DeviceRole["EnergySensor"] = "energy-sensor";
6455
+ DeviceRole["VoltageSensor"] = "voltage-sensor";
6456
+ DeviceRole["CurrentSensor"] = "current-sensor";
6457
+ DeviceRole["AirQualitySensor"] = "air-quality-sensor";
6458
+ /** Battery level (numeric % via `sensor` OR low-bool via
6459
+ * `binary_sensor` — the cap distinguishes via the value type). */
6460
+ DeviceRole["BatterySensor"] = "battery-sensor";
6461
+ /** Fallback for `sensor` numeric without a known `device_class`. */
6462
+ DeviceRole["NumericSensor"] = "numeric-sensor";
6463
+ /** String / enum state (HA `sensor` with `state_class: enum` or
6464
+ * `attributes.options`). */
6465
+ DeviceRole["EnumSensor"] = "enum-sensor";
6466
+ /** Date / timestamp state (HA `sensor` with `device_class: timestamp`
6467
+ * or `date`). The slice carries the raw ISO string verbatim (hosted on
6468
+ * the `enum-sensor` cap); the UI renders it locale-formatted. */
6469
+ DeviceRole["DateTimeSensor"] = "datetime-sensor";
6470
+ /** Last-resort fallback when nothing else matches. */
6471
+ DeviceRole["GenericSensor"] = "generic-sensor";
6472
+ DeviceRole["NumericControl"] = "numeric-control";
6473
+ DeviceRole["SelectControl"] = "select-control";
6474
+ DeviceRole["TextControl"] = "text-control";
6475
+ DeviceRole["DateTimeControl"] = "datetime-control";
6476
+ /** Mobile push notifier (HA `notify.mobile_app_*`) — supports
6477
+ * rich features (image, priority, channel routing). */
6478
+ DeviceRole["MobilePushNotifier"] = "mobile-push-notifier";
6479
+ /** Chat / messaging service (HA `notify.telegram_*`,
6480
+ * `notify.discord_*`, etc.). */
6481
+ DeviceRole["MessagingNotifier"] = "messaging-notifier";
6482
+ /** Email-based delivery (HA `notify.smtp`, etc.). */
6483
+ DeviceRole["EmailNotifier"] = "email-notifier";
6484
+ /** Fallback when the notifier service name doesn't match a known
6485
+ * pattern. */
6486
+ DeviceRole["GenericNotifier"] = "generic-notifier";
6487
+ return DeviceRole;
6948
6488
  }({});
6949
- var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
6950
- DeviceFeature["BatteryOperated"] = "battery-operated";
6951
- DeviceFeature["Rebootable"] = "rebootable";
6489
+ /**
6490
+ * Generic types for capability definitions.
6491
+ *
6492
+ * A capability is defined with Zod schemas for methods, events, and settings.
6493
+ * TypeScript types are inferred via z.infer<> — zero duplication.
6494
+ *
6495
+ * Pattern:
6496
+ * 1. Define Zod schemas for data, methods, settings
6497
+ * 2. Export const capabilityDef = { ... } satisfies CapabilityDefinition
6498
+ * 3. Export type IProvider = InferProvider<typeof capabilityDef>
6499
+ * 4. Addon implements IProvider
6500
+ * 5. Registry auto-mounts tRPC router from definition.methods
6501
+ */
6502
+ /**
6503
+ * Output schema shared by the contribution + live methods.
6504
+ *
6505
+ * Mirrors the `ConfigUISchemaWithValues` shape (sections[] + optional
6506
+ * tabs[]) without importing from `../interfaces/config-ui.js` — a
6507
+ * concrete-but-lenient Zod object keeps tRPC output inference happy
6508
+ * (using `z.unknown()` here collapses unrelated router branches to
6509
+ * `unknown` when the generator re-inlines the huge AppRouter type).
6510
+ *
6511
+ * `.passthrough()` on sections/fields accepts whatever FormBuilder
6512
+ * extensions the caller adds (showWhen, displayScale, …) without
6513
+ * rebuilding every time a new field kind is introduced.
6514
+ */
6515
+ var ContributionSectionSchema = object({
6516
+ id: string(),
6517
+ title: string(),
6518
+ description: string().optional(),
6519
+ style: _enum(["card", "accordion"]).optional(),
6520
+ defaultCollapsed: boolean().optional(),
6521
+ columns: union([
6522
+ literal(1),
6523
+ literal(2),
6524
+ literal(3),
6525
+ literal(4)
6526
+ ]).optional(),
6527
+ tab: string().optional(),
6528
+ location: _enum(["settings", "top-tab"]).optional(),
6529
+ order: number().optional(),
6530
+ fields: array(any())
6531
+ });
6532
+ object({
6533
+ tabs: array(object({
6534
+ id: string(),
6535
+ label: string(),
6536
+ icon: string(),
6537
+ order: number().optional()
6538
+ })).optional(),
6539
+ sections: array(ContributionSectionSchema)
6540
+ }).nullable();
6541
+ object({ deviceId: number() }), object({ deviceId: number() }), object({
6542
+ deviceId: number(),
6543
+ patch: record(string(), unknown())
6544
+ }), object({ success: literal(true) });
6545
+ object({ deviceId: number() }), unknown().nullable();
6546
+ /** Shorthand to define a method schema */
6547
+ function method(input, output, options) {
6548
+ return {
6549
+ input,
6550
+ output,
6551
+ kind: options?.kind ?? "query",
6552
+ auth: options?.auth ?? "protected",
6553
+ ...options?.access !== void 0 ? { access: options.access } : {},
6554
+ timeoutMs: options?.timeoutMs
6555
+ };
6556
+ }
6557
+ var StaticDirOutputSchema = object({ staticDir: string() });
6558
+ var VersionOutputSchema = object({ version: string() });
6559
+ method(_void(), StaticDirOutputSchema), method(_void(), VersionOutputSchema);
6560
+ /**
6561
+ * device-ops — device-scoped cap that unifies the per-IDevice operations
6562
+ * previously routed through the `.device-ops` Moleculer bridge service.
6563
+ *
6564
+ * Each worker that hosts live `IDevice` instances auto-registers a native
6565
+ * provider for this cap (per device) backed by its local
6566
+ * `DeviceRegistry`. Hub-side callers reach it transparently through
6567
+ * `ctx.fetchDevice(id).deviceOps.*` — the DeviceProxy injects
6568
+ * `deviceId` + `nodeId` and dispatches through the standard cap-router,
6569
+ * so there's no parallel bridge path anymore.
6570
+ *
6571
+ * The surface is intentionally small — every method corresponds to a
6572
+ * single action on the live `IDevice` (or `ICameraDevice` for
6573
+ * `getStreamSources`). Richer orchestration (enable/disable with
6574
+ * integration plumbing, bulk updates) stays in the `device-manager` cap;
6575
+ * `device-ops` is the per-device primitive the device-manager routes to.
6576
+ */
6577
+ var StreamSourceEntrySchema = object({
6578
+ id: string(),
6579
+ label: string(),
6580
+ protocol: _enum([
6581
+ "rtsp",
6582
+ "rtmp",
6583
+ "annexb",
6584
+ "http-mjpeg",
6585
+ "webrtc",
6586
+ "custom"
6587
+ ]),
6588
+ url: string().optional(),
6589
+ resolution: object({
6590
+ width: number(),
6591
+ height: number()
6592
+ }).optional(),
6593
+ fps: number().optional(),
6594
+ bitrate: number().optional(),
6595
+ codec: string().optional(),
6596
+ profileHint: CamProfileSchema.optional(),
6597
+ sdp: string().optional()
6598
+ });
6599
+ var ConfigEntrySchema$1 = object({
6600
+ key: string(),
6601
+ value: unknown()
6602
+ });
6603
+ var RawStateResultSchema = object({
6604
+ /** Originating provider id, e.g. 'homeassistant' | 'reolink' | 'hikvision'. */
6605
+ source: string(),
6606
+ /** Opaque, DISPLAY-SAFE upstream blob (no secrets/PII). */
6607
+ data: record(string(), unknown())
6608
+ });
6609
+ method(object({ deviceId: number() }), array(StreamSourceEntrySchema)), method(object({ deviceId: number() }), array(ConfigEntrySchema$1)), method(object({
6610
+ deviceId: number(),
6611
+ values: record(string(), unknown())
6612
+ }), _void(), { kind: "mutation" }), method(object({
6613
+ deviceId: number(),
6614
+ action: string().min(1),
6615
+ input: unknown()
6616
+ }), unknown(), { kind: "mutation" }), method(object({ deviceId: number() }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), unknown().nullable()), method(object({ deviceId: number() }), RawStateResultSchema.nullable(), { auth: "protected" });
6617
+ //#endregion
6618
+ //#region ../types/dist/index.mjs
6619
+ /**
6620
+ * Deep wiring healthcheck — snapshot of active reachability probes across
6621
+ * every declared capability + widget of every installed plugin, on every
6622
+ * node. Produced by the backend `WiringHealthService` and surfaced via
6623
+ * `GET /health/wiring`, the tRPC `health.wiring` query, and the boot-gate.
6624
+ *
6625
+ * Unlike `/health` (process liveness), this reflects whether each cap/widget
6626
+ * is actually *reachable* over the real cap-dispatch path. See spec
6627
+ * `docs/superpowers/specs/2026-05-23-deep-healthcheck-design.md`.
6628
+ */
6629
+ /** What kind of target a probe addressed. */
6630
+ var wiringProbeKindSchema = _enum([
6631
+ "singleton",
6632
+ "device",
6633
+ "widget"
6634
+ ]);
6635
+ /** Result of probing a single (cap|widget [, device]) target. */
6636
+ var wiringProbeResultSchema = object({
6637
+ capName: string(),
6638
+ kind: wiringProbeKindSchema,
6639
+ deviceId: number().optional(),
6640
+ reachable: boolean(),
6641
+ latencyMs: number(),
6642
+ error: string().optional()
6643
+ });
6644
+ /** Per-addon roll-up of cap + widget probe results. */
6645
+ var wiringAddonHealthSchema = object({
6646
+ addonId: string(),
6647
+ caps: array(wiringProbeResultSchema).readonly(),
6648
+ widgets: array(wiringProbeResultSchema).readonly()
6649
+ });
6650
+ /** Per-node roll-up. */
6651
+ var wiringNodeHealthSchema = object({
6652
+ nodeId: string(),
6653
+ addons: array(wiringAddonHealthSchema).readonly()
6654
+ });
6655
+ object({
6656
+ /** True only when every probed target is reachable. */
6657
+ ok: boolean(),
6658
+ /** True when at least one target is unreachable. */
6659
+ degraded: boolean(),
6660
+ checkedAt: string(),
6661
+ nodes: array(wiringNodeHealthSchema).readonly(),
6662
+ summary: object({
6663
+ total: number(),
6664
+ reachable: number(),
6665
+ unreachable: number()
6666
+ })
6667
+ });
6668
+ var MODEL_FORMATS = [
6669
+ "onnx",
6670
+ "coreml",
6671
+ "openvino",
6672
+ "tflite",
6673
+ "pt"
6674
+ ];
6675
+ /**
6676
+ * Numeric day-of-week: 0 = Sunday … 6 = Saturday (matches `Date.getDay`).
6677
+ * Named `RecordingWeekday` to avoid collision with the string-union
6678
+ * `Weekday` exported from `interfaces/timezones.ts`.
6679
+ */
6680
+ var RecordingWeekdaySchema = number().int().min(0).max(6);
6681
+ var HHMM = /^([01]\d|2[0-3]):[0-5]\d$/;
6682
+ var RecordingScheduleSchema = discriminatedUnion("kind", [object({ kind: literal("always") }), object({
6683
+ kind: literal("timeOfDay"),
6684
+ start: string().regex(HHMM),
6685
+ end: string().regex(HHMM),
6686
+ /** Restrict to these weekdays; omit = every day. */
6687
+ days: array(RecordingWeekdaySchema).optional()
6688
+ })]);
6689
+ var RecordingModeSchema = _enum([
6690
+ "continuous",
6691
+ "onMotion",
6692
+ "onAudioThreshold"
6693
+ ]);
6694
+ /**
6695
+ * First-class, authoritative per-camera storage mode — the netta choice the UI
6696
+ * reads directly (never inferred from `rules`):
6697
+ * - `off` — not recording.
6698
+ * - `events` — record only around triggers (motion / audio threshold),
6699
+ * with pre/post-buffer.
6700
+ * - `continuous` — record 24/7 within the schedule.
6701
+ *
6702
+ * `mode` compiles one-way to the internal `rules[]` consumed by the policy
6703
+ * engine (see `compileRules`); `rules[]` is never authored directly anymore.
6704
+ */
6705
+ var RecordingStorageModeSchema = _enum([
6706
+ "off",
6707
+ "events",
6708
+ "continuous"
6709
+ ]);
6710
+ /** Which detectors trigger an `events`-mode recording. */
6711
+ var RecordingTriggersSchema = object({
6712
+ motion: boolean().optional(),
6713
+ audioThresholdDbfs: number().optional()
6714
+ });
6715
+ /**
6716
+ * Mode of a single recording band — the recorder per-band vocabulary.
6717
+ *
6718
+ * Distinct from `RecordingStorageModeSchema` (which carries `off`): a band is
6719
+ * only ever `continuous` or `events`; "off" is expressed by the absence of a
6720
+ * covering band, not by a band value.
6721
+ */
6722
+ var RecordingBandModeSchema = _enum(["continuous", "events"]);
6723
+ /**
6724
+ * Triggers for an `events`-mode band. Identical shape to
6725
+ * `RecordingTriggersSchema` — reuse that schema as the band trigger type so the
6726
+ * two never drift.
6727
+ */
6728
+ var RecordingBandTriggersSchema = RecordingTriggersSchema;
6729
+ /**
6730
+ * A single mode-per-band window — the canonical recorder band shape, the
6731
+ * single source of truth re-used by `addon-pipeline/recorder`.
6732
+ *
6733
+ * `days` lists the weekdays the band covers (empty = every day, matching the
6734
+ * band engine's `applies` rule). `start`/`end` are `HH:MM`; an `end <= start`
6735
+ * span wraps past midnight (handled by the band engine).
6736
+ */
6737
+ var RecordingBandSchema = object({
6738
+ days: array(RecordingWeekdaySchema),
6739
+ start: string().regex(HHMM),
6740
+ end: string().regex(HHMM),
6741
+ mode: RecordingBandModeSchema,
6742
+ triggers: RecordingBandTriggersSchema.optional(),
6743
+ preBufferSec: number().min(0).optional(),
6744
+ postBufferSec: number().min(0).optional()
6745
+ });
6746
+ var RecordingRuleSchema = object({
6747
+ schedule: RecordingScheduleSchema,
6748
+ mode: RecordingModeSchema,
6749
+ /** Seconds of footage to retain BEFORE a trigger (applied at keep/discard). */
6750
+ preBufferSec: number().min(0).default(0),
6751
+ /** Keep recording until this many seconds after the last trigger. */
6752
+ postBufferSec: number().min(0).default(0),
6753
+ /** Each new trigger restarts the post-buffer window. */
6754
+ resetTimeoutOnNewEvent: boolean().default(true),
6755
+ /** onAudioThreshold only — dBFS level that counts as a trigger. */
6756
+ thresholdDbfs: number().optional()
6757
+ });
6758
+ /**
6759
+ * Per-device retention overrides. Every field is optional; an unset or `0`
6760
+ * value inherits the node-wide recorder default. Only footage-lifetime limits
6761
+ * live per-camera: `maxAgeDays` and `maxSizeGb`. The disk-occupancy threshold
6762
+ * (when the volume is too full to keep recording) is NOT a per-camera concern —
6763
+ * it belongs to the StorageLocation (`StorageLocation.config.minFreePercent`),
6764
+ * shared by every camera writing to that volume.
6765
+ */
6766
+ var RecordingRetentionSchema = object({
6767
+ maxAgeDays: number().min(0).optional(),
6768
+ maxSizeGb: number().min(0).optional()
6769
+ });
6770
+ /**
6771
+ * The full per-camera recording intent — the wire shape of a RecordingTarget.
6772
+ *
6773
+ * `mode` is the authoritative storage choice; `schedule`/`triggers`/`pre`/`post`
6774
+ * are its mode-specific parameters. `rules` is a DEPRECATED authoring input kept
6775
+ * only for transition + migration (`migrateRulesToMode`); the policy engine
6776
+ * consumes the compiled output of `compileRules(config)`, never `rules` directly.
6777
+ */
6778
+ var RecordingConfigSchema = object({
6779
+ enabled: boolean(),
6780
+ /** Authoritative storage mode. Absent on legacy targets → derived once via
6781
+ * `migrateRulesToMode`, then persisted. */
6782
+ mode: RecordingStorageModeSchema.optional(),
6783
+ profiles: array(CamProfileSchema).optional(),
6784
+ segmentSeconds: number().int().positive().optional(),
6785
+ /** Shared recording time-bands for `events` & `continuous` — record only when
6786
+ * the wall-clock falls inside one of these windows. Omit or empty = always.
6787
+ * `continuous` compiles to one rule per band; `events` to band × trigger. */
6788
+ schedules: array(RecordingScheduleSchema).optional(),
6789
+ /** Legacy single-band predecessor of `schedules`. Read-compat only — it is
6790
+ * normalized into `schedules` on read and never written going forward. (Not
6791
+ * tagged `@deprecated`: the normalization paths must read it cast-free.) */
6792
+ schedule: RecordingScheduleSchema.optional(),
6793
+ /** `events`-mode only — which detectors trigger a recording. */
6794
+ triggers: RecordingTriggersSchema.optional(),
6795
+ /** `events`-mode only — seconds retained before / after a trigger. */
6796
+ preBufferSec: number().min(0).optional(),
6797
+ postBufferSec: number().min(0).optional(),
6798
+ /** DEPRECATED authoring input; retained for migration/transition. */
6799
+ rules: array(RecordingRuleSchema).optional(),
6800
+ /**
6801
+ * AUTHORITATIVE mode-per-band recording model (recorder). When present it
6802
+ * is the single source of truth; the legacy `mode`/`schedules`/`schedule`/
6803
+ * `triggers`/`rules` fields above are kept for READ-COMPAT only and are
6804
+ * derived into bands once via `migrateConfigToBands`.
6805
+ */
6806
+ bands: array(RecordingBandSchema).optional(),
6807
+ retention: RecordingRetentionSchema.optional()
6808
+ });
6809
+ /**
6810
+ * `StorageLocationType` — an addon-declared id that identifies the *kind* of
6811
+ * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
6812
+ * so the persisted record schema and the consumer-facing cap can both consume it
6813
+ * without forming a circular import. The `storage` cap re-exports it
6814
+ * verbatim for back-compat.
6815
+ *
6816
+ * This Zod schema is the **authoritative source** for `StorageLocationType`.
6817
+ * The TS alias in `./storage.ts` re-exports `z.infer<typeof
6818
+ * StorageLocationTypeSchema>` so the wire surface (cap) and the legacy
6819
+ * `IStorageProvider` interface stay in lockstep.
6820
+ *
6821
+ * The type is now an **open string** (not a closed enum) — addons declare
6822
+ * their own location kinds via `StorageLocationDeclaration.id`. The regex
6823
+ * enforces a safe id format: lowercase-start, alphanumeric + hyphens.
6824
+ */
6825
+ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
6826
+ /**
6827
+ * Persisted record for a storage location instance. Operators can register
6828
+ * multiple instances for multi-cardinality types (e.g. two `backups`
6829
+ * locations with different `providerId`s). Cardinality is now declared per
6830
+ * location via `StorageLocationDeclaration.cardinality` — the static
6831
+ * `STORAGE_LOCATION_CARDINALITY` map has been removed.
6832
+ *
6833
+ * `id` is a stable namespaced string of the form `<type>:<slug>`.
6834
+ * The default location for a type uses `id === <type>:default` by
6835
+ * convention (the bare type ref like `'backups'` resolves to it).
6836
+ *
6837
+ * `isSystem: true` marks a location as orchestrator-seeded and
6838
+ * undeletable. The bootstrap-installed defaults (one per type) carry
6839
+ * this flag; operator-added locations don't. Editing the config of
6840
+ * a system location is allowed (path migration, provider swap) but
6841
+ * deleting it is rejected at the cap level.
6842
+ */
6843
+ var StorageLocationSchema = object({
6844
+ id: string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
6845
+ type: string(),
6846
+ displayName: string().min(1),
6847
+ providerId: string().min(1),
6848
+ config: record(string(), unknown()),
6849
+ /**
6850
+ * Cluster node this location physically lives on. REQUIRED for node-local
6851
+ * providers (filesystem — the path exists on one node's disk), null/absent
6852
+ * for node-agnostic providers (S3/SFTP/WebDAV, reachable from any node).
6853
+ * `'hub'` is the hub node. Validated against the provider's `nodeLocal`
6854
+ * flag at upsert time, not here (the schema is provider-agnostic).
6855
+ */
6856
+ nodeId: string().optional(),
6857
+ isDefault: boolean().default(false),
6858
+ isSystem: boolean().default(false),
6859
+ createdAt: number(),
6860
+ updatedAt: number()
6861
+ });
6862
+ /**
6863
+ * Reference accepted by consumer-facing `api.storage.*` calls.
6864
+ * Either:
6865
+ * - a `StorageLocationType` (e.g. `'backups'`) → orchestrator resolves to the default of that type
6866
+ * - a fully-qualified id (e.g. `'backups:nas-01'`) → addresses a specific instance
6867
+ *
6868
+ * The orchestrator's `resolveRef(ref)` handles both cases.
6869
+ */
6870
+ var StorageLocationRefSchema = union([StorageLocationTypeSchema, string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/)]);
6871
+ /**
6872
+ * `StorageLocationDeclaration` — a single storage-location entry declared by
6873
+ * an addon in its `package.json` under `camstack.storageLocations`.
6874
+ *
6875
+ * Design intent:
6876
+ * - **Addon declares its needs** — each addon describes the logical storage
6877
+ * slots it requires (e.g. `recordings`, `recordingsLow`) without caring
6878
+ * about the physical path.
6879
+ * - **Kernel aggregates** — at boot the kernel collects declarations from all
6880
+ * installed addons, deduplicates by `id`, and exposes the union via the
6881
+ * storage-locations settings surface.
6882
+ * - **Orchestrator seeds** — for every declared `id` the orchestrator ensures
6883
+ * at least one instance named `<id>:default` is present, using
6884
+ * `defaultsTo` to inherit the resolved root from another location when the
6885
+ * declaration is a derivative slot (e.g. `recordingsLow` defaults to
6886
+ * `recordings`).
6887
+ * - **ids are global** — `id` values are shared across the entire deployment;
6888
+ * two addons declaring the same `id` must agree on `cardinality` (validated
6889
+ * at kernel aggregation time, not here).
6890
+ */
6891
+ var StorageLocationDeclarationSchema = object({
6892
+ /**
6893
+ * Global location identifier, e.g. `recordings` or `recordingsLow`.
6894
+ * Must start with a lowercase letter and may contain letters, digits, and
6895
+ * hyphens.
6896
+ */
6897
+ id: string().regex(/^[a-z][a-zA-Z0-9-]*$/, { message: "id must start with a lowercase letter and contain only letters, digits, or hyphens" }),
6898
+ /** Human-readable name shown in the admin UI. */
6899
+ displayName: string().min(1, { message: "displayName must not be empty" }),
6900
+ /** Optional longer explanation of what data this location stores. */
6901
+ description: string().optional(),
6902
+ /**
6903
+ * `single` — exactly one instance of this location is allowed system-wide
6904
+ * (e.g. `logs`, `models`). The operator can edit it but not add more.
6905
+ * `multi` — the operator may register several instances (e.g. a second
6906
+ * `recordings` on a NAS for disk tiering); one is the default at any time.
6907
+ */
6908
+ cardinality: _enum(["single", "multi"]),
6909
+ /**
6910
+ * When set, the default instance for this location inherits its resolved
6911
+ * root from the named location's default instance. Useful for derivative
6912
+ * slots (e.g. `recordingsLow` → `recordings`) so operators only need to
6913
+ * configure the primary location.
6914
+ */
6915
+ defaultsTo: string().optional()
6916
+ });
6917
+ var DecoderStatsSchema = object({
6918
+ inputFps: number(),
6919
+ outputFps: number(),
6920
+ avgDecodeTimeMs: number(),
6921
+ droppedFrames: number()
6922
+ });
6923
+ var DecoderSessionConfigSchema = object({
6924
+ codec: string(),
6925
+ maxFps: number().default(0),
6926
+ outputFormat: _enum([
6927
+ "jpeg",
6928
+ "rgb",
6929
+ "bgr",
6930
+ "yuv420",
6931
+ "gray"
6932
+ ]).default("jpeg"),
6933
+ scale: number().default(1),
6934
+ width: number().optional(),
6935
+ height: number().optional(),
6952
6936
  /**
6953
- * Device supports an on-demand re-sync of its derived spec with its
6954
- * upstream source drives the generic Re-sync button. The owning
6955
- * provider implements the action via the `device-adoption.resync` cap.
6937
+ * Identifier of the camera this decoder session serves. Optional
6938
+ * because the cap is generic (any caller could request decode), but
6939
+ * stream-broker passes it so decoder logs include `deviceId` for
6940
+ * per-camera filtering when diagnosing failures (e.g. node-av
6941
+ * sendPacket errors on a single hung camera).
6956
6942
  */
6957
- DeviceFeature["Resyncable"] = "resyncable";
6958
- DeviceFeature["NativeSnapshot"] = "native-snapshot";
6959
- DeviceFeature["DoorbellButton"] = "doorbell-button";
6960
- DeviceFeature["TwoWayAudio"] = "two-way-audio";
6961
- DeviceFeature["PanTiltZoom"] = "pan-tilt-zoom";
6943
+ deviceId: number().int().nonnegative().optional(),
6962
6944
  /**
6963
- * Camera supports the on-firmware autotrack subsystem (subject-
6964
- * following). Distinct from `PanTiltZoom` because not every PTZ
6965
- * camera ships autotrack the admin UI uses this flag to gate
6966
- * the autotrack toggle / settings card without re-deriving from
6967
- * the cap registry. Mirrors `ptz-autotrack` cap registration:
6968
- * driver sets this feature when probe confirms the firmware
6969
- * surface, and registers the cap in the same code path.
6945
+ * Free-form tag for log scoping. Stream-broker uses
6946
+ * `broker:<deviceId>/<profile>`. Decoder session logger surfaces it
6947
+ * on every line so `grep tag=broker:5/high` filters one camera
6948
+ * profile cleanly.
6970
6949
  */
6971
- DeviceFeature["PtzAutotrack"] = "ptz-autotrack";
6950
+ tag: string().optional(),
6972
6951
  /**
6973
- * Accessory exposes a "trigger on motion" toggle the parent camera's
6974
- * motion detection automatically activates this device. Mirrors
6975
- * `motion-trigger` cap registration: drivers set this feature in the
6976
- * same code path that calls `ctx.registerNativeCap(motionTriggerCapability, ...)`.
6952
+ * Where the session delivers decoded frames (Phase 5 / D9):
6977
6953
  *
6978
- * Used by admin UI (gate the in-hero `MotionTriggerToggle` against a
6979
- * fast scalar without binding fetch), notifier rules, and `listAll`
6980
- * filters that want "all devices with on-motion behaviour".
6954
+ * - `'callback'` (default) the legacy pixel path: decoded frames are
6955
+ * buffered as `DecodedFrame`s and drained via `pullFrames`.
6956
+ * - `'shm'` the shared-memory frame plane: decoded frames are written
6957
+ * into an OS shared-memory ring and drained as zero-pixel
6958
+ * `FrameHandle`s via `pullHandles`. A session is one mode or the
6959
+ * other — `pullFrames` returns nothing for an `'shm'` session and
6960
+ * `pullHandles` returns nothing for a `'callback'` session.
6981
6961
  */
6982
- DeviceFeature["MotionTrigger"] = "motion-trigger";
6983
- /** Light supports rgb-triplet color via `color` cap. */
6984
- DeviceFeature["LightColorRgb"] = "light-color-rgb";
6985
- /** Light supports HSV color via `color` cap. */
6986
- DeviceFeature["LightColorHsv"] = "light-color-hsv";
6987
- /** Light supports color-temperature (mired) via `color` cap. */
6988
- DeviceFeature["LightColorMired"] = "light-color-mired";
6989
- /** Thermostat supports a `heat_cool` dual setpoint (targetLow +
6990
- * targetHigh). Gates the range slider UI. */
6991
- DeviceFeature["ClimateDualSetpoint"] = "climate-dual-setpoint";
6992
- /** Thermostat exposes target humidity and/or current humidity
6993
- * readings. Gates the humidity controls. */
6994
- DeviceFeature["ClimateHumidity"] = "climate-humidity";
6995
- /** Thermostat exposes a fan-mode selector. */
6996
- DeviceFeature["ClimateFanMode"] = "climate-fan-mode";
6997
- /** Thermostat exposes preset modes (eco / away / sleep / vendor). */
6998
- DeviceFeature["ClimatePreset"] = "climate-preset";
6999
- /** Cover exposes intermediate position control (0..100). Gates the
7000
- * position slider UI. */
7001
- DeviceFeature["CoverPositionable"] = "cover-positionable";
7002
- /** Cover exposes slat-tilt control. Gates the tilt slider UI. */
7003
- DeviceFeature["CoverTilt"] = "cover-tilt";
7004
- /** Valve exposes intermediate position control (0..100). Gates the
7005
- * position slider / drag surface UI. */
7006
- DeviceFeature["ValvePositionable"] = "valve-positionable";
7007
- /** Fan exposes a speed-percentage setter. Gates the speed slider UI. */
7008
- DeviceFeature["FanSpeed"] = "fan-speed";
7009
- /** Fan exposes a preset mode selector. */
7010
- DeviceFeature["FanPreset"] = "fan-preset";
7011
- /** Fan exposes blade direction (forward/reverse) — typical of
7012
- * ceiling fans. */
7013
- DeviceFeature["FanDirection"] = "fan-direction";
7014
- /** Fan exposes an oscillation toggle. */
7015
- DeviceFeature["FanOscillating"] = "fan-oscillating";
7016
- /** Lock requires a PIN code on lock/unlock. Gates the code-entry
7017
- * field on the UI lock-controls panel. */
7018
- DeviceFeature["LockPinRequired"] = "lock-pin-required";
7019
- /** Lock supports a latch-release ("open door") action distinct from
7020
- * unlock. Mirrors HA `LockEntityFeature.OPEN` (bit 1) in
7021
- * `supported_features`. Gates the Open Door button in the UI. */
7022
- DeviceFeature["LockOpen"] = "lock-open";
7023
- /** Media player exposes a seek-to-position surface. */
7024
- DeviceFeature["MediaPlayerSeek"] = "media-player-seek";
7025
- /** Media player exposes a volume-level setter. */
7026
- DeviceFeature["MediaPlayerVolume"] = "media-player-volume";
7027
- /** Media player exposes a mute toggle distinct from volume=0. */
7028
- DeviceFeature["MediaPlayerMute"] = "media-player-mute";
7029
- /** Media player exposes a shuffle toggle. */
7030
- DeviceFeature["MediaPlayerShuffle"] = "media-player-shuffle";
7031
- /** Media player exposes a repeat mode (off / all / one). */
7032
- DeviceFeature["MediaPlayerRepeat"] = "media-player-repeat";
7033
- /** Media player exposes a source / input selector. */
7034
- DeviceFeature["MediaPlayerSelectSource"] = "media-player-select-source";
7035
- /** Media player exposes a play-arbitrary-media surface (URL / id). */
7036
- DeviceFeature["MediaPlayerPlayMedia"] = "media-player-play-media";
7037
- /** Media player exposes next-track. */
7038
- DeviceFeature["MediaPlayerNext"] = "media-player-next";
7039
- /** Media player exposes previous-track. */
7040
- DeviceFeature["MediaPlayerPrevious"] = "media-player-previous";
7041
- /** Media player exposes stop distinct from pause. */
7042
- DeviceFeature["MediaPlayerStop"] = "media-player-stop";
7043
- /** Alarm panel requires a PIN code on arm/disarm. */
7044
- DeviceFeature["AlarmPinRequired"] = "alarm-pin-required";
7045
- /** Presence device carries GPS coordinates (lat/lng/accuracy) in
7046
- * addition to a textual location. */
7047
- DeviceFeature["PresenceGps"] = "presence-gps";
7048
- /** Notifier accepts an inline / URL image attachment. */
7049
- DeviceFeature["NotifierImage"] = "notifier-image";
7050
- /** Notifier accepts a priority hint (high/normal/low). */
7051
- DeviceFeature["NotifierPriority"] = "notifier-priority";
7052
- /** Notifier accepts a free-form `data` payload for platform-specific
7053
- * fields. */
7054
- DeviceFeature["NotifierData"] = "notifier-data";
7055
- /** Notifier supports interactive action buttons / callbacks. */
7056
- DeviceFeature["NotifierActions"] = "notifier-actions";
7057
- /** Notifier supports per-call recipient targeting (multi-user). */
7058
- DeviceFeature["NotifierRecipients"] = "notifier-recipients";
7059
- /** Script runner accepts a variables map on each run invocation. */
7060
- DeviceFeature["ScriptVariables"] = "script-variables";
7061
- /** Automation `trigger` accepts a skipCondition flag — fires the
7062
- * automation's actions while bypassing its condition block. */
7063
- DeviceFeature["AutomationSkipCondition"] = "automation-skip-condition";
7064
- return DeviceFeature;
7065
- }({});
7066
- /**
7067
- * Semantic role a device plays within its parent. Populated by driver
7068
- * addons when creating accessory devices (Reolink siren/floodlight/
7069
- * PIR/chime/autotrack/doorbell, ONVIF relay outputs, …). Used by the
7070
- * admin UI to pick icons, labels, and widgets — a `Switch` with
7071
- * `role: Floodlight` renders as a bulb with a brightness slider,
7072
- * whereas a `Switch` with `role: Siren` renders as a klaxon.
7073
- *
7074
- * Undefined for top-level devices (cameras, NVRs, hubs). Persisted in
7075
- * sqlite as a nullable TEXT column — old rows keep working unchanged.
7076
- */
7077
- var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
7078
- DeviceRole["Siren"] = "siren";
7079
- DeviceRole["Floodlight"] = "floodlight";
7080
- DeviceRole["Spotlight"] = "spotlight";
7081
- DeviceRole["PirSensor"] = "pir-sensor";
7082
- DeviceRole["Chime"] = "chime";
7083
- DeviceRole["Autotrack"] = "autotrack";
7084
- DeviceRole["Nightvision"] = "nightvision";
7085
- DeviceRole["PrivacyMask"] = "privacy-mask";
7086
- DeviceRole["Doorbell"] = "doorbell";
7087
- /** Virtual HA toggle (input_boolean.*) — distinguishable from a
7088
- * real Switch device for UI rendering / export adapters. */
7089
- DeviceRole["BinaryHelper"] = "binary-helper";
7090
- /** Generic motion / occupancy / moving event source. Distinct from
7091
- * the camera accessory PirSensor role: that one is a camera child;
7092
- * this is a standalone HA / 3rd-party motion sensor. */
7093
- DeviceRole["MotionSensor"] = "motion-sensor";
7094
- DeviceRole["ContactSensor"] = "contact-sensor";
7095
- DeviceRole["LeakSensor"] = "leak-sensor";
7096
- DeviceRole["SmokeSensor"] = "smoke-sensor";
7097
- DeviceRole["COSensor"] = "co-sensor";
7098
- DeviceRole["GasSensor"] = "gas-sensor";
7099
- DeviceRole["TamperSensor"] = "tamper-sensor";
7100
- DeviceRole["VibrationSensor"] = "vibration-sensor";
7101
- DeviceRole["ConnectivitySensor"] = "connectivity-sensor";
7102
- DeviceRole["SoundSensor"] = "sound-sensor";
7103
- /** Fallback for `binary_sensor` without a known `device_class`. */
7104
- DeviceRole["BinarySensor"] = "binary-sensor";
7105
- DeviceRole["TemperatureSensor"] = "temperature-sensor";
7106
- DeviceRole["HumiditySensor"] = "humidity-sensor";
7107
- DeviceRole["AmbientLightSensor"] = "ambient-light-sensor";
7108
- DeviceRole["PressureSensor"] = "pressure-sensor";
7109
- DeviceRole["PowerSensor"] = "power-sensor";
7110
- DeviceRole["EnergySensor"] = "energy-sensor";
7111
- DeviceRole["VoltageSensor"] = "voltage-sensor";
7112
- DeviceRole["CurrentSensor"] = "current-sensor";
7113
- DeviceRole["AirQualitySensor"] = "air-quality-sensor";
7114
- /** Battery level (numeric % via `sensor` OR low-bool via
7115
- * `binary_sensor` — the cap distinguishes via the value type). */
7116
- DeviceRole["BatterySensor"] = "battery-sensor";
7117
- /** Fallback for `sensor` numeric without a known `device_class`. */
7118
- DeviceRole["NumericSensor"] = "numeric-sensor";
7119
- /** String / enum state (HA `sensor` with `state_class: enum` or
7120
- * `attributes.options`). */
7121
- DeviceRole["EnumSensor"] = "enum-sensor";
7122
- /** Date / timestamp state (HA `sensor` with `device_class: timestamp`
7123
- * or `date`). The slice carries the raw ISO string verbatim (hosted on
7124
- * the `enum-sensor` cap); the UI renders it locale-formatted. */
7125
- DeviceRole["DateTimeSensor"] = "datetime-sensor";
7126
- /** Last-resort fallback when nothing else matches. */
7127
- DeviceRole["GenericSensor"] = "generic-sensor";
7128
- DeviceRole["NumericControl"] = "numeric-control";
7129
- DeviceRole["SelectControl"] = "select-control";
7130
- DeviceRole["TextControl"] = "text-control";
7131
- DeviceRole["DateTimeControl"] = "datetime-control";
7132
- /** Mobile push notifier (HA `notify.mobile_app_*`) — supports
7133
- * rich features (image, priority, channel routing). */
7134
- DeviceRole["MobilePushNotifier"] = "mobile-push-notifier";
7135
- /** Chat / messaging service (HA `notify.telegram_*`,
7136
- * `notify.discord_*`, etc.). */
7137
- DeviceRole["MessagingNotifier"] = "messaging-notifier";
7138
- /** Email-based delivery (HA `notify.smtp`, etc.). */
7139
- DeviceRole["EmailNotifier"] = "email-notifier";
7140
- /** Fallback when the notifier service name doesn't match a known
7141
- * pattern. */
7142
- DeviceRole["GenericNotifier"] = "generic-notifier";
7143
- return DeviceRole;
7144
- }({});
6962
+ frameSink: _enum(["callback", "shm"]).default("callback")
6963
+ });
6964
+ var EncodeProfileSchema = object({
6965
+ video: object({
6966
+ codec: _enum([
6967
+ "h264",
6968
+ "h265",
6969
+ "copy"
6970
+ ]),
6971
+ profile: _enum([
6972
+ "baseline",
6973
+ "main",
6974
+ "high"
6975
+ ]).optional(),
6976
+ width: number().int().positive().optional(),
6977
+ height: number().int().positive().optional(),
6978
+ fps: number().positive().optional(),
6979
+ bitrateKbps: number().int().positive().optional(),
6980
+ gopFrames: number().int().positive().optional(),
6981
+ bf: number().int().min(0).optional(),
6982
+ preset: _enum([
6983
+ "ultrafast",
6984
+ "superfast",
6985
+ "veryfast",
6986
+ "faster",
6987
+ "fast",
6988
+ "medium"
6989
+ ]).optional(),
6990
+ tune: _enum([
6991
+ "zerolatency",
6992
+ "film",
6993
+ "animation"
6994
+ ]).optional()
6995
+ }),
6996
+ audio: union([literal("passthrough"), object({
6997
+ codec: _enum([
6998
+ "opus",
6999
+ "aac",
7000
+ "pcmu",
7001
+ "pcma",
7002
+ "copy"
7003
+ ]),
7004
+ bitrateKbps: number().int().positive().optional(),
7005
+ sampleRateHz: number().int().positive().optional(),
7006
+ channels: union([literal(1), literal(2)]).optional()
7007
+ })]),
7008
+ /**
7009
+ * ffmpeg input-side args, inserted between the fixed global flags
7010
+ * (`-hide_banner -loglevel error`) and `-i pipe:0`. Free-text array
7011
+ * the widget surfaces a textarea + suggestion chips for the most-
7012
+ * used demuxer/format options.
7013
+ */
7014
+ inputArgs: array(string()).optional(),
7015
+ /**
7016
+ * ffmpeg output-side args, inserted between the encode block and
7017
+ * the final `-f <muxer> pipe:1`. Use for muxer options, bitstream
7018
+ * filters, codec-specific overrides. Free-text array.
7019
+ */
7020
+ outputArgs: array(string()).optional()
7021
+ });
7022
+ var YAMNET_TO_MACRO = {
7023
+ mapping: {
7024
+ Speech: "speech",
7025
+ "Child speech, kid speaking": "speech",
7026
+ Conversation: "speech",
7027
+ "Narration, monologue": "speech",
7028
+ Babbling: "speech",
7029
+ Whispering: "speech",
7030
+ "Speech synthesizer": "speech",
7031
+ Humming: "speech",
7032
+ Rapping: "speech",
7033
+ Singing: "speech",
7034
+ Choir: "speech",
7035
+ "Child singing": "speech",
7036
+ Shout: "scream",
7037
+ Bellow: "scream",
7038
+ Yell: "scream",
7039
+ Screaming: "scream",
7040
+ "Children shouting": "scream",
7041
+ Whoop: "scream",
7042
+ "Crying, sobbing": "crying",
7043
+ "Baby cry, infant cry": "crying",
7044
+ Whimper: "crying",
7045
+ "Wail, moan": "crying",
7046
+ Groan: "crying",
7047
+ Laughter: "laughter",
7048
+ "Baby laughter": "laughter",
7049
+ Giggle: "laughter",
7050
+ Snicker: "laughter",
7051
+ "Belly laugh": "laughter",
7052
+ "Chuckle, chortle": "laughter",
7053
+ Music: "music",
7054
+ "Musical instrument": "music",
7055
+ Guitar: "music",
7056
+ Piano: "music",
7057
+ Drum: "music",
7058
+ "Drum kit": "music",
7059
+ "Violin, fiddle": "music",
7060
+ Flute: "music",
7061
+ Saxophone: "music",
7062
+ Trumpet: "music",
7063
+ Synthesizer: "music",
7064
+ "Pop music": "music",
7065
+ "Rock music": "music",
7066
+ "Hip hop music": "music",
7067
+ "Classical music": "music",
7068
+ Jazz: "music",
7069
+ "Electronic music": "music",
7070
+ "Background music": "music",
7071
+ Dog: "dog",
7072
+ Bark: "dog",
7073
+ Yip: "dog",
7074
+ Howl: "dog",
7075
+ "Bow-wow": "dog",
7076
+ Growling: "dog",
7077
+ "Whimper (dog)": "dog",
7078
+ Cat: "cat",
7079
+ Purr: "cat",
7080
+ Meow: "cat",
7081
+ Hiss: "cat",
7082
+ Caterwaul: "cat",
7083
+ Bird: "bird",
7084
+ "Bird vocalization, bird call, bird song": "bird",
7085
+ "Chirp, tweet": "bird",
7086
+ Squawk: "bird",
7087
+ Crow: "bird",
7088
+ Owl: "bird",
7089
+ "Pigeon, dove": "bird",
7090
+ Animal: "animal",
7091
+ "Domestic animals, pets": "animal",
7092
+ "Livestock, farm animals, working animals": "animal",
7093
+ Horse: "animal",
7094
+ "Cattle, bovinae": "animal",
7095
+ Pig: "animal",
7096
+ Sheep: "animal",
7097
+ Goat: "animal",
7098
+ Frog: "animal",
7099
+ Insect: "animal",
7100
+ Cricket: "animal",
7101
+ Alarm: "alarm",
7102
+ "Alarm clock": "alarm",
7103
+ "Smoke detector, smoke alarm": "alarm",
7104
+ "Fire alarm": "alarm",
7105
+ Buzzer: "alarm",
7106
+ "Civil defense siren": "alarm",
7107
+ "Car alarm": "alarm",
7108
+ Siren: "siren",
7109
+ "Police car (siren)": "siren",
7110
+ "Ambulance (siren)": "siren",
7111
+ "Fire engine, fire truck (siren)": "siren",
7112
+ "Emergency vehicle": "siren",
7113
+ Foghorn: "siren",
7114
+ Doorbell: "doorbell",
7115
+ "Ding-dong": "doorbell",
7116
+ Knock: "doorbell",
7117
+ Tap: "doorbell",
7118
+ Glass: "glass_breaking",
7119
+ Shatter: "glass_breaking",
7120
+ "Chink, clink": "glass_breaking",
7121
+ "Gunshot, gunfire": "gunshot",
7122
+ "Machine gun": "gunshot",
7123
+ Explosion: "gunshot",
7124
+ Fireworks: "gunshot",
7125
+ Firecracker: "gunshot",
7126
+ "Artillery fire": "gunshot",
7127
+ "Cap gun": "gunshot",
7128
+ Boom: "gunshot",
7129
+ Vehicle: "vehicle",
7130
+ Car: "vehicle",
7131
+ Truck: "vehicle",
7132
+ Bus: "vehicle",
7133
+ Motorcycle: "vehicle",
7134
+ "Car passing by": "vehicle",
7135
+ "Vehicle horn, car horn, honking": "vehicle",
7136
+ "Traffic noise, roadway noise": "vehicle",
7137
+ Train: "vehicle",
7138
+ Aircraft: "vehicle",
7139
+ Helicopter: "vehicle",
7140
+ Bicycle: "vehicle",
7141
+ Skateboard: "vehicle",
7142
+ Fire: "fire",
7143
+ Crackle: "fire",
7144
+ Water: "water",
7145
+ Rain: "water",
7146
+ Raindrop: "water",
7147
+ "Rain on surface": "water",
7148
+ Stream: "water",
7149
+ Waterfall: "water",
7150
+ Ocean: "water",
7151
+ "Waves, surf": "water",
7152
+ "Splash, splatter": "water",
7153
+ Wind: "wind",
7154
+ Thunderstorm: "wind",
7155
+ Thunder: "wind",
7156
+ "Wind noise (microphone)": "wind",
7157
+ "Rustling leaves": "wind",
7158
+ Door: "door",
7159
+ "Sliding door": "door",
7160
+ Slam: "door",
7161
+ "Cupboard open or close": "door",
7162
+ "Walk, footsteps": "footsteps",
7163
+ Run: "footsteps",
7164
+ Shuffle: "footsteps",
7165
+ Crowd: "crowd",
7166
+ Chatter: "crowd",
7167
+ Cheering: "crowd",
7168
+ Applause: "crowd",
7169
+ "Children playing": "crowd",
7170
+ "Hubbub, speech noise, speech babble": "crowd",
7171
+ Telephone: "telephone",
7172
+ "Telephone bell ringing": "telephone",
7173
+ Ringtone: "telephone",
7174
+ "Telephone dialing, DTMF": "telephone",
7175
+ "Busy signal": "telephone",
7176
+ Engine: "engine",
7177
+ "Engine starting": "engine",
7178
+ Idling: "engine",
7179
+ "Accelerating, revving, vroom": "engine",
7180
+ "Light engine (high frequency)": "engine",
7181
+ "Medium engine (mid frequency)": "engine",
7182
+ "Heavy engine (low frequency)": "engine",
7183
+ "Lawn mower": "engine",
7184
+ Chainsaw: "engine",
7185
+ Hammer: "tools",
7186
+ Jackhammer: "tools",
7187
+ Sawing: "tools",
7188
+ "Power tool": "tools",
7189
+ Drill: "tools",
7190
+ Sanding: "tools",
7191
+ Silence: "silence"
7192
+ },
7193
+ preserveOriginal: false
7194
+ };
7195
+ var APPLE_SA_TO_MACRO = {
7196
+ mapping: {
7197
+ speech: "speech",
7198
+ child_speech: "speech",
7199
+ conversation: "speech",
7200
+ whispering: "speech",
7201
+ singing: "speech",
7202
+ humming: "speech",
7203
+ shout: "scream",
7204
+ yell: "scream",
7205
+ screaming: "scream",
7206
+ crying: "crying",
7207
+ baby_crying: "crying",
7208
+ sobbing: "crying",
7209
+ laughter: "laughter",
7210
+ baby_laughter: "laughter",
7211
+ giggling: "laughter",
7212
+ music: "music",
7213
+ guitar: "music",
7214
+ piano: "music",
7215
+ drums: "music",
7216
+ dog_bark: "dog",
7217
+ dog_bow_wow: "dog",
7218
+ dog_growling: "dog",
7219
+ dog_howl: "dog",
7220
+ cat_meow: "cat",
7221
+ cat_purr: "cat",
7222
+ cat_hiss: "cat",
7223
+ bird: "bird",
7224
+ bird_chirp: "bird",
7225
+ bird_squawk: "bird",
7226
+ animal: "animal",
7227
+ horse: "animal",
7228
+ cow_moo: "animal",
7229
+ insect: "animal",
7230
+ alarm: "alarm",
7231
+ smoke_alarm: "alarm",
7232
+ fire_alarm: "alarm",
7233
+ car_alarm: "alarm",
7234
+ siren: "siren",
7235
+ police_siren: "siren",
7236
+ ambulance_siren: "siren",
7237
+ doorbell: "doorbell",
7238
+ door_knock: "doorbell",
7239
+ knocking: "doorbell",
7240
+ glass_breaking: "glass_breaking",
7241
+ glass_shatter: "glass_breaking",
7242
+ gunshot: "gunshot",
7243
+ explosion: "gunshot",
7244
+ fireworks: "gunshot",
7245
+ car: "vehicle",
7246
+ truck: "vehicle",
7247
+ motorcycle: "vehicle",
7248
+ car_horn: "vehicle",
7249
+ vehicle_horn: "vehicle",
7250
+ traffic: "vehicle",
7251
+ fire: "fire",
7252
+ fire_crackle: "fire",
7253
+ water: "water",
7254
+ rain: "water",
7255
+ ocean: "water",
7256
+ splash: "water",
7257
+ wind: "wind",
7258
+ thunder: "wind",
7259
+ thunderstorm: "wind",
7260
+ door: "door",
7261
+ door_slam: "door",
7262
+ sliding_door: "door",
7263
+ footsteps: "footsteps",
7264
+ walking: "footsteps",
7265
+ running: "footsteps",
7266
+ crowd: "crowd",
7267
+ chatter: "crowd",
7268
+ cheering: "crowd",
7269
+ applause: "crowd",
7270
+ telephone_ring: "telephone",
7271
+ ringtone: "telephone",
7272
+ engine: "engine",
7273
+ engine_starting: "engine",
7274
+ lawn_mower: "engine",
7275
+ chainsaw: "engine",
7276
+ hammer: "tools",
7277
+ jackhammer: "tools",
7278
+ drill: "tools",
7279
+ power_tool: "tools",
7280
+ silence: "silence"
7281
+ },
7282
+ preserveOriginal: false
7283
+ };
7284
+ var _macroLookup = /* @__PURE__ */ new Map();
7285
+ for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
7286
+ for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
7145
7287
  /**
7146
7288
  * Accessory device helpers — shared across drivers.
7147
7289
  *
@@ -7301,74 +7443,6 @@ object({
7301
7443
  });
7302
7444
  DeviceType.Sensor;
7303
7445
  /**
7304
- * Generic types for capability definitions.
7305
- *
7306
- * A capability is defined with Zod schemas for methods, events, and settings.
7307
- * TypeScript types are inferred via z.infer<> — zero duplication.
7308
- *
7309
- * Pattern:
7310
- * 1. Define Zod schemas for data, methods, settings
7311
- * 2. Export const capabilityDef = { ... } satisfies CapabilityDefinition
7312
- * 3. Export type IProvider = InferProvider<typeof capabilityDef>
7313
- * 4. Addon implements IProvider
7314
- * 5. Registry auto-mounts tRPC router from definition.methods
7315
- */
7316
- /**
7317
- * Output schema shared by the contribution + live methods.
7318
- *
7319
- * Mirrors the `ConfigUISchemaWithValues` shape (sections[] + optional
7320
- * tabs[]) without importing from `../interfaces/config-ui.js` — a
7321
- * concrete-but-lenient Zod object keeps tRPC output inference happy
7322
- * (using `z.unknown()` here collapses unrelated router branches to
7323
- * `unknown` when the generator re-inlines the huge AppRouter type).
7324
- *
7325
- * `.passthrough()` on sections/fields accepts whatever FormBuilder
7326
- * extensions the caller adds (showWhen, displayScale, …) without
7327
- * rebuilding every time a new field kind is introduced.
7328
- */
7329
- var ContributionSectionSchema = object({
7330
- id: string(),
7331
- title: string(),
7332
- description: string().optional(),
7333
- style: _enum(["card", "accordion"]).optional(),
7334
- defaultCollapsed: boolean().optional(),
7335
- columns: union([
7336
- literal(1),
7337
- literal(2),
7338
- literal(3),
7339
- literal(4)
7340
- ]).optional(),
7341
- tab: string().optional(),
7342
- location: _enum(["settings", "top-tab"]).optional(),
7343
- order: number().optional(),
7344
- fields: array(any())
7345
- });
7346
- object({
7347
- tabs: array(object({
7348
- id: string(),
7349
- label: string(),
7350
- icon: string(),
7351
- order: number().optional()
7352
- })).optional(),
7353
- sections: array(ContributionSectionSchema)
7354
- }).nullable();
7355
- object({ deviceId: number() }), object({ deviceId: number() }), object({
7356
- deviceId: number(),
7357
- patch: record(string(), unknown())
7358
- }), object({ success: literal(true) });
7359
- object({ deviceId: number() }), unknown().nullable();
7360
- /** Shorthand to define a method schema */
7361
- function method(input, output, options) {
7362
- return {
7363
- input,
7364
- output,
7365
- kind: options?.kind ?? "query",
7366
- auth: options?.auth ?? "protected",
7367
- ...options?.access !== void 0 ? { access: options.access } : {},
7368
- timeoutMs: options?.timeoutMs
7369
- };
7370
- }
7371
- /**
7372
7446
  * Alarm-panel cap. Models HA `alarm_control_panel.*` on
7373
7447
  * `DeviceType.AlarmPanel`. State follows HA's canonical lifecycle
7374
7448
  * across disarmed / armed_(home|away|night|vacation|custom_bypass) /
@@ -9183,6 +9257,24 @@ var DetectorOutputSchema = object({
9183
9257
  inferenceMs: number(),
9184
9258
  modelId: string()
9185
9259
  });
9260
+ var EngineProvisioningSchema = object({
9261
+ runtimeId: _enum([
9262
+ "onnx",
9263
+ "openvino",
9264
+ "coreml"
9265
+ ]).nullable(),
9266
+ device: string().nullable(),
9267
+ state: _enum([
9268
+ "idle",
9269
+ "installing",
9270
+ "verifying",
9271
+ "ready",
9272
+ "failed"
9273
+ ]),
9274
+ progress: number().optional(),
9275
+ error: string().optional(),
9276
+ nextRetryAt: number().optional()
9277
+ });
9186
9278
  var PipelineStepInputSchema = lazy(() => object({
9187
9279
  addonId: string(),
9188
9280
  modelId: string(),
@@ -9251,7 +9343,7 @@ var PipelineRunResultBridge = custom();
9251
9343
  method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
9252
9344
  kind: "mutation",
9253
9345
  auth: "admin"
9254
- }), method(_void(), record(string(), object({
9346
+ }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
9255
9347
  modelId: string(),
9256
9348
  settings: record(string(), unknown()).readonly()
9257
9349
  }))), method(object({ steps: record(string(), object({
@@ -11352,9 +11444,6 @@ method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
11352
11444
  limit: number().optional(),
11353
11445
  tags: record(string(), string()).optional()
11354
11446
  }), array(LogEntrySchema).readonly());
11355
- var StaticDirOutputSchema = object({ staticDir: string() });
11356
- var VersionOutputSchema = object({ version: string() });
11357
- method(_void(), StaticDirOutputSchema), method(_void(), VersionOutputSchema);
11358
11447
  /**
11359
11448
  * Zod schemas for persisted record types.
11360
11449
  *
@@ -12851,7 +12940,10 @@ var AgentAddonConfigSchema = object({
12851
12940
  modelId: string(),
12852
12941
  settings: record(string(), unknown()).readonly()
12853
12942
  });
12854
- var AgentPipelineSettingsSchema = object({ addonDefaults: record(string(), AgentAddonConfigSchema).readonly() });
12943
+ var AgentPipelineSettingsSchema = object({
12944
+ addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
12945
+ maxCameras: number().int().nonnegative().nullable().default(null)
12946
+ });
12855
12947
  var CameraPipelineForAgentSchema = object({
12856
12948
  steps: array(PipelineStepInputSchema).readonly(),
12857
12949
  audio: object({
@@ -12953,6 +13045,133 @@ var GlobalMetricsSchema = object({
12953
13045
  * capability providers.
12954
13046
  */
12955
13047
  var CapabilityBindingsSchema = record(string(), string());
13048
+ /** Source block — always present; derives from the stream catalog. */
13049
+ var CameraSourceStatusSchema = object({ streams: array(object({
13050
+ camStreamId: string(),
13051
+ codec: string(),
13052
+ width: number(),
13053
+ height: number(),
13054
+ fps: number(),
13055
+ kind: string()
13056
+ })).readonly() });
13057
+ /** Assignment block — always present (orchestrator-local, no remote call). */
13058
+ var CameraAssignmentStatusSchema = object({
13059
+ detectionNodeId: string().nullable(),
13060
+ decoderNodeId: string().nullable(),
13061
+ audioNodeId: string().nullable(),
13062
+ pinned: object({
13063
+ detection: boolean(),
13064
+ decoder: boolean(),
13065
+ audio: boolean()
13066
+ }),
13067
+ reasons: object({
13068
+ detection: string().optional(),
13069
+ decoder: string().optional(),
13070
+ audio: string().optional()
13071
+ })
13072
+ });
13073
+ /** Broker block — null when the broker stage is unreachable or inactive. */
13074
+ var CameraBrokerStatusSchema = object({
13075
+ profiles: array(object({
13076
+ profile: string(),
13077
+ status: string(),
13078
+ codec: string(),
13079
+ width: number(),
13080
+ height: number(),
13081
+ subscribers: number(),
13082
+ inFps: number(),
13083
+ outFps: number()
13084
+ })).readonly(),
13085
+ webrtcSessions: number(),
13086
+ rtspRestream: boolean()
13087
+ });
13088
+ /** Shared-memory ring statistics within the decoder block. */
13089
+ var CameraDecoderShmSchema = object({
13090
+ framesWritten: number(),
13091
+ getFrameHits: number(),
13092
+ getFrameMisses: number(),
13093
+ budgetMb: number()
13094
+ });
13095
+ /** Decoder block — null when the decoder stage is unreachable or inactive. */
13096
+ var CameraDecoderStatusSchema = object({
13097
+ nodeId: string(),
13098
+ formats: array(string()).readonly(),
13099
+ sessionCount: number(),
13100
+ shm: CameraDecoderShmSchema
13101
+ });
13102
+ /** Motion block — null when motion detection is not active for this device. */
13103
+ var CameraMotionStatusSchema = object({
13104
+ enabled: boolean(),
13105
+ fps: number()
13106
+ });
13107
+ /** Detection provisioning sub-block. */
13108
+ var CameraDetectionProvisioningSchema = object({
13109
+ state: _enum([
13110
+ "idle",
13111
+ "installing",
13112
+ "verifying",
13113
+ "ready",
13114
+ "failed"
13115
+ ]),
13116
+ error: string().optional()
13117
+ });
13118
+ /** Detection phase — derived from the runner's engine phase. */
13119
+ var CameraDetectionPhaseSchema = _enum([
13120
+ "idle",
13121
+ "watching",
13122
+ "active"
13123
+ ]);
13124
+ /** Detection block — null when no detection node is assigned or reachable. */
13125
+ var CameraDetectionStatusSchema = object({
13126
+ nodeId: string(),
13127
+ engine: object({
13128
+ backend: string(),
13129
+ device: string()
13130
+ }),
13131
+ phase: CameraDetectionPhaseSchema,
13132
+ configuredFps: number(),
13133
+ actualFps: number(),
13134
+ queueDepth: number(),
13135
+ avgInferenceMs: number(),
13136
+ provisioning: CameraDetectionProvisioningSchema
13137
+ });
13138
+ /** Audio block — null when no audio node is assigned or reachable. */
13139
+ var CameraAudioStatusSchema = object({
13140
+ nodeId: string(),
13141
+ enabled: boolean()
13142
+ });
13143
+ /** Recording block — null when no recording cap is active for this device. */
13144
+ var CameraRecordingStatusSchema = object({
13145
+ mode: _enum([
13146
+ "off",
13147
+ "continuous",
13148
+ "events"
13149
+ ]),
13150
+ active: boolean(),
13151
+ storageBytes: number()
13152
+ });
13153
+ /**
13154
+ * Aggregated per-camera pipeline status — server-composed, single call.
13155
+ *
13156
+ * The `assignment` and `source` blocks are always present.
13157
+ * Every other block is `null` when the stage is inactive or unreachable
13158
+ * during the bounded parallel fan-out in the orchestrator implementation.
13159
+ *
13160
+ * See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
13161
+ */
13162
+ var CameraStatusSchema = object({
13163
+ deviceId: number(),
13164
+ assignment: CameraAssignmentStatusSchema,
13165
+ source: CameraSourceStatusSchema,
13166
+ broker: CameraBrokerStatusSchema.nullable(),
13167
+ decoder: CameraDecoderStatusSchema.nullable(),
13168
+ motion: CameraMotionStatusSchema.nullable(),
13169
+ detection: CameraDetectionStatusSchema.nullable(),
13170
+ audio: CameraAudioStatusSchema.nullable(),
13171
+ recording: CameraRecordingStatusSchema.nullable(),
13172
+ /** Unix timestamp (ms) when this snapshot was composed server-side. */
13173
+ fetchedAt: number()
13174
+ });
12956
13175
  method(object({
12957
13176
  deviceId: number(),
12958
13177
  agentNodeId: string()
@@ -13020,6 +13239,12 @@ method(object({
13020
13239
  }), {
13021
13240
  kind: "mutation",
13022
13241
  auth: "admin"
13242
+ }), method(object({
13243
+ agentNodeId: string(),
13244
+ maxCameras: number().int().nonnegative().nullable()
13245
+ }), object({ success: literal(true) }), {
13246
+ kind: "mutation",
13247
+ auth: "admin"
13023
13248
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
13024
13249
  deviceId: number(),
13025
13250
  addonId: string(),
@@ -13045,7 +13270,7 @@ method(object({
13045
13270
  }), method(object({
13046
13271
  deviceId: number(),
13047
13272
  agentNodeId: string().optional()
13048
- }), CameraPipelineConfigSchema), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13273
+ }), CameraPipelineConfigSchema), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13049
13274
  name: string(),
13050
13275
  description: string().optional(),
13051
13276
  config: CameraPipelineConfigSchema
@@ -13532,7 +13757,7 @@ method(object({
13532
13757
  }), _void(), {
13533
13758
  kind: "mutation",
13534
13759
  auth: "admin"
13535
- }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
13760
+ }), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({ addonId: string().optional() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
13536
13761
  deviceId: number(),
13537
13762
  values: record(string(), unknown())
13538
13763
  }), object({ success: literal(true) }), {
@@ -14214,7 +14439,20 @@ var DiskSpaceInfoSchema = object({
14214
14439
  var PidResourceStatsSchema = object({
14215
14440
  pid: number(),
14216
14441
  cpu: number(),
14217
- memory: number()
14442
+ memory: number(),
14443
+ /**
14444
+ * Private (anonymous) resident bytes — the per-process V8 heap + native
14445
+ * allocations NOT shared with other processes (Linux RssAnon). This is the
14446
+ * "real" per-runner cost; summing it across runners is meaningful, unlike
14447
+ * `memory` (RSS), which double-counts the shared mmap'd framework code.
14448
+ * Undefined where /proc is unavailable (e.g. macOS).
14449
+ */
14450
+ privateBytes: number().optional(),
14451
+ /**
14452
+ * Shared file-backed resident bytes (Linux RssFile) — mmap'd framework/lib
14453
+ * code shared copy-on-write across runners. Undefined on macOS.
14454
+ */
14455
+ sharedBytes: number().optional()
14218
14456
  });
14219
14457
  var AddonInstanceSchema = object({
14220
14458
  addonId: string(),
@@ -14263,6 +14501,17 @@ var KillProcessResultSchema = object({
14263
14501
  reason: string().optional(),
14264
14502
  signal: _enum(["SIGTERM", "SIGKILL"]).optional()
14265
14503
  });
14504
+ var DumpHeapSnapshotInputSchema = object({
14505
+ /** The addon whose runner should dump a heap snapshot. */
14506
+ addonId: string() });
14507
+ var DumpHeapSnapshotResultSchema = object({
14508
+ success: boolean(),
14509
+ /** Path of the written .heapsnapshot inside the runner's container/host. */
14510
+ path: string().optional(),
14511
+ /** Process pid that was signalled. */
14512
+ pid: number().optional(),
14513
+ reason: string().optional()
14514
+ });
14266
14515
  var SystemMetricsSchema = object({
14267
14516
  cpuPercent: number(),
14268
14517
  memoryPercent: number(),
@@ -14276,6 +14525,9 @@ var SystemMetricsSchema = object({
14276
14525
  method(_void(), SystemResourceSnapshotSchema), method(_void(), SystemResourceSnapshotSchema.nullable()), method(_void(), SystemMetricsSchema), method(object({ dirPath: string() }), DiskSpaceInfoSchema), method(_void(), MetricsGpuInfoSchema.nullable()), method(_void(), number().nullable()), method(object({ pids: array(number()) }), array(PidResourceStatsSchema)), method(_void(), array(AddonInstanceSchema).readonly()), method(object({ addonId: string() }), PidResourceStatsSchema.nullable()), method(_void(), array(NodeProcessSchema).readonly()), method(KillProcessInputSchema, KillProcessResultSchema, {
14277
14526
  kind: "mutation",
14278
14527
  auth: "admin"
14528
+ }), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
14529
+ kind: "mutation",
14530
+ auth: "admin"
14279
14531
  });
14280
14532
  var PtzPresetSchema = object({
14281
14533
  id: string(),
@@ -14642,63 +14894,6 @@ method(object({
14642
14894
  auth: "admin"
14643
14895
  });
14644
14896
  /**
14645
- * device-ops — device-scoped cap that unifies the per-IDevice operations
14646
- * previously routed through the `.device-ops` Moleculer bridge service.
14647
- *
14648
- * Each worker that hosts live `IDevice` instances auto-registers a native
14649
- * provider for this cap (per device) backed by its local
14650
- * `DeviceRegistry`. Hub-side callers reach it transparently through
14651
- * `ctx.fetchDevice(id).deviceOps.*` — the DeviceProxy injects
14652
- * `deviceId` + `nodeId` and dispatches through the standard cap-router,
14653
- * so there's no parallel bridge path anymore.
14654
- *
14655
- * The surface is intentionally small — every method corresponds to a
14656
- * single action on the live `IDevice` (or `ICameraDevice` for
14657
- * `getStreamSources`). Richer orchestration (enable/disable with
14658
- * integration plumbing, bulk updates) stays in the `device-manager` cap;
14659
- * `device-ops` is the per-device primitive the device-manager routes to.
14660
- */
14661
- var StreamSourceEntrySchema$1 = object({
14662
- id: string(),
14663
- label: string(),
14664
- protocol: _enum([
14665
- "rtsp",
14666
- "rtmp",
14667
- "annexb",
14668
- "http-mjpeg",
14669
- "webrtc",
14670
- "custom"
14671
- ]),
14672
- url: string().optional(),
14673
- resolution: object({
14674
- width: number(),
14675
- height: number()
14676
- }).optional(),
14677
- fps: number().optional(),
14678
- bitrate: number().optional(),
14679
- codec: string().optional(),
14680
- profileHint: CamProfileSchema.optional(),
14681
- sdp: string().optional()
14682
- });
14683
- var ConfigEntrySchema$1 = object({
14684
- key: string(),
14685
- value: unknown()
14686
- });
14687
- var RawStateResultSchema = object({
14688
- /** Originating provider id, e.g. 'homeassistant' | 'reolink' | 'hikvision'. */
14689
- source: string(),
14690
- /** Opaque, DISPLAY-SAFE upstream blob (no secrets/PII). */
14691
- data: record(string(), unknown())
14692
- });
14693
- method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema$1)), method(object({
14694
- deviceId: number(),
14695
- values: record(string(), unknown())
14696
- }), _void(), { kind: "mutation" }), method(object({
14697
- deviceId: number(),
14698
- action: string().min(1),
14699
- input: unknown()
14700
- }), unknown(), { kind: "mutation" }), method(object({ deviceId: number() }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), unknown().nullable()), method(object({ deviceId: number() }), RawStateResultSchema.nullable(), { auth: "protected" });
14701
- /**
14702
14897
  * camera-credentials — device-scoped cap exposing the camera's network
14703
14898
  * + auth surface in a vendor-neutral shape.
14704
14899
  *
@@ -18381,6 +18576,12 @@ Object.freeze({
18381
18576
  addonId: null,
18382
18577
  access: "view"
18383
18578
  },
18579
+ "metricsProvider.dumpHeapSnapshot": {
18580
+ capName: "metrics-provider",
18581
+ capScope: "system",
18582
+ addonId: null,
18583
+ access: "create"
18584
+ },
18384
18585
  "metricsProvider.getAddonStats": {
18385
18586
  capName: "metrics-provider",
18386
18587
  capScope: "system",
@@ -18837,6 +19038,12 @@ Object.freeze({
18837
19038
  addonId: null,
18838
19039
  access: "view"
18839
19040
  },
19041
+ "pipelineExecutor.getEngineProvisioning": {
19042
+ capName: "pipeline-executor",
19043
+ capScope: "system",
19044
+ addonId: null,
19045
+ access: "view"
19046
+ },
18840
19047
  "pipelineExecutor.getGlobalPipelineConfig": {
18841
19048
  capName: "pipeline-executor",
18842
19049
  capScope: "system",
@@ -19041,6 +19248,18 @@ Object.freeze({
19041
19248
  addonId: null,
19042
19249
  access: "view"
19043
19250
  },
19251
+ "pipelineOrchestrator.getCameraStatus": {
19252
+ capName: "pipeline-orchestrator",
19253
+ capScope: "system",
19254
+ addonId: null,
19255
+ access: "view"
19256
+ },
19257
+ "pipelineOrchestrator.getCameraStatuses": {
19258
+ capName: "pipeline-orchestrator",
19259
+ capScope: "system",
19260
+ addonId: null,
19261
+ access: "view"
19262
+ },
19044
19263
  "pipelineOrchestrator.getCameraStepOverrides": {
19045
19264
  capName: "pipeline-orchestrator",
19046
19265
  capScope: "system",
@@ -19125,6 +19344,12 @@ Object.freeze({
19125
19344
  addonId: null,
19126
19345
  access: "create"
19127
19346
  },
19347
+ "pipelineOrchestrator.setAgentMaxCameras": {
19348
+ capName: "pipeline-orchestrator",
19349
+ capScope: "system",
19350
+ addonId: null,
19351
+ access: "create"
19352
+ },
19128
19353
  "pipelineOrchestrator.setCameraPipelineForAgent": {
19129
19354
  capName: "pipeline-orchestrator",
19130
19355
  capScope: "system",