@camstack/addon-provider-homematic 1.1.21 → 1.1.22

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.
package/dist/addon.mjs CHANGED
@@ -9,6 +9,547 @@ import { join } from "path";
9
9
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
10
10
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
11
11
  //#endregion
12
+ //#region ../types/dist/event-category-CFZs3jI4.mjs
13
+ var EventCategory = /* @__PURE__ */ function(EventCategory) {
14
+ EventCategory["SystemBoot"] = "system.boot";
15
+ EventCategory["SystemAddonsReady"] = "system.addons-ready";
16
+ EventCategory["SystemRestarting"] = "system.restarting";
17
+ /**
18
+ * Fired exactly once after the hub finishes booting following a
19
+ * restart that was triggered by `RestartCoordinator` (today: framework
20
+ * live-update). Payload is the marker that was on disk at boot
21
+ * (`PendingRestartMarkerPayload`); admin UI listens for it to display a
22
+ * success toast describing what changed.
23
+ *
24
+ * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
25
+ */
26
+ EventCategory["SystemRestartCompleted"] = "system.restart-completed";
27
+ /**
28
+ * Readiness transition for a capability provider. Every producer emits
29
+ * this event on `onInitialize` completion, `onDestroy`, and
30
+ * `$node.reconnect`; every consumer that needs to gate on a cross-process
31
+ * cap subscribes via the kernel's readiness module (`awaitReady` /
32
+ * `onReadyState`) instead of polling. Payload is
33
+ * `SystemReadyStatePayload` — see event-bus.ts.
34
+ */
35
+ EventCategory["SystemReadyState"] = "system.ready-state";
36
+ EventCategory["AddonStarted"] = "addon.started";
37
+ EventCategory["AddonStopped"] = "addon.stopped";
38
+ EventCategory["AddonRestarted"] = "addon.restarted";
39
+ EventCategory["AddonUpdated"] = "addon.updated";
40
+ EventCategory["AddonInstalled"] = "addon.installed";
41
+ EventCategory["AddonUninstalled"] = "addon.uninstalled";
42
+ EventCategory["AddonCrashed"] = "addon.crashed";
43
+ EventCategory["AddonError"] = "addon.error";
44
+ EventCategory["AddonPageReady"] = "addon.page-ready";
45
+ EventCategory["AddonWidgetReady"] = "addon.widget-ready";
46
+ /**
47
+ * Addon failed to load (import or initialize). Emitted by the kernel's
48
+ * AddonHealthMonitor only AFTER the boot grace period ends — failures
49
+ * during the first 5 minutes are silently retried without alerting
50
+ * (slow-starting addons must have time to come up). Post-grace, this
51
+ * event is emitted exactly once per failure-streak; AlertCenter
52
+ * consumes it to create a persistent operator-visible alert.
53
+ *
54
+ * Payload: `{ packageName, addonId?, error: { message, stack }, retryCount, nextRetryAt }`.
55
+ */
56
+ EventCategory["AddonLoadFailed"] = "addon.load-failed";
57
+ /**
58
+ * Addon recovered from a previous failure. Emitted when an addon
59
+ * transitions from `failed` back to `healthy` (typically via the
60
+ * monitor's auto-retry loop, or after manual `addons.retryLoad`).
61
+ * AlertCenter dismisses the corresponding `AddonLoadFailed` alert
62
+ * on this event.
63
+ */
64
+ EventCategory["AddonLoadRecovered"] = "addon.load-recovered";
65
+ /**
66
+ * Monitor scheduled the next retry for a failed addon. Transient —
67
+ * surfaced to the UI for live-updating the "next retry in Ns"
68
+ * countdown on the Addons page row, NOT persisted as an alert.
69
+ */
70
+ EventCategory["AddonRetryScheduled"] = "addon.retry-scheduled";
71
+ /**
72
+ * Monitor is attempting to reload a failed addon NOW. UI uses this
73
+ * to show a spinner during the retry attempt. Same transient nature
74
+ * as AddonRetryScheduled.
75
+ */
76
+ EventCategory["AddonRetryAttempting"] = "addon.retry-attempting";
77
+ EventCategory["DeviceRegistered"] = "device.registered";
78
+ EventCategory["DeviceUnregistered"] = "device.unregistered";
79
+ EventCategory["DeviceEnabled"] = "device.enabled";
80
+ EventCategory["DeviceDisabled"] = "device.disabled";
81
+ EventCategory["DeviceSettingsUpdated"] = "device.settings-updated";
82
+ /**
83
+ * Emitted when the set of native capability providers bound to a device
84
+ * changes — e.g. an addon registers a new native cap via
85
+ * `DeviceContext.registerNativeCap`, or all native bindings for a device
86
+ * are cleared on removal. Hub consumers re-resolve device-proxy routes
87
+ * when this fires.
88
+ */
89
+ EventCategory["DeviceBindingsChanged"] = "device.bindings-changed";
90
+ /**
91
+ * Emitted when the operator-organisational meta surface changes
92
+ * (`name` / `location` / `disabled`). Payload: `{deviceId, field,
93
+ * value}`. Live consumers (UI device list, alert center) react
94
+ * without polling. Distinct from `DeviceSettingsUpdated` which
95
+ * fires on hardware-config changes (host/port/credentials/etc).
96
+ */
97
+ EventCategory["DeviceMetaChanged"] = "device.meta-changed";
98
+ /**
99
+ * Emitted by `BaseDevice.updateSourceInfo()` after a successful patch
100
+ * to the device's upstream-system identity / rendering envelope. The
101
+ * full new SourceInfo travels in the payload so cross-process listeners
102
+ * (UI, export adapters) don't need to re-read the meta blob.
103
+ *
104
+ * Payload: `{deviceId, sourceInfo}`.
105
+ *
106
+ * Distinct from `DeviceMetaChanged` which covers the operator-edited
107
+ * surface (`name` / `location` / `disabled`). The two share the
108
+ * persistence layer (both ride on `device-manager.setMetadata` for
109
+ * SourceInfo, or `setName`/`setLocation`/`setDisabled` for the meta
110
+ * fields) but consumers care about different subsets.
111
+ */
112
+ EventCategory["DeviceSourceInfoChanged"] = "device.source-info-changed";
113
+ /**
114
+ * Emitted by DeviceStreamWiringService after a successful
115
+ * `stream-broker.registerDeviceStreams` call. Payload includes
116
+ * deviceId — consumers look up the full registered device info via
117
+ * `brokerManager.getRegisteredDevice(deviceId)`.
118
+ *
119
+ * Replaces the legacy `StreamRouterService.onDeviceRegistered` callback.
120
+ */
121
+ EventCategory["DeviceStreamsRegistered"] = "device.streams-registered";
122
+ /**
123
+ * Device-level "fully provisioned" signal — the EXPORT trigger. Emitted once
124
+ * a device's persisted export-relevant shape (its `DeviceFeature` set) is
125
+ * established or changes, carrying `{deviceId, fingerprint, generation}`.
126
+ * Export adapters (Alexa / HAP) react to THIS instead of the chatty per-cap
127
+ * `DeviceBindingsChanged`, turning a boot's incomplete→complete trickle into
128
+ * one clean delta. `fingerprint` is `canonicalDeviceFingerprint(shape)`.
129
+ *
130
+ * Spec: docs/superpowers/specs/2026-06-01-alexa-hap-export-reconciler-design.md
131
+ */
132
+ EventCategory["DeviceProvisioned"] = "device.provisioned";
133
+ /**
134
+ * Fires once when a device's initial feature-probe completes successfully
135
+ * (lastProbedAt 0→>0); exported shape is now stable. Telemetry (may be
136
+ * dropped) — consumers MUST also gate on the device record's `probed` flag.
137
+ */
138
+ EventCategory["DeviceReady"] = "device.ready";
139
+ EventCategory["IntegrationEnabled"] = "integration.enabled";
140
+ EventCategory["IntegrationDisabled"] = "integration.disabled";
141
+ EventCategory["IntegrationDeleted"] = "integration.deleted";
142
+ /** Emitted when a broker connection's status flips (connected /
143
+ * disconnected / error). Carries `{ brokerId, status, error? }`. */
144
+ EventCategory["BrokerStatusChanged"] = "broker.status-changed";
145
+ /** Emitted for every subscription-matched message routed by a
146
+ * broker provider. Carries `{ brokerId, subscriptionId, key, payload }`.
147
+ * Consumers filter by `brokerId` + `subscriptionId` in the handler. */
148
+ EventCategory["BrokerMessage"] = "broker.message";
149
+ EventCategory["ProviderStarted"] = "provider.started";
150
+ EventCategory["ProviderStopped"] = "provider.stopped";
151
+ EventCategory["ProcessCrashed"] = "process.crashed";
152
+ EventCategory["ProcessRestartScheduled"] = "process.restart_scheduled";
153
+ EventCategory["ProcessRestarted"] = "process.restarted";
154
+ EventCategory["RecordingStarted"] = "recording.started";
155
+ EventCategory["RecordingStopped"] = "recording.stopped";
156
+ EventCategory["RecordingError"] = "recording.error";
157
+ EventCategory["RecordingHealthDegraded"] = "recording.health.degraded";
158
+ EventCategory["RecordingStorageCritical"] = "recording.storage.critical";
159
+ EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
160
+ EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
161
+ EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
162
+ EventCategory["DetectionEvent"] = "detection.event";
163
+ EventCategory["SessionTrackNew"] = "session.track.new";
164
+ EventCategory["SessionTrackExpired"] = "session.track.expired";
165
+ EventCategory["BenchmarkProgress"] = "benchmark.progress";
166
+ EventCategory["PlatformProbePhase"] = "platform-probe.phase";
167
+ EventCategory["PipelineProgress"] = "pipeline.progress";
168
+ /** Per-frame execution trace emitted by the pipeline executor for live observability. */
169
+ EventCategory["PipelineTrace"] = "pipeline.trace";
170
+ /**
171
+ * Raw inference output emitted by `addon-pipeline-runner` after running the
172
+ * detection pipeline on a frame. Carries the `FrameResult` (with
173
+ * `detections[]`, `width`/`height`, timing debug) — never the frame
174
+ * buffer itself. Hub-side consumers (analysis pipeline, class filters,
175
+ * notifications) subscribe to this and re-emit `detection.result` after
176
+ * post-processing.
177
+ */
178
+ EventCategory["PipelineInferenceResult"] = "pipeline.inference-result";
179
+ /**
180
+ * Camera lifecycle event emitted by `addon-pipeline-orchestrator` when it
181
+ * assigns or unassigns a camera to/from an agent. Carries no frame data;
182
+ * pure observability for UI dashboards and metrics consumers.
183
+ */
184
+ EventCategory["PipelineCameraAssigned"] = "pipeline.camera-assigned";
185
+ EventCategory["PipelineCameraUnassigned"] = "pipeline.camera-unassigned";
186
+ /**
187
+ * Per-camera pipeline config was mutated by the orchestrator
188
+ * (3-level settings change via `setAgentAddonDefaults` /
189
+ * `setCameraStepToggle` / `setCameraPipelineForAgent` or a
190
+ * pipeline-scoped `applyDeviceSettingsPatch`). Orchestrator
191
+ * subscribes to its own emission to hot-reload the assigned runner
192
+ * via `attachCamera` so the next frame executes against the new
193
+ * engine/steps without waiting for a rebalance or the next
194
+ * `DeviceStreamsRegistered` cycle.
195
+ */
196
+ EventCategory["PipelineCameraUpdated"] = "pipeline.camera-updated";
197
+ /**
198
+ * The cluster camera-source OWNER changed (`clusterRoles.ingestNode`).
199
+ * Emitted by addon-pipeline-orchestrator whenever it (re)derives node
200
+ * capabilities — at boot, on agent online/offline, and on an ingest-node
201
+ * flip. Carries the resolved `ownerNodeId`. The stream-broker consumes it to
202
+ * keep its ingest-owner-gate decision current WITHOUT a per-`ensureBroker`
203
+ * cross-process `getIngestOwner` query (push the authority's decision instead
204
+ * of polling it on the hot path). Idempotent state — re-emitted on every
205
+ * topology change, so a dropped event self-heals on the next one (plus the
206
+ * broker's long backstop reconcile query).
207
+ */
208
+ EventCategory["PipelineIngestOwnerChanged"] = "pipeline.ingest-owner-changed";
209
+ /**
210
+ * Periodic snapshot of per-node pipeline-runner load
211
+ * (`RunnerLocalLoad`). Emitted ~1Hz by every runner so UI dashboards
212
+ * subscribe instead of polling `pipelineRunner.getLocalLoad`.
213
+ * `nodeId` carried in the payload + on `event.source.nodeId`.
214
+ */
215
+ EventCategory["PipelineRunnerLoadSnapshot"] = "pipeline.runner-load-snapshot";
216
+ /**
217
+ * Periodic snapshot of per-camera pipeline metrics (`CameraMetrics`
218
+ * + `deviceId` + `nodeId`). Emitted ~1Hz by every runner for each
219
+ * attached camera. UI subscribes to drive overlay phase / fps /
220
+ * inference time without polling `getCameraMetrics`.
221
+ */
222
+ EventCategory["PipelineCameraMetricsSnapshot"] = "pipeline.camera-metrics-snapshot";
223
+ /**
224
+ * Periodic snapshot of stream-broker per-broker statistics (input
225
+ * fps, decoded fps, bitrate, codec). Emitted ~1Hz by every
226
+ * stream-broker process for each active broker so the UI can drive
227
+ * the Stream / Cluster dashboards without polling
228
+ * `streamBroker.listAllProfileSlots` and friends.
229
+ */
230
+ EventCategory["StreamBrokerMetricsSnapshot"] = "stream-broker.metrics-snapshot";
231
+ /**
232
+ * Cap event fired by `stream-broker` when a profile slot enters
233
+ * "demanded" state — a cam stream has been assigned and at least one
234
+ * consumer (RTSP restream, decoded subscriber, WebRTC session, …) is
235
+ * present. Camera-provider addons (Reolink Baichuan push, …)
236
+ * subscribe to this category to start their underlying transport
237
+ * lazily. Payload: `{ deviceId, camStreamId, profile }`.
238
+ */
239
+ EventCategory["StreamBrokerOnCamStreamDemand"] = "stream-broker.onCamStreamDemand";
240
+ /**
241
+ * Cap event fired by `stream-broker` when the last consumer leaves a
242
+ * previously-demanded cam stream. Providers tear down their
243
+ * underlying transport on receipt. Payload: `{ deviceId, camStreamId }`.
244
+ */
245
+ EventCategory["StreamBrokerOnCamStreamIdle"] = "stream-broker.onCamStreamIdle";
246
+ /**
247
+ * Cap event fired by `stream-broker` when a broker fails to dial a
248
+ * managed-loopback source (today: `pull-rfc4571`) and the publisher
249
+ * needs to refresh the cached URL. The lib's TCP server idle-tears-down
250
+ * on its own schedule, so a re-publish with a fresh `host:port` is the
251
+ * only way to keep the broker dialable. Camera providers (Reolink
252
+ * Baichuan native, …) subscribe and respond by re-running their publish
253
+ * pipeline.
254
+ * Payload: `{ deviceId, camStreamId, brokerId }`.
255
+ */
256
+ EventCategory["StreamBrokerOnRequestStreamSourceRefresh"] = "stream-broker.onRequestStreamSourceRefresh";
257
+ /**
258
+ * A camera provider changed a device's stream parameters (codec /
259
+ * resolution / bitrate / a stream added or removed). A LOW-LATENCY NUDGE
260
+ * for the stream-broker's catalog reconcile: it carries NO authoritative
261
+ * data — the broker re-PULLS that device's `stream-catalog` cap on receipt
262
+ * (the 30s reconcile poll is the backstop if this nudge is dropped). Emitted
263
+ * by providers from `stream-params.setProfile`. Payload: `{ deviceId }`.
264
+ */
265
+ EventCategory["StreamParamsChanged"] = "stream-params.changed";
266
+ /**
267
+ * Generic per-device runtime-state change. Fired by `device-manager`
268
+ * whenever a persisted slice in any cap's `runtimeState` shape
269
+ * mutates. Payload: `{deviceId, capName, slice}`. Subscribers are
270
+ * the `deviceState` cap router (cross-process listeners) and the
271
+ * deviceProxy reactive bindings (`device.state.<capName>.value`).
272
+ * Cap-specific events (`battery.onStatusChanged`, …) still fire
273
+ * — they're authoritative for callers that want a typed payload
274
+ * without filtering on `capName`.
275
+ */
276
+ EventCategory["DeviceStateChanged"] = "device.state-changed";
277
+ /**
278
+ * Cap event fired by every device that registers the `battery`
279
+ * capability. Mirrors the cap definition's `onStatusChanged`. Carries
280
+ * `{ deviceId, status: BatteryStatus }`. Subscribers (alert center,
281
+ * snapshot wrapper, UI) react to charge/sleep transitions without
282
+ * polling `batteryCapability.getStatus`.
283
+ */
284
+ EventCategory["BatteryOnStatusChanged"] = "battery.onStatusChanged";
285
+ /**
286
+ * Emitted by the battery cap provider WHEN `wakeForStream` enters the
287
+ * "wake in progress" window — between the Baichuan wake-up issue and
288
+ * the camera's first dialed-back RTP packet. The stream-broker
289
+ * manager subscribes to flip the per-broker placeholder reason to
290
+ * `'waking'` so viewers see a labelled "WAKING UP" tile instead of
291
+ * the generic `'reconnecting'` frame. Carries `{ deviceId }`. The
292
+ * complementary "wake complete" signal is the existing
293
+ * `BatteryOnStatusChanged { sleeping: false }` event.
294
+ */
295
+ EventCategory["BatteryOnWakeStarted"] = "battery.onWakeStarted";
296
+ /**
297
+ * Cap event fired by every device that registers the `doorbell`
298
+ * capability. Mirrors `doorbellCapability.events.onPressed`. Carries
299
+ * `{ deviceId, timestamp }`. Operators consuming the UI subscribe
300
+ * here to render transient ring toasts and a "Recent presses" row
301
+ * on the device detail page.
302
+ */
303
+ EventCategory["DoorbellOnPressed"] = "doorbell.onPressed";
304
+ /**
305
+ * Cap event fired by every device that registers the `event-emitter`
306
+ * capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
307
+ * `{ deviceId, eventType, data, timestamp, seq }` — the device's EXACT
308
+ * declared event verbatim (NO normalization). Subscribers (UI event
309
+ * stream, advanced-notifier rules) react to fired events without
310
+ * holding a cap reference.
311
+ */
312
+ EventCategory["EventEmitted"] = "event-emitter.event";
313
+ /**
314
+ * Periodic snapshot of the per-node detection-pipeline engine
315
+ * registry (loaded engines, models resident, in-use cameras, idle
316
+ * TTL). Emitted ~0.2Hz (every 5 s) by every detection-pipeline
317
+ * process. The Engines tab subscribes to drive its inventory view
318
+ * without polling `pipelineExecutor.listLoadedEngines`.
319
+ */
320
+ EventCategory["PipelineEngineMetricsSnapshot"] = "pipeline.engine-metrics-snapshot";
321
+ /**
322
+ * Per-node detection-engine runtime-provisioning transition. Emitted by
323
+ * the detection-pipeline provider on every state change of its lazy
324
+ * engine-provisioning machine (idle → installing → verifying → ready,
325
+ * or → failed with a `nextRetryAt`). Payload is the
326
+ * `EngineProvisioningState` snapshot; `event.source.nodeId` carries the
327
+ * node. The Pipeline page subscribes to drive a live "installing
328
+ * OpenVINO… / ready" indicator per node without polling
329
+ * `pipelineExecutor.getEngineProvisioning`. Telemetry-grade (D8): the UI
330
+ * also reads the cap snapshot on mount / reconnect. Phase 2.
331
+ */
332
+ EventCategory["PipelineEngineProvisioning"] = "pipeline.engine-provisioning";
333
+ /**
334
+ * Cluster topology snapshot. Carries the same payload returned by
335
+ * `nodes.topology` (every reachable node + addons + processes).
336
+ * Emitted by the hub on any agent / addon lifecycle change
337
+ * (debounced) plus a periodic safety net. Replaces UI polling on
338
+ * `nodes.topology` — admin-ui dashboards subscribe to drive the
339
+ * cluster view directly from the event payload.
340
+ */
341
+ EventCategory["ClusterTopologySnapshot"] = "cluster.topology-snapshot";
342
+ /**
343
+ * Periodic per-node system metrics snapshot (CPU / memory / GPU /
344
+ * disk / network). Emitted ~0.2 Hz by the metrics-provider addon
345
+ * for each node. Drives the dashboard SystemStatus / ProcessResources
346
+ * widgets without polling `metricsProvider.getCurrent`.
347
+ */
348
+ EventCategory["MetricsNodeResourcesSnapshot"] = "metrics.node-resources-snapshot";
349
+ /**
350
+ * Periodic per-node process-tree snapshot (camstack-related pids
351
+ * with ghost / managed / root classification). Emitted ~0.2 Hz by
352
+ * the metrics-provider addon. Drives the Cluster → Processes tab
353
+ * without polling `metricsProvider.listNodeProcesses`.
354
+ */
355
+ EventCategory["MetricsNodeProcessesSnapshot"] = "metrics.node-processes-snapshot";
356
+ /**
357
+ * Capability binding change event emitted by `addon-pipeline-orchestrator`
358
+ * when a user changes which addon implements a cap on a node. Subscribed
359
+ * by every kernel process to update its local `preferredProviderRegistry`
360
+ * so future capability lookups respect the new binding.
361
+ */
362
+ /**
363
+ * A capability binding was changed for a node — addon X now provides
364
+ * capability `cap` on node `nodeId`. Lives under the generic
365
+ * `capability.*` namespace because capability bindings are a kernel-
366
+ * level concept used by many addons, not strictly pipeline-scoped.
367
+ */
368
+ EventCategory["CapabilityBindingChanged"] = "capability.binding-changed";
369
+ EventCategory["ModelDownloadProgress"] = "model.download.progress";
370
+ EventCategory["AgentRegistered"] = "agent.registered";
371
+ EventCategory["AgentUnregistered"] = "agent.unregistered";
372
+ EventCategory["AgentOnline"] = "agent.online";
373
+ EventCategory["AgentOffline"] = "agent.offline";
374
+ /** Forked worker process (e.g. hub/pipeline) connected to the broker. */
375
+ EventCategory["WorkerOnline"] = "worker.online";
376
+ /** Forked worker process disconnected from the broker. */
377
+ EventCategory["WorkerOffline"] = "worker.offline";
378
+ EventCategory["AgentTaskDispatched"] = "agent.task.dispatched";
379
+ EventCategory["AgentTaskAssigned"] = "agent.task.assigned";
380
+ EventCategory["AgentTrpcConnected"] = "agent.trpc.connected";
381
+ EventCategory["AgentWsConnected"] = "agent.ws.connected";
382
+ EventCategory["AgentWsDisconnected"] = "agent.ws.disconnected";
383
+ EventCategory["AgentBackupActivated"] = "agent.backup.activated";
384
+ EventCategory["OrchestrationSettingsUpdated"] = "orchestration.settings-updated";
385
+ /**
386
+ * Per-agent hwaccel preference changed (user override set, cleared, or
387
+ * re-probed). Observability event — decoders pull the current pref at
388
+ * `createSession`, so running sessions keep their current backend until
389
+ * they rotate naturally (camera add/remove, stream restart). Future
390
+ * work can wire a listener in stream-broker that force-rotates live
391
+ * sessions; for now this event powers logs + admin-UI toast feedback.
392
+ */
393
+ EventCategory["PipelineAgentHwaccelChanged"] = "pipeline.agent-hwaccel-changed";
394
+ EventCategory["MotionAnalysis"] = "detection.motion-analysis";
395
+ /** All raw motion zones from CCL before minArea filter — for UI debug overlay. */
396
+ EventCategory["MotionZonesRaw"] = "detection.motion-zones-raw";
397
+ /**
398
+ * Per-camera motion phase transition (`watching ↔ active`) emitted
399
+ * by the runner. Mirrors the `motion.onMotionChanged` cap event
400
+ * surface — payload `MotionOnMotionChangedPayload` carries
401
+ * `{deviceId, detected, timestamp, source, regions?}`. Subscribers
402
+ * include addons that need to react to motion state without
403
+ * polling the runtime-state mirror.
404
+ */
405
+ EventCategory["MotionOnMotionChanged"] = "motion.on-motion-changed";
406
+ EventCategory["DetectionResult"] = "detection.result";
407
+ EventCategory["DetectionRaw"] = "detection.raw";
408
+ EventCategory["DetectionCameraNative"] = "detection.camera-native";
409
+ /**
410
+ * Canonical per-chunk live audio pipeline output. Payload is
411
+ * `PipelineAudioInferenceResultPayload` carrying a full `AudioResult`
412
+ * (level + detections + debug). Lives on the pipeline.* namespace
413
+ * alongside `pipeline.inference-result` (video) for symmetry.
414
+ */
415
+ EventCategory["PipelineAudioInferenceResult"] = "pipeline.audio-inference-result";
416
+ EventCategory["DetectionPhaseTransition"] = "detection.phase-transition";
417
+ EventCategory["ProviderMotion"] = "provider.motion";
418
+ EventCategory["ProviderDetection"] = "provider.detection";
419
+ EventCategory["EnrichmentEmbeddingStored"] = "enrichment.embedding.stored";
420
+ EventCategory["EnrichmentSceneStateChanged"] = "enrichment.scene.state-changed";
421
+ EventCategory["EnrichmentActivitySummary"] = "enrichment.activity.summary";
422
+ /**
423
+ * Unified track-lifecycle event: ONE category carrying `phase:
424
+ * 'start' | 'update' | 'end'` with a rich, typed
425
+ * `PipelineAnalyticsTrackLifecyclePayload`. Supersedes the thin
426
+ * `PipelineAnalyticsTrackStarted` / `PipelineAnalyticsTrackEnded`
427
+ * pair — a consumer subscribes once and branches on `phase`.
428
+ */
429
+ EventCategory["PipelineAnalyticsTrackLifecycle"] = "pipeline-analytics.track-lifecycle";
430
+ /**
431
+ * @deprecated Superseded by {@link PipelineAnalyticsTrackLifecycle}
432
+ * (`phase:'start'`). Kept as a soft alias — no known subscribers.
433
+ */
434
+ EventCategory["PipelineAnalyticsTrackStarted"] = "pipeline-analytics.track-started";
435
+ /**
436
+ * @deprecated Superseded by {@link PipelineAnalyticsTrackLifecycle}
437
+ * (`phase:'end'`). Kept as a soft alias — no known subscribers.
438
+ */
439
+ EventCategory["PipelineAnalyticsTrackEnded"] = "pipeline-analytics.track-ended";
440
+ EventCategory["PipelineAnalyticsDetectionEvent"] = "pipeline-analytics.detection-event";
441
+ EventCategory["PipelineAnalyticsFrameTracked"] = "pipeline-analytics.frame-tracked";
442
+ /**
443
+ * Fired by `addon-post-analysis` when a parked (stationary) object appears
444
+ * (a track was promoted to a stationary-registry entry) or departs (the
445
+ * object moved / was removed). Telemetry (D8): lossy, drives a UI refresh of
446
+ * the dedicated "Stationary" section — never the live event feed. Payload:
447
+ * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp }`.
448
+ */
449
+ EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
450
+ /**
451
+ * Fired by `addon-post-analysis` whenever a gallery face row changes:
452
+ * `kind:'buffered'` a new detected face was persisted, `'assigned'` /
453
+ * `'unassigned'` its identity link changed, `'deleted'` the row was
454
+ * removed. Telemetry semantics (D8): a lost event only delays a refresh,
455
+ * never a correctness issue. Payload `PipelineAnalyticsFaceGalleryChangedPayload`.
456
+ */
457
+ EventCategory["PipelineAnalyticsFaceGalleryChanged"] = "pipeline-analytics.face-gallery-changed";
458
+ /**
459
+ * Fired by `addon-post-analysis` whenever a gallery plate row changes:
460
+ * `kind:'buffered'` a new read was persisted (`PlateRecognizer.onTrackEnd`),
461
+ * `'assigned'` / `'unassigned'` its vehicle link changed
462
+ * (`PlateGalleryProvider`), `'deleted'` the row was removed. Telemetry
463
+ * semantics (D8): a lost event only delays a refresh, never a correctness
464
+ * issue. Payload `PipelineAnalyticsPlateGalleryChangedPayload`.
465
+ */
466
+ EventCategory["PipelineAnalyticsPlateGalleryChanged"] = "pipeline-analytics.plate-gallery-changed";
467
+ EventCategory["FrigateLiveEvent"] = "frigate.live-event";
468
+ EventCategory["CameraStreamsProfileSlotsChanged"] = "camera-streams.onProfileSlotsChanged";
469
+ /**
470
+ * Stream-broker health watchdog. Per-broker (deviceId/profile) emission.
471
+ * `stream.offline` fires after STREAM_STALE_TIMEOUT_MS without an encoded
472
+ * packet on an active broker. `stream.online` fires on first packet
473
+ * after a stale gap (or on initial first packet). Payload includes
474
+ * the assigned camStreamId as `profileKey`.
475
+ */
476
+ EventCategory["StreamOnline"] = "stream.online";
477
+ EventCategory["StreamOffline"] = "stream.offline";
478
+ EventCategory["NetworkTunnelStarted"] = "network.tunnel.started";
479
+ EventCategory["NetworkTunnelStopped"] = "network.tunnel.stopped";
480
+ /** Fired by the `local-network` cap when the host's interface set
481
+ * changes (new IP from DHCP, VPN connect, docker bridge added). */
482
+ EventCategory["LocalNetworkChanged"] = "network.local.changed";
483
+ /**
484
+ * Fired by a `mesh-network` provider (Tailscale, …) when its
485
+ * mesh-reachable host changes (join / leave / MagicDNS or 100.x IP
486
+ * change). Lets `local-network` fold the mesh endpoint into its
487
+ * connection-endpoint list without a cross-package import. Payload
488
+ * carries the preferred host (`host: ''` = no longer reachable),
489
+ * the hub port, and the scheme. Telemetry-grade (D8): consumers
490
+ * pull-reconcile from the provider's `getStatus` on reconnect. */
491
+ EventCategory["MeshNetworkChanged"] = "network.mesh.changed";
492
+ EventCategory["BackupCompleted"] = "backup.completed";
493
+ EventCategory["BackupRestored"] = "backup.restored";
494
+ EventCategory["NotificationDispatched"] = "notification.dispatched";
495
+ EventCategory["NotificationFailed"] = "notification.failed";
496
+ EventCategory["DeviceUpdated"] = "device.updated";
497
+ /**
498
+ * Transport-level connectivity. Emitted by the device driver when
499
+ * the underlying control socket actually connects / disconnects
500
+ * (Baichuan TCP, ONVIF probe response, RTSP DESCRIBE, …) — NOT for
501
+ * power-state transitions on a battery camera. For battery wake /
502
+ * doze cycles see `DeviceAwake` / `DeviceSleeping`.
503
+ */
504
+ EventCategory["DeviceOnline"] = "device.online";
505
+ /**
506
+ * Stream-broker watchdog — emitted when no encoded packet has been
507
+ * received for STREAM_STALE_TIMEOUT_MS on an active broker (rtsp or
508
+ * push). Paired with DeviceOnline which fires on first packet after
509
+ * a stale gap. Payload: DeviceStreamHealthPayload.
510
+ */
511
+ EventCategory["DeviceOffline"] = "device.offline";
512
+ /**
513
+ * Battery cam woke up — physical power-state transition reported
514
+ * by the device firmware. Distinct from `DeviceOnline` so a UI panel
515
+ * watching power state doesn't flap on every UDP socket reconnect.
516
+ */
517
+ EventCategory["DeviceAwake"] = "device.awake";
518
+ /**
519
+ * Battery cam went to sleep. See `DeviceAwake`.
520
+ */
521
+ EventCategory["DeviceSleeping"] = "device.sleeping";
522
+ EventCategory["RetentionCleanup"] = "retention.cleanup";
523
+ /**
524
+ * Legacy bulk-update progress snapshot (payload `BulkUpdateState`). No longer
525
+ * emitted — F3 removed the coordinator that produced it; "Update all" now runs
526
+ * as one lifecycle engine job (`AddonsJobProgress`/`AddonsJobLog`). Retained
527
+ * (with `BulkUpdateState`) only to avoid regenerating the event maps; removed
528
+ * in F4 once live bulk progress is re-implemented over the engine events.
529
+ */
530
+ EventCategory["AddonsBulkUpdateProgress"] = "addons.bulk-update-progress";
531
+ EventCategory["AddonsJobProgress"] = "addons.job-progress";
532
+ EventCategory["AddonsJobLog"] = "addons.job-log";
533
+ /**
534
+ * A container's child visibility toggled (hidden/shown). Emitted by the
535
+ * `accessories` cap when a child device is hidden or revealed.
536
+ * Payload: `{ deviceId, childDeviceId, hidden }`.
537
+ */
538
+ EventCategory["AccessoriesChildVisibilityChanged"] = "accessories.onChildVisibilityChanged";
539
+ /**
540
+ * A container's child set changed (children added/removed/reordered).
541
+ * Payload: `{ deviceId, childDeviceIds, hiddenChildIds }`.
542
+ */
543
+ EventCategory["AccessoriesChanged"] = "accessories.onAccessoriesChanged";
544
+ /**
545
+ * Progress update from a running model conversion job.
546
+ * Payload: `{ kind: 'model-convert', phase, sessionId?, pct?, detail? }`.
547
+ * Emitted by `addon-model-studio` on the converting node.
548
+ */
549
+ EventCategory["ModelConvertProgress"] = "model-convert.progress";
550
+ return EventCategory;
551
+ }({});
552
+ //#endregion
12
553
  //#region ../../node_modules/zod/v4/core/core.js
13
554
  var _a$1;
14
555
  function $constructor(name, initializer, params) {
@@ -4300,6 +4841,14 @@ function object(shape, params) {
4300
4841
  ...normalizeParams(params)
4301
4842
  });
4302
4843
  }
4844
+ function looseObject(shape, params) {
4845
+ return new ZodObject({
4846
+ type: "object",
4847
+ shape,
4848
+ catchall: unknown(),
4849
+ ...normalizeParams(params)
4850
+ });
4851
+ }
4303
4852
  var ZodUnion = /*@__PURE__*/ $constructor("ZodUnion", (inst, def) => {
4304
4853
  $ZodUnion.init(inst, def);
4305
4854
  ZodType.init(inst, def);
@@ -4651,506 +5200,6 @@ function preprocess(fn, schema) {
4651
5200
  out: schema
4652
5201
  });
4653
5202
  }
4654
- //#endregion
4655
- //#region ../types/dist/sleep-Baang_XW.mjs
4656
- var EventCategory = /* @__PURE__ */ function(EventCategory) {
4657
- EventCategory["SystemBoot"] = "system.boot";
4658
- EventCategory["SystemAddonsReady"] = "system.addons-ready";
4659
- EventCategory["SystemRestarting"] = "system.restarting";
4660
- /**
4661
- * Fired exactly once after the hub finishes booting following a
4662
- * restart that was triggered by `RestartCoordinator` (today: framework
4663
- * live-update). Payload is the marker that was on disk at boot
4664
- * (`PendingRestartMarkerPayload`); admin UI listens for it to display a
4665
- * success toast describing what changed.
4666
- *
4667
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
4668
- */
4669
- EventCategory["SystemRestartCompleted"] = "system.restart-completed";
4670
- /**
4671
- * Readiness transition for a capability provider. Every producer emits
4672
- * this event on `onInitialize` completion, `onDestroy`, and
4673
- * `$node.reconnect`; every consumer that needs to gate on a cross-process
4674
- * cap subscribes via the kernel's readiness module (`awaitReady` /
4675
- * `onReadyState`) instead of polling. Payload is
4676
- * `SystemReadyStatePayload` — see event-bus.ts.
4677
- */
4678
- EventCategory["SystemReadyState"] = "system.ready-state";
4679
- EventCategory["AddonStarted"] = "addon.started";
4680
- EventCategory["AddonStopped"] = "addon.stopped";
4681
- EventCategory["AddonRestarted"] = "addon.restarted";
4682
- EventCategory["AddonUpdated"] = "addon.updated";
4683
- EventCategory["AddonInstalled"] = "addon.installed";
4684
- EventCategory["AddonUninstalled"] = "addon.uninstalled";
4685
- EventCategory["AddonCrashed"] = "addon.crashed";
4686
- EventCategory["AddonError"] = "addon.error";
4687
- EventCategory["AddonPageReady"] = "addon.page-ready";
4688
- EventCategory["AddonWidgetReady"] = "addon.widget-ready";
4689
- /**
4690
- * Addon failed to load (import or initialize). Emitted by the kernel's
4691
- * AddonHealthMonitor only AFTER the boot grace period ends — failures
4692
- * during the first 5 minutes are silently retried without alerting
4693
- * (slow-starting addons must have time to come up). Post-grace, this
4694
- * event is emitted exactly once per failure-streak; AlertCenter
4695
- * consumes it to create a persistent operator-visible alert.
4696
- *
4697
- * Payload: `{ packageName, addonId?, error: { message, stack }, retryCount, nextRetryAt }`.
4698
- */
4699
- EventCategory["AddonLoadFailed"] = "addon.load-failed";
4700
- /**
4701
- * Addon recovered from a previous failure. Emitted when an addon
4702
- * transitions from `failed` back to `healthy` (typically via the
4703
- * monitor's auto-retry loop, or after manual `addons.retryLoad`).
4704
- * AlertCenter dismisses the corresponding `AddonLoadFailed` alert
4705
- * on this event.
4706
- */
4707
- EventCategory["AddonLoadRecovered"] = "addon.load-recovered";
4708
- /**
4709
- * Monitor scheduled the next retry for a failed addon. Transient —
4710
- * surfaced to the UI for live-updating the "next retry in Ns"
4711
- * countdown on the Addons page row, NOT persisted as an alert.
4712
- */
4713
- EventCategory["AddonRetryScheduled"] = "addon.retry-scheduled";
4714
- /**
4715
- * Monitor is attempting to reload a failed addon NOW. UI uses this
4716
- * to show a spinner during the retry attempt. Same transient nature
4717
- * as AddonRetryScheduled.
4718
- */
4719
- EventCategory["AddonRetryAttempting"] = "addon.retry-attempting";
4720
- EventCategory["DeviceRegistered"] = "device.registered";
4721
- EventCategory["DeviceUnregistered"] = "device.unregistered";
4722
- EventCategory["DeviceEnabled"] = "device.enabled";
4723
- EventCategory["DeviceDisabled"] = "device.disabled";
4724
- EventCategory["DeviceSettingsUpdated"] = "device.settings-updated";
4725
- /**
4726
- * Emitted when the set of native capability providers bound to a device
4727
- * changes — e.g. an addon registers a new native cap via
4728
- * `DeviceContext.registerNativeCap`, or all native bindings for a device
4729
- * are cleared on removal. Hub consumers re-resolve device-proxy routes
4730
- * when this fires.
4731
- */
4732
- EventCategory["DeviceBindingsChanged"] = "device.bindings-changed";
4733
- /**
4734
- * Emitted when the operator-organisational meta surface changes
4735
- * (`name` / `location` / `disabled`). Payload: `{deviceId, field,
4736
- * value}`. Live consumers (UI device list, alert center) react
4737
- * without polling. Distinct from `DeviceSettingsUpdated` which
4738
- * fires on hardware-config changes (host/port/credentials/etc).
4739
- */
4740
- EventCategory["DeviceMetaChanged"] = "device.meta-changed";
4741
- /**
4742
- * Emitted by `BaseDevice.updateSourceInfo()` after a successful patch
4743
- * to the device's upstream-system identity / rendering envelope. The
4744
- * full new SourceInfo travels in the payload so cross-process listeners
4745
- * (UI, export adapters) don't need to re-read the meta blob.
4746
- *
4747
- * Payload: `{deviceId, sourceInfo}`.
4748
- *
4749
- * Distinct from `DeviceMetaChanged` which covers the operator-edited
4750
- * surface (`name` / `location` / `disabled`). The two share the
4751
- * persistence layer (both ride on `device-manager.setMetadata` for
4752
- * SourceInfo, or `setName`/`setLocation`/`setDisabled` for the meta
4753
- * fields) but consumers care about different subsets.
4754
- */
4755
- EventCategory["DeviceSourceInfoChanged"] = "device.source-info-changed";
4756
- /**
4757
- * Emitted by DeviceStreamWiringService after a successful
4758
- * `stream-broker.registerDeviceStreams` call. Payload includes
4759
- * deviceId — consumers look up the full registered device info via
4760
- * `brokerManager.getRegisteredDevice(deviceId)`.
4761
- *
4762
- * Replaces the legacy `StreamRouterService.onDeviceRegistered` callback.
4763
- */
4764
- EventCategory["DeviceStreamsRegistered"] = "device.streams-registered";
4765
- /**
4766
- * Device-level "fully provisioned" signal — the EXPORT trigger. Emitted once
4767
- * a device's persisted export-relevant shape (its `DeviceFeature` set) is
4768
- * established or changes, carrying `{deviceId, fingerprint, generation}`.
4769
- * Export adapters (Alexa / HAP) react to THIS instead of the chatty per-cap
4770
- * `DeviceBindingsChanged`, turning a boot's incomplete→complete trickle into
4771
- * one clean delta. `fingerprint` is `canonicalDeviceFingerprint(shape)`.
4772
- *
4773
- * Spec: docs/superpowers/specs/2026-06-01-alexa-hap-export-reconciler-design.md
4774
- */
4775
- EventCategory["DeviceProvisioned"] = "device.provisioned";
4776
- /**
4777
- * Fires once when a device's initial feature-probe completes successfully
4778
- * (lastProbedAt 0→>0); exported shape is now stable. Telemetry (may be
4779
- * dropped) — consumers MUST also gate on the device record's `probed` flag.
4780
- */
4781
- EventCategory["DeviceReady"] = "device.ready";
4782
- EventCategory["IntegrationEnabled"] = "integration.enabled";
4783
- EventCategory["IntegrationDisabled"] = "integration.disabled";
4784
- EventCategory["IntegrationDeleted"] = "integration.deleted";
4785
- /** Emitted when a broker connection's status flips (connected /
4786
- * disconnected / error). Carries `{ brokerId, status, error? }`. */
4787
- EventCategory["BrokerStatusChanged"] = "broker.status-changed";
4788
- /** Emitted for every subscription-matched message routed by a
4789
- * broker provider. Carries `{ brokerId, subscriptionId, key, payload }`.
4790
- * Consumers filter by `brokerId` + `subscriptionId` in the handler. */
4791
- EventCategory["BrokerMessage"] = "broker.message";
4792
- EventCategory["ProviderStarted"] = "provider.started";
4793
- EventCategory["ProviderStopped"] = "provider.stopped";
4794
- EventCategory["ProcessCrashed"] = "process.crashed";
4795
- EventCategory["ProcessRestartScheduled"] = "process.restart_scheduled";
4796
- EventCategory["ProcessRestarted"] = "process.restarted";
4797
- EventCategory["RecordingStarted"] = "recording.started";
4798
- EventCategory["RecordingStopped"] = "recording.stopped";
4799
- EventCategory["RecordingError"] = "recording.error";
4800
- EventCategory["RecordingHealthDegraded"] = "recording.health.degraded";
4801
- EventCategory["RecordingStorageCritical"] = "recording.storage.critical";
4802
- EventCategory["RecordingSegmentWritten"] = "recording.segment.written";
4803
- EventCategory["RecordingPolicyFallback"] = "recording.policy.fallback";
4804
- EventCategory["RecordingRetentionCompleted"] = "recording.retention.completed";
4805
- EventCategory["DetectionEvent"] = "detection.event";
4806
- EventCategory["SessionTrackNew"] = "session.track.new";
4807
- EventCategory["SessionTrackExpired"] = "session.track.expired";
4808
- EventCategory["BenchmarkProgress"] = "benchmark.progress";
4809
- EventCategory["PlatformProbePhase"] = "platform-probe.phase";
4810
- EventCategory["PipelineProgress"] = "pipeline.progress";
4811
- /** Per-frame execution trace emitted by the pipeline executor for live observability. */
4812
- EventCategory["PipelineTrace"] = "pipeline.trace";
4813
- /**
4814
- * Raw inference output emitted by `addon-pipeline-runner` after running the
4815
- * detection pipeline on a frame. Carries the `FrameResult` (with
4816
- * `detections[]`, `width`/`height`, timing debug) — never the frame
4817
- * buffer itself. Hub-side consumers (analysis pipeline, class filters,
4818
- * notifications) subscribe to this and re-emit `detection.result` after
4819
- * post-processing.
4820
- */
4821
- EventCategory["PipelineInferenceResult"] = "pipeline.inference-result";
4822
- /**
4823
- * Camera lifecycle event emitted by `addon-pipeline-orchestrator` when it
4824
- * assigns or unassigns a camera to/from an agent. Carries no frame data;
4825
- * pure observability for UI dashboards and metrics consumers.
4826
- */
4827
- EventCategory["PipelineCameraAssigned"] = "pipeline.camera-assigned";
4828
- EventCategory["PipelineCameraUnassigned"] = "pipeline.camera-unassigned";
4829
- /**
4830
- * Per-camera pipeline config was mutated by the orchestrator
4831
- * (3-level settings change via `setAgentAddonDefaults` /
4832
- * `setCameraStepToggle` / `setCameraPipelineForAgent` or a
4833
- * pipeline-scoped `applyDeviceSettingsPatch`). Orchestrator
4834
- * subscribes to its own emission to hot-reload the assigned runner
4835
- * via `attachCamera` so the next frame executes against the new
4836
- * engine/steps without waiting for a rebalance or the next
4837
- * `DeviceStreamsRegistered` cycle.
4838
- */
4839
- EventCategory["PipelineCameraUpdated"] = "pipeline.camera-updated";
4840
- /**
4841
- * The cluster camera-source OWNER changed (`clusterRoles.ingestNode`).
4842
- * Emitted by addon-pipeline-orchestrator whenever it (re)derives node
4843
- * capabilities — at boot, on agent online/offline, and on an ingest-node
4844
- * flip. Carries the resolved `ownerNodeId`. The stream-broker consumes it to
4845
- * keep its ingest-owner-gate decision current WITHOUT a per-`ensureBroker`
4846
- * cross-process `getIngestOwner` query (push the authority's decision instead
4847
- * of polling it on the hot path). Idempotent state — re-emitted on every
4848
- * topology change, so a dropped event self-heals on the next one (plus the
4849
- * broker's long backstop reconcile query).
4850
- */
4851
- EventCategory["PipelineIngestOwnerChanged"] = "pipeline.ingest-owner-changed";
4852
- /**
4853
- * Periodic snapshot of per-node pipeline-runner load
4854
- * (`RunnerLocalLoad`). Emitted ~1Hz by every runner so UI dashboards
4855
- * subscribe instead of polling `pipelineRunner.getLocalLoad`.
4856
- * `nodeId` carried in the payload + on `event.source.nodeId`.
4857
- */
4858
- EventCategory["PipelineRunnerLoadSnapshot"] = "pipeline.runner-load-snapshot";
4859
- /**
4860
- * Periodic snapshot of per-camera pipeline metrics (`CameraMetrics`
4861
- * + `deviceId` + `nodeId`). Emitted ~1Hz by every runner for each
4862
- * attached camera. UI subscribes to drive overlay phase / fps /
4863
- * inference time without polling `getCameraMetrics`.
4864
- */
4865
- EventCategory["PipelineCameraMetricsSnapshot"] = "pipeline.camera-metrics-snapshot";
4866
- /**
4867
- * Periodic snapshot of stream-broker per-broker statistics (input
4868
- * fps, decoded fps, bitrate, codec). Emitted ~1Hz by every
4869
- * stream-broker process for each active broker so the UI can drive
4870
- * the Stream / Cluster dashboards without polling
4871
- * `streamBroker.listAllProfileSlots` and friends.
4872
- */
4873
- EventCategory["StreamBrokerMetricsSnapshot"] = "stream-broker.metrics-snapshot";
4874
- /**
4875
- * Cap event fired by `stream-broker` when a profile slot enters
4876
- * "demanded" state — a cam stream has been assigned and at least one
4877
- * consumer (RTSP restream, decoded subscriber, WebRTC session, …) is
4878
- * present. Camera-provider addons (Reolink Baichuan push, …)
4879
- * subscribe to this category to start their underlying transport
4880
- * lazily. Payload: `{ deviceId, camStreamId, profile }`.
4881
- */
4882
- EventCategory["StreamBrokerOnCamStreamDemand"] = "stream-broker.onCamStreamDemand";
4883
- /**
4884
- * Cap event fired by `stream-broker` when the last consumer leaves a
4885
- * previously-demanded cam stream. Providers tear down their
4886
- * underlying transport on receipt. Payload: `{ deviceId, camStreamId }`.
4887
- */
4888
- EventCategory["StreamBrokerOnCamStreamIdle"] = "stream-broker.onCamStreamIdle";
4889
- /**
4890
- * Cap event fired by `stream-broker` when a broker fails to dial a
4891
- * managed-loopback source (today: `pull-rfc4571`) and the publisher
4892
- * needs to refresh the cached URL. The lib's TCP server idle-tears-down
4893
- * on its own schedule, so a re-publish with a fresh `host:port` is the
4894
- * only way to keep the broker dialable. Camera providers (Reolink
4895
- * Baichuan native, …) subscribe and respond by re-running their publish
4896
- * pipeline.
4897
- * Payload: `{ deviceId, camStreamId, brokerId }`.
4898
- */
4899
- EventCategory["StreamBrokerOnRequestStreamSourceRefresh"] = "stream-broker.onRequestStreamSourceRefresh";
4900
- /**
4901
- * A camera provider changed a device's stream parameters (codec /
4902
- * resolution / bitrate / a stream added or removed). A LOW-LATENCY NUDGE
4903
- * for the stream-broker's catalog reconcile: it carries NO authoritative
4904
- * data — the broker re-PULLS that device's `stream-catalog` cap on receipt
4905
- * (the 30s reconcile poll is the backstop if this nudge is dropped). Emitted
4906
- * by providers from `stream-params.setProfile`. Payload: `{ deviceId }`.
4907
- */
4908
- EventCategory["StreamParamsChanged"] = "stream-params.changed";
4909
- /**
4910
- * Generic per-device runtime-state change. Fired by `device-manager`
4911
- * whenever a persisted slice in any cap's `runtimeState` shape
4912
- * mutates. Payload: `{deviceId, capName, slice}`. Subscribers are
4913
- * the `deviceState` cap router (cross-process listeners) and the
4914
- * deviceProxy reactive bindings (`device.state.<capName>.value`).
4915
- * Cap-specific events (`battery.onStatusChanged`, …) still fire
4916
- * — they're authoritative for callers that want a typed payload
4917
- * without filtering on `capName`.
4918
- */
4919
- EventCategory["DeviceStateChanged"] = "device.state-changed";
4920
- /**
4921
- * Cap event fired by every device that registers the `battery`
4922
- * capability. Mirrors the cap definition's `onStatusChanged`. Carries
4923
- * `{ deviceId, status: BatteryStatus }`. Subscribers (alert center,
4924
- * snapshot wrapper, UI) react to charge/sleep transitions without
4925
- * polling `batteryCapability.getStatus`.
4926
- */
4927
- EventCategory["BatteryOnStatusChanged"] = "battery.onStatusChanged";
4928
- /**
4929
- * Emitted by the battery cap provider WHEN `wakeForStream` enters the
4930
- * "wake in progress" window — between the Baichuan wake-up issue and
4931
- * the camera's first dialed-back RTP packet. The stream-broker
4932
- * manager subscribes to flip the per-broker placeholder reason to
4933
- * `'waking'` so viewers see a labelled "WAKING UP" tile instead of
4934
- * the generic `'reconnecting'` frame. Carries `{ deviceId }`. The
4935
- * complementary "wake complete" signal is the existing
4936
- * `BatteryOnStatusChanged { sleeping: false }` event.
4937
- */
4938
- EventCategory["BatteryOnWakeStarted"] = "battery.onWakeStarted";
4939
- /**
4940
- * Cap event fired by every device that registers the `doorbell`
4941
- * capability. Mirrors `doorbellCapability.events.onPressed`. Carries
4942
- * `{ deviceId, timestamp }`. Operators consuming the UI subscribe
4943
- * here to render transient ring toasts and a "Recent presses" row
4944
- * on the device detail page.
4945
- */
4946
- EventCategory["DoorbellOnPressed"] = "doorbell.onPressed";
4947
- /**
4948
- * Cap event fired by every device that registers the `event-emitter`
4949
- * capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
4950
- * `{ deviceId, eventType, data, timestamp, seq }` — the device's EXACT
4951
- * declared event verbatim (NO normalization). Subscribers (UI event
4952
- * stream, advanced-notifier rules) react to fired events without
4953
- * holding a cap reference.
4954
- */
4955
- EventCategory["EventEmitted"] = "event-emitter.event";
4956
- /**
4957
- * Periodic snapshot of the per-node detection-pipeline engine
4958
- * registry (loaded engines, models resident, in-use cameras, idle
4959
- * TTL). Emitted ~0.2Hz (every 5 s) by every detection-pipeline
4960
- * process. The Engines tab subscribes to drive its inventory view
4961
- * without polling `pipelineExecutor.listLoadedEngines`.
4962
- */
4963
- EventCategory["PipelineEngineMetricsSnapshot"] = "pipeline.engine-metrics-snapshot";
4964
- /**
4965
- * Per-node detection-engine runtime-provisioning transition. Emitted by
4966
- * the detection-pipeline provider on every state change of its lazy
4967
- * engine-provisioning machine (idle → installing → verifying → ready,
4968
- * or → failed with a `nextRetryAt`). Payload is the
4969
- * `EngineProvisioningState` snapshot; `event.source.nodeId` carries the
4970
- * node. The Pipeline page subscribes to drive a live "installing
4971
- * OpenVINO… / ready" indicator per node without polling
4972
- * `pipelineExecutor.getEngineProvisioning`. Telemetry-grade (D8): the UI
4973
- * also reads the cap snapshot on mount / reconnect. Phase 2.
4974
- */
4975
- EventCategory["PipelineEngineProvisioning"] = "pipeline.engine-provisioning";
4976
- /**
4977
- * Cluster topology snapshot. Carries the same payload returned by
4978
- * `nodes.topology` (every reachable node + addons + processes).
4979
- * Emitted by the hub on any agent / addon lifecycle change
4980
- * (debounced) plus a periodic safety net. Replaces UI polling on
4981
- * `nodes.topology` — admin-ui dashboards subscribe to drive the
4982
- * cluster view directly from the event payload.
4983
- */
4984
- EventCategory["ClusterTopologySnapshot"] = "cluster.topology-snapshot";
4985
- /**
4986
- * Periodic per-node system metrics snapshot (CPU / memory / GPU /
4987
- * disk / network). Emitted ~0.2 Hz by the metrics-provider addon
4988
- * for each node. Drives the dashboard SystemStatus / ProcessResources
4989
- * widgets without polling `metricsProvider.getCurrent`.
4990
- */
4991
- EventCategory["MetricsNodeResourcesSnapshot"] = "metrics.node-resources-snapshot";
4992
- /**
4993
- * Periodic per-node process-tree snapshot (camstack-related pids
4994
- * with ghost / managed / root classification). Emitted ~0.2 Hz by
4995
- * the metrics-provider addon. Drives the Cluster → Processes tab
4996
- * without polling `metricsProvider.listNodeProcesses`.
4997
- */
4998
- EventCategory["MetricsNodeProcessesSnapshot"] = "metrics.node-processes-snapshot";
4999
- /**
5000
- * Capability binding change event emitted by `addon-pipeline-orchestrator`
5001
- * when a user changes which addon implements a cap on a node. Subscribed
5002
- * by every kernel process to update its local `preferredProviderRegistry`
5003
- * so future capability lookups respect the new binding.
5004
- */
5005
- /**
5006
- * A capability binding was changed for a node — addon X now provides
5007
- * capability `cap` on node `nodeId`. Lives under the generic
5008
- * `capability.*` namespace because capability bindings are a kernel-
5009
- * level concept used by many addons, not strictly pipeline-scoped.
5010
- */
5011
- EventCategory["CapabilityBindingChanged"] = "capability.binding-changed";
5012
- EventCategory["ModelDownloadProgress"] = "model.download.progress";
5013
- EventCategory["AgentRegistered"] = "agent.registered";
5014
- EventCategory["AgentUnregistered"] = "agent.unregistered";
5015
- EventCategory["AgentOnline"] = "agent.online";
5016
- EventCategory["AgentOffline"] = "agent.offline";
5017
- /** Forked worker process (e.g. hub/pipeline) connected to the broker. */
5018
- EventCategory["WorkerOnline"] = "worker.online";
5019
- /** Forked worker process disconnected from the broker. */
5020
- EventCategory["WorkerOffline"] = "worker.offline";
5021
- EventCategory["AgentTaskDispatched"] = "agent.task.dispatched";
5022
- EventCategory["AgentTaskAssigned"] = "agent.task.assigned";
5023
- EventCategory["AgentTrpcConnected"] = "agent.trpc.connected";
5024
- EventCategory["AgentWsConnected"] = "agent.ws.connected";
5025
- EventCategory["AgentWsDisconnected"] = "agent.ws.disconnected";
5026
- EventCategory["AgentBackupActivated"] = "agent.backup.activated";
5027
- EventCategory["OrchestrationSettingsUpdated"] = "orchestration.settings-updated";
5028
- /**
5029
- * Per-agent hwaccel preference changed (user override set, cleared, or
5030
- * re-probed). Observability event — decoders pull the current pref at
5031
- * `createSession`, so running sessions keep their current backend until
5032
- * they rotate naturally (camera add/remove, stream restart). Future
5033
- * work can wire a listener in stream-broker that force-rotates live
5034
- * sessions; for now this event powers logs + admin-UI toast feedback.
5035
- */
5036
- EventCategory["PipelineAgentHwaccelChanged"] = "pipeline.agent-hwaccel-changed";
5037
- EventCategory["MotionAnalysis"] = "detection.motion-analysis";
5038
- /** All raw motion zones from CCL before minArea filter — for UI debug overlay. */
5039
- EventCategory["MotionZonesRaw"] = "detection.motion-zones-raw";
5040
- /**
5041
- * Per-camera motion phase transition (`watching ↔ active`) emitted
5042
- * by the runner. Mirrors the `motion.onMotionChanged` cap event
5043
- * surface — payload `MotionOnMotionChangedPayload` carries
5044
- * `{deviceId, detected, timestamp, source, regions?}`. Subscribers
5045
- * include addons that need to react to motion state without
5046
- * polling the runtime-state mirror.
5047
- */
5048
- EventCategory["MotionOnMotionChanged"] = "motion.on-motion-changed";
5049
- EventCategory["DetectionResult"] = "detection.result";
5050
- EventCategory["DetectionRaw"] = "detection.raw";
5051
- EventCategory["DetectionCameraNative"] = "detection.camera-native";
5052
- /**
5053
- * Canonical per-chunk live audio pipeline output. Payload is
5054
- * `PipelineAudioInferenceResultPayload` carrying a full `AudioResult`
5055
- * (level + detections + debug). Lives on the pipeline.* namespace
5056
- * alongside `pipeline.inference-result` (video) for symmetry.
5057
- */
5058
- EventCategory["PipelineAudioInferenceResult"] = "pipeline.audio-inference-result";
5059
- EventCategory["DetectionPhaseTransition"] = "detection.phase-transition";
5060
- EventCategory["ProviderMotion"] = "provider.motion";
5061
- EventCategory["ProviderDetection"] = "provider.detection";
5062
- EventCategory["EnrichmentEmbeddingStored"] = "enrichment.embedding.stored";
5063
- EventCategory["EnrichmentSceneStateChanged"] = "enrichment.scene.state-changed";
5064
- EventCategory["EnrichmentActivitySummary"] = "enrichment.activity.summary";
5065
- EventCategory["PipelineAnalyticsTrackStarted"] = "pipeline-analytics.track-started";
5066
- EventCategory["PipelineAnalyticsTrackEnded"] = "pipeline-analytics.track-ended";
5067
- EventCategory["PipelineAnalyticsDetectionEvent"] = "pipeline-analytics.detection-event";
5068
- EventCategory["PipelineAnalyticsFrameTracked"] = "pipeline-analytics.frame-tracked";
5069
- EventCategory["FrigateLiveEvent"] = "frigate.live-event";
5070
- EventCategory["CameraStreamsProfileSlotsChanged"] = "camera-streams.onProfileSlotsChanged";
5071
- /**
5072
- * Stream-broker health watchdog. Per-broker (deviceId/profile) emission.
5073
- * `stream.offline` fires after STREAM_STALE_TIMEOUT_MS without an encoded
5074
- * packet on an active broker. `stream.online` fires on first packet
5075
- * after a stale gap (or on initial first packet). Payload includes
5076
- * the assigned camStreamId as `profileKey`.
5077
- */
5078
- EventCategory["StreamOnline"] = "stream.online";
5079
- EventCategory["StreamOffline"] = "stream.offline";
5080
- EventCategory["NetworkTunnelStarted"] = "network.tunnel.started";
5081
- EventCategory["NetworkTunnelStopped"] = "network.tunnel.stopped";
5082
- /** Fired by the `local-network` cap when the host's interface set
5083
- * changes (new IP from DHCP, VPN connect, docker bridge added). */
5084
- EventCategory["LocalNetworkChanged"] = "network.local.changed";
5085
- /**
5086
- * Fired by a `mesh-network` provider (Tailscale, …) when its
5087
- * mesh-reachable host changes (join / leave / MagicDNS or 100.x IP
5088
- * change). Lets `local-network` fold the mesh endpoint into its
5089
- * connection-endpoint list without a cross-package import. Payload
5090
- * carries the preferred host (`host: ''` = no longer reachable),
5091
- * the hub port, and the scheme. Telemetry-grade (D8): consumers
5092
- * pull-reconcile from the provider's `getStatus` on reconnect. */
5093
- EventCategory["MeshNetworkChanged"] = "network.mesh.changed";
5094
- EventCategory["BackupCompleted"] = "backup.completed";
5095
- EventCategory["BackupRestored"] = "backup.restored";
5096
- EventCategory["NotificationDispatched"] = "notification.dispatched";
5097
- EventCategory["NotificationFailed"] = "notification.failed";
5098
- EventCategory["DeviceUpdated"] = "device.updated";
5099
- /**
5100
- * Transport-level connectivity. Emitted by the device driver when
5101
- * the underlying control socket actually connects / disconnects
5102
- * (Baichuan TCP, ONVIF probe response, RTSP DESCRIBE, …) — NOT for
5103
- * power-state transitions on a battery camera. For battery wake /
5104
- * doze cycles see `DeviceAwake` / `DeviceSleeping`.
5105
- */
5106
- EventCategory["DeviceOnline"] = "device.online";
5107
- /**
5108
- * Stream-broker watchdog — emitted when no encoded packet has been
5109
- * received for STREAM_STALE_TIMEOUT_MS on an active broker (rtsp or
5110
- * push). Paired with DeviceOnline which fires on first packet after
5111
- * a stale gap. Payload: DeviceStreamHealthPayload.
5112
- */
5113
- EventCategory["DeviceOffline"] = "device.offline";
5114
- /**
5115
- * Battery cam woke up — physical power-state transition reported
5116
- * by the device firmware. Distinct from `DeviceOnline` so a UI panel
5117
- * watching power state doesn't flap on every UDP socket reconnect.
5118
- */
5119
- EventCategory["DeviceAwake"] = "device.awake";
5120
- /**
5121
- * Battery cam went to sleep. See `DeviceAwake`.
5122
- */
5123
- EventCategory["DeviceSleeping"] = "device.sleeping";
5124
- EventCategory["RetentionCleanup"] = "retention.cleanup";
5125
- /**
5126
- * Legacy bulk-update progress snapshot (payload `BulkUpdateState`). No longer
5127
- * emitted — F3 removed the coordinator that produced it; "Update all" now runs
5128
- * as one lifecycle engine job (`AddonsJobProgress`/`AddonsJobLog`). Retained
5129
- * (with `BulkUpdateState`) only to avoid regenerating the event maps; removed
5130
- * in F4 once live bulk progress is re-implemented over the engine events.
5131
- */
5132
- EventCategory["AddonsBulkUpdateProgress"] = "addons.bulk-update-progress";
5133
- EventCategory["AddonsJobProgress"] = "addons.job-progress";
5134
- EventCategory["AddonsJobLog"] = "addons.job-log";
5135
- /**
5136
- * A container's child visibility toggled (hidden/shown). Emitted by the
5137
- * `accessories` cap when a child device is hidden or revealed.
5138
- * Payload: `{ deviceId, childDeviceId, hidden }`.
5139
- */
5140
- EventCategory["AccessoriesChildVisibilityChanged"] = "accessories.onChildVisibilityChanged";
5141
- /**
5142
- * A container's child set changed (children added/removed/reordered).
5143
- * Payload: `{ deviceId, childDeviceIds, hiddenChildIds }`.
5144
- */
5145
- EventCategory["AccessoriesChanged"] = "accessories.onAccessoriesChanged";
5146
- /**
5147
- * Progress update from a running model conversion job.
5148
- * Payload: `{ kind: 'model-convert', phase, sessionId?, pct?, detail? }`.
5149
- * Emitted by `addon-model-studio` on the converting node.
5150
- */
5151
- EventCategory["ModelConvertProgress"] = "model-convert.progress";
5152
- return EventCategory;
5153
- }({});
5154
5203
  Object.fromEntries([
5155
5204
  {
5156
5205
  id: "overview",
@@ -6910,7 +6959,8 @@ var MODEL_FORMATS = [
6910
6959
  "coreml",
6911
6960
  "openvino",
6912
6961
  "tflite",
6913
- "pt"
6962
+ "pt",
6963
+ "gguf"
6914
6964
  ];
6915
6965
  /**
6916
6966
  * Multi-file format payload.
@@ -6954,7 +7004,8 @@ var ModelFormatsSchema = object({
6954
7004
  coreml: ModelFormatEntrySchema.optional(),
6955
7005
  openvino: ModelFormatEntrySchema.optional(),
6956
7006
  tflite: ModelFormatEntrySchema.optional(),
6957
- pt: ModelFormatEntrySchema.optional()
7007
+ pt: ModelFormatEntrySchema.optional(),
7008
+ gguf: ModelFormatEntrySchema.optional()
6958
7009
  });
6959
7010
  /**
6960
7011
  * Variant-selector grouping axes. Shared by the full `ModelCatalogEntry` and by
@@ -6995,6 +7046,15 @@ var ModelCatalogEntrySchema = object({
6995
7046
  width: number(),
6996
7047
  height: number()
6997
7048
  }),
7049
+ /**
7050
+ * Channel count of the model input tensor. Omit ⇒ 3 (RGB), the default for
7051
+ * every detector / classifier / embedder. Set to 1 for a grayscale CTC text
7052
+ * recognizer (EasyOCR VGG plate-OCR: input `[N,1,H,W]`) so the preprocess
7053
+ * feeds a single-channel, EasyOCR-normalized tensor instead of the default
7054
+ * 3-channel RGB one. Threaded through `PoolModelConfig.inputChannels` to the
7055
+ * Python inference pool.
7056
+ */
7057
+ inputChannels: number().int().positive().optional(),
6998
7058
  labels: array(LabelDefinitionSchema).readonly(),
6999
7059
  inputLayout: _enum(["nchw", "nhwc"]).optional(),
7000
7060
  inputNormalization: _enum([
@@ -7004,6 +7064,16 @@ var ModelCatalogEntrySchema = object({
7004
7064
  ]).optional(),
7005
7065
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7006
7066
  /**
7067
+ * Per-MODEL postprocessor override. Absent ⇒ the step's own
7068
+ * `StepDefinition.postprocessor` applies (the normal case — every model in a
7069
+ * step shares its decode). Set it when a step hosts models with DIFFERENT raw
7070
+ * output layouts under one slot: e.g. object-detection is `'yolo'` by default,
7071
+ * but a Coral SSD MobileNet build emits the `TFLite_Detection_PostProcess`
7072
+ * 4-tensor layout and needs `'ssd'`. Threaded into `PoolModelConfig.postprocessor`
7073
+ * by the engine factory (`modelEntry.postprocessor ?? def.postprocessor`).
7074
+ */
7075
+ postprocessor: custom().optional(),
7076
+ /**
7007
7077
  * When true, the executor produces a landmark-aligned crop (similarity warp
7008
7078
  * onto the canonical template) before this step runs, instead of a plain
7009
7079
  * axis-aligned bbox crop. Required for face-recognition embedders (ArcFace):
@@ -11710,7 +11780,8 @@ var ModelFormatSchema$1 = _enum([
11710
11780
  "coreml",
11711
11781
  "openvino",
11712
11782
  "tflite",
11713
- "pt"
11783
+ "pt",
11784
+ "gguf"
11714
11785
  ]);
11715
11786
  var PipelineSlotSchema = _enum([
11716
11787
  "detector",
@@ -11804,7 +11875,8 @@ var EngineProvisioningSchema = object({
11804
11875
  runtimeId: _enum([
11805
11876
  "onnx",
11806
11877
  "openvino",
11807
- "coreml"
11878
+ "coreml",
11879
+ "edgetpu"
11808
11880
  ]).nullable(),
11809
11881
  device: string().nullable(),
11810
11882
  state: _enum([
@@ -13445,6 +13517,167 @@ var ptzAutotrackCapability = {
13445
13517
  runtimeState: PtzAutotrackRuntimeStateSchema
13446
13518
  };
13447
13519
  /**
13520
+ * scene-monitor — device-scoped reference-region state cap. An operator marks
13521
+ * a rect ROI on a camera frame and names one or more states; the engine
13522
+ * (pipeline-analytics, designated post-processing node) reports which state is
13523
+ * active on an ongoing basis. Two operator-selectable check modes share every-
13524
+ * thing except the comparator: `similarity` (CLIP cosine at the same ROI coords
13525
+ * vs condition-tagged references) and `llm` (vision-LLM judgment over the crop).
13526
+ *
13527
+ * D14 device-config archetype (`deviceConfig.ui.kind:'widget'`) — the framework
13528
+ * derives the device-detail contribution; the provider carries NO hand-written
13529
+ * settings-contribution methods. `status.kind:'push'` — the engine pushes on
13530
+ * every hysteresis flip / availability change; consumers never poll.
13531
+ */
13532
+ /** Extensible condition tag. Seeded 'day' | 'night'; open by design so more can
13533
+ * be added without a wire break (matching falls back to any-condition refs). */
13534
+ var SceneConditionSchema = string();
13535
+ /** One captured reference — condition-tagged, model-version-gated. `embedding`
13536
+ * is `number[]` (Float32Array does NOT survive MsgPack/UDS). */
13537
+ var SceneReferenceSchema = object({
13538
+ embedding: array(number()),
13539
+ modelId: string(),
13540
+ condition: SceneConditionSchema,
13541
+ capturedAt: number(),
13542
+ thumbnailMediaId: string().optional()
13543
+ });
13544
+ var SceneMonitorStateSchema = object({
13545
+ id: string(),
13546
+ label: string(),
13547
+ references: array(SceneReferenceSchema),
13548
+ textPrompts: array(string()).optional(),
13549
+ referenceCount: number(),
13550
+ currentlyMatched: boolean()
13551
+ });
13552
+ /** Per-mode comparator params in a discriminated union so an `llm` scene never
13553
+ * carries similarity knobs and vice-versa. */
13554
+ var SceneCheckSchema = discriminatedUnion("mode", [object({
13555
+ mode: literal("similarity"),
13556
+ threshold: number().min(0).max(1),
13557
+ hysteresisCount: number().int().positive()
13558
+ }), object({
13559
+ mode: literal("llm"),
13560
+ prompt: string(),
13561
+ profileId: string().optional(),
13562
+ hysteresisCount: number().int().positive()
13563
+ })]);
13564
+ var SceneMonitorSchema = object({
13565
+ id: string(),
13566
+ label: string(),
13567
+ roi: MaskRectShapeSchema,
13568
+ enabled: boolean(),
13569
+ triggerMode: _enum([
13570
+ "periodic",
13571
+ "on-motion",
13572
+ "both"
13573
+ ]),
13574
+ checkIntervalSec: number().optional(),
13575
+ check: SceneCheckSchema,
13576
+ states: array(SceneMonitorStateSchema),
13577
+ currentStateId: string().nullable(),
13578
+ lastCheckedAt: number().nullable(),
13579
+ lastConfidence: number().nullable(),
13580
+ currentCondition: SceneConditionSchema.nullable(),
13581
+ availability: _enum(["ok", "unavailable"]),
13582
+ unavailableReason: string().nullable()
13583
+ });
13584
+ var SceneMonitorStatusSchema = object({
13585
+ monitors: array(SceneMonitorSchema),
13586
+ lastFetchedAt: number()
13587
+ });
13588
+ var sceneMonitorCapability = {
13589
+ name: "scene-monitor",
13590
+ scope: "device",
13591
+ mode: "singleton",
13592
+ kind: "wrapper",
13593
+ defaultActive: true,
13594
+ deviceTypes: [DeviceType.Camera],
13595
+ deviceConfig: { ui: {
13596
+ kind: "widget",
13597
+ widgetId: "host/scene-monitor-editor",
13598
+ tab: "scenes",
13599
+ label: "Scenes"
13600
+ } },
13601
+ methods: {
13602
+ listScenes: method(object({ deviceId: number() }), SceneMonitorStatusSchema),
13603
+ createScene: method(object({
13604
+ deviceId: number(),
13605
+ label: string(),
13606
+ roi: MaskRectShapeSchema,
13607
+ check: SceneCheckSchema,
13608
+ triggerMode: _enum([
13609
+ "periodic",
13610
+ "on-motion",
13611
+ "both"
13612
+ ]).optional(),
13613
+ checkIntervalSec: number().optional()
13614
+ }), SceneMonitorSchema, {
13615
+ kind: "mutation",
13616
+ auth: "admin"
13617
+ }),
13618
+ updateScene: method(object({
13619
+ deviceId: number(),
13620
+ monitorId: string(),
13621
+ patch: object({
13622
+ label: string().optional(),
13623
+ roi: MaskRectShapeSchema.optional(),
13624
+ enabled: boolean().optional(),
13625
+ triggerMode: _enum([
13626
+ "periodic",
13627
+ "on-motion",
13628
+ "both"
13629
+ ]).optional(),
13630
+ checkIntervalSec: number().optional(),
13631
+ check: SceneCheckSchema.optional()
13632
+ })
13633
+ }), _void(), {
13634
+ kind: "mutation",
13635
+ auth: "admin"
13636
+ }),
13637
+ deleteScene: method(object({
13638
+ deviceId: number(),
13639
+ monitorId: string()
13640
+ }), _void(), {
13641
+ kind: "mutation",
13642
+ auth: "admin"
13643
+ }),
13644
+ captureReference: method(object({
13645
+ deviceId: number(),
13646
+ monitorId: string(),
13647
+ stateId: string().optional(),
13648
+ label: string().optional(),
13649
+ condition: SceneConditionSchema.optional()
13650
+ }), object({
13651
+ stateId: string(),
13652
+ referenceCount: number()
13653
+ }), {
13654
+ kind: "mutation",
13655
+ auth: "admin"
13656
+ }),
13657
+ deleteReference: method(object({
13658
+ deviceId: number(),
13659
+ monitorId: string(),
13660
+ stateId: string(),
13661
+ index: number()
13662
+ }), _void(), {
13663
+ kind: "mutation",
13664
+ auth: "admin"
13665
+ }),
13666
+ recheckNow: method(object({
13667
+ deviceId: number(),
13668
+ monitorId: string()
13669
+ }), _void(), {
13670
+ kind: "mutation",
13671
+ auth: "admin"
13672
+ })
13673
+ },
13674
+ status: {
13675
+ schema: SceneMonitorStatusSchema,
13676
+ kind: "push"
13677
+ },
13678
+ runtimeState: SceneMonitorStatusSchema
13679
+ };
13680
+ /**
13448
13681
  * Script-runner cap. Models HA `script.*` entities on
13449
13682
  * `DeviceType.Script`. A Script is a pre-recorded action sequence
13450
13683
  * that can be invoked imperatively — optionally with a variables
@@ -14176,6 +14409,36 @@ var ZoneScopeBreakdownSchema = PerScopeBreakdownSchema.extend({
14176
14409
  * with the per-track detail panel and live overlay. */
14177
14410
  trackIds: array(string()).readonly()
14178
14411
  });
14412
+ /**
14413
+ * A parked ("stationary") object surfaced alongside occupancy — an object that
14414
+ * settled and stopped moving. It is NO LONGER a tracked object (the tracker was
14415
+ * told to forget it so it stops re-spawning tracks/events), but it IS still
14416
+ * physically present, so it keeps counting toward `frame` occupancy and is
14417
+ * listed here so the UI can show it in a dedicated "Stationary" section instead
14418
+ * of flooding the live event feed.
14419
+ */
14420
+ var StationaryObjectSchema = object({
14421
+ id: string(),
14422
+ className: string(),
14423
+ bbox: object({
14424
+ x: number(),
14425
+ y: number(),
14426
+ w: number(),
14427
+ h: number()
14428
+ }),
14429
+ frameWidth: number().int().nonnegative(),
14430
+ frameHeight: number().int().nonnegative(),
14431
+ /** When the source track was first seen. */
14432
+ firstSeenAt: number().int(),
14433
+ /** When the object was recognised as parked (promotion time). */
14434
+ becameStationaryAt: number().int(),
14435
+ /** Last frame a detection confirmed the object is still there. */
14436
+ lastConfirmedAt: number().int(),
14437
+ /** Enrichment label carried from the source track (identity / plate). */
14438
+ label: string().optional(),
14439
+ /** Native-resolution key-frame media key for the parked object's best image. */
14440
+ keyFrameMediaKey: string().optional()
14441
+ });
14179
14442
  var CameraOccupancySnapshotSchema = object({
14180
14443
  /** Frame timestamp of the inference result that produced this snapshot. */
14181
14444
  ts: number().int(),
@@ -14184,10 +14447,15 @@ var CameraOccupancySnapshotSchema = object({
14184
14447
  frameHeight: number().int().nonnegative(),
14185
14448
  /** Per-zone breakdown — one entry per defined zone (user + onboard). */
14186
14449
  zones: array(ZoneScopeBreakdownSchema).readonly(),
14187
- /** Frame-wide aggregate (everywhere, regardless of zone membership). */
14450
+ /** Frame-wide aggregate (everywhere, regardless of zone membership).
14451
+ * INCLUDES currently-confirmed stationary objects (they are still present). */
14188
14452
  frame: PerScopeBreakdownSchema,
14189
14453
  /** Detections that landed outside every zone. Empty when no zones defined. */
14190
- unzoned: PerScopeBreakdownSchema
14454
+ unzoned: PerScopeBreakdownSchema,
14455
+ /** Parked objects on this camera (additive — absent on legacy snapshots).
14456
+ * Surfaced separately so the UI shows them in a dedicated section rather
14457
+ * than as repeated tracks/events. */
14458
+ stationaryObjects: array(StationaryObjectSchema).readonly().optional()
14191
14459
  });
14192
14460
  /**
14193
14461
  * Time-series resolution. The history methods return one bucket per
@@ -14422,6 +14690,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
14422
14690
  pressureSensor: pressureSensorCapability,
14423
14691
  privacyMask: privacyMaskCapability,
14424
14692
  ptzAutotrack: ptzAutotrackCapability,
14693
+ sceneMonitor: sceneMonitorCapability,
14425
14694
  scriptRunner: scriptRunnerCapability,
14426
14695
  smoke: smokeCapability,
14427
14696
  streamParams: streamParamsCapability,
@@ -15707,7 +15976,12 @@ var NotificationRuleConditionsSchema = object({
15707
15976
  clipDescription: object({
15708
15977
  text: string().min(1),
15709
15978
  minSimilarity: number().min(0).max(1)
15710
- }).optional()
15979
+ }).optional(),
15980
+ /** Match events whose recognized-entity label (face identity name or plate
15981
+ * vehicle name, propagated onto `event.data.label`) is one of these values.
15982
+ * Empty/absent → unaffected (back-compat). Enables "notify me when <named
15983
+ * vehicle/person> is seen". */
15984
+ labels: array(string()).readonly().optional()
15711
15985
  });
15712
15986
  var NotificationRuleTemplateSchema = object({
15713
15987
  title: string(),
@@ -15965,11 +16239,19 @@ method(object({
15965
16239
  * login page needs NO change.
15966
16240
  *
15967
16241
  * - `widget` — a Module-Federation widget the login page mounts (via
15968
- * `loadRemoteBundle`) for an in-page ceremony. Covers the passkey
15969
- * login ceremony, which must run `@simplewebauthn/browser` INSIDE the
15970
- * addon bundle. The referenced widget also declares `preAuth: true` in
15971
- * its `addon-widgets-source` catalog entry. `auth.listLoginMethods`
15972
- * stamps a public `bundleUrl` from `addonId` + `bundle`.
16242
+ * `loadRemoteBundle`) for an in-page ceremony. `auth.listLoginMethods`
16243
+ * stamps a public `bundleUrl` from `addonId` + `bundle`. Generic
16244
+ * mechanism kept for future use; no shipped addon uses it on the login
16245
+ * page (the passkey ceremony below runs natively in the shell instead).
16246
+ *
16247
+ * - `passkey` — a declarative WebAuthn ceremony the shell renders
16248
+ * natively (`@simplewebauthn/browser` lives in `addon-admin-ui`, not in
16249
+ * a remotely-loaded bundle). Carries the addon's effective `rpId` /
16250
+ * `origin` (from its `resolveRpID()` / `resolveOrigin()`) so the shell
16251
+ * can gate visibility (IP-literal origin, hostname/rpId mismatch) WITHOUT
16252
+ * fetching any remote code pre-auth. Contribution stays unconditional —
16253
+ * enrollment state is never leaked pre-auth; visibility is a shell
16254
+ * decision.
15973
16255
  *
15974
16256
  * Every contribution carries a `stage`:
15975
16257
  * - `primary` — shown on the first credentials screen (OIDC /
@@ -15983,30 +16265,45 @@ method(object({
15983
16265
  */
15984
16266
  /** When a login method renders in the two-phase login flow. */
15985
16267
  var LoginStageEnum = _enum(["primary", "second-factor"]);
15986
- /** One login-method contribution — redirect button OR pre-auth widget. */
15987
- var LoginMethodContributionSchema = discriminatedUnion("kind", [object({
15988
- kind: literal("redirect"),
15989
- /** Stable id within the login-method set (e.g. `auth-oidc/google`). */
15990
- id: string(),
15991
- /** Operator-facing button label. */
15992
- label: string(),
15993
- /** lucide-react icon name. */
15994
- icon: string().optional(),
15995
- /** Addon-owned HTTP route the button navigates to (GET). */
15996
- startUrl: string(),
15997
- stage: LoginStageEnum
15998
- }), object({
15999
- kind: literal("widget"),
16000
- /** Stable id within the login-method set (e.g. `auth-webauthn/passkey-login`). */
16001
- id: string(),
16002
- /** Owning addon id — drives the public bundle URL + the MF namespace. */
16003
- addonId: string(),
16004
- /** Bundle filename inside the addon's dist dir (`remoteEntry.js`). */
16005
- bundle: string(),
16006
- /** MF remote descriptor — `{ remoteName, exposedModule, componentKey }`. */
16007
- remote: WidgetRemoteSchema,
16008
- stage: LoginStageEnum
16009
- })]);
16268
+ /** One login-method contribution — redirect button, pre-auth widget, or native passkey ceremony. */
16269
+ var LoginMethodContributionSchema = discriminatedUnion("kind", [
16270
+ object({
16271
+ kind: literal("redirect"),
16272
+ /** Stable id within the login-method set (e.g. `auth-oidc/google`). */
16273
+ id: string(),
16274
+ /** Operator-facing button label. */
16275
+ label: string(),
16276
+ /** lucide-react icon name. */
16277
+ icon: string().optional(),
16278
+ /** Addon-owned HTTP route the button navigates to (GET). */
16279
+ startUrl: string(),
16280
+ stage: LoginStageEnum
16281
+ }),
16282
+ object({
16283
+ kind: literal("widget"),
16284
+ /** Stable id within the login-method set (e.g. `auth-webauthn/passkey-login`). */
16285
+ id: string(),
16286
+ /** Owning addon id — drives the public bundle URL + the MF namespace. */
16287
+ addonId: string(),
16288
+ /** Bundle filename inside the addon's dist dir (`remoteEntry.js`). */
16289
+ bundle: string(),
16290
+ /** MF remote descriptor — `{ remoteName, exposedModule, componentKey }`. */
16291
+ remote: WidgetRemoteSchema,
16292
+ stage: LoginStageEnum
16293
+ }),
16294
+ object({
16295
+ kind: literal("passkey"),
16296
+ /** Stable id within the login-method set (e.g. `auth-webauthn/passkey-direct-login`). */
16297
+ id: string(),
16298
+ /** Operator-facing button label. */
16299
+ label: string(),
16300
+ stage: LoginStageEnum,
16301
+ /** Effective WebAuthn RP ID (`resolveRpID()`) — the shell gates visibility on it. */
16302
+ rpId: string(),
16303
+ /** Effective expected origin (`resolveOrigin()`), null when unconfigured. */
16304
+ origin: string().nullable()
16305
+ })
16306
+ ]);
16010
16307
  method(_void(), array(LoginMethodContributionSchema).readonly());
16011
16308
  /**
16012
16309
  * Orchestrator-side destination metadata. The orchestrator computes
@@ -17900,14 +18197,14 @@ var TargetKindCapsSchema = object({
17900
18197
  * the union is large and not meant for runtime validation here; the exported
17901
18198
  * `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
17902
18199
  */
17903
- var ConfigSchemaPassthrough = unknown();
18200
+ var ConfigSchemaPassthrough$1 = unknown();
17904
18201
  var TargetKindSchema = object({
17905
18202
  kind: string(),
17906
18203
  label: string(),
17907
18204
  icon: string(),
17908
18205
  /** Stamped by each provider so the concat-fanned catalog stays routable. */
17909
18206
  addonId: string(),
17910
- configSchema: ConfigSchemaPassthrough,
18207
+ configSchema: ConfigSchemaPassthrough$1,
17911
18208
  supportsDiscovery: boolean(),
17912
18209
  caps: TargetKindCapsSchema
17913
18210
  });
@@ -17960,6 +18257,298 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
17960
18257
  enabled: boolean()
17961
18258
  }), _void(), { kind: "mutation" });
17962
18259
  /**
18260
+ * Shared LLM generate contracts — imported by BOTH `llm.cap.ts` (consumer
18261
+ * surface) and `llm-runtime.cap.ts` (node-side managed executor) so the two
18262
+ * caps stay wire-compatible without a circular cap→cap import.
18263
+ *
18264
+ * Errors are a discriminated-union RESULT, never thrown: the shape survives
18265
+ * every transport tier structurally, and failed calls still write usage rows.
18266
+ * Token counts only in v1 — no costUsd (operator decision, 2026-07-15).
18267
+ */
18268
+ var LlmUsageSchema = object({
18269
+ inputTokens: number(),
18270
+ outputTokens: number()
18271
+ });
18272
+ var LlmErrorCodeSchema = _enum([
18273
+ "timeout",
18274
+ "rate-limited",
18275
+ "auth",
18276
+ "refusal",
18277
+ "bad-request",
18278
+ "unavailable",
18279
+ "no-profile",
18280
+ "budget-exceeded",
18281
+ "adapter-error"
18282
+ ]);
18283
+ var LlmGenerateResultSchema = discriminatedUnion("ok", [object({
18284
+ ok: literal(true),
18285
+ text: string(),
18286
+ model: string(),
18287
+ usage: LlmUsageSchema,
18288
+ truncated: boolean(),
18289
+ latencyMs: number()
18290
+ }), object({
18291
+ ok: literal(false),
18292
+ code: LlmErrorCodeSchema,
18293
+ message: string(),
18294
+ retryAfterMs: number().optional()
18295
+ })]);
18296
+ /**
18297
+ * `Uint8Array` is the sanctioned binary convention — superjson + the UDS
18298
+ * MsgPack channel round-trip typed arrays (embedding-encoder.cap.ts:29,
18299
+ * notification-output.cap.ts:27-31 precedents).
18300
+ */
18301
+ var LlmImageSchema = object({
18302
+ bytes: _instanceof(Uint8Array),
18303
+ mimeType: string()
18304
+ });
18305
+ var LlmGenerateBaseInputSchema = object({
18306
+ /** Collection routing (the notification-output posture). */
18307
+ addonId: string().optional(),
18308
+ /** Explicit profile; else the resolution chain (spec §3). */
18309
+ profileId: string().optional(),
18310
+ /** MANDATORY usage tag: 'ai-summary', 'notifier-rules', 'adhoc-ui', … */
18311
+ consumer: string(),
18312
+ system: string().optional(),
18313
+ /** v1: single-turn. `messages[]` is a v2 additive field. */
18314
+ prompt: string(),
18315
+ /** Structured output — adapter-mapped (response_format / forced tool / responseSchema). */
18316
+ jsonSchema: record(string(), unknown()).optional(),
18317
+ /** Per-call override of the profile default. */
18318
+ maxTokens: number().int().positive().optional(),
18319
+ temperature: number().optional()
18320
+ });
18321
+ /**
18322
+ * `llm-runtime` — node-side managed llama.cpp executor (spec §4). Registered
18323
+ * on EVERY node where `addon-ai` is installed; the hub `llm` provider reaches
18324
+ * a specific node's runtime with `nodePin(profile.runtime.nodeId)` — normal
18325
+ * cap routing, zero bespoke plumbing. `internal: true`: the operator reaches
18326
+ * this only through the `llm` cap's methods.
18327
+ *
18328
+ * One running llama-server child per node in v1 (models are RAM-heavy).
18329
+ * Resource ceiling = llama-server flags + idleStopMinutes ONLY (no RSS
18330
+ * watchdog — operator decision #3).
18331
+ */
18332
+ var ManagedModelRefSchema = discriminatedUnion("kind", [
18333
+ object({
18334
+ kind: literal("catalog"),
18335
+ catalogId: string()
18336
+ }),
18337
+ object({
18338
+ kind: literal("url"),
18339
+ url: string(),
18340
+ sha256: string().optional()
18341
+ }),
18342
+ object({
18343
+ kind: literal("path"),
18344
+ path: string()
18345
+ })
18346
+ ]);
18347
+ var ManagedRuntimeConfigSchema = object({
18348
+ /** WHERE the runtime lives — hub or any agent. */
18349
+ nodeId: string(),
18350
+ /** Closed for v1; 'ollama' is a v2 candidate. */
18351
+ engine: _enum(["llama-cpp"]),
18352
+ model: ManagedModelRefSchema,
18353
+ contextSize: number().int().default(4096),
18354
+ /** 0 = CPU-only. */
18355
+ gpuLayers: number().int().default(0),
18356
+ /** Default: cpus-2, clamped ≥1 (resolved node-side). */
18357
+ threads: number().int().optional(),
18358
+ /** Concurrent slots. */
18359
+ parallel: number().int().default(1),
18360
+ /** Else lazy: first generate boots it. */
18361
+ autoStart: boolean().default(false),
18362
+ /** 0 = never; frees RAM after quiet periods. */
18363
+ idleStopMinutes: number().int().default(30)
18364
+ });
18365
+ var LlmRuntimeStatusSchema = object({
18366
+ /** Status is ALWAYS node-qualified. */
18367
+ nodeId: string(),
18368
+ state: _enum([
18369
+ "stopped",
18370
+ "downloading",
18371
+ "starting",
18372
+ "ready",
18373
+ "crashed",
18374
+ "failed"
18375
+ ]),
18376
+ pid: number().optional(),
18377
+ port: number().optional(),
18378
+ modelPath: string().optional(),
18379
+ modelId: string().optional(),
18380
+ downloadProgress: number().min(0).max(1).optional(),
18381
+ lastError: string().optional(),
18382
+ crashesInWindow: number(),
18383
+ /** Child RSS (sampled best-effort). */
18384
+ memoryBytes: number().optional(),
18385
+ vramBytes: number().optional()
18386
+ });
18387
+ var LlmNodeModelSchema = object({
18388
+ file: string(),
18389
+ sizeBytes: number(),
18390
+ catalogId: string().optional(),
18391
+ installedAt: number().optional()
18392
+ });
18393
+ var LlmRuntimeDiskUsageSchema = object({
18394
+ nodeId: string(),
18395
+ modelsBytes: number(),
18396
+ freeBytes: number().optional()
18397
+ });
18398
+ method(LlmGenerateBaseInputSchema.extend({
18399
+ images: array(LlmImageSchema).optional(),
18400
+ runtime: ManagedRuntimeConfigSchema,
18401
+ /** The managed profile's timeout, threaded by the hub provider. */
18402
+ timeoutMs: number().int().positive().optional()
18403
+ }), LlmGenerateResultSchema, { kind: "mutation" }), method(object({ runtime: ManagedRuntimeConfigSchema }), LlmRuntimeStatusSchema, {
18404
+ kind: "mutation",
18405
+ auth: "admin"
18406
+ }), method(object({}), _void(), {
18407
+ kind: "mutation",
18408
+ auth: "admin"
18409
+ }), method(object({}), LlmRuntimeStatusSchema), method(object({ model: ManagedModelRefSchema }), _void(), {
18410
+ kind: "mutation",
18411
+ auth: "admin"
18412
+ }), method(object({ file: string() }), _void(), {
18413
+ kind: "mutation",
18414
+ auth: "admin"
18415
+ }), method(object({}), array(LlmNodeModelSchema)), method(object({}), LlmRuntimeDiskUsageSchema);
18416
+ /**
18417
+ * `llm` — consumer-facing LLM surface (spec §1-§3). Collection-mode: array
18418
+ * methods concat-fan across providers; single-row methods route to ONE
18419
+ * provider by the `addonId` in the call input (the notification-output
18420
+ * posture, notification-output.cap.ts:215-250). Provided by `addon-ai`
18421
+ * (hub-placed); the cap stays open for future providers.
18422
+ *
18423
+ * Profiles are ROWS (data), not addons: one row = one usable model endpoint.
18424
+ * `apiKey` is a password field — providers REDACT it on read and merge on
18425
+ * write; a stored key NEVER round-trips to a client.
18426
+ */
18427
+ var LlmProfileKindSchema = _enum([
18428
+ "openai-compatible",
18429
+ "openai",
18430
+ "anthropic",
18431
+ "google",
18432
+ "managed-local"
18433
+ ]);
18434
+ var LlmProfileSchema = object({
18435
+ id: string(),
18436
+ name: string(),
18437
+ kind: LlmProfileKindSchema,
18438
+ /** Stamped by the provider — keeps the fanned catalog routable. */
18439
+ addonId: string(),
18440
+ enabled: boolean(),
18441
+ /** Vendor model id, or the managed runtime's loaded model. */
18442
+ model: string(),
18443
+ /** Required for openai-compatible; override for cloud kinds. */
18444
+ baseUrl: string().optional(),
18445
+ /** ConfigUISchema type:'password' — never round-trips (spec §5). */
18446
+ apiKey: string().optional(),
18447
+ supportsVision: boolean(),
18448
+ temperature: number().min(0).max(2).optional(),
18449
+ maxTokens: number().int().positive().optional(),
18450
+ timeoutMs: number().int().positive().default(6e4),
18451
+ extraHeaders: record(string(), string()).optional(),
18452
+ /** kind === 'managed-local' only (spec §4). */
18453
+ runtime: ManagedRuntimeConfigSchema.optional()
18454
+ });
18455
+ /** ConfigUISchema tree passed through untyped on the wire (the
18456
+ * notification-output `ConfigSchemaPassthrough` precedent at
18457
+ * notification-output.cap.ts:151); the exported TS type re-tightens it. */
18458
+ var ConfigSchemaPassthrough = unknown();
18459
+ var LlmProfileKindDescriptorSchema = object({
18460
+ kind: LlmProfileKindSchema,
18461
+ label: string(),
18462
+ icon: string(),
18463
+ /** Stamped by each provider so the concat-fanned catalog stays routable. */
18464
+ addonId: string(),
18465
+ configSchema: ConfigSchemaPassthrough
18466
+ });
18467
+ var LlmDefaultSelectorSchema = union([object({ consumer: string() }), object({ purpose: _enum(["text", "vision"]) })]);
18468
+ var LlmDefaultSchema = object({
18469
+ selector: LlmDefaultSelectorSchema,
18470
+ profileId: string()
18471
+ });
18472
+ /** Server-side rollup row — getUsage never dumps raw call rows (spec §6). */
18473
+ var LlmUsageRollupSchema = object({
18474
+ day: string(),
18475
+ consumer: string(),
18476
+ profileId: string(),
18477
+ calls: number(),
18478
+ okCalls: number(),
18479
+ errorCalls: number(),
18480
+ inputTokens: number(),
18481
+ outputTokens: number(),
18482
+ avgLatencyMs: number()
18483
+ });
18484
+ /** LLM-facing view over the reused ModelCatalogEntry mechanism (spec §4.2). */
18485
+ var ManagedModelCatalogEntrySchema = object({
18486
+ id: string(),
18487
+ label: string(),
18488
+ family: string(),
18489
+ purpose: _enum(["text", "vision"]),
18490
+ url: string(),
18491
+ sha256: string(),
18492
+ sizeBytes: number(),
18493
+ quantization: string(),
18494
+ /** Load-time guidance shown in the picker. */
18495
+ minRamBytes: number(),
18496
+ contextSizeDefault: number().int(),
18497
+ /** Vision models: companion projector file. */
18498
+ mmprojUrl: string().optional()
18499
+ });
18500
+ var LlmRuntimeNodeSchema = object({
18501
+ nodeId: string(),
18502
+ reachable: boolean(),
18503
+ status: LlmRuntimeStatusSchema.optional(),
18504
+ disk: LlmRuntimeDiskUsageSchema.optional(),
18505
+ error: string().optional()
18506
+ });
18507
+ var GenerateVisionInputSchema = LlmGenerateBaseInputSchema.extend({ images: array(LlmImageSchema).min(1) });
18508
+ var ProfileRefInputSchema = object({
18509
+ addonId: string(),
18510
+ profileId: string()
18511
+ });
18512
+ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, { kind: "mutation" }), method(GenerateVisionInputSchema, LlmGenerateResultSchema, { kind: "mutation" }), method(object({}), array(LlmProfileKindDescriptorSchema)), method(object({}), array(LlmProfileSchema)), method(object({ profile: LlmProfileSchema }), LlmProfileSchema, {
18513
+ kind: "mutation",
18514
+ auth: "admin"
18515
+ }), method(ProfileRefInputSchema, _void(), {
18516
+ kind: "mutation",
18517
+ auth: "admin"
18518
+ }), method(ProfileRefInputSchema, LlmGenerateResultSchema, {
18519
+ kind: "mutation",
18520
+ auth: "admin"
18521
+ }), method(ProfileRefInputSchema, array(string())), method(object({}), array(LlmDefaultSchema)), method(object({
18522
+ selector: LlmDefaultSelectorSchema,
18523
+ profileId: string().nullable()
18524
+ }), _void(), {
18525
+ kind: "mutation",
18526
+ auth: "admin"
18527
+ }), method(object({
18528
+ since: number().optional(),
18529
+ until: number().optional(),
18530
+ consumer: string().optional(),
18531
+ profileId: string().optional()
18532
+ }), array(LlmUsageRollupSchema)), method(object({}), array(ManagedModelCatalogEntrySchema)), method(object({}), array(LlmRuntimeNodeSchema)), method(object({ nodeId: string() }), array(LlmNodeModelSchema)), method(object({
18533
+ nodeId: string(),
18534
+ model: ManagedModelRefSchema
18535
+ }), _void(), {
18536
+ kind: "mutation",
18537
+ auth: "admin"
18538
+ }), method(object({
18539
+ nodeId: string(),
18540
+ file: string()
18541
+ }), _void(), {
18542
+ kind: "mutation",
18543
+ auth: "admin"
18544
+ }), method(ProfileRefInputSchema, LlmRuntimeStatusSchema), method(ProfileRefInputSchema, LlmRuntimeStatusSchema, {
18545
+ kind: "mutation",
18546
+ auth: "admin"
18547
+ }), method(ProfileRefInputSchema, _void(), {
18548
+ kind: "mutation",
18549
+ auth: "admin"
18550
+ });
18551
+ /**
17963
18552
  * Zod schemas for persisted record types.
17964
18553
  *
17965
18554
  * These schemas serve as the single source of truth for types that are
@@ -18161,6 +18750,22 @@ var TrackSnapshotSchema = object({
18161
18750
  /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
18162
18751
  mediaKey: string()
18163
18752
  });
18753
+ /**
18754
+ * One audio-classification label heard on the track's camera while the
18755
+ * track was alive, aggregated per label. An "episode" is one persisted
18756
+ * audio event (the confident-classification path: score ≥ the device's
18757
+ * `classificationMinScore`, class-change-or-heartbeat coalesced) — NOT
18758
+ * one 32 ms inference chunk, so counts stay human-scaled.
18759
+ */
18760
+ var TrackAudioLabelSchema = object({
18761
+ label: string(),
18762
+ /** Highest classification score observed across the label's episodes. */
18763
+ peakScore: number(),
18764
+ /** Number of coalesced audio-event episodes carrying this label. */
18765
+ count: number(),
18766
+ firstAt: number(),
18767
+ lastAt: number()
18768
+ });
18164
18769
  var TrackSchema = object({
18165
18770
  trackId: string(),
18166
18771
  deviceId: number(),
@@ -18175,6 +18780,10 @@ var TrackSchema = object({
18175
18780
  snapshots: array(TrackSnapshotSchema).readonly(),
18176
18781
  /** Deduplicated zones the track has entered at least once. */
18177
18782
  zonesVisited: array(string()).readonly(),
18783
+ /** Deduplicated set of detector classes observed for this track over its
18784
+ * life (a track may be reclassified, e.g. person→vehicle). Absent on
18785
+ * legacy rows written before class accumulation shipped. */
18786
+ classes: array(string()).readonly().optional(),
18178
18787
  /** Cumulative normalized distance travelled (0..1 units = full frame width). */
18179
18788
  totalDistance: number(),
18180
18789
  state: TrackStateSchema,
@@ -18188,7 +18797,11 @@ var TrackSchema = object({
18188
18797
  bestEventId: string().optional(),
18189
18798
  /** Tag of the importance sub-signal that dominated the score
18190
18799
  * (identity|dwell|proximity|class|confidence|travel|zone). */
18191
- importanceReason: string().optional()
18800
+ importanceReason: string().optional(),
18801
+ /** Audio-classification labels heard on the camera during the track's
18802
+ * life (score ≥ device `classificationMinScore`), aggregated per label.
18803
+ * Absent on legacy rows / tracks with no confident audio. */
18804
+ audioLabels: array(TrackAudioLabelSchema).readonly().optional()
18192
18805
  });
18193
18806
  var BaseEventFields = {
18194
18807
  id: string(),
@@ -18336,7 +18949,7 @@ var KeyEventSchema = object({
18336
18949
  /** Track lifetime in ms (lastSeen - firstSeen). */
18337
18950
  windowMs: number().optional()
18338
18951
  });
18339
- var TrackedDetectionSchema = object({
18952
+ object({
18340
18953
  trackId: string(),
18341
18954
  className: string(),
18342
18955
  confidence: number(),
@@ -18344,6 +18957,23 @@ var TrackedDetectionSchema = object({
18344
18957
  zones: array(string()).readonly(),
18345
18958
  state: TrackStateSchema
18346
18959
  });
18960
+ var OverlayDetectionSchema = looseObject({
18961
+ id: string(),
18962
+ kind: _enum(["first-level", "detail"]),
18963
+ macroClass: string(),
18964
+ score: number(),
18965
+ bbox: object({
18966
+ x: number(),
18967
+ y: number(),
18968
+ width: number(),
18969
+ height: number()
18970
+ }),
18971
+ labels: array(looseObject({
18972
+ label: string(),
18973
+ score: number()
18974
+ })).readonly(),
18975
+ parentId: string().optional()
18976
+ });
18347
18977
  var ScoredObjectEventSchema = ObjectEventSchema.extend({ score: number() });
18348
18978
  var SearchObjectEventsInput = object({
18349
18979
  text: string(),
@@ -18354,6 +18984,20 @@ var SearchObjectEventsInput = object({
18354
18984
  limit: number().default(50),
18355
18985
  minScore: number().min(0).max(1).default(.2)
18356
18986
  });
18987
+ var TrackCascadeCountsSchema = object({
18988
+ /** Persisted track roots deleted (authoritative). */
18989
+ tracks: number().int(),
18990
+ /** Object events removed with their tracks (best-effort; see note above). */
18991
+ events: number().int(),
18992
+ /** Track/face/plate-owned media removed (best-effort). Never identity media. */
18993
+ media: number().int(),
18994
+ /** Unassigned (non-enrolled) face reads removed (best-effort). */
18995
+ faces: number().int(),
18996
+ /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
18997
+ plates: number().int(),
18998
+ /** Per-track CLIP search vectors removed (best-effort). */
18999
+ embeddings: number().int()
19000
+ });
18357
19001
  DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
18358
19002
  deviceId: number(),
18359
19003
  trackId: string()
@@ -18385,6 +19029,24 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
18385
19029
  }), {
18386
19030
  kind: "mutation",
18387
19031
  auth: "admin"
19032
+ }), method(object({
19033
+ deviceId: number(),
19034
+ cutoffMs: number()
19035
+ }), TrackCascadeCountsSchema, {
19036
+ kind: "mutation",
19037
+ auth: "admin"
19038
+ }), method(object({ deviceId: number() }), TrackCascadeCountsSchema, {
19039
+ kind: "mutation",
19040
+ auth: "admin"
19041
+ }), method(object({
19042
+ deviceId: number(),
19043
+ trackIds: array(string()).min(1)
19044
+ }), object({
19045
+ deleted: number().int(),
19046
+ failed: array(string()).readonly()
19047
+ }), {
19048
+ kind: "mutation",
19049
+ auth: "admin"
18388
19050
  }), method(object({
18389
19051
  eventId: string(),
18390
19052
  kind: MediaFileKindEnum.optional()
@@ -18393,7 +19055,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
18393
19055
  timestamp: number(),
18394
19056
  frameWidth: number(),
18395
19057
  frameHeight: number(),
18396
- detections: array(TrackedDetectionSchema).readonly()
19058
+ detections: array(OverlayDetectionSchema).readonly()
18397
19059
  }), object({
18398
19060
  deviceId: number(),
18399
19061
  trackId: string(),
@@ -19709,7 +20371,15 @@ DeviceType.Camera, method(object({ deviceId: number().int().nonnegative() }), ar
19709
20371
  */
19710
20372
  disableIpv6: boolean().optional(),
19711
20373
  /** Subscriber attribution. See `createSession` for the contract. */
19712
- consumerAttribution: BrokerConsumerAttributionSchema.optional()
20374
+ consumerAttribution: BrokerConsumerAttributionSchema.optional(),
20375
+ /**
20376
+ * Client-side stream hints (viewport, downlink) — same contract as
20377
+ * `createSession.hints`. Client-offer viewers (the RN viewer's
20378
+ * `WebrtcLiveSession`) negotiate via `handleOffer`, so without this
20379
+ * field their hints were silently stripped by the schema and the
20380
+ * adaptive ladder started blind on the client's display size.
20381
+ */
20382
+ hints: webrtcClientHintsSchema.optional()
19713
20383
  }), object({
19714
20384
  sessionId: string(),
19715
20385
  sdpAnswer: string()
@@ -21162,6 +21832,24 @@ DeviceType.Camera, method(object({
21162
21832
  deviceId: number(),
21163
21833
  status: OsdStatusSchema
21164
21834
  });
21835
+ var VehicleSchema = object({
21836
+ id: string(),
21837
+ name: string(),
21838
+ sampleCount: number().int().nonnegative(),
21839
+ coverMediaKey: string().optional(),
21840
+ /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaKey`. */
21841
+ coverBase64: string().optional()
21842
+ });
21843
+ var VehicleSampleInfoSchema = object({
21844
+ id: string(),
21845
+ /** The plate text this sample enrolled (self-labeling — no embedding). */
21846
+ text: string(),
21847
+ /** OCR confidence of the enrolled read (0..1). */
21848
+ score: number(),
21849
+ addedAt: number().int(),
21850
+ deviceId: number().int().optional(),
21851
+ base64: string().optional()
21852
+ });
21165
21853
  var PlateInfoSchema = object({
21166
21854
  plateId: string(),
21167
21855
  deviceId: number().int(),
@@ -21173,6 +21861,16 @@ var PlateInfoSchema = object({
21173
21861
  score: number(),
21174
21862
  /** True when the text was manually corrected (exempt from retention). */
21175
21863
  corrected: boolean(),
21864
+ /** Recognized vehicle id when a matcher lookup named this read (SQL NULL → absent). */
21865
+ recognizedVehicleId: string().optional(),
21866
+ /** Resolved vehicle name for `recognizedVehicleId` (UI convenience). */
21867
+ vehicleName: string().optional(),
21868
+ /** True once the read was assigned to a vehicle (enrolled as a sample). */
21869
+ assigned: boolean(),
21870
+ /** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
21871
+ plateBbox: BoundingBoxSchema.optional(),
21872
+ /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
21873
+ keyFrameMediaKey: string().optional(),
21176
21874
  base64: string().optional()
21177
21875
  });
21178
21876
  var MediaFileLiteSchema = object({
@@ -21212,6 +21910,48 @@ method(object({
21212
21910
  }), method(object({ plateId: string() }), _void(), {
21213
21911
  kind: "mutation",
21214
21912
  auth: "admin"
21913
+ }), method(_void(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
21914
+ kind: "mutation",
21915
+ auth: "admin"
21916
+ }), method(object({
21917
+ id: string(),
21918
+ name: string().min(1)
21919
+ }), _void(), {
21920
+ kind: "mutation",
21921
+ auth: "admin"
21922
+ }), method(object({ id: string() }), _void(), {
21923
+ kind: "mutation",
21924
+ auth: "admin"
21925
+ }), method(object({ vehicleId: string() }), array(VehicleSampleInfoSchema).readonly()), method(object({
21926
+ vehicleId: string(),
21927
+ sampleId: string()
21928
+ }), _void(), {
21929
+ kind: "mutation",
21930
+ auth: "admin"
21931
+ }), method(object({
21932
+ plateId: string(),
21933
+ vehicleId: string()
21934
+ }), _void(), {
21935
+ kind: "mutation",
21936
+ auth: "admin"
21937
+ }), method(object({ plateId: string() }), _void(), {
21938
+ kind: "mutation",
21939
+ auth: "admin"
21940
+ }), method(object({
21941
+ plateIds: array(string()).min(1),
21942
+ vehicleId: string()
21943
+ }), object({
21944
+ assigned: number().int(),
21945
+ failed: array(string()).readonly()
21946
+ }), {
21947
+ kind: "mutation",
21948
+ auth: "admin"
21949
+ }), method(object({ plateIds: array(string()).min(1) }), object({
21950
+ unassigned: number().int(),
21951
+ failed: array(string()).readonly()
21952
+ }), {
21953
+ kind: "mutation",
21954
+ auth: "admin"
21215
21955
  });
21216
21956
  var ModelFormatSchema = _enum(MODEL_FORMATS);
21217
21957
  var HwAccelBackendInputSchema = _enum([
@@ -21290,6 +22030,10 @@ var GpuInfoSchema = object({
21290
22030
  memoryMB: number().optional()
21291
22031
  });
21292
22032
  var NpuInfoSchema = object({ type: _enum(["apple-ane", "intel-npu"]) });
22033
+ var CoralInfoSchema = object({
22034
+ type: literal("coral-edgetpu"),
22035
+ bus: string().optional()
22036
+ });
21293
22037
  var HardwareInfoSchema = object({
21294
22038
  platform: HardwarePlatformSchema,
21295
22039
  arch: HardwareArchSchema,
@@ -21298,7 +22042,8 @@ var HardwareInfoSchema = object({
21298
22042
  totalRAM_MB: number(),
21299
22043
  availableRAM_MB: number(),
21300
22044
  gpu: GpuInfoSchema.nullable(),
21301
- npu: NpuInfoSchema.nullable()
22045
+ npu: NpuInfoSchema.nullable(),
22046
+ coral: CoralInfoSchema.nullable().optional()
21302
22047
  });
21303
22048
  var PlatformScoreSchema = object({
21304
22049
  runtime: _enum(["node", "python"]),
@@ -23757,6 +24502,168 @@ Object.freeze({
23757
24502
  addonId: null,
23758
24503
  access: "create"
23759
24504
  },
24505
+ "llm.deleteModel": {
24506
+ capName: "llm",
24507
+ capScope: "system",
24508
+ addonId: null,
24509
+ access: "delete"
24510
+ },
24511
+ "llm.deleteProfile": {
24512
+ capName: "llm",
24513
+ capScope: "system",
24514
+ addonId: null,
24515
+ access: "delete"
24516
+ },
24517
+ "llm.generate": {
24518
+ capName: "llm",
24519
+ capScope: "system",
24520
+ addonId: null,
24521
+ access: "create"
24522
+ },
24523
+ "llm.generateVision": {
24524
+ capName: "llm",
24525
+ capScope: "system",
24526
+ addonId: null,
24527
+ access: "create"
24528
+ },
24529
+ "llm.getDefaults": {
24530
+ capName: "llm",
24531
+ capScope: "system",
24532
+ addonId: null,
24533
+ access: "view"
24534
+ },
24535
+ "llm.getRuntimeStatus": {
24536
+ capName: "llm",
24537
+ capScope: "system",
24538
+ addonId: null,
24539
+ access: "view"
24540
+ },
24541
+ "llm.getUsage": {
24542
+ capName: "llm",
24543
+ capScope: "system",
24544
+ addonId: null,
24545
+ access: "view"
24546
+ },
24547
+ "llm.installModel": {
24548
+ capName: "llm",
24549
+ capScope: "system",
24550
+ addonId: null,
24551
+ access: "create"
24552
+ },
24553
+ "llm.listModelCatalog": {
24554
+ capName: "llm",
24555
+ capScope: "system",
24556
+ addonId: null,
24557
+ access: "view"
24558
+ },
24559
+ "llm.listModels": {
24560
+ capName: "llm",
24561
+ capScope: "system",
24562
+ addonId: null,
24563
+ access: "view"
24564
+ },
24565
+ "llm.listNodeModels": {
24566
+ capName: "llm",
24567
+ capScope: "system",
24568
+ addonId: null,
24569
+ access: "view"
24570
+ },
24571
+ "llm.listProfileKinds": {
24572
+ capName: "llm",
24573
+ capScope: "system",
24574
+ addonId: null,
24575
+ access: "view"
24576
+ },
24577
+ "llm.listProfiles": {
24578
+ capName: "llm",
24579
+ capScope: "system",
24580
+ addonId: null,
24581
+ access: "view"
24582
+ },
24583
+ "llm.listRuntimeNodes": {
24584
+ capName: "llm",
24585
+ capScope: "system",
24586
+ addonId: null,
24587
+ access: "view"
24588
+ },
24589
+ "llm.setDefault": {
24590
+ capName: "llm",
24591
+ capScope: "system",
24592
+ addonId: null,
24593
+ access: "create"
24594
+ },
24595
+ "llm.startRuntime": {
24596
+ capName: "llm",
24597
+ capScope: "system",
24598
+ addonId: null,
24599
+ access: "create"
24600
+ },
24601
+ "llm.stopRuntime": {
24602
+ capName: "llm",
24603
+ capScope: "system",
24604
+ addonId: null,
24605
+ access: "create"
24606
+ },
24607
+ "llm.testProfile": {
24608
+ capName: "llm",
24609
+ capScope: "system",
24610
+ addonId: null,
24611
+ access: "create"
24612
+ },
24613
+ "llm.upsertProfile": {
24614
+ capName: "llm",
24615
+ capScope: "system",
24616
+ addonId: null,
24617
+ access: "create"
24618
+ },
24619
+ "llmRuntime.complete": {
24620
+ capName: "llm-runtime",
24621
+ capScope: "system",
24622
+ addonId: null,
24623
+ access: "create"
24624
+ },
24625
+ "llmRuntime.deleteModel": {
24626
+ capName: "llm-runtime",
24627
+ capScope: "system",
24628
+ addonId: null,
24629
+ access: "delete"
24630
+ },
24631
+ "llmRuntime.ensureStarted": {
24632
+ capName: "llm-runtime",
24633
+ capScope: "system",
24634
+ addonId: null,
24635
+ access: "create"
24636
+ },
24637
+ "llmRuntime.getDiskUsage": {
24638
+ capName: "llm-runtime",
24639
+ capScope: "system",
24640
+ addonId: null,
24641
+ access: "view"
24642
+ },
24643
+ "llmRuntime.installModel": {
24644
+ capName: "llm-runtime",
24645
+ capScope: "system",
24646
+ addonId: null,
24647
+ access: "create"
24648
+ },
24649
+ "llmRuntime.listLocalModels": {
24650
+ capName: "llm-runtime",
24651
+ capScope: "system",
24652
+ addonId: null,
24653
+ access: "view"
24654
+ },
24655
+ "llmRuntime.status": {
24656
+ capName: "llm-runtime",
24657
+ capScope: "system",
24658
+ addonId: null,
24659
+ access: "view"
24660
+ },
24661
+ "llmRuntime.stop": {
24662
+ capName: "llm-runtime",
24663
+ capScope: "system",
24664
+ addonId: null,
24665
+ access: "create"
24666
+ },
23760
24667
  "localNetwork.getAllowedAddresses": {
23761
24668
  capName: "local-network",
23762
24669
  capScope: "system",
@@ -24387,6 +25294,12 @@ Object.freeze({
24387
25294
  addonId: null,
24388
25295
  access: "delete"
24389
25296
  },
25297
+ "pipelineAnalytics.deleteTracks": {
25298
+ capName: "pipeline-analytics",
25299
+ capScope: "device",
25300
+ addonId: null,
25301
+ access: "delete"
25302
+ },
24390
25303
  "pipelineAnalytics.getActiveTracks": {
24391
25304
  capName: "pipeline-analytics",
24392
25305
  capScope: "device",
@@ -24453,12 +25366,24 @@ Object.freeze({
24453
25366
  addonId: null,
24454
25367
  access: "create"
24455
25368
  },
25369
+ "pipelineAnalytics.pruneTracksBefore": {
25370
+ capName: "pipeline-analytics",
25371
+ capScope: "device",
25372
+ addonId: null,
25373
+ access: "create"
25374
+ },
24456
25375
  "pipelineAnalytics.searchObjectEvents": {
24457
25376
  capName: "pipeline-analytics",
24458
25377
  capScope: "device",
24459
25378
  addonId: null,
24460
25379
  access: "view"
24461
25380
  },
25381
+ "pipelineAnalytics.wipeAllAnalytics": {
25382
+ capName: "pipeline-analytics",
25383
+ capScope: "device",
25384
+ addonId: null,
25385
+ access: "delete"
25386
+ },
24462
25387
  "pipelineExecutor.cacheFrameInPool": {
24463
25388
  capName: "pipeline-executor",
24464
25389
  capScope: "system",
@@ -24963,18 +25888,42 @@ Object.freeze({
24963
25888
  addonId: null,
24964
25889
  access: "create"
24965
25890
  },
25891
+ "plateGallery.assignPlate": {
25892
+ capName: "plate-gallery",
25893
+ capScope: "system",
25894
+ addonId: null,
25895
+ access: "create"
25896
+ },
25897
+ "plateGallery.assignPlates": {
25898
+ capName: "plate-gallery",
25899
+ capScope: "system",
25900
+ addonId: null,
25901
+ access: "create"
25902
+ },
24966
25903
  "plateGallery.correctPlateText": {
24967
25904
  capName: "plate-gallery",
24968
25905
  capScope: "system",
24969
25906
  addonId: null,
24970
25907
  access: "create"
24971
25908
  },
25909
+ "plateGallery.createVehicle": {
25910
+ capName: "plate-gallery",
25911
+ capScope: "system",
25912
+ addonId: null,
25913
+ access: "create"
25914
+ },
24972
25915
  "plateGallery.deletePlate": {
24973
25916
  capName: "plate-gallery",
24974
25917
  capScope: "system",
24975
25918
  addonId: null,
24976
25919
  access: "delete"
24977
25920
  },
25921
+ "plateGallery.deleteVehicle": {
25922
+ capName: "plate-gallery",
25923
+ capScope: "system",
25924
+ addonId: null,
25925
+ access: "delete"
25926
+ },
24978
25927
  "plateGallery.getPlateByTrack": {
24979
25928
  capName: "plate-gallery",
24980
25929
  capScope: "system",
@@ -24993,6 +25942,30 @@ Object.freeze({
24993
25942
  addonId: null,
24994
25943
  access: "view"
24995
25944
  },
25945
+ "plateGallery.listVehicles": {
25946
+ capName: "plate-gallery",
25947
+ capScope: "system",
25948
+ addonId: null,
25949
+ access: "view"
25950
+ },
25951
+ "plateGallery.listVehicleSamples": {
25952
+ capName: "plate-gallery",
25953
+ capScope: "system",
25954
+ addonId: null,
25955
+ access: "view"
25956
+ },
25957
+ "plateGallery.removeVehicleSample": {
25958
+ capName: "plate-gallery",
25959
+ capScope: "system",
25960
+ addonId: null,
25961
+ access: "delete"
25962
+ },
25963
+ "plateGallery.renameVehicle": {
25964
+ capName: "plate-gallery",
25965
+ capScope: "system",
25966
+ addonId: null,
25967
+ access: "create"
25968
+ },
24996
25969
  "plateGallery.searchPlates": {
24997
25970
  capName: "plate-gallery",
24998
25971
  capScope: "system",
@@ -25005,6 +25978,18 @@ Object.freeze({
25005
25978
  addonId: null,
25006
25979
  access: "view"
25007
25980
  },
25981
+ "plateGallery.unassignPlate": {
25982
+ capName: "plate-gallery",
25983
+ capScope: "system",
25984
+ addonId: null,
25985
+ access: "create"
25986
+ },
25987
+ "plateGallery.unassignPlates": {
25988
+ capName: "plate-gallery",
25989
+ capScope: "system",
25990
+ addonId: null,
25991
+ access: "create"
25992
+ },
25008
25993
  "platformProbe.getCapabilities": {
25009
25994
  capName: "platform-probe",
25010
25995
  capScope: "system",
@@ -25197,6 +26182,48 @@ Object.freeze({
25197
26182
  addonId: null,
25198
26183
  access: "create"
25199
26184
  },
26185
+ "sceneMonitor.captureReference": {
26186
+ capName: "scene-monitor",
26187
+ capScope: "device",
26188
+ addonId: null,
26189
+ access: "create"
26190
+ },
26191
+ "sceneMonitor.createScene": {
26192
+ capName: "scene-monitor",
26193
+ capScope: "device",
26194
+ addonId: null,
26195
+ access: "create"
26196
+ },
26197
+ "sceneMonitor.deleteReference": {
26198
+ capName: "scene-monitor",
26199
+ capScope: "device",
26200
+ addonId: null,
26201
+ access: "delete"
26202
+ },
26203
+ "sceneMonitor.deleteScene": {
26204
+ capName: "scene-monitor",
26205
+ capScope: "device",
26206
+ addonId: null,
26207
+ access: "delete"
26208
+ },
26209
+ "sceneMonitor.listScenes": {
26210
+ capName: "scene-monitor",
26211
+ capScope: "device",
26212
+ addonId: null,
26213
+ access: "view"
26214
+ },
26215
+ "sceneMonitor.recheckNow": {
26216
+ capName: "scene-monitor",
26217
+ capScope: "device",
26218
+ addonId: null,
26219
+ access: "create"
26220
+ },
26221
+ "sceneMonitor.updateScene": {
26222
+ capName: "scene-monitor",
26223
+ capScope: "device",
26224
+ addonId: null,
26225
+ access: "create"
26226
+ },
25200
26227
  "scriptRunner.run": {
25201
26228
  capName: "script-runner",
25202
26229
  capScope: "device",
@@ -26281,6 +27308,7 @@ Object.freeze({
26281
27308
  Object.freeze({
26282
27309
  "broker": "broker",
26283
27310
  "device-export": "device-export",
27311
+ "llm": "ai",
26284
27312
  "mesh-network": "mesh",
26285
27313
  "mqtt-broker": "broker",
26286
27314
  "network-access": "ingress",
@@ -52223,4 +53251,4 @@ var HomematicProviderAddon = class extends BaseDeviceProvider {
52223
53251
  }
52224
53252
  };
52225
53253
  //#endregion
52226
- export { motionCapability as C, createEvent as D, EventCategory as E, HomematicProviderAddon, object as O, lockControlCapability as S, DeviceType as T, toHomematicOptions as _, decodeClimate as a, coverCapability as b, toHmClimateMode as c, mapHmChannel as d, mapHmDeviceChannels as f, homematicConfigSchema as g, homematicAddonConfigSchema as h, registerTemperatureCap as i, string as k, deriveHmEntitySpecs as l, buildConnectionFormSchema as m, registerHumidityCap as n, decodeCover as o, homematicFacades as p, registerPowerMeterCap as r, decodeLock as s, registerAmbientLightCap as t, inferHmDeviceType as u, BaseDevice as v, switchCapability as w, eventEmitterCapability as x, climateControlCapability as y };
53254
+ export { motionCapability as C, object as D, createEvent as E, HomematicProviderAddon, string as O, lockControlCapability as S, DeviceType as T, toHomematicOptions as _, decodeClimate as a, coverCapability as b, toHmClimateMode as c, mapHmChannel as d, mapHmDeviceChannels as f, homematicConfigSchema as g, homematicAddonConfigSchema as h, registerTemperatureCap as i, EventCategory as k, deriveHmEntitySpecs as l, buildConnectionFormSchema as m, registerHumidityCap as n, decodeCover as o, homematicFacades as p, registerPowerMeterCap as r, decodeLock as s, registerAmbientLightCap as t, inferHmDeviceType as u, BaseDevice as v, switchCapability as w, eventEmitterCapability as x, climateControlCapability as y };