@camstack/types 0.1.15 → 0.1.16
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/auth-records-BDg37fy9.mjs +8297 -0
- package/dist/auth-records-BDg37fy9.mjs.map +1 -0
- package/dist/auth-records-D5ZNaUos.js +8296 -0
- package/dist/auth-records-D5ZNaUos.js.map +1 -0
- package/dist/capabilities/addons.cap.d.ts +76 -0
- package/dist/capabilities/addons.cap.d.ts.map +1 -1
- package/dist/capabilities/alerts.cap.d.ts +5 -5
- package/dist/capabilities/authentication.cap.d.ts +83 -0
- package/dist/capabilities/authentication.cap.d.ts.map +1 -0
- package/dist/capabilities/backup.cap.d.ts +224 -3
- package/dist/capabilities/backup.cap.d.ts.map +1 -1
- package/dist/capabilities/index.d.ts +16 -2
- package/dist/capabilities/index.d.ts.map +1 -1
- package/dist/capabilities/local-network.cap.d.ts +216 -0
- package/dist/capabilities/local-network.cap.d.ts.map +1 -0
- package/dist/capabilities/mesh-network.cap.d.ts +160 -0
- package/dist/capabilities/mesh-network.cap.d.ts.map +1 -0
- package/dist/capabilities/mesh-orchestrator.cap.d.ts +96 -0
- package/dist/capabilities/mesh-orchestrator.cap.d.ts.map +1 -0
- package/dist/capabilities/platform-probe.cap.d.ts.map +1 -1
- package/dist/capabilities/remote-access.cap.d.ts +103 -0
- package/dist/capabilities/remote-access.cap.d.ts.map +1 -0
- package/dist/capabilities/storage-provider.cap.d.ts +432 -0
- package/dist/capabilities/storage-provider.cap.d.ts.map +1 -0
- package/dist/capabilities/storage.cap.d.ts +287 -24
- package/dist/capabilities/storage.cap.d.ts.map +1 -1
- package/dist/capabilities/turn-orchestrator.cap.d.ts +74 -0
- package/dist/capabilities/turn-orchestrator.cap.d.ts.map +1 -0
- package/dist/device/base-device-provider.d.ts +8 -0
- package/dist/device/base-device-provider.d.ts.map +1 -1
- package/dist/disposer-chain.d.ts +32 -0
- package/dist/disposer-chain.d.ts.map +1 -0
- package/dist/enums/event-category.d.ts +34 -0
- package/dist/enums/event-category.d.ts.map +1 -1
- package/dist/generated/addon-api.d.ts +1433 -245
- package/dist/generated/addon-api.d.ts.map +1 -1
- package/dist/generated/capability-router-map.d.ts +25 -4
- package/dist/generated/capability-router-map.d.ts.map +1 -1
- package/dist/generated/system-proxy.d.ts +15 -3
- package/dist/generated/system-proxy.d.ts.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +805 -8331
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +607 -7715
- package/dist/index.mjs.map +1 -1
- package/dist/interfaces/addon.d.ts +82 -0
- package/dist/interfaces/addon.d.ts.map +1 -1
- package/dist/interfaces/api-responses.d.ts +7 -0
- package/dist/interfaces/api-responses.d.ts.map +1 -1
- package/dist/interfaces/capability.d.ts +13 -2
- package/dist/interfaces/capability.d.ts.map +1 -1
- package/dist/interfaces/config-ui.d.ts +140 -3
- package/dist/interfaces/config-ui.d.ts.map +1 -1
- package/dist/interfaces/storage-location.d.ts +120 -0
- package/dist/interfaces/storage-location.d.ts.map +1 -0
- package/dist/interfaces/storage.d.ts +2 -6
- package/dist/interfaces/storage.d.ts.map +1 -1
- package/dist/node.js +141 -7243
- package/dist/node.js.map +1 -1
- package/dist/node.mjs +59 -7150
- package/dist/node.mjs.map +1 -1
- package/dist/storage/filesystem-storage-provider.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/types/models.ts","../src/interfaces/addon.ts","../src/enums/event-category.ts","../src/interfaces/config-ui.ts","../src/interfaces/event-bus.ts","../src/addon/base-addon.ts","../src/readiness/readiness-registry.ts","../src/interfaces/device-capabilities/camera.ts","../src/interfaces/feature-flags.ts","../src/interfaces/server-analysis.ts","../src/interfaces/stream-broker.ts","../src/interfaces/analysis-persistence.ts","../src/enums/event-source-type.ts","../src/constants.ts","../src/utils/json-safe.ts","../src/utils/hf-url.ts","../src/utils/cosine-similarity.ts","../src/utils/element-config-store.ts","../src/utils/runtime-mapping.ts","../src/utils/err-msg.ts","../src/utils/run-inference-step.ts","../src/catalogs/coco-classmap.ts","../src/catalogs/audio-classmap.ts","../src/types/device-type.ts","../src/device/device-type.ts","../src/device/accessory.ts","../src/device/device-profile.ts","../src/device/device-config.ts","../src/device/device-runtime-state.ts","../src/device/runtime-state-helpers.ts","../src/capabilities/device-status.cap.ts","../src/capabilities/feature-probe.cap.ts","../src/capabilities/audio-metrics.cap.ts","../src/capabilities/capability-definition.ts","../src/capabilities/battery.cap.ts","../src/capabilities/brightness.cap.ts","../src/capabilities/camera-streams.cap.ts","../src/capabilities/schemas/streaming-shared.ts","../src/capabilities/stream-broker.cap.ts","../src/capabilities/streaming-engine.cap.ts","../src/capabilities/device-discovery.cap.ts","../src/capabilities/doorbell.cap.ts","../src/capabilities/motion.cap.ts","../src/capabilities/motion-detection.cap.ts","../src/capabilities/schemas/detection-shared.ts","../src/capabilities/pipeline-runner.cap.ts","../src/capabilities/schemas/orchestrator-metrics.ts","../src/capabilities/pipeline-executor.cap.ts","../src/capabilities/zones.cap.ts","../src/capabilities/motion-trigger.cap.ts","../src/capabilities/ptz-autotrack.cap.ts","../src/capabilities/switch.cap.ts","../src/capabilities/zone-analytics.cap.ts","../src/capabilities/zone-rules.cap.ts","../src/capabilities/schemas/zone-rule.ts","../src/generated/device-local-state.ts","../src/device/base-device.ts","../src/capabilities/device-provider.cap.ts","../src/device/base-device-provider.ts","../src/device/zod-to-config-ui.ts","../src/device/device-state-handle.ts","../src/generated/device-proxy.ts","../src/utils/zone-rule-eval.ts","../src/generated/system-proxy.ts","../src/device/system-mirror.ts","../src/capabilities/custom-actions.ts","../src/capabilities/addon-settings.cap.ts","../src/capabilities/alerts.cap.ts","../src/capabilities/storage.cap.ts","../src/capabilities/backup.cap.ts","../src/capabilities/settings-store.cap.ts","../src/capabilities/log-destination.cap.ts","../src/capabilities/admin-ui.cap.ts","../src/capabilities/addon-pages.cap.ts","../src/capabilities/addon-pages-source.cap.ts","../src/capabilities/addon-widgets.cap.ts","../src/capabilities/addon-widgets-source.cap.ts","../src/capabilities/addon-routes.cap.ts","../src/capabilities/decoder.cap.ts","../src/capabilities/restreamer.cap.ts","../src/capabilities/webrtc.cap.ts","../src/capabilities/webrtc-session.cap.ts","../src/capabilities/pipeline-orchestrator.cap.ts","../src/capabilities/audio-analyzer.cap.ts","../src/capabilities/audio-analysis.cap.ts","../src/capabilities/audio-codec.cap.ts","../src/capabilities/embedding-encoder.cap.ts","../src/capabilities/device-manager.cap.ts","../src/capabilities/device-state.cap.ts","../src/capabilities/auth-provider.cap.ts","../src/capabilities/network-access.cap.ts","../src/capabilities/turn-provider.cap.ts","../src/capabilities/snapshot.cap.ts","../src/capabilities/snapshot-provider.cap.ts","../src/capabilities/notification-output.cap.ts","../src/capabilities/advanced-notifier.cap.ts","../src/capabilities/recording-engine.cap.ts","../src/capabilities/detection-pipeline.cap.ts","../src/capabilities/pipeline-analytics.cap.ts","../src/capabilities/metrics-provider.cap.ts","../src/capabilities/ptz.cap.ts","../src/capabilities/events.cap.ts","../src/capabilities/recording.cap.ts","../src/capabilities/device-ops.cap.ts","../src/capabilities/camera-credentials.cap.ts","../src/capabilities/reboot.cap.ts","../src/capabilities/osd.cap.ts","../src/capabilities/accessories.cap.ts","../src/capabilities/intercom.cap.ts","../src/capabilities/native-object-detection.cap.ts","../src/capabilities/platform-probe.cap.ts","../src/capabilities/user-management.cap.ts","../src/capabilities/system.cap.ts","../src/capabilities/network-quality.cap.ts","../src/capabilities/toast.cap.ts","../src/capabilities/nodes.cap.ts","../src/capabilities/integrations.cap.ts","../src/capabilities/addons.cap.ts","../src/capabilities/index.ts","../src/generated/capability-router-map.ts","../src/generated/cap-status-types.ts","../src/schemas/auth-records.ts","../src/utils/mask-url.ts","../src/utils/ring-buffer.ts","../src/helpers/bind-addon-actions.ts"],"sourcesContent":["export * from './types/io.js'\nexport * from './types/labels.js'\nexport * from './types/detection.js'\nexport * from './types/tracked.js'\nexport * from './types/events.js'\nexport * from './types/config.js'\nexport * from './types/entities.js'\nexport * from './types/models.js'\nexport type { EngineOutput, LetterboxMeta, ModelInputMeta } from './types/engine-output.js'\nexport * from './types/pipeline.js'\nexport * from './types/pipeline-step.js'\n// `PipelineTemplate` collides with the legacy detection-pipeline type on\n// line 24 below (removed in Phase 4). Until then, expose the new shape\n// under an alias so both can coexist.\nexport type {\n CameraPipelineConfig,\n PipelineTemplate as CameraPipelineTemplate,\n} from './types/camera-pipeline.js'\nexport type {\n AgentAddonConfig,\n AgentPipelineSettings,\n CameraPipelineSettings,\n CameraStepOverridePatch,\n} from './types/agent-pipeline-settings.js'\nexport * from './types/live-state.js'\nexport * from './types/analytics.js'\nexport type {\n PipelineAddonSchema,\n PipelineModelOption,\n PipelineSlotSchema,\n PipelineSchema,\n AvailableEngine,\n PipelineDefaultStep,\n PipelineTemplateStep,\n PipelineTemplate,\n TemplateValidationResult,\n} from './types/pipeline-schema.js'\n\n// --- Core interfaces (used by addons and server) ---\nexport type * from './interfaces/addon.js'\nexport {\n isDeployableToAgent,\n isAgentOnlyPlacement,\n resolveAddonExecution,\n resolveAddonGroup,\n resolveAddonPlacement,\n DEFAULT_ADDON_GROUP,\n DEFAULT_ADDON_PLACEMENT,\n} from './interfaces/addon.js'\nexport { BaseAddon, normalizeAddonInitResult } from './addon/base-addon.js'\nexport type { CapabilitiesAccess } from './addon/base-addon.js'\nexport type * from './interfaces/capability.js'\nexport type * from './interfaces/config-ui.js'\nexport { WELL_KNOWN_TABS, WELL_KNOWN_TAB_MAP, hydrateSchema } from './interfaces/config-ui.js'\n// Cleanup: `addon-settings-resolver.js` deleted. The helpers it\n// exported (`iterateConfigFields`, `extractSchemaDefaults`,\n// `getDeviceScopedFieldKeys`, `resolveAddonSettings`,\n// `filterDeviceScoped`) only existed to back the legacy merging\n// `getGlobal / getDevice / updateGlobal / updateDevice` quartet on\n// `SettingsResolverService`, which was itself deleted after every\n// addon migrated to the raw three-level store API.\nexport type * from './interfaces/pipeline-slot.js'\nexport type * from './interfaces/engine-slots.js'\nexport type * from './interfaces/detection-addon.js'\nexport type * from './interfaces/inference-engine.js'\nexport type * from './interfaces/audio-inference-engine.js'\nexport type { IAudioAnalyzer, AudioClassificationResult } from './interfaces/audio-analyzer.js'\nexport type * from './interfaces/raw-tensor-engine.js'\nexport type * from './interfaces/inference-capabilities.js'\nexport type * from './interfaces/analysis.js'\nexport type * from './interfaces/advanced-notifier.js'\nexport type * from './interfaces/python-env.js'\nexport type * from './interfaces/network.js'\nexport type * from './interfaces/router.js'\nexport type * from './interfaces/logging.js'\nexport type * from './interfaces/event-bus.js'\nexport { createEvent, isEvent, emitReadiness } from './interfaces/event-bus.js'\nexport type * from './interfaces/readiness.js'\n\n// Readiness protocol — cross-process capability lifecycle tracker.\n// Spec: docs/superpowers/specs/2026-04-19-system-readiness-design.md\nexport {\n ReadinessRegistry,\n ReadinessTimeoutError,\n readinessKey,\n scopeKey,\n emitDownForOwnedCaps,\n} from './readiness/index.js'\nexport type {\n ReadinessHandler,\n ReadinessTransition,\n AwaitReadyOptions,\n ReadinessRegistryOptions,\n} from './readiness/index.js'\nexport type * from './interfaces/pipeline-runner.js'\nexport type * from './interfaces/pipeline-executor-capability.js'\nexport type * from './interfaces/pipeline-orchestrator-capability.js'\nexport type * from './interfaces/pipeline-runner-capability.js'\nexport type * from './interfaces/embedding-encoder.js'\nexport type * from './interfaces/auth-provider.js'\nexport type * from './interfaces/notification.js'\nexport type * from './interfaces/addon-routes.js'\nexport type * from './interfaces/scoped-token.js'\nexport type * from './interfaces/task-handler.js'\n\n// --- Server interfaces (consolidated from server/backend/src/interfaces/) ---\nexport type * from './interfaces/storage.js'\nexport type * from './interfaces/context.js'\nexport type { DeviceState, DeviceMetadata, DeviceEvent } from './interfaces/device.js'\nexport type { ProviderStatus, LiveEvent, IDeviceProvider } from './interfaces/device-provider.js'\nexport type * from './interfaces/device-capabilities/index.js'\nexport { classifyStream, classifyStreams, streamPixels, toStreamSourceEntry, parseCameraStreamConfig, autoAssignProfiles } from './interfaces/device-capabilities/camera.js'\nexport type * from './interfaces/streaming.js'\nexport type * from './interfaces/auth.js'\nexport type * from './interfaces/lifecycle.js'\nexport type * from './interfaces/server-network.js'\nexport type * from './interfaces/process.js'\nexport * from './interfaces/feature-flags.js'\nexport type * from './interfaces/agent.js'\nexport type * from './interfaces/agent-protocol.js'\nexport * from './interfaces/agent-protocol.js'\nexport type * from './interfaces/camera-pipeline.js'\nexport type * from './interfaces/server-analysis.js'\nexport * from './interfaces/server-analysis.js'\nexport * from './interfaces/stream-broker.js'\nexport * from './interfaces/analysis-persistence.js'\nexport type * from './interfaces/restreamer.js'\nexport type * from './interfaces/decoder.js'\nexport type * from './interfaces/ffmpeg.js'\nexport type * from './interfaces/network-quality.js'\nexport type * from './interfaces/webrtc-provider.js'\nexport type * from './interfaces/repl.js'\nexport type * from './interfaces/platform.js'\nexport type {\n Integration,\n PersistedDevice,\n TypedSetting,\n CreateIntegrationInput,\n CreateDeviceInput,\n DeviceIdentity,\n IIntegrationRegistry,\n} from './interfaces/integration-registry.js'\nexport type * from './interfaces/api-shared.js'\nexport type * from './interfaces/api-responses.js'\nexport type * from './interfaces/metrics-provider.js'\nexport type * from './interfaces/kernel-abstractions.js'\nexport type * from './interfaces/alerts.js'\nexport type * from './interfaces/queryable.js'\n\n// Phase 11 (settings redesign): `schemas/system-settings-schemas.ts`\n// deleted. Hub yml sections migrated to the `system-config` built-in\n// addon's `getGlobalSettings()` method.\n\n// Enums\nexport * from './enums/index.js'\n\n// Constants\nexport * from './constants.js'\n\n// Utils\nexport {\n parseJsonUnknown,\n parseJsonObject,\n parseJsonArray,\n asJsonObject,\n asJsonArray,\n asString,\n asNumber,\n asBoolean,\n} from './utils/json-safe.js'\nexport { hfModelUrl } from './utils/hf-url.js'\nexport { cosineSimilarity } from './utils/cosine-similarity.js'\nexport { ElementConfigStore } from './utils/element-config-store.js'\nexport {\n resolveDetectionRuntime,\n resolveModelFormat,\n resolveAddonRuntime,\n formatForBackend,\n formatForRuntime,\n pythonScriptForBackend,\n requiresPython,\n BACKEND_TO_FORMAT,\n RUNTIME_TO_FORMAT,\n PYTHON_SCRIPT,\n} from './utils/runtime-mapping.js'\nexport type { PipelineRuntime } from './utils/runtime-mapping.js'\nexport { runInferenceStep } from './utils/run-inference-step.js'\nexport type { InferenceStepResult } from './utils/run-inference-step.js'\n\n// Catalogs (coco-classmap stays in types — used by object-detection addon and other consumers)\nexport {\n COCO_80_LABELS,\n COCO_TO_MACRO,\n MACRO_LABELS,\n} from './catalogs/coco-classmap.js'\n\nexport {\n AUDIO_MACRO_LABELS,\n YAMNET_TO_MACRO,\n APPLE_SA_TO_MACRO,\n mapAudioLabelToMacro,\n getAudioMacroClassIds,\n} from './catalogs/audio-classmap.js'\n\nexport type {\n CameraMotionConfig,\n CameraNativeDetectionConfig,\n CameraDetectionCapabilities,\n} from './types/camera-detection.js'\n\nexport { type DeviceTypeInfo, DEVICE_TYPE_INFO } from './types/device-type.js'\nexport type { DeviceBinding, DeviceBindingEntry } from './device/device-binding.js'\n\n// ── Device architecture ──────────────────────────────────────────────\n// DeviceType (enum), DeviceFeature, ChargingStatus, DeviceRole\nexport { DeviceType, DeviceFeature, ChargingStatus, DeviceRole } from './device/device-type.js'\n// Accessory child helpers (kind alias + label map + stableId).\nexport {\n AccessoryKind, ACCESSORY_LABEL, accessoryStableId,\n} from './device/accessory.js'\n// Device profiles — declarative defaults applied to feature-matched devices.\nexport {\n DEVICE_PROFILES, BATTERY_DEVICE_PROFILE, deviceMatchesProfile, resolveDeviceProfile,\n} from './device/device-profile.js'\nexport type {\n DeviceProfile, DeviceProfileMatch, DeviceProfileDefaults,\n PipelinePhaseMode,\n} from './device/device-profile.js'\nexport type { AccessoryKindValue } from './device/accessory.js'\n// Device config + base class\nexport { DeviceConfig } from './device/device-config.js'\nexport { DeviceRuntimeState } from './device/device-runtime-state.js'\nexport type { IDeviceRuntimeState } from './device/device-runtime-state.js'\nexport { createRuntimeStateBridge } from './device/runtime-state-helpers.js'\nexport type { RuntimeStateBridge } from './device/runtime-state-helpers.js'\nexport { BaseDevice } from './device/base-device.js'\nexport type { AccessoryChildSpec } from './device/base-device.js'\nexport { BaseDeviceProvider, toDeviceSummary } from './device/base-device-provider.js'\nexport type { DiscoveryCandidate, DeviceSummary, FieldProbeResult } from './device/base-device-provider.js'\n// Device context\nexport type { DeviceContext, DeviceManagerApi, DeviceConstructor, IDeviceRegistryReader, IDeviceRegistry } from './device/device-context.js'\n// Device interface (canonical — new architecture)\nexport type { IDevice } from './device/device.js'\n// Device feature interfaces\nexport type { IBatteryOperated, IRebootable, INativeSnapshot, IDoorbellButton, ITwoWayAudio, IPanTiltZoom } from './device/features.js'\n// Camera device interface + stream sources\nexport type { ICameraDevice, StreamSourceEntry } from './device/camera-device.js'\nexport type { StreamQuality } from './interfaces/device-capabilities/camera.js'\nexport { STREAM_QUALITY_LABELS, streamQualityLabel } from './interfaces/device-capabilities/camera.js'\n\n// Audio codec session types\nexport type {\n AudioCodecInfo,\n AudioDecodeSessionConfig,\n AudioEncodeSessionConfig,\n AudioPcmChunk,\n AudioEncodedChunk,\n PcmSampleFormat,\n} from './interfaces/audio-codec.js'\n// Device management\nexport type { DeviceManualCreation, DeviceDiscovery, DiscoveredDevice, SavedDevice, DeviceMeta, InitialDeviceMeta, CreateDeviceSpec } from './device/device-management.js'\n// Zod → ConfigUISchema converter\nexport { zodEntriesToConfigUI } from './device/zod-to-config-ui.js'\nexport type { DeviceConfigEntry } from './device/zod-to-config-ui.js'\n\n// Enums\nexport { EventCategory } from './enums/event-category.js'\n\nexport type { AppRouter, AddonApi } from './generated/addon-api.js'\nexport { createDeviceProxy } from './generated/device-proxy.js'\nexport { evaluateZoneRules, type ZoneRuleEvalResult } from './utils/zone-rule-eval.js'\nexport type { DeviceProxy } from './generated/device-proxy.js'\nexport { createSystemProxy } from './generated/system-proxy.js'\nexport type { SystemProxy } from './generated/system-proxy.js'\nexport { SystemMirror } from './device/system-mirror.js'\nexport type {\n SystemMirrorApi,\n SystemMirrorListener,\n DeviceCapListener,\n DeviceLifecycleListener,\n DeviceQueryFilters,\n StringMatch,\n} from './device/system-mirror.js'\nexport {\n createSliceHandle,\n createLazyTrpcSource,\n createMirrorSource,\n} from './device/device-state-handle.js'\nexport type {\n SliceHandle,\n SliceHandleApi,\n SliceHandleSource,\n} from './device/device-state-handle.js'\n\n// ── Capability definitions (Zod-schema-first) ──────────────────\nexport * from './capabilities/index.js'\n\n// ── Generated capability router map (codegen) ────────────────────────\nexport { CAPABILITY_NAMES, CAPABILITY_ROUTER_KEYS, ALL_CAPABILITY_DEFINITIONS } from './generated/capability-router-map.js'\nexport type { CapabilityName, CapabilityRouterMap } from './generated/capability-router-map.js'\n\n// ── Generated capability status map (codegen) ────────────────────────\nexport { CAP_NAMES_WITH_STATUS } from './generated/cap-status-types.js'\nexport type { CapNameWithStatus, CapStatusTypeMap } from './generated/cap-status-types.js'\n\n// Persisted record schemas (Zod-first — source of truth for persisted types)\nexport {\n UserRecordSchema, ApiKeyRecordSchema, ScopedTokenSchema, TokenScopeSchema, UserRoleSchema,\n type UserRecord, type ApiKeyRecord, type ScopedToken, type TokenScope, type UserRole,\n} from './schemas/auth-records.js'\n\nexport { errMsg } from './utils/err-msg.js'\nexport { maskUrlCredentials } from './utils/mask-url.js'\nexport { RingBuffer } from './utils/ring-buffer.js'\n\n// Client-side helpers\nexport { bindAddonActions } from './helpers/bind-addon-actions.js'\n\n// Node-only infrastructure utilities are exposed on the\n// `@camstack/types/node` sub-entry, NOT here. Keeping `node:fs` / `node:path`\n// imports out of the root entry is what lets the browser-side widget\n// bundlers (Vite + rollup) consume `@camstack/types` without choking on\n// `__vite-browser-external` placeholders.\n","import type { LabelDefinition, ClassMapDefinition } from './labels.js'\n\nexport const MODEL_FORMATS = ['onnx', 'coreml', 'openvino', 'tflite', 'pt'] as const\nexport type ModelFormat = (typeof MODEL_FORMATS)[number]\nexport type ModelOutputFormat = 'yolo' | 'ssd' | 'embedding' | 'classification' | 'ocr' | 'segmentation'\n\nexport interface ModelFormatEntry {\n readonly url: string\n readonly sizeMB: number\n /** Whether this format is a directory bundle (e.g., .mlpackage) rather than a single file */\n readonly isDirectory?: boolean\n /**\n * For directory formats: list of files relative to the directory root.\n * The downloader fetches each file from `{url}/{file}` and saves to `{modelDir}/{file}`.\n * If omitted for a directory format, the downloader probes HuggingFace API (slower).\n */\n readonly files?: readonly string[]\n /** Runtime(s) that can use this format. If omitted, inferred from ModelFormat key */\n readonly runtimes?: readonly ('node' | 'python')[]\n}\n\n/**\n * Extra file that must be downloaded alongside the model (e.g., labels JSON, dict.txt).\n * The downloader fetches from `url` and saves to `{modelsDir}/{filename}`.\n */\nexport interface ModelExtraFile {\n readonly url: string\n readonly filename: string\n readonly sizeMB: number\n}\n\nexport interface ModelCatalogEntry {\n readonly id: string\n readonly name: string\n readonly description: string\n readonly formats: Partial<Readonly<Record<ModelFormat, ModelFormatEntry>>>\n readonly inputSize: { readonly width: number; readonly height: number }\n readonly labels: readonly LabelDefinition[]\n readonly inputLayout?: 'nchw' | 'nhwc'\n readonly inputNormalization?: 'zero-one' | 'imagenet' | 'none'\n readonly preprocessMode?: 'letterbox' | 'resize'\n /**\n * Auxiliary files required at runtime (labels JSON, charset dict, etc.).\n * Downloaded into the same modelsDir alongside the model file.\n */\n readonly extraFiles?: readonly ModelExtraFile[]\n}\n\nexport interface DetectionModel {\n readonly id: string\n readonly name: string\n readonly labels: readonly string[]\n readonly inputSize: { readonly width: number; readonly height: number }\n}\n\nexport interface ModelDownloadOptions {\n readonly url: string\n readonly fallbackUrls?: readonly string[]\n readonly destDir: string\n readonly filename?: string\n readonly expectedSha256?: string\n readonly onProgress?: (downloaded: number, total: number) => void\n}\n\nexport interface ModelDownloadResult {\n readonly filePath: string\n readonly downloadedBytes: number\n readonly fromCache: boolean\n}\n\nexport interface CustomModelMetadata {\n readonly name: string\n readonly inputSize: { readonly width: number; readonly height: number }\n readonly labels: readonly LabelDefinition[]\n readonly classMap?: ClassMapDefinition\n readonly inputLayout?: 'nchw' | 'nhwc'\n readonly inputNormalization?: 'zero-one' | 'imagenet' | 'none'\n readonly outputFormat: ModelOutputFormat\n}\n","import type { PipelineSlot } from '../types/pipeline.js'\nimport type { ConfigUISchemaWithValues, FieldProbeResult } from './config-ui.js'\nimport type { IScopedLogger } from './logging.js'\nimport type { IEventBus, ReadinessScope } from './event-bus.js'\nimport type { ICapabilityHandle } from './readiness.js'\nimport type { CapabilityDeclaration } from './capability.js'\nimport type { ICapabilityRegistry } from './kernel-abstractions.js'\nimport type { CapabilityDefinition, InferProvider } from '../capabilities/capability-definition.js'\nimport type { CustomActionsSpec } from '../capabilities/custom-actions.js'\nimport type { z } from 'zod'\n/** Sub-process info (inlined from deleted worker-protocol.ts) */\nexport interface SubProcessInfo {\n readonly pid: number\n readonly name: string\n readonly command: string\n readonly state: 'running' | 'stopped' | 'crashed'\n readonly cpuPercent: number\n readonly memoryRss: number\n readonly uptimeSeconds: number\n}\n\n/** Worker process stats (inlined from deleted worker-protocol.ts) */\nexport interface WorkerProcessStats {\n readonly pid: number\n readonly cpuPercent: number\n readonly memoryRss: number\n readonly heapUsed?: number\n readonly uptimeSeconds: number\n readonly restartCount: number\n readonly state: 'starting' | 'running' | 'stopping' | 'stopped' | 'crashed'\n}\n\n/** Storage interface for addon file operations */\nexport interface IAddonFileStorage {\n readFile(path: string): Promise<Buffer>\n writeFile(path: string, data: Buffer): Promise<void>\n deleteFile(path: string): Promise<void>\n listFiles(prefix?: string): Promise<readonly string[]>\n exists(path: string): Promise<boolean>\n}\n\nexport interface RequiredStep {\n readonly slot: PipelineSlot\n readonly outputClasses: readonly string[]\n readonly description: string\n}\n\n/**\n * Minimal model-management API exposed to addons via AddonContext.\n */\nexport interface IAddonModelManager {\n /** Ensure a model is downloaded. Returns the local file path. */\n ensure(modelId: string, format?: import('../types/models.js').ModelFormat): Promise<string>\n\n /** Ensure extra files for a model are downloaded. Returns paths. */\n ensureExtraFiles(modelId: string): Promise<readonly string[]>\n\n /** Absolute path to the shared models directory. */\n getModelsDir(): string\n\n /** Check if a model is already downloaded. */\n isDownloaded(modelId: string, format?: import('../types/models.js').ModelFormat): boolean\n\n}\n\n/** Process management for addon sub-processes (ffmpeg, python, etc.) */\nexport interface IAddonProcessManager {\n /** Spawn a child process managed by this addon's worker */\n spawn(config: SubProcessConfig): Promise<IManagedSubProcess>\n /** List all sub-processes spawned by this addon */\n listProcesses(): readonly SubProcessInfo[]\n /** Get worker stats (this addon's worker process) */\n getWorkerStats(): WorkerProcessStats\n}\n\nexport interface SubProcessConfig {\n readonly name: string\n readonly command: string\n readonly args?: readonly string[]\n readonly cwd?: string\n readonly env?: Readonly<Record<string, string>>\n readonly autoRestart?: boolean\n readonly maxRestarts?: number\n}\n\nexport interface IManagedSubProcess {\n readonly pid: number\n readonly name: string\n getStats(): WorkerProcessStats\n write(data: Buffer): void\n readonly stdout: AsyncIterable<Buffer>\n readonly stderr: AsyncIterable<Buffer>\n kill(signal?: NodeJS.Signals): void\n wait(): Promise<{ code: number | null; signal: string | null }>\n onExit(handler: (code: number | null) => void): void\n onError(handler: (error: Error) => void): void\n}\n\n/** Dependency manager — ensures binaries/tools are available for addons */\nexport interface IAddonDepsManager {\n /** Ensure a named binary is available (check local -> PATH -> download) */\n ensureBinary(opts: {\n readonly name: string\n readonly downloadUrl: string\n readonly isArchive?: boolean\n readonly archiveFormat?: 'zip' | 'tar.gz' | 'tar.xz'\n readonly archiveInnerPath?: string\n }): Promise<string>\n\n /** Ensure ffmpeg is available */\n ensureFfmpeg(): Promise<string>\n\n /** Ensure Python is available, returns path or null if unavailable */\n ensurePython(): Promise<string | null>\n\n /** Install Python packages in the managed Python environment */\n installPythonPackages(packages: readonly string[]): Promise<void>\n\n /**\n * Install a pip requirements file into the embedded Python.\n * Idempotent: keyed on (file basename + sha256 of contents). Marker\n * lives under the python install dir so re-downloading python wipes\n * everything together.\n */\n installPythonRequirements(requirementsFile: string): Promise<void>\n\n /** Get the deps directory path */\n getDepsDir(): string\n}\n\n/**\n * AddonContext -- injected into every addon at initialize().\n *\n * The context includes both the CamstackContext fields (id, logger, eventBus, storage, config)\n * and addon-specific extras (addonConfig, models, locationPaths, router, network).\n */\n/**\n * AddonContext -- injected into every addon at initialize().\n *\n * The `api` field is typed as `AddonApi` — a generated interface that\n * mirrors the server's tRPC router namespaces. This gives addons type-safe\n * access to server procedures without depending on the server package.\n *\n * To regenerate after changing routers: npx tsx scripts/generate-api-types.ts\n */\n// ── Provider registration (return from initialize) ──────────────────────\n/**\n * A capability provider binding returned from `ICamstackAddon.initialize()`.\n * The kernel registers each entry in the CapabilityRegistry after init completes.\n */\nexport interface ProviderRegistration<TCap extends CapabilityDefinition = CapabilityDefinition> {\n /** Capability definition this provider implements. Read `capability.name` to look up by name. */\n readonly capability: TCap\n /**\n * The provider object implementing the capability interface.\n *\n * - With a specific `TCap` (e.g. `ProviderRegistration<typeof metricsProviderCapability>`)\n * the provider is strictly checked against `InferProvider<TCap>`.\n * - With the default `TCap = CapabilityDefinition` (used by heterogeneous arrays like\n * `ProviderRegistration[]` returned from `onInitialize()`) the provider is typed as\n * `object`: a mapped type over the default `Record<string, CapabilityMethodSchema>`\n * collapses to an index signature that class instances cannot satisfy structurally.\n * The runtime capability router enforces the contract; the strict compile-time check\n * is applied at the specific-cap boundary (ProviderRegistration<typeof xxxCap>) instead.\n */\n readonly provider: CapabilityDefinition extends TCap ? object : InferProvider<TCap>\n /** 'native' (default) — absolute provider.\n * 'wrapper' — user-toggleable decorator that delegates to a native via `ctx.getNativeProvider`. */\n readonly kind?: 'native' | 'wrapper'\n /** Wrapper only — active by default for every compatible device. */\n readonly defaultActive?: boolean\n}\n\n/**\n * Return value of `ICamstackAddon.initialize()`. Both sections are optional —\n * addons that provide only capabilities omit `customActions`; addons that only\n * expose actions omit `providers`; pure consumers may return void.\n */\nexport interface AddonInitResult<TCatalog extends CustomActionsSpec = CustomActionsSpec> {\n readonly providers?: readonly ProviderRegistration[]\n readonly customActions?: TCatalog\n /**\n * Required iff `customActions` is set. One async handler per catalog entry —\n * a typed dispatch map rather than a single generic function so that each\n * handler's input/output types collapse to the concrete `z.infer<...>` of\n * its schema at the provider site (TypeScript cannot unify the output of a\n * generic `<K>(action: K, input) => Promise<...>` signature with a concrete\n * per-action return type, so the map form is strictly more typeable).\n */\n readonly actionHandlers?: {\n readonly [K in keyof TCatalog & string]: (\n input: z.infer<TCatalog[K]['input']>,\n ) => Promise<z.infer<TCatalog[K]['output']>>\n }\n}\n\n// ── Kernel services ─────────────────────────────────────────────────────\n/**\n * Infrastructure services injected by the kernel at boot time.\n * Grouped under `ctx.kernel` to separate kernel plumbing from\n * addon-level concerns (logger, settings, devices, api).\n */\nexport interface IKernelServices {\n /**\n * The Moleculer nodeID for this process (e.g. `'hub'` on the hub, or the\n * agent's own name on remote nodes). Addons use this to distinguish local\n * dispatch from remote dispatch without a direct Moleculer dependency.\n */\n readonly localNodeId?: string\n\n /**\n * Local storage provider — direct filesystem access with zero serialization.\n * Use for file I/O (write/read with Buffer data) that can't go through tRPC.\n * Always co-located: storage is a kernel-level service injected at boot.\n */\n readonly storage?: import('./storage.js').IStorageProvider\n\n /**\n * Per-process system-readiness tracker. One `ReadinessRegistry` is\n * created per broker by the kernel at boot and shared across every\n * addon on that broker — consumers that need `awaitReady` /\n * `onReadyState` should use this singleton rather than constructing\n * their own so subscriptions on the event bus stay de-duplicated and\n * the snapshot is consistent across the process.\n *\n * Tests that run without a real kernel (no `ctx.kernel`) should\n * either inject a mock or fall back to creating a local\n * `ReadinessRegistry`; the production code in kernel always\n * populates this field.\n */\n readonly readinessRegistry?: import('../capabilities/index.js').ITypedReadinessRegistry\n\n /**\n * Global device registry — read + mutate devices across all addons.\n * Hub-only: workers don't have a local registry (use `ctx.devices`\n * for per-addon scoped management, or `ctx.api.deviceManager.*` for\n * cross-process access).\n */\n readonly deviceRegistry?: import('../device/device-context.js').IDeviceRegistry\n\n /**\n * Per-addon scoped device management — create, register, remove, list devices.\n * Used by device provider addons (rtsp, onvif, frigate) to manage cameras.\n */\n readonly devices: import('../device/device-context.js').DeviceManagerApi\n\n /**\n * Cluster runtime — exposes the underlying message broker for addons that\n * need to participate in cluster-wide RPC outside the capability/tRPC\n * surface (e.g. log forwarding, hub readiness probes).\n *\n * Optional: only the agent and hub processes populate this. Forked workers\n * receive their broker through their own runner harness — they do not see\n * `cluster.broker` on ctx.kernel.\n */\n readonly cluster?: {\n readonly broker: IClusterBroker\n }\n\n /**\n * Kernel stream-probe bundle. Both entrypoints land on the same\n * hub-side `StreamProbeService` (ffprobe + HTTP reachability check\n * with a 1h cache). Hub resolves them directly; forked workers +\n * remote agents route through the `$stream-probe.*` Moleculer\n * broker service. Providers that call\n * `ctx.kernel.streamProbe.probe(url)` don't need to know where\n * they run.\n */\n readonly streamProbe?: IKernelStreamProbe\n\n /**\n * Kernel hardware-accel resolver. Platform-probe that picks an\n * ordered preference list of hw decode backends for the **local\n * host**. Every node (hub + forked worker + remote agent) runs its\n * own probe because hwaccel is inherently hardware-bound: decoder\n * addons on an NVIDIA agent get `['cuda', 'nvdec']`, the same addon\n * on a Mac hub gets `['videotoolbox']`. Cross-node queries for the\n * admin UI go via the `$hwaccel.resolve` Moleculer service\n * registered on every node.\n */\n readonly hwaccel?: IKernelHwAccel\n\n /**\n * Capability registry — provider lookups, native-cap resolution, wrapper listing.\n * Hub-only: forked workers don't see this (they use `ctx.api` for cross-process calls).\n */\n readonly capabilityRegistry?: ICapabilityRegistry\n}\n\n/**\n * Canonical hwaccel backend names. Accepted by both the `ffmpeg` CLI\n * (`-hwaccel <name>`) and node-av `HardwareDeviceContext.create()`\n * (`AV_HWDEVICE_TYPE_<upper>`), so a single string drives both layers.\n */\nexport type HwAccelBackend =\n | 'videotoolbox'\n | 'cuda'\n | 'nvdec'\n | 'vaapi'\n | 'qsv'\n | 'd3d11va'\n | 'dxva2'\n | 'amf'\n | 'vdpau'\n | 'drm'\n\n/** Resolution output — preference list + rationale for observability. */\nexport interface HwAccelResolution {\n readonly preferred: readonly HwAccelBackend[]\n readonly rationale: string\n}\n\nexport interface IKernelHwAccel {\n /**\n * Probe the local host and return the preferred backends.\n *\n * `prefer` accepts:\n * - `null` / `undefined` → auto, use platform probe\n * - `'none'` → hwaccel disabled; returns empty list\n * - an explicit backend name → single-entry list (skip probe)\n *\n * Implementations are pure functions over the host — safe to call\n * repeatedly; results are deterministic per host.\n */\n readonly resolve: (prefer?: HwAccelBackend | 'none' | null) => Promise<HwAccelResolution>\n}\n\nexport interface IKernelStreamProbe {\n /**\n * Run ffprobe on an RTSP / HTTP stream URL and return the raw\n * metadata. Use this when you need the width/height/codec/fps data\n * for profile classification. `classifyStream` / `classifyStreams`\n * in `@camstack/types` turn the metadata into a `StreamQuality`.\n */\n readonly probe: (url: string, options?: { force?: boolean }) => Promise<import('./device-capabilities/camera.js').StreamMetadata>\n /**\n * Generic field probe dispatcher — keys starting with `stream` run\n * ffprobe, others run an HTTP GET that aborts at response headers.\n * Returns a `FieldProbeResult` suitable for the admin UI's \"Test\"\n * button on any `probe`-typed form field.\n */\n readonly probeField: (key: string, value: unknown) => Promise<FieldProbeResult>\n}\n\n/**\n * Minimal structural shape of a cluster-message-broker (Moleculer in the\n * current implementation). Captured in @camstack/types so cluster-aware\n * addons can consume it without pulling a moleculer dependency.\n *\n * Add new methods sparingly — every addition becomes a contract the broker\n * implementation must satisfy.\n */\nexport interface IClusterBroker {\n readonly nodeID: string\n call<TParams = unknown, TResult = unknown>(\n action: string,\n params?: TParams,\n opts?: { nodeID?: string; timeout?: number },\n ): Promise<TResult>\n waitForServices(service: string | readonly string[], timeout?: number): Promise<void>\n readonly localBus: {\n on(event: string, handler: (payload: { node: { id: string } }) => void): void\n }\n}\n\nexport interface AddonContext<TConfig = Record<string, unknown>> {\n /** Immutable progressive ID */\n readonly id: string\n /** Pre-scoped logger */\n readonly logger: IScopedLogger\n /** System event bus */\n readonly eventBus: IEventBus\n /** Bootstrap configuration from server settings (read-only) */\n readonly addonConfig: Readonly<TConfig>\n /**\n * Private data directory for this addon.\n * Resolved via storageProvider.resolve('addons-data', '{addonId}/').\n * The addon owns this directory exclusively.\n */\n readonly dataDir: string\n\n // --- Kernel services ---\n\n /** Infrastructure services provided by the kernel. */\n readonly kernel: IKernelServices\n\n // --- Settings ---\n\n /**\n * Capability settings API — 3-level resolution (defaults → global → per-device).\n * Replaces context.config (IElementConfig) and context.addonConfig.\n */\n /**\n * Three-level settings store API.\n *\n * Raw, non-merging accessors for the addon's `addon_settings` row and\n * per-device overrides, plus a `(getSection, setSection)` pair for the\n * cluster-wide yml-backed sections consumed by the built-in\n * `system-config` addon.\n *\n * The addon combines these raw reads with its own schema via\n * `hydrateSchema()` inside `getAddonSettings / getGlobalSettings /\n * getDeviceSettings` on `ICamstackAddon`. There is no defaults\n * injection or cross-level merge at this layer.\n *\n * Cleanup note: the earlier `getGlobal / getDevice / updateGlobal /\n * updateDevice` trio (with a polymorphic `getGlobal({ section })`\n * overload) was removed after every caller migrated. The only\n * consumer of the yml-section path was `system-config`, which now\n * goes through the explicit `getSection / setSection` pair below.\n */\n readonly settings?: {\n /**\n * Read the raw addon store for this addon. Holds both `addon`-level\n * and `global`-level values; they're disjoint by schema invariant so\n * they can share one physical store. No defaults merged in. Returns\n * an empty object if the addon has never written anything.\n */\n readAddonStore(): Promise<Record<string, unknown>>\n\n /**\n * Write a patch into the addon store. Keys not in the patch are\n * preserved. Keys explicitly set to `null` are preserved as-is (they\n * do NOT fall back to schema default on subsequent reads — that\n * layering happens only at `hydrateSchema` time).\n */\n writeAddonStore(patch: Record<string, unknown>): Promise<void>\n\n /**\n * Read the raw per-device store for this addon + device. No defaults,\n * no merge with the addon store. Returns `{}` when no overrides exist.\n */\n readDeviceStore(deviceId: number): Promise<Record<string, unknown>>\n\n /**\n * Write a patch into the per-device store. Does NOT touch the\n * addon-level store. Keys preserved as in `writeAddonStore`.\n */\n writeDeviceStore(deviceId: number, patch: Record<string, unknown>): Promise<void>\n\n /**\n * Delete all keys for a device from the per-device store.\n * Use on device removal to guarantee no orphaned settings rows remain.\n */\n clearDeviceStore(deviceId: number): Promise<void>\n\n /**\n * Read a device's runtime-state blob — separate namespace from\n * `readDeviceStore` (which is the addon's config blob). Holds\n * mutable runtime signals discovered after boot (battery\n * snapshot, sleep flag, last-seen) that survive restart. Stored\n * under the kernel's reserved `__device-state` namespace so the\n * addon's config schema never sees it.\n */\n readDeviceRuntimeState(deviceId: number): Promise<Record<string, unknown>>\n\n /**\n * Replace the runtime-state blob for a device. The kernel's\n * `DeviceRuntimeState` always hands over the FULL persistent\n * slice — no shallow merge here, the latest blob wins.\n */\n writeDeviceRuntimeState(deviceId: number, data: Record<string, unknown>): Promise<void>\n\n /**\n * Delete the device's runtime-state blob. Use on device removal\n * so a recreated device with the same id starts clean instead\n * of inheriting stale runtime state from the previous lifetime.\n */\n clearDeviceRuntimeState(deviceId: number): Promise<void>\n\n /**\n * Read a cluster-wide yml-backed section (server, auth, ffmpeg,\n * logging, recording, retention — whatever\n * `ConfigManager.getSection` recognises). Returns the raw section\n * record with no schema merging. Used by the built-in\n * `system-config` addon to surface the legacy `config.yaml`\n * sections through its `getGlobalSettings()` method.\n */\n getSection(section: string): Promise<Record<string, unknown>>\n\n /**\n * Write a cluster-wide yml-backed section. Shallow-merges the patch\n * into the existing section so unrelated keys are preserved.\n * Hub-only — agents have no concept of yml sections and will\n * throw. Used by the `system-config` addon's\n * `updateGlobalSettings()` implementation.\n */\n setSection(section: string, patch: Record<string, unknown>): Promise<void>\n }\n\n /**\n * Full tRPC client — same API as the frontend.\n * Transport is transparent: direct caller (in-process), WSS (worker), or WSS (remote agent).\n * Use this for all server interactions: storage, events, devices, streaming, etc.\n */\n readonly api: import('../generated/addon-api.js').AddonApi\n\n /**\n * Binary / tool dependency manager. Addons call\n * `ctx.deps.ensureBinary(...)` / `ensureFfmpeg()` / `ensurePython()` to\n * materialise per-addon runtime deps under the shared `data/deps` tree.\n * Injected by the addon host so addons never import the concrete\n * implementation from `@camstack/core` directly.\n */\n readonly deps: IAddonDepsManager\n\n /**\n * Typed handle to the native provider of `cap` for `deviceId`. Bypasses the\n * currently-active wrapper — call this ONLY from the wrapper that owns\n * `cap`. Every other consumer should use `fetchDevice(id).<cap>.<method>()`\n * instead, which routes through the cap-router and respects the wrapper\n * chain.\n *\n * Wrapper-vs-consumer rule (memorise this):\n * - \"I am the wrapper for this cap and I need to delegate to the camera\n * driver\" → `getNativeProvider(cap, id)` (bypasses self, no recursion).\n * - \"I am consuming someone else's cap\" → `fetchDevice(id).<cap>...`\n * (uses the wrapper chain — cache, fallback, validation, etc.).\n *\n * Calling `fetchDevice` from inside the cap's own wrapper would re-enter\n * the wrapper and produce infinite recursion through the cap-router.\n *\n * Returns `null` when no addon has published a native provider for this\n * `(cap, deviceId)` — e.g. a camera driver that doesn't implement the cap\n * natively (RtspCamera without `snapshotUrl` does not register snapshot).\n * Wrappers use this to decide between native delegation and their own\n * fallback strategy; they MUST check for null.\n *\n * When the native is registered in this process, returns the local object\n * directly (zero serialization). When it lives in a forked worker, returns\n * a Moleculer-backed proxy constructed by the hub's native-cap fallback\n * (see `CapabilityRegistry.setNativeFallback`) — standard\n * `<addonId>.native-provider.<capName>.<method>` RPC path.\n */\n getNativeProvider<TCap extends CapabilityDefinition>(\n cap: TCap,\n deviceId: number,\n ): InferProvider<TCap> | null\n\n /**\n * Fetch a typed proxy for a device. THE canonical entry point for any\n * consumer that wants to read state, subscribe to changes, or dispatch\n * cap methods on a device — equivalent to `BackendClient.fetchDevice(id)`\n * on the client side.\n *\n * What you can do with the returned proxy:\n * - Read live state slices: `dev.state.battery.value` (typed\n * `BatteryStatus | undefined`, no provider call — reads the kernel's\n * mirrored snapshot).\n * - Subscribe to slice changes: `dev.state.battery.subscribe(cb)` —\n * refcounted, auto-seeds the callback with the current value.\n * - Invoke cap methods through the wrapper chain:\n * `await dev.snapshot.getSnapshot({...})`. Methods are typed against\n * each cap's definition; absent caps appear as `undefined`.\n *\n * Routing semantics: every method call on the returned proxy goes through\n * the tRPC cap-router → the active wrapper (if any) → the native provider.\n * That means a wrapper consuming its OWN cap via `fetchDevice` would\n * recurse — wrappers must use `getNativeProvider` instead. See the rule\n * documented on `getNativeProvider` above.\n *\n * Bindings are cached per-addon-context: the first call resolves bindings\n * via `deviceManager.getBindings.query`, subsequent calls reuse the cache.\n * The cache is invalidated implicitly when the device is removed.\n */\n fetchDevice(deviceId: number): Promise<import('../generated/device-proxy.js').DeviceProxy>\n\n /**\n * Runtime accessor for the capability registry — exposed to addons that\n * need to enumerate peers of a collection cap (e.g. `turn-provider`) or\n * grab the active singleton for a system cap. Injected by the kernel at\n * addon instantiation; absent when the addon is loaded in isolation\n * (tests, tooling), which is why the field is optional.\n */\n readonly capabilities?: CapabilitiesAccess\n\n /**\n * Returns a capability handle immediately (non-blocking). The handle tracks\n * ready/down state via the ReadinessRegistry and gates calls accordingly.\n * Repeated calls with the same `(capName, scope)` return the same cached instance.\n *\n * Use for runtime cap consumption where the cap may not be ready yet and\n * you want calls to block transparently via `handle.call(fn)`.\n */\n useCapability<T = unknown>(capName: string, scope?: ReadinessScope): ICapabilityHandle<T>\n\n /**\n * Blocks until the capability is ready, then returns the cached handle.\n * Throws `CapabilityUnavailableError` if the cap does not become ready\n * within `timeoutMs` (default 15 000ms).\n *\n * Use for boot sequencing where downstream work must not start until\n * the cap is confirmed available.\n */\n acquireCapability<T = unknown>(\n capName: string,\n scope?: ReadinessScope,\n opts?: { timeoutMs?: number },\n ): Promise<ICapabilityHandle<T>>\n\n /**\n * Subscribe to capability state changes (ready / down).\n * Returns an unsubscribe function. Thin wrapper over `ReadinessRegistry.onReadyState`.\n */\n onCapabilityStateChange(\n capName: string,\n scope: ReadinessScope,\n handler: (state: 'ready' | 'down') => void,\n ): () => void\n}\n\n/**\n * Runtime-only capability registry surface — kept minimal on purpose.\n * `getCollection` returns every registered provider for a collection cap\n * (order-unstable); `get` returns the active provider for a singleton.\n * Both return `undefined` when the cap isn't declared or has no provider.\n */\nexport interface CapabilitiesAccess {\n /** All providers registered on a collection capability (by cap name). */\n getCollection<T = unknown>(name: string): readonly T[] | undefined\n /**\n * Like `getCollection` but returns `[addonId, provider]` tuples so\n * callers can attribute work back to the contributing addon. The\n * `addonId` for cap-routed remote providers is `<addonName>@<workerNodeId>`\n * (e.g. `decoder-nodeav@dev-agent-1/decoder-nodeav`); local providers\n * are just `<addonName>` (no `@`). Used by stream-broker to filter the\n * decoder collection by the orchestrator's per-camera placement\n * decision (`getDecoderAssignment.decoderNodeId`).\n */\n getCollectionEntries<T = unknown>(name: string): readonly (readonly [string, T])[] | undefined\n /** The active provider of a singleton capability (by cap name). */\n get<T = unknown>(name: string): T | undefined\n}\n\nexport interface ICamstackAddon {\n readonly id?: string\n /** Addon declaration — injected by the framework from package.json. Do not declare in addon class. */\n readonly manifest?: AddonDeclaration\n /**\n * Initialize the addon. Return capability provider bindings for the kernel\n * to register in the CapabilityRegistry. Returning `void` or an empty array\n * is valid for addons that don't provide capabilities (e.g. pure consumers).\n *\n * The kernel validates that every capability declared in `package.json`\n * has a corresponding entry in the returned array.\n *\n * @example\n * ```ts\n * async initialize(ctx: AddonContext): Promise<AddonInitResult> {\n * this.detector = new WasmMotionDetector()\n * await this.detector.load()\n * return { providers: [{ capability: motionDetectionCapability, provider: this }] }\n * }\n * ```\n */\n initialize(context: AddonContext): Promise<ProviderRegistration[] | AddonInitResult | void>\n /**\n * Called by the isolated-process runner after `broker.start()`.\n * In-process addons never need this — the hub broker is already running\n * when `initialize()` fires. Forked children emit readiness inside\n * `initialize()` before the broker is live; this re-emits it once the\n * transport is ready so consumers actually receive the event.\n */\n postBrokerStart(): void\n /**\n * Optional hook. Fires on forked workers / remote agents once the\n * broker has started AND the hub node has been discovered via the\n * Moleculer `$node.connected` event — the moment at which\n * `ctx.api.*` calls to hub-provided capabilities become safe.\n *\n * Use this instead of `initialize()` for any bootstrap work that\n * needs to query the hub (e.g. restoring persisted state, reading\n * hub-owned settings). Calling `ctx.api.*` from `initialize()` on a\n * worker is a documented foot-gun: the broker is not connected yet\n * and requests either time out or throw \"Service not found\".\n *\n * On the hub itself this never fires (the hub is its own node; there\n * is no separate hub to wait for).\n */\n onHubReachable?(): Promise<void> | void\n shutdown(): Promise<void>\n\n // Cleanup: the legacy `getConfigSchema / getConfig / onConfigChange`\n // trio was removed. Every addon implements the three-level settings\n // API below and nothing on the server reads the legacy shape any\n // more — the adapter shim in `addon-registry.service.ts` and the\n // `addons.getConfigSchema / getConfig / updateConfig` tRPC endpoints\n // are gone.\n\n // -- Three-level settings API --\n //\n // An addon implements only the levels it needs. Each level has a\n // disjoint schema — field keys must not collide across levels. Each\n // getter returns a hydrated `ConfigUISchemaWithValues` (schema + values\n // inline) so the admin UI can render in one pass.\n //\n // Level 1 — addon settings: pipeline/context-specific fields, rendered\n // by whatever page knows the addon belongs to it (e.g. the\n // Pipeline page hardcodes PIPELINE_CAPABILITIES and iterates\n // providers).\n // Level 2 — node-global settings: node-level fields shown in Cluster →\n // NodeDetailPanel → Settings. Dynamic discovery: an addon\n // that doesn't implement `getGlobalSettings` doesn't appear\n // there.\n // Level 3 — device settings: per-camera fields shown in Device\n // Overrides.\n //\n // All six methods are OPTIONAL. They will become the canonical way\n // addons expose settings once Phase 3 removes the deprecated trio\n // above. See docs/superpowers/specs/2026-04-11-settings-redesign-design.md.\n\n /** Level 1 — node-global settings (schema + values). Appears in\n * Cluster → Settings tab. `overlay` is an optional preview merge\n * consumed by override-mode UIs (benchmark) so cascade-aware\n * addons can re-derive dependent options without touching the\n * persisted store. */\n getGlobalSettings?(overlay?: Record<string, unknown>): Promise<ConfigUISchemaWithValues>\n updateGlobalSettings?(patch: Record<string, unknown>): Promise<void>\n\n /** Level 2 — per-device settings (schema + values). Appears in\n * Device Overrides. */\n getDeviceSettings?(deviceId: number): Promise<ConfigUISchemaWithValues>\n updateDeviceSettings?(deviceId: number, patch: Record<string, unknown>): Promise<void>\n\n /**\n * Called at boot after initialize() with all previously persisted devices.\n * The addon should re-instantiate device objects and register them via context.devices.register().\n */\n restoreDevices?(savedDevices: readonly import('../device/device-management.js').SavedDevice[]): Promise<void>\n\n // -- Model catalog (optional — only for inference addons) --\n getModelCatalog?(): unknown[]\n // `getModelRequirements` and `configure` were removed — inference addons\n // now resolve their own config inside `initialize()` by calling\n // `ctx.api.platformProbe.resolveInferenceConfig.query({ requirements })`.\n\n // -- Inference methods (optional — only for detection/classification addons) --\n\n /** Load/prepare a model engine for a given modelId. Called before process()/classifyAudio(). */\n ensureEngine?(modelId: string): Promise<void>\n\n /** Unified vision inference — handles detection, cropping, classification, refinement.\n * Input is FrameInput (root) or CropInput (child node). Output shape determines slot. */\n process?(input: unknown): Promise<unknown>\n\n /** Audio classification — separate from vision pipeline */\n classifyAudio?(input: unknown): Promise<unknown>\n}\n\n/** Declaration of a UI page provided by an addon */\nexport interface AddonPageDeclaration {\n /** Unique page ID (scoped to addon) */\n readonly id: string\n /** Display label for sidebar */\n readonly label: string\n /** Lucide icon name for sidebar */\n readonly icon: string\n /** Route path (e.g., '/benchmark') */\n readonly path: string\n /**\n * Module Federation remote name — must match the `name` field on the\n * page addon's `federation()` plugin config. Used by admin-ui's\n * `<AddonPageLoader>` to call `loadRemote('<remoteName>/page')`.\n * Conventionally `addon_<id>_page` (snake_case; MF names cannot\n * contain hyphens).\n */\n readonly remoteName: string\n /**\n * Bundle filename inside the addon's `dist/` dir served at\n * `/api/addon-pages/<addonId>/<bundle>`. With Module Federation this\n * is always `'remoteEntry.js'`.\n */\n readonly bundle: string\n}\n\n/** Provider interface for addons that expose UI pages */\nexport interface IAddonPageProvider {\n readonly id: string\n listPages(): readonly AddonPageDeclaration[]\n}\n\n/** Provider interface for the admin UI shell (singleton capability) */\nexport interface IAdminUI {\n getStaticDir(): string\n getVersion(): string\n}\n\n/**\n * Full addon declaration — lives in package.json `camstack.addons[]`.\n * This is the SINGLE SOURCE OF TRUTH for addon identity and metadata.\n * Addon classes no longer declare a `manifest` property.\n */\nexport interface AddonDeclaration {\n // ── Identity ────────────────────────────────────────────────────────\n readonly id: string\n /** JS entry point relative to package root (e.g., \"./dist/addon.js\") */\n readonly entry?: string\n /** Human-readable name */\n readonly name?: string\n /** Semver version */\n readonly version?: string\n /** Short description */\n readonly description?: string\n\n // ── Display ────────────────────────────────────────────────────────\n /** Relative path to SVG icon asset within the addon package */\n readonly icon?: string\n /** Brand hex color for UI display (e.g., \"#3b82f6\") */\n readonly color?: string\n\n // ── Runtime ────────────────────────────────────────────────────────\n readonly slot?: PipelineSlot | null\n /** Instance mode: 'unique' or 'multiple'. Default: 'multiple' */\n readonly instanceMode?: 'unique' | 'multiple'\n /** Whether this addon is protected (required by the system, cannot be uninstalled) */\n readonly protected?: boolean\n /**\n * Group-runner execution model.\n *\n * Every addon lives in a forked subprocess; the question is which one.\n * Addons sharing the same `group` value share one subprocess and one\n * Moleculer broker, so cap calls between them resolve in-process via\n * `localProviderLink` (zero IPC). Different groups speak via Moleculer\n * TCP.\n *\n * Defaults (when `execution` is omitted entirely):\n * - `placement: 'hub-only'` — addon does NOT deploy to agents.\n * - `group: 'main-group'` — joins the catch-all subprocess.\n *\n * Examples:\n * ```jsonc\n * // hub-only addon, joins main-group (most common)\n * \"execution\": {}\n *\n * // deployable to any node (cluster scenario)\n * \"execution\": { \"placement\": \"any-node\" }\n *\n * // bundle detection on a dedicated subprocess\n * \"execution\": { \"placement\": \"any-node\", \"group\": \"detection\" }\n *\n * // hardware-bound, only runs on agents (no hub instance)\n * \"execution\": { \"placement\": \"agent-only\" }\n *\n * // crash-isolated (private subprocess; unique group per addon)\n * \"execution\": { \"group\": \"untrusted-foo\" }\n * ```\n */\n readonly execution?: AddonExecution\n\n // ── Capabilities ───────────────────────────────────────────────────\n /** Capabilities this addon provides */\n readonly capabilities?: readonly CapabilityDeclaration[]\n /** UI pages provided by this addon */\n readonly pages?: readonly AddonPageDeclaration[]\n\n // ── Pipeline-specific ──────────────────────────────────────────────\n readonly requiredFeatures?: readonly string[]\n readonly inputClasses?: readonly string[]\n readonly outputClasses?: readonly string[]\n readonly requiredSteps?: readonly RequiredStep[]\n readonly supportsCustomModels?: boolean\n readonly mayRequirePython?: boolean\n /** Whether this addon performs active inference. Passive addons are excluded from inference pipeline. Default: true. */\n readonly passive?: boolean\n /**\n * Label output type for classifier/recognizer addons.\n *\n * `classification` — generic class name (e.g. `'bird'`, `'labrador'`)\n * `face` — recognised face identity\n * `plate` — recognised licence plate OCR\n * `recognition` — generic recognition result (embedding gallery)\n */\n readonly labelOutputType?: 'classification' | 'face' | 'plate' | 'recognition'\n\n // ── Python (auto-managed deps) ─────────────────────────────────────\n /**\n * Optional Python runtime dependencies. Declares the pip requirements\n * file the kernel must install into the embedded portable Python\n * before this addon's `onInitialize()` runs. Resolved relative to the\n * addon's package root.\n *\n * Idempotent: install is keyed on (file basename + sha256 of contents)\n * via the marker dir under the python install — back-to-back boots\n * skip the pip subprocess after the first install.\n *\n * Example:\n * ```jsonc\n * \"camstack\": {\n * \"addons\": [{\n * \"id\": \"detection-pipeline\",\n * \"python\": { \"requirements\": \"./python/requirements.txt\" }\n * }]\n * }\n * ```\n *\n * Backend / feature-specific deps that depend on user settings should\n * NOT be listed here — addons install those lazily via\n * `ctx.deps.installPythonRequirements(absolutePath)`.\n */\n readonly python?: AddonPythonRequirements\n\n // ── Config ─────────────────────────────────────────────────────────\n /** Default configuration values */\n readonly defaultConfig?: Readonly<Record<string, unknown>>\n}\n\n/**\n * Manifest declaration for an addon's Python runtime dependencies.\n * See `AddonDeclaration.python`.\n */\nexport interface AddonPythonRequirements {\n /**\n * Path to the pip requirements file the kernel installs into the\n * embedded portable Python before `onInitialize()` runs. Resolved\n * relative to the addon package root.\n */\n readonly requirements: string\n}\n\nexport interface AddonPackageManifest {\n /** Human-readable package name for UI display (e.g., \"CamStack Vision\") */\n readonly displayName?: string\n readonly addons: readonly AddonDeclaration[]\n}\n\n/**\n * Where an addon may be deployed. The kernel honours this when picking\n * which node hosts the group-runner that will load the addon.\n *\n * - `'hub-only'` — runs only on the hub process. Default.\n * - `'agent-only'` — runs only on remote agent processes.\n * - `'any-node'` — eligible to run on either hub or agents.\n */\nexport type AddonPlacement = 'hub-only' | 'agent-only' | 'any-node'\n\n/**\n * Effective execution model for an addon. See `AddonDeclaration.execution`\n * for the full semantics.\n */\nexport interface AddonExecution {\n readonly placement?: AddonPlacement\n /**\n * Subprocess group label. Addons sharing the same value share one\n * forked subprocess + one Moleculer broker. Defaults to `'main-group'`\n * — the catch-all bucket for every addon that doesn't opt out.\n */\n readonly group?: string\n}\n\nexport const DEFAULT_ADDON_GROUP = 'main-group'\nexport const DEFAULT_ADDON_PLACEMENT: AddonPlacement = 'hub-only'\n\n/**\n * Resolve the effective `AddonExecution` for an addon. Returns a fully\n * populated value (placement + group always set) so callers can read\n * either field without a separate fallback.\n */\nexport function resolveAddonExecution(\n decl: Pick<AddonDeclaration, 'execution'>,\n): Required<AddonExecution> {\n return {\n placement: decl.execution?.placement ?? DEFAULT_ADDON_PLACEMENT,\n group: decl.execution?.group ?? DEFAULT_ADDON_GROUP,\n }\n}\n\n/** True when the addon may run on a remote agent (deployable from hub). */\nexport function isDeployableToAgent(decl: Pick<AddonDeclaration, 'execution'>): boolean {\n const placement = resolveAddonExecution(decl).placement\n return placement === 'any-node' || placement === 'agent-only'\n}\n\n/** True when the addon is skipped on the hub (agent-only deployment). */\nexport function isAgentOnlyPlacement(decl: Pick<AddonDeclaration, 'execution'>): boolean {\n return resolveAddonExecution(decl).placement === 'agent-only'\n}\n\n/** Convenience accessor — the resolved subprocess group label. */\nexport function resolveAddonGroup(decl: Pick<AddonDeclaration, 'execution'>): string {\n return resolveAddonExecution(decl).group\n}\n\n/** Convenience accessor — the resolved placement (defaults to `hub-only`). */\nexport function resolveAddonPlacement(decl: Pick<AddonDeclaration, 'execution'>): AddonPlacement {\n return resolveAddonExecution(decl).placement\n}\n\n// ── Kernel-internal context ─────────────────────────────────────────────\n/**\n * Extended AddonContext used exclusively by the kernel (hub + worker boot\n * sequences) to wire providers into the CapabilityRegistry after\n * `initialize()` returns. Addon code never sees this — it only receives\n * the public `AddonContext`.\n */\nexport interface InternalAddonContext extends AddonContext {\n /** Register a provider in the local capability registry. Kernel-only. */\n registerProvider(capabilityName: string, provider: unknown): void\n\n /** Resolve the preferred provider for a capability. Kernel-only. */\n resolveProvider<T = unknown>(capabilityName: string): T | null\n}\n","export enum EventCategory {\n // System\n SystemBoot = 'system.boot',\n SystemAddonsReady = 'system.addons-ready',\n SystemRestarting = 'system.restarting',\n /**\n * Readiness transition for a capability provider. Every producer emits\n * this event on `onInitialize` completion, `onDestroy`, and\n * `$node.reconnect`; every consumer that needs to gate on a cross-process\n * cap subscribes via the kernel's readiness module (`awaitReady` /\n * `onReadyState`) instead of polling. Payload is\n * `SystemReadyStatePayload` — see event-bus.ts.\n */\n SystemReadyState = 'system.ready-state',\n\n // Addon lifecycle\n AddonStarted = 'addon.started',\n AddonStopped = 'addon.stopped',\n AddonRestarted = 'addon.restarted',\n AddonUpdated = 'addon.updated',\n AddonInstalled = 'addon.installed',\n AddonUninstalled = 'addon.uninstalled',\n AddonCrashed = 'addon.crashed',\n AddonError = 'addon.error',\n AddonPageReady = 'addon.page-ready',\n AddonWidgetReady = 'addon.widget-ready',\n\n // Device\n DeviceRegistered = 'device.registered',\n DeviceUnregistered = 'device.unregistered',\n DeviceEnabled = 'device.enabled',\n DeviceDisabled = 'device.disabled',\n DeviceSettingsUpdated = 'device.settings-updated',\n /**\n * Emitted when the set of native capability providers bound to a device\n * changes — e.g. an addon registers a new native cap via\n * `DeviceContext.registerNativeCap`, or all native bindings for a device\n * are cleared on removal. Hub consumers re-resolve device-proxy routes\n * when this fires.\n */\n DeviceBindingsChanged = 'device.bindings-changed',\n /**\n * Emitted when the operator-organisational meta surface changes\n * (`name` / `location` / `disabled`). Payload: `{deviceId, field,\n * value}`. Live consumers (UI device list, alert center) react\n * without polling. Distinct from `DeviceSettingsUpdated` which\n * fires on hardware-config changes (host/port/credentials/etc).\n */\n DeviceMetaChanged = 'device.meta-changed',\n /**\n * Emitted by DeviceStreamWiringService after a successful\n * `stream-broker.registerDeviceStreams` call. Payload includes\n * deviceId — consumers look up the full registered device info via\n * `brokerManager.getRegisteredDevice(deviceId)`.\n *\n * Replaces the legacy `StreamRouterService.onDeviceRegistered` callback.\n */\n DeviceStreamsRegistered = 'device.streams-registered',\n\n // Integration\n IntegrationEnabled = 'integration.enabled',\n IntegrationDisabled = 'integration.disabled',\n IntegrationDeleted = 'integration.deleted',\n\n // Provider\n ProviderStarted = 'provider.started',\n ProviderStopped = 'provider.stopped',\n\n // Process\n ProcessCrashed = 'process.crashed',\n ProcessRestartScheduled = 'process.restart_scheduled',\n ProcessRestarted = 'process.restarted',\n\n // Recording\n RecordingStarted = 'recording.started',\n RecordingStopped = 'recording.stopped',\n RecordingError = 'recording.error',\n RecordingHealthDegraded = 'recording.health.degraded',\n RecordingStorageCritical = 'recording.storage.critical',\n RecordingSegmentWritten = 'recording.segment.written',\n RecordingPolicyFallback = 'recording.policy.fallback',\n RecordingRetentionCompleted = 'recording.retention.completed',\n\n // Detection & analysis\n DetectionEvent = 'detection.event',\n\n // Session tracking\n SessionTrackNew = 'session.track.new',\n SessionTrackExpired = 'session.track.expired',\n\n // Benchmark\n BenchmarkProgress = 'benchmark.progress',\n\n // Platform probe\n PlatformProbePhase = 'platform-probe.phase',\n\n // Pipeline & inference\n PipelineProgress = 'pipeline.progress',\n /** Per-frame execution trace emitted by the pipeline executor for live observability. */\n PipelineTrace = 'pipeline.trace',\n /**\n * Raw inference output emitted by `addon-pipeline-runner` after running the\n * detection pipeline on a frame. Carries the `FrameResult` (with\n * `detections[]`, `width`/`height`, timing debug) — never the frame\n * buffer itself. Hub-side consumers (analysis pipeline, class filters,\n * notifications) subscribe to this and re-emit `detection.result` after\n * post-processing.\n */\n PipelineInferenceResult = 'pipeline.inference-result',\n /**\n * Camera lifecycle event emitted by `addon-pipeline-orchestrator` when it\n * assigns or unassigns a camera to/from an agent. Carries no frame data;\n * pure observability for UI dashboards and metrics consumers.\n */\n PipelineCameraAssigned = 'pipeline.camera-assigned',\n PipelineCameraUnassigned = 'pipeline.camera-unassigned',\n /**\n * Per-camera pipeline config was mutated by the orchestrator\n * (3-level settings change via `setAgentAddonDefaults` /\n * `setCameraStepToggle` / `setCameraPipelineForAgent` or a\n * pipeline-scoped `applyDeviceSettingsPatch`). Orchestrator\n * subscribes to its own emission to hot-reload the assigned runner\n * via `attachCamera` so the next frame executes against the new\n * engine/steps without waiting for a rebalance or the next\n * `DeviceStreamsRegistered` cycle.\n */\n PipelineCameraUpdated = 'pipeline.camera-updated',\n /**\n * Periodic snapshot of per-node pipeline-runner load\n * (`RunnerLocalLoad`). Emitted ~1Hz by every runner so UI dashboards\n * subscribe instead of polling `pipelineRunner.getLocalLoad`.\n * `nodeId` carried in the payload + on `event.source.nodeId`.\n */\n PipelineRunnerLoadSnapshot = 'pipeline.runner-load-snapshot',\n /**\n * Periodic snapshot of per-camera pipeline metrics (`CameraMetrics`\n * + `deviceId` + `nodeId`). Emitted ~1Hz by every runner for each\n * attached camera. UI subscribes to drive overlay phase / fps /\n * inference time without polling `getCameraMetrics`.\n */\n PipelineCameraMetricsSnapshot = 'pipeline.camera-metrics-snapshot',\n /**\n * Periodic snapshot of stream-broker per-broker statistics (input\n * fps, decoded fps, bitrate, codec). Emitted ~1Hz by every\n * stream-broker process for each active broker so the UI can drive\n * the Stream / Cluster dashboards without polling\n * `streamBroker.listAllProfileSlots` and friends.\n */\n StreamBrokerMetricsSnapshot = 'stream-broker.metrics-snapshot',\n /**\n * Cap event fired by `stream-broker` when a profile slot enters\n * \"demanded\" state — a cam stream has been assigned and at least one\n * consumer (RTSP restream, decoded subscriber, WebRTC session, …) is\n * present. Camera-provider addons (Reolink Baichuan push, …)\n * subscribe to this category to start their underlying transport\n * lazily. Payload: `{ deviceId, camStreamId, profile }`.\n */\n StreamBrokerOnCamStreamDemand = 'stream-broker.onCamStreamDemand',\n /**\n * Cap event fired by `stream-broker` when the last consumer leaves a\n * previously-demanded cam stream. Providers tear down their\n * underlying transport on receipt. Payload: `{ deviceId, camStreamId }`.\n */\n StreamBrokerOnCamStreamIdle = 'stream-broker.onCamStreamIdle',\n /**\n * Cap event fired by `stream-broker` when a broker fails to dial a\n * managed-loopback source (today: `pull-rfc4571`) and the publisher\n * needs to refresh the cached URL. Mirrors Scrypted's\n * `ensureRfcServer` self-heal pattern: the lib's TCP server\n * idle-tears-down on its own schedule, so a re-publish with a fresh\n * `host:port` is the only way to keep the broker dialable. Camera\n * providers (Reolink Baichuan native, …) subscribe and respond by\n * re-running their publish pipeline.\n * Payload: `{ deviceId, camStreamId, brokerId }`.\n */\n StreamBrokerOnRequestStreamSourceRefresh = 'stream-broker.onRequestStreamSourceRefresh',\n /**\n * Generic per-device runtime-state change. Fired by `device-manager`\n * whenever a persisted slice in any cap's `runtimeState` shape\n * mutates. Payload: `{deviceId, capName, slice}`. Subscribers are\n * the `deviceState` cap router (cross-process listeners) and the\n * deviceProxy reactive bindings (`device.state.<capName>.value`).\n * Cap-specific events (`battery.onStatusChanged`, …) still fire\n * — they're authoritative for callers that want a typed payload\n * without filtering on `capName`.\n */\n DeviceStateChanged = 'device.state-changed',\n /**\n * Cap event fired by every device that registers the `battery`\n * capability. Mirrors the cap definition's `onStatusChanged`. Carries\n * `{ deviceId, status: BatteryStatus }`. Subscribers (alert center,\n * snapshot wrapper, UI) react to charge/sleep transitions without\n * polling `batteryCapability.getStatus`.\n */\n BatteryOnStatusChanged = 'battery.onStatusChanged',\n /**\n * Cap event fired by every device that registers the `doorbell`\n * capability. Mirrors `doorbellCapability.events.onPressed`. Carries\n * `{ deviceId, timestamp }`. Operators consuming the UI subscribe\n * here to render transient ring toasts and a \"Recent presses\" row\n * on the device detail page.\n */\n DoorbellOnPressed = 'doorbell.onPressed',\n /**\n * Periodic snapshot of the per-node detection-pipeline engine\n * registry (loaded engines, models resident, in-use cameras, idle\n * TTL). Emitted ~0.2Hz (every 5 s) by every detection-pipeline\n * process. The Engines tab subscribes to drive its inventory view\n * without polling `pipelineExecutor.listLoadedEngines`.\n */\n PipelineEngineMetricsSnapshot = 'pipeline.engine-metrics-snapshot',\n /**\n * Cluster topology snapshot. Carries the same payload returned by\n * `nodes.topology` (every reachable node + addons + processes).\n * Emitted by the hub on any agent / addon lifecycle change\n * (debounced) plus a periodic safety net. Replaces UI polling on\n * `nodes.topology` — admin-ui dashboards subscribe to drive the\n * cluster view directly from the event payload.\n */\n ClusterTopologySnapshot = 'cluster.topology-snapshot',\n /**\n * Periodic per-node system metrics snapshot (CPU / memory / GPU /\n * disk / network). Emitted ~0.2 Hz by the metrics-provider addon\n * for each node. Drives the dashboard SystemStatus / ProcessResources\n * widgets without polling `metricsProvider.getCurrent`.\n */\n MetricsNodeResourcesSnapshot = 'metrics.node-resources-snapshot',\n /**\n * Periodic per-node process-tree snapshot (camstack-related pids\n * with ghost / managed / root classification). Emitted ~0.2 Hz by\n * the metrics-provider addon. Drives the Cluster → Processes tab\n * without polling `metricsProvider.listNodeProcesses`.\n */\n MetricsNodeProcessesSnapshot = 'metrics.node-processes-snapshot',\n /**\n * Capability binding change event emitted by `addon-pipeline-orchestrator`\n * when a user changes which addon implements a cap on a node. Subscribed\n * by every kernel process to update its local `preferredProviderRegistry`\n * so future capability lookups respect the new binding.\n */\n /**\n * A capability binding was changed for a node — addon X now provides\n * capability `cap` on node `nodeId`. Lives under the generic\n * `capability.*` namespace because capability bindings are a kernel-\n * level concept used by many addons, not strictly pipeline-scoped.\n */\n CapabilityBindingChanged = 'capability.binding-changed',\n ModelDownloadProgress = 'model.download.progress',\n\n // Agent\n AgentRegistered = 'agent.registered',\n AgentUnregistered = 'agent.unregistered',\n AgentOnline = 'agent.online',\n AgentOffline = 'agent.offline',\n /** Forked worker process (e.g. hub/pipeline) connected to the broker. */\n WorkerOnline = 'worker.online',\n /** Forked worker process disconnected from the broker. */\n WorkerOffline = 'worker.offline',\n AgentTaskDispatched = 'agent.task.dispatched',\n AgentTaskAssigned = 'agent.task.assigned',\n AgentTrpcConnected = 'agent.trpc.connected',\n AgentWsConnected = 'agent.ws.connected',\n AgentWsDisconnected = 'agent.ws.disconnected',\n AgentBackupActivated = 'agent.backup.activated',\n\n // Detection settings\n OrchestrationSettingsUpdated = 'orchestration.settings-updated',\n\n /**\n * Per-agent hwaccel preference changed (user override set, cleared, or\n * re-probed). Observability event — decoders pull the current pref at\n * `createSession`, so running sessions keep their current backend until\n * they rotate naturally (camera add/remove, stream restart). Future\n * work can wire a listener in stream-broker that force-rotates live\n * sessions; for now this event powers logs + admin-UI toast feedback.\n */\n PipelineAgentHwaccelChanged = 'pipeline.agent-hwaccel-changed',\n\n // Motion analysis\n MotionAnalysis = 'detection.motion-analysis',\n /** All raw motion zones from CCL before minArea filter — for UI debug overlay. */\n MotionZonesRaw = 'detection.motion-zones-raw',\n /**\n * Per-camera motion phase transition (`watching ↔ active`) emitted\n * by the runner. Mirrors the `motion.onMotionChanged` cap event\n * surface — payload `MotionOnMotionChangedPayload` carries\n * `{deviceId, detected, timestamp, source, regions?}`. Subscribers\n * include addons that need to react to motion state without\n * polling the runtime-state mirror.\n */\n MotionOnMotionChanged = 'motion.on-motion-changed',\n\n // Detection extended\n DetectionResult = 'detection.result',\n DetectionRaw = 'detection.raw',\n DetectionCameraNative = 'detection.camera-native',\n /**\n * Canonical per-chunk live audio pipeline output. Payload is\n * `PipelineAudioInferenceResultPayload` carrying a full `AudioResult`\n * (level + detections + debug). Lives on the pipeline.* namespace\n * alongside `pipeline.inference-result` (video) for symmetry.\n */\n PipelineAudioInferenceResult = 'pipeline.audio-inference-result',\n DetectionPhaseTransition = 'detection.phase-transition',\n ProviderMotion = 'provider.motion',\n ProviderDetection = 'provider.detection',\n\n // Enrichment\n EnrichmentEmbeddingStored = 'enrichment.embedding.stored',\n EnrichmentSceneStateChanged = 'enrichment.scene.state-changed',\n EnrichmentActivitySummary = 'enrichment.activity.summary',\n\n // Pipeline analytics\n PipelineAnalyticsTrackStarted = 'pipeline-analytics.track-started',\n PipelineAnalyticsTrackEnded = 'pipeline-analytics.track-ended',\n PipelineAnalyticsDetectionEvent = 'pipeline-analytics.detection-event',\n PipelineAnalyticsFrameTracked = 'pipeline-analytics.frame-tracked',\n\n // Provider-specific\n FrigateLiveEvent = 'frigate.live-event',\n\n // Camera streams\n CameraStreamsProfileSlotsChanged = 'camera-streams.onProfileSlotsChanged',\n /**\n * Stream-broker health watchdog. Per-broker (deviceId/profile) emission.\n * `stream.offline` fires after STREAM_STALE_TIMEOUT_MS without an encoded\n * packet on an active broker. `stream.online` fires on first packet\n * after a stale gap (or on initial first packet). Payload includes\n * the assigned camStreamId as `profileKey`.\n */\n StreamOnline = 'stream.online',\n StreamOffline = 'stream.offline',\n\n // Network\n NetworkTunnelStarted = 'network.tunnel.started',\n NetworkTunnelStopped = 'network.tunnel.stopped',\n\n // Backup\n BackupCompleted = 'backup.completed',\n BackupRestored = 'backup.restored',\n\n // Notification\n NotificationDispatched = 'notification.dispatched',\n NotificationFailed = 'notification.failed',\n\n // Device extended\n DeviceUpdated = 'device.updated',\n /**\n * Transport-level connectivity. Emitted by the device driver when\n * the underlying control socket actually connects / disconnects\n * (Baichuan TCP, ONVIF probe response, RTSP DESCRIBE, …) — NOT for\n * power-state transitions on a battery camera. For battery wake /\n * doze cycles see `DeviceAwake` / `DeviceSleeping`.\n */\n DeviceOnline = 'device.online',\n /**\n * Stream-broker watchdog — emitted when no encoded packet has been\n * received for STREAM_STALE_TIMEOUT_MS on an active broker (rtsp or\n * push). Paired with DeviceOnline which fires on first packet after\n * a stale gap. Payload: DeviceStreamHealthPayload.\n */\n DeviceOffline = 'device.offline',\n /**\n * Battery cam woke up — physical power-state transition reported\n * by the device firmware. Distinct from `DeviceOnline` so a UI panel\n * watching power state doesn't flap on every UDP socket reconnect.\n */\n DeviceAwake = 'device.awake',\n /**\n * Battery cam went to sleep. See `DeviceAwake`.\n */\n DeviceSleeping = 'device.sleeping',\n\n // Retention\n RetentionCleanup = 'retention.cleanup',\n}\n","import type { ModelCatalogEntry, ModelFormat, ModelOutputFormat, CustomModelMetadata } from '../types/models.js'\n\n/**\n * Configuration UI Schema -- declarative form definition for any element.\n *\n * Used by addons to declare their settings UI. The admin UI collects schemas\n * from all active addons, merges tabs with the same ID, and renders responsive forms.\n *\n * Layout hierarchy: Tab → Section → Field\n * Multiple addons can contribute sections to the same tab.\n */\n\n// --- Well-Known Tabs ─────────────────────────────────────────────────\n\n/** Predefined tab identifiers that addons reference by ID. */\nexport type WellKnownTabId =\n | 'overview'\n | 'general'\n | 'image'\n | 'light'\n | 'motion'\n | 'audio'\n | 'snapshot'\n | 'osd'\n | 'alarms'\n | 'pipeline'\n | 'stream-broker'\n | 'streaming'\n | 'zones'\n | 'live-stats'\n | 'recording'\n | 'notifications'\n | 'network'\n | 'storage'\n | 'engine'\n | 'scheduler'\n | 'decoder'\n | 'advanced'\n\nexport interface WellKnownTab {\n readonly id: WellKnownTabId\n readonly label: string\n readonly icon: string\n readonly order: number\n}\n\n/** Predefined tabs with standard label, icon, and sort order.\n *\n * Pipeline (renamed Orchestrator in the UI) holds the four\n * pipeline-orchestrator sections: General, Object Detection, Audio,\n * and Cluster Assignment. Motion stays its own tab.\n * `streaming` remains for older payloads that haven't been retagged. */\nexport const WELL_KNOWN_TABS: readonly WellKnownTab[] = [\n { id: 'overview', label: 'Overview', icon: 'layout-dashboard', order: -10 },\n { id: 'general', label: 'General', icon: 'settings', order: 0 },\n { id: 'image', label: 'Image', icon: 'image', order: 5 },\n { id: 'light', label: 'Light', icon: 'lightbulb', order: 7 },\n { id: 'motion', label: 'Motion', icon: 'activity', order: 10 },\n { id: 'audio', label: 'Audio', icon: 'mic', order: 12 },\n { id: 'alarms', label: 'Alarms', icon: 'bell-ring', order: 13 },\n { id: 'snapshot', label: 'Snapshot', icon: 'camera', order: 15 },\n { id: 'osd', label: 'OSD', icon: 'type', order: 18 },\n { id: 'stream-broker', label: 'Stream Broker', icon: 'radio', order: 20 },\n { id: 'streaming', label: 'Streaming', icon: 'video', order: 35 },\n { id: 'pipeline', label: 'Detection Pipeline', icon: 'cpu', order: 39 },\n { id: 'zones', label: 'Detection', icon: 'shapes', order: 38 },\n { id: 'live-stats', label: 'Live Stats', icon: 'activity', order: 39 },\n { id: 'recording', label: 'Recording', icon: 'circle-dot', order: 40 },\n // Pipeline-page tabs — `engine` co-locates `detection-pipeline`'s\n // vision-engine section + `audio-analyzer`'s audio-engine section\n // (same modality of choice, different pipelines). `scheduler` and\n // `decoder` group the runner / decoder addon settings under their\n // own tabs so the pipeline page bar stays manageable.\n { id: 'engine', label: 'Inference Engine', icon: 'zap', order: 41 },\n { id: 'scheduler', label: 'Scheduler', icon: 'list-checks', order: 42 },\n { id: 'decoder', label: 'Decoder', icon: 'film', order: 43 },\n { id: 'notifications', label: 'Notifications', icon: 'bell', order: 50 },\n { id: 'network', label: 'Network', icon: 'globe', order: 60 },\n { id: 'storage', label: 'Storage', icon: 'hard-drive', order: 70 },\n { id: 'advanced', label: 'Advanced', icon: 'wrench', order: 100 },\n] as const\n\n/** Lookup map for well-known tabs by ID. */\nexport const WELL_KNOWN_TAB_MAP: Readonly<Record<WellKnownTabId, WellKnownTab>> =\n Object.fromEntries(WELL_KNOWN_TABS.map(t => [t.id, t])) as Record<WellKnownTabId, WellKnownTab>\n\n// --- Tab Declaration ─────────────────────────────────────────────────\n\n/**\n * Custom tab declaration by an addon.\n * Use well-known tab IDs when possible. Custom tabs are for addon-specific UI.\n */\nexport interface ConfigTabDeclaration {\n /** Unique tab identifier. Use WellKnownTabId for standard tabs. */\n readonly id: string\n /** Display label (ignored for well-known tabs — their label is used). */\n readonly label: string\n /** Icon identifier (ignored for well-known tabs — their icon is used). */\n readonly icon: string\n /** Sort order within the tab bar. Lower = left. */\n readonly order?: number\n}\n\n// --- Schema Definition ───────────────────────────────────────────────\n\nexport interface ConfigUISchema {\n /**\n * Tabs contributed by this addon.\n * Multiple addons can reference the same tab ID — the UI merges them.\n * For well-known tabs, label/icon from WELL_KNOWN_TABS takes precedence.\n * Omit to use only well-known tabs referenced by sections.\n */\n readonly tabs?: readonly ConfigTabDeclaration[]\n readonly sections: readonly ConfigSection[]\n}\n\nexport interface ConfigSection {\n readonly id: string\n readonly title: string\n readonly description?: string\n readonly style?: 'card' | 'accordion'\n readonly defaultCollapsed?: boolean\n readonly columns?: 1 | 2 | 3 | 4\n /** Which tab this section belongs to. Default: 'general'. */\n readonly tab?: string\n /**\n * Where the section is rendered in the device page. Default\n * `'settings'` keeps the section under the device Settings panel\n * (existing behavior). `'top-tab'` hoists the section into a\n * top-level device tab (sibling of Live / Streams / Recordings /\n * Settings) keyed by the section's `tab` value. Multiple addons\n * targeting the same `(tab, location: 'top-tab')` pair render\n * inside the same top tab in `order` sequence — used for the\n * Zones tab where orchestrator (geometry CRUD) + motion-wasm\n * (motion rules) + detection-pipeline (detection rules) all\n * contribute to one operator surface.\n */\n readonly location?: 'settings' | 'top-tab'\n /** Sort order within the tab. Lower = top. */\n readonly order?: number\n /**\n * When true, every field in this section saves immediately on change\n * (no Save button needed). Per-field `immediate: false` overrides this.\n */\n readonly immediate?: boolean\n readonly fields: readonly ConfigField[]\n}\n\n// --- Field Types ---\n\nexport type ConfigField =\n | ConfigTextField\n | ConfigNumberField\n | ConfigBooleanField\n | ConfigSelectField\n | ConfigMultiSelectField\n | ConfigColorField\n | ConfigPasswordField\n | ConfigTextAreaField\n | ConfigSliderField\n | ConfigTagsField\n | ConfigGroupField\n | ConfigSubTabsField\n | ConfigSeparatorField\n | ConfigInfoField\n | ConfigObjectArrayField\n | ConfigModelSelectorField\n | ConfigStorageLocationField\n | ConfigProbeField\n | ConfigButtonField\n | ConfigPipelineEditorField\n | ConfigNodeSelectField\n | ConfigNodeMultiSelectField\n | ConfigZoneEditorField\n | ConfigLiveStatsField\n | ConfigLiveStreamViewerField\n | ConfigPipelineStatsField\n | ConfigStreamNetworkStatsField\n | ConfigDoorbellRecentField\n | ConfigDeviceInfoField\n | ConfigWidgetField\n\nexport interface ConfigFieldBase {\n readonly key: string\n readonly label: string\n readonly description?: string\n readonly required?: boolean\n readonly disabled?: boolean\n readonly placeholder?: string\n /** Default value used when the current value is undefined */\n readonly default?: unknown\n readonly span?: 1 | 2 | 3 | 4\n readonly showWhen?: ConfigCondition\n // Settings-redesign cleanup: `scope?: 'device' | 'global'` removed.\n // In the three-level model, a field's scope is determined by WHICH\n // schema it lives in — `getAddonSettings / getGlobalSettings /\n // getDeviceSettings` — not by a field-level marker. The keys are\n // disjoint across levels by invariant, so a scope marker is\n // redundant.\n /**\n * Save behavior when value changes.\n * - true: save immediately on change (toggles, selects, checkboxes)\n * - false (default): debounce 2 seconds for text/number inputs before saving\n *\n * The UI FormBuilder reads this flag and applies debounce accordingly.\n */\n readonly immediate?: boolean\n /**\n * Declares that changes to this field can only take effect after the\n * owning addon is (re)started — the field is bound at boot time and\n * cannot be hot-reloaded from `onConfigChanged()`. Example: Python\n * inference-pool `concurrency` (pool threads are allocated at pool\n * spawn). The UI surfaces a \"Restart required\" hint, and the\n * framework auto-restarts the addon after the update lands on a flag\n * transition — see `BaseAddon.updateGlobalSettings` /\n * `updateAddonSettings`.\n */\n readonly requiresRestart?: boolean\n /**\n * Override the default placement of this field.\n * Moves it to a different tab and/or section than its parent section.\n * Useful for placing a single setting in a shared tab (e.g., 'advanced').\n */\n readonly placement?: {\n /** Target tab ID (well-known or custom). */\n readonly tab?: string\n /** Target section ID within the tab. Created if it doesn't exist. */\n readonly section?: string\n }\n /**\n * Device-aggregator metadata — only meaningful when this field is part of\n * a `ConfigUISchemaWithValues` merged by `deviceManager.getDeviceSettingsAggregate`\n * / `getDeviceLiveInfoAggregate`.\n *\n * - `readonlyField: true` — render as display-only, no mutation handler\n * - `source: 'live'` — the value comes from the fast-poll live\n * aggregator; the UI re-queries it on its own\n * cadence and swaps the value in place. Default:\n * 'settings' (slow, cached, invalidated on save)\n * - `writerCapName` — when editable, the capability whose provider\n * accepts the mutation via\n * `deviceManager.updateDeviceField`.\n * - `writerAddonId` — when editable, the addon id of the provider\n * for `writerCapName`. Ignored for\n * `readonlyField: true`.\n * - `minRole` — minimum user role required to edit this\n * field. UI uses it to disable the input and\n * show a lock icon; the server still enforces\n * cap-level auth (`admin` for the aggregator\n * writers today). Default: 'admin'.\n *\n * The aggregator tags fields with `writerCapName` + `writerAddonId` before\n * returning them — providers produce clean schemas; provenance is injected\n * based on which (cap, provider) contributed the section.\n *\n * Named `readonlyField` instead of `readonly` to avoid colliding with the\n * TS modifier already implied by the interface fields.\n */\n readonly readonlyField?: boolean\n readonly source?: 'settings' | 'live'\n readonly writerCapName?: string\n readonly writerAddonId?: string\n readonly minRole?: 'viewer' | 'admin' | 'super_admin'\n /**\n * Optional inline action icons shown on the right of the field\n * control. Each action is a compact icon button that dispatches\n * through the same `onAction(action, key)` handler the button-field\n * type uses — keeps the action pipeline single-sourced. Common use:\n * readonly URL field with a \"regenerate\" icon, probe field with a\n * \"copy\" shortcut, etc.\n */\n readonly actions?: readonly FieldInlineAction[]\n /**\n * Declare this field as a *collection* of its underlying primitive.\n * When set, the stored value is an array (`T[]`) instead of a scalar\n * (`T`), and the form renderer shows:\n * - `min` initial instances (empty slots if no value stored yet)\n * - an `+ Add` button when the current count < `max`\n * - a remove icon on each instance when the current count > `min`\n * - an item counter badge (e.g. `2/3`) next to the section header\n *\n * Applies uniformly to every scalar-valued field type (text, number,\n * boolean, select, color, probe, password, textarea, slider, tags,\n * model-selector, storage-location). Structural fields (separator,\n * info, button) and group fields ignore this flag.\n *\n * Probe fields hit `testCreationField` / settings-contribution\n * probing per-index — the handler receives the full array and an\n * `index` hint so it can resolve just that slot.\n */\n readonly multiple?: ConfigFieldMultiple\n}\n\n/**\n * Array-widget metadata for a `ConfigFieldBase`. See `multiple` on\n * `ConfigFieldBase` for the activation semantics.\n */\nexport interface ConfigFieldMultiple {\n /** Minimum item count — always rendered, no remove button when count == min. */\n readonly min: number\n /** Maximum item count — Add button hidden when count == max. */\n readonly max: number\n /** Label for the \"add\" affordance. Default: \"Add\". */\n readonly addLabel?: string\n /** Template for each item's label (${n} = 1-based index). Default: none. */\n readonly itemLabel?: string\n /**\n * Default value each newly-added instance starts with. Falls back to\n * the field-level `default`, then to the empty string for string\n * fields or `null` for everything else.\n */\n readonly itemDefault?: unknown\n}\n\n/** Inline action icon attached to any ConfigField. */\nexport interface FieldInlineAction {\n /** Action identifier forwarded to the FormBuilder `onAction` handler. */\n readonly action: string\n /** Lucide icon name (e.g. 'refresh-cw', 'copy', 'external-link'). */\n readonly icon: string\n /** Tooltip shown on hover. */\n readonly tooltip: string\n /** Visual variant — `danger` flags destructive actions in red. */\n readonly variant?: 'default' | 'danger' | 'primary'\n /** Optional confirmation prompt before dispatching. */\n readonly confirmMessage?: string\n}\n\nexport interface ConfigCondition {\n field: string\n equals?: unknown\n notEquals?: unknown\n in?: unknown[]\n notIn?: unknown[]\n /**\n * For `multiselect` / `tags` / array-valued fields: matches when the\n * referenced field's array value INCLUDES the given primitive. Example:\n * `{ field: 'motionSources', includes: 'analyzer' }` shows the\n * dependent field only when the analyzer source is selected.\n */\n includes?: unknown\n /** Inverse of `includes` — show when the field's array value does NOT\n * contain the given primitive. */\n notIncludes?: unknown\n}\n\nexport interface ConfigTextField extends ConfigFieldBase {\n type: 'text'\n maxLength?: number\n pattern?: string\n inputType?: 'text' | 'url' | 'email'\n}\n\nexport interface ConfigNumberField extends ConfigFieldBase {\n type: 'number'\n min?: number\n max?: number\n step?: number\n unit?: string\n}\n\nexport interface ConfigBooleanField extends ConfigFieldBase {\n type: 'boolean'\n style?: 'switch' | 'checkbox'\n}\n\nexport interface ConfigSelectField extends ConfigFieldBase {\n type: 'select'\n options: ConfigOption[]\n dependsOn?: Record<string, unknown>\n}\n\nexport interface ConfigMultiSelectField extends ConfigFieldBase {\n type: 'multiselect'\n options: ConfigOption[]\n maxItems?: number\n}\n\nexport interface ConfigColorField extends ConfigFieldBase {\n type: 'color'\n presets?: string[]\n}\n\n/** Select a single cluster node from the live topology. Options are\n * populated dynamically by the UI via useClusterNodes — no server-side\n * option list needed. */\nexport interface ConfigNodeSelectField extends ConfigFieldBase {\n type: 'node-select'\n /** When true, include offline nodes (greyed out). Default: false. */\n showOffline?: boolean\n}\n\n/** Select multiple cluster nodes from the live topology. */\nexport interface ConfigNodeMultiSelectField extends ConfigFieldBase {\n type: 'node-multiselect'\n showOffline?: boolean\n maxItems?: number\n}\n\nexport interface ConfigPasswordField extends ConfigFieldBase {\n type: 'password'\n showToggle?: boolean\n}\n\nexport interface ConfigTextAreaField extends ConfigFieldBase {\n type: 'textarea'\n rows?: number\n maxLength?: number\n /**\n * When true, the stored value is a JSON-serializable object/array and\n * the UI shows it as pretty-printed JSON, with parse-on-save semantics.\n * `hydrateSchema` takes care of stringifying on the way out; the\n * FormBuilder is expected to parse before emitting the patch.\n *\n * Used by `zodEntriesToConfigUI` when the Zod schema is an\n * array/object — falls back gracefully when the FormBuilder hasn't\n * implemented parse-on-save yet (the field still renders the JSON\n * string instead of `[object Object],…`).\n */\n isJson?: boolean\n}\n\nexport interface ConfigSliderField extends ConfigFieldBase {\n type: 'slider'\n min: number\n max: number\n step?: number\n showValue?: boolean\n unit?: string\n default?: number\n /** Display scale factor: displayed = stored / displayScale. E.g., displayScale=1000 shows ms as seconds. */\n displayScale?: number\n /** When true, allows a \"not set\" state where the value is null (e.g., \"Auto\" mode) */\n nullable?: boolean\n /** Label shown when the value is null (default: \"Auto\") */\n nullLabel?: string\n /**\n * When true, render +/− stepper buttons flanking the numeric input.\n * Each click increments/decrements by `step` (default 1) and clamps\n * to `[min, max]`. Pairs with `showValue` so the operator can fine-\n * tune from the keyboard / pointer without scrubbing the slider.\n */\n showStepper?: boolean\n}\n\nexport interface ConfigTagsField extends ConfigFieldBase {\n type: 'tags'\n suggestions?: string[]\n maxTags?: number\n}\n\nexport interface ConfigGroupField extends ConfigFieldBase {\n type: 'group'\n fields: readonly ConfigField[]\n style?: 'card' | 'inline' | 'accordion'\n defaultCollapsed?: boolean\n}\n\n/** Visual separator between fields */\nexport interface ConfigSeparatorField {\n type: 'separator'\n key: string\n}\n\n// --- Sub-tabs Field ---\n//\n// Renders a nested tab strip inside a section. Each sub-tab carries its\n// own list of `ConfigField`s. Values are flat across all sub-tabs (the\n// outer save controller treats them like any other field key) — the\n// sub-tabs are purely a layout primitive, not a save scope. Use when a\n// section needs to host many fields that fall into clearly separable\n// categories (e.g. one sub-tab per camera stream source).\n\n/** A single sub-tab inside a `ConfigSubTabsField`. */\nexport interface ConfigSubTabDefinition {\n readonly id: string\n readonly label: string\n readonly icon?: string\n /** Short text shown next to the label (e.g. live status / counter). */\n readonly badge?: string\n readonly fields: readonly ConfigField[]\n}\n\nexport interface ConfigSubTabsField extends ConfigFieldBase {\n type: 'sub-tabs'\n /** Tab definitions; rendered in array order. The first tab is active by default. */\n tabs: readonly ConfigSubTabDefinition[]\n}\n\n/** Read-only informational text */\nexport interface ConfigInfoField {\n type: 'info'\n key: string\n label: string\n content: string\n variant?: 'info' | 'warning' | 'success' | 'danger'\n}\n\n/**\n * Read-only structured table for diagnostic data. Renders as a row-per-\n * entry list with column headers. Use when a section needs to surface\n * multiple parallel records (live sessions, socket-pool entries, recent\n * doorbell presses, …) — replaces the older \"joined-string in an info\n * field\" pattern that lost structure on long entries.\n *\n * Columns describe how to render each cell. Each entry in `value` is a\n * record keyed by the column `key`. Missing keys render as em-dash.\n *\n * NOT editable — the FormBuilder ignores the field for save patches.\n */\nexport interface ConfigObjectArrayField {\n type: 'object-array'\n key: string\n label: string\n description?: string\n /**\n * Column definitions in render order. The `kind` hint controls cell\n * formatting:\n * - `text` (default): plain string; null/undefined → em-dash\n * - `monospace`: monospace font (good for IPs, sessionIds)\n * - `status`: small colored dot + label, value should be one of\n * 'ok' | 'warn' | 'danger' | 'idle' | 'unknown'\n * - `duration`: number of ms, formatted as \"1m 23s\"\n * - `timestamp`: number (ms epoch), formatted as locale time\n */\n columns: ReadonlyArray<{\n readonly key: string\n readonly label: string\n readonly kind?: 'text' | 'monospace' | 'status' | 'duration' | 'timestamp'\n /** Optional fixed width hint (CSS values: '120px', '20%', etc). */\n readonly width?: string\n }>\n /** Rows. Empty array renders `emptyMessage`. */\n value: ReadonlyArray<Record<string, unknown>>\n /** Shown when `value` is empty. Default: \"No entries\". */\n emptyMessage?: string\n}\n\nexport interface ConfigOption {\n value: string\n label: string\n description?: string\n icon?: string\n}\n\n// --- Model Selector Field ---\n\nexport interface ConfigModelSelectorField extends ConfigFieldBase {\n type: 'model-selector'\n /** Filter models by type */\n modelType?: string\n /** Allow user to enter a custom local path or URL (default: true) */\n allowCustomPath?: boolean\n /** Allow file upload via UI (default: true) */\n allowUpload?: boolean\n /** Accepted file extensions for upload (default: ['.onnx']) */\n acceptExtensions?: string[]\n /** URL to model conversion documentation/guide */\n conversionGuideUrl?: string\n /** Brief text explaining what models are compatible */\n compatibilityNote?: string\n /** Legacy: inline catalog entries */\n catalog?: readonly ModelCatalogEntry[]\n allowCustom?: boolean\n acceptFormats?: readonly ModelFormat[]\n allowConversion?: boolean\n requiredMetadata?: readonly (keyof CustomModelMetadata)[]\n outputFormatHint?: ModelOutputFormat\n}\n\n// --- Probe Field ---\n\n/** Result of probing a single field value (returned by IDeviceProvider.testField) */\nexport interface FieldProbeResult {\n status: 'ok' | 'error'\n /** Labels to display as chips (e.g. \"1920×1080\", \"H.265\", \"25fps\") */\n labels?: readonly string[]\n /** Error message when status is 'error' */\n error?: string\n}\n\n/**\n * A probeable input field. Renders as a text input with a test button.\n * The provider implements the actual probing logic via IDeviceProvider.testField.\n *\n * UX states:\n * - idle: muted icon, no labels\n * - probing: spinner icon\n * - ok: green check icon + provider-returned labels as chips\n * - error: red icon + error message\n */\nexport interface ConfigProbeField extends ConfigFieldBase {\n type: 'probe'\n /** Input type hint for the text input (default: 'url') */\n inputType?: 'url' | 'text'\n}\n\n// --- Storage Location Selector Field ---\n\nimport type { StorageLocationType } from './storage.js'\n\nexport interface ConfigStorageLocationField extends ConfigFieldBase {\n type: 'storage-location'\n /** Which location type this field selects a provider for */\n locationType: StorageLocationType\n /** Show available space indicator next to each provider option */\n showAvailableSpace?: boolean\n}\n\nexport interface ConfigButtonField extends ConfigFieldBase {\n type: 'button'\n /** Button label text */\n buttonLabel: string\n /** Visual variant */\n variant?: 'default' | 'danger' | 'primary'\n /** tRPC action identifier — the form handler calls this action when pressed */\n action: string\n /** Confirmation prompt before executing (optional) */\n confirmMessage?: string\n}\n\n/**\n * Describes an async resolver that the form renderer should call to\n * fetch deferred-load data a field depends on (e.g. the addon catalog\n * for a pipeline-editor, a dynamic options list for a select, …).\n *\n * The renderer dispatches through `client.trpc[capName][methodName]\n * .query(input)` — the field declares WHICH cap + method + input to\n * call, and the renderer stays oblivious to the endpoint naming.\n * Results are cached client-side keyed by `(capName, methodName,\n * input)` so two fields pointing at the same resolver deduplicate\n * automatically.\n *\n * Not an endpoint to arbitrary HTTP — the tRPC proxy gates it to the\n * server's declared cap surface + each cap's auth rules, same as\n * every other `.query()` call the UI makes.\n */\nexport interface AsyncResolverRef {\n /** tRPC cap namespace (e.g. `pipelineExecutor`, `pipelineOrchestrator`). */\n readonly capName: string\n /** Method on that cap — must be a `.query()` (no mutations via resolvers). */\n readonly methodName: string\n /** Input payload passed verbatim; serialised into the React Query key. */\n readonly input?: Readonly<Record<string, unknown>>\n}\n\n/**\n * Camera pipeline editor field (stateless-pipeline Phase 6, option B).\n *\n * The FormBuilder renders this as the rich `PipelineBuilder` composite\n * (step tree + engine picker + template picker) instead of a flat\n * input. `value` is always a fully-resolved `CameraPipelineConfig` —\n * when the camera has no persisted pipeline, the contributor\n * (orchestrator) fills it with the cluster default server-side so\n * the renderer stays dumb about nullability.\n *\n * `nodeId` names the runner node whose addon catalog powers the\n * editor. It's exposed explicitly (rather than buried inside the\n * resolver) for diagnostics, UI labels, and cache keying. The\n * catalog itself isn't embedded — `catalogResolver` tells the\n * renderer how to lazy-load it via the shared resolver hook, which\n * React Query caches once per `(capName, methodName, input)`. That\n * way 50 cameras assigned to the same node don't each trigger 50\n * catalog fetches.\n *\n * Templates are NOT described by a resolver — they're a hub-wide\n * library fetched in one place by the editor directly.\n */\nexport interface ConfigPipelineEditorField extends ConfigFieldBase {\n type: 'pipeline-editor'\n /** Runner node whose catalog powers the editor. */\n readonly nodeId: string\n /** The camera this field edits — used by the renderer to fetch per-camera settings. */\n readonly deviceId: number\n /** How to fetch the addon catalog for this node. */\n readonly catalogResolver: AsyncResolverRef\n}\n\n/**\n * Polygon zone CRUD editor field. Renders a canvas with a backdrop\n * (stream snapshot or live preview) where the operator draws polygon\n * zones, plus the list of existing zones (user + onboard) with\n * editing affordances.\n *\n * Stateless from the form's point of view: bound directly to\n * `api.zones.*` mutations, NOT to the form's `value`. The renderer\n * subscribes to `dev.state.zones.onChanged` for live updates so two\n * operators editing the same camera see each other's changes\n * immediately. `value` is therefore not consumed by the renderer\n * (kept on the discriminated union only so the form layout engine\n * stays homogeneous).\n *\n * Every zone is operator-drawn and fully editable — firmware-reported\n * onboard zones are deliberately out of scope for the first iteration.\n */\nexport interface ConfigZoneEditorField extends ConfigFieldBase {\n type: 'zone-editor'\n /**\n * Optional backdrop hint. `'snapshot'` (default) fetches a still\n * via the snapshot cap; `'stream'` overlays the live WebRTC view.\n *\n * The renderer reads the `deviceId` from the device-details page\n * context — the field doesn't carry it inline so the schema stays\n * device-agnostic and addons can ship a static contribution.\n */\n readonly backdrop?: 'snapshot' | 'stream'\n}\n\n/**\n * Live statistics field — bound to the \"Live Stats\" top-tab declared\n * by the analytics addon. Renders occupancy snapshots, audio metrics\n * (current + history), and rolling-window charts. The form's `value`\n * is unused; the renderer reads `deviceId` from the device-details\n * page context and pulls live data through DeviceProxy.\n */\nexport interface ConfigLiveStatsField extends ConfigFieldBase {\n type: 'live-stats'\n}\n\n// ---------------------------------------------------------------------------\n// Overview-tab field types\n// ---------------------------------------------------------------------------\n//\n// These five field types describe the \"overview\" top-tab blocks. Each\n// addon contributes the block(s) it owns via `getDeviceSettingsContribution`\n// (`tab: 'overview', location: 'top-tab'`), and the admin-ui's\n// `CustomFieldRenderersProvider` resolves the field `type` to the\n// corresponding adapter component. Field shapes are intentionally\n// minimal — the renderer reads everything from the device-details\n// context (deviceId, name, capabilities, …) so the schema stays\n// device-agnostic and addons can ship static contributions.\n//\n// Owners (Fase B will wire these):\n// - live-stream-viewer → addon-stream-broker\n// - pipeline-stats → addon-pipeline-orchestrator\n// - stream-network-stats → addon-stream-broker (network-quality cap)\n// - doorbell-recent → addon-provider-reolink (gated on Doorbell feature)\n// - device-info → device-manager (base section, redirected to overview)\n\n/**\n * Live-stream player block — snapshot poster + play/stop + quality\n * selector + detection overlay. Contributed by `addon-stream-broker`.\n */\nexport interface ConfigLiveStreamViewerField extends ConfigFieldBase {\n type: 'live-stream-viewer'\n}\n\n/**\n * Pipeline-quick-stats block — Phase / Detection FPS / Inference time /\n * Active Tracks. Contributed by `addon-pipeline-orchestrator`. The\n * adapter pulls live values from `pipelineRunner.getCameraMetrics` +\n * `pipelineAnalytics.getActiveTracks` via the device proxy.\n */\nexport interface ConfigPipelineStatsField extends ConfigFieldBase {\n type: 'pipeline-stats'\n}\n\n/**\n * Stream network-quality block — per-stream bitrate / packet loss\n * table sourced from the network-quality cap.\n */\nexport interface ConfigStreamNetworkStatsField extends ConfigFieldBase {\n type: 'stream-network-stats'\n}\n\n/**\n * Doorbell recent-press history block. Contributed by\n * `addon-provider-reolink` only when the device advertises the\n * `DoorbellButton` feature; absent on every other camera.\n */\nexport interface ConfigDoorbellRecentField extends ConfigFieldBase {\n type: 'doorbell-recent'\n /** Max history rows to render (default: 10). */\n readonly historyLimit?: number\n}\n\n/**\n * Device-info block — id / stableId / name / type / provider / capability\n * badges. Contributed by `device-manager`'s base section, redirected to\n * the overview tab via `placement.tab = 'overview'`.\n */\nexport interface ConfigDeviceInfoField extends ConfigFieldBase {\n type: 'device-info'\n}\n\n/**\n * Generic widget field — addon-contributed widget mounted by the\n * shared `<WidgetSlot>` runtime via the `WidgetRegistry`.\n *\n * The form-builder reads `widgetId` as the public widget identifier\n * (`<addonId>/<stableId>`) and forwards `widgetConfig` as `props.config`\n * to the widget. Different from the legacy bespoke field types\n * (`'live-stats'`, `'zone-editor'`, `'pipeline-stats'`, …) which are now\n * DEPRECATED — those required per-type renderer registration in\n * admin-ui; widget fields go through the generic registry without a\n * code change in admin-ui.\n *\n * `key` is the form-field's unique identifier (kept distinct from the\n * widget identifier so the same widget can be mounted twice in the\n * same form). `widgetId` is the public id resolved against the\n * WidgetRegistry.\n *\n * Field carries no stored value — the widget owns its own state via\n * DeviceProxy / runtime-state hooks. Placed in\n * `ConfigFieldWithValue` only so the discriminated-union round-trip\n * through `hydrateSchema` stays homogeneous (`value: null`).\n */\nexport interface ConfigWidgetField extends ConfigFieldBase {\n readonly type: 'widget'\n /** `<addonId>/<stableId>` — resolved via the WidgetRegistry. */\n readonly widgetId: string\n /** Per-instance config payload forwarded to the widget as `props.config`. */\n readonly widgetConfig?: Readonly<Record<string, unknown>>\n}\n\n\n// IConfigurable is no longer a separate interface — config methods are part of ICamstackAddon.\n\n// ---------------------------------------------------------------------------\n// Schema + values fused (\"hydrated\") for the new three-level settings API\n// ---------------------------------------------------------------------------\n//\n// `ConfigUISchemaWithValues` is the shape returned by the new\n// `getAddonSettings() / getGlobalSettings() / getDeviceSettings()` family of\n// methods on `ICamstackAddon`. Each leaf field carries its *current* value\n// inline so the admin UI form builder can render in one pass without having\n// to cross-reference a separate `values` object.\n//\n// Hydration rule (applied by `hydrateSchema` below):\n// value = storedValues[key] ?? field.default ?? null\n//\n// `value` is NEVER `undefined` — consumers can rely on `in` / `??` without\n// surprises. Fields that don't carry a value (separator, info) are returned\n// unchanged.\n\n/** A `ConfigField` with its current value attached inline. */\nexport type ConfigFieldWithValue =\n | (ConfigTextField & { readonly value: unknown })\n | (ConfigNumberField & { readonly value: unknown })\n | (ConfigBooleanField & { readonly value: unknown })\n | (ConfigSelectField & { readonly value: unknown })\n | (ConfigMultiSelectField & { readonly value: unknown })\n | (ConfigColorField & { readonly value: unknown })\n | (ConfigPasswordField & { readonly value: unknown })\n | (ConfigTextAreaField & { readonly value: unknown })\n | (ConfigSliderField & { readonly value: unknown })\n | (ConfigTagsField & { readonly value: unknown })\n | (ConfigGroupFieldWithValue)\n | (ConfigSubTabsFieldWithValue)\n | ConfigSeparatorField\n | ConfigInfoField\n | ConfigObjectArrayField\n | (ConfigModelSelectorField & { readonly value: unknown })\n | (ConfigStorageLocationField & { readonly value: unknown })\n | (ConfigProbeField & { readonly value: unknown })\n | (ConfigButtonField) // buttons are actions, not values\n | (ConfigPipelineEditorField & { readonly value: unknown })\n | (ConfigNodeSelectField & { readonly value: unknown })\n | (ConfigNodeMultiSelectField & { readonly value: unknown })\n | (ConfigZoneEditorField & { readonly value: unknown })\n | (ConfigLiveStatsField & { readonly value: unknown })\n | (ConfigLiveStreamViewerField & { readonly value: unknown })\n | (ConfigPipelineStatsField & { readonly value: unknown })\n | (ConfigStreamNetworkStatsField & { readonly value: unknown })\n | (ConfigDoorbellRecentField & { readonly value: unknown })\n | (ConfigDeviceInfoField & { readonly value: unknown })\n | ConfigWidgetField // widgets manage their own state; no form value\n\n/** Recursive version of `ConfigGroupField` with hydrated child fields. */\nexport interface ConfigGroupFieldWithValue extends ConfigFieldBase {\n readonly type: 'group'\n readonly fields: readonly ConfigFieldWithValue[]\n readonly style?: 'card' | 'inline' | 'accordion'\n readonly defaultCollapsed?: boolean\n readonly value?: undefined // groups don't carry their own value\n}\n\n/** Hydrated sibling of `ConfigSubTabDefinition` — fields inside each\n * sub-tab carry their resolved values. */\nexport interface ConfigSubTabDefinitionWithValue {\n readonly id: string\n readonly label: string\n readonly icon?: string\n readonly badge?: string\n readonly fields: readonly ConfigFieldWithValue[]\n}\n\n/** Recursive version of `ConfigSubTabsField` with hydrated child fields. */\nexport interface ConfigSubTabsFieldWithValue extends ConfigFieldBase {\n readonly type: 'sub-tabs'\n readonly tabs: readonly ConfigSubTabDefinitionWithValue[]\n readonly value?: undefined // sub-tabs are layout, not a value\n}\n\nexport interface ConfigSectionWithValues extends Omit<ConfigSection, 'fields'> {\n /**\n * Array kept mutable (not `readonly`) to stay assignable to the Zod-inferred\n * wire shape produced by `DEVICE_SETTINGS_CONTRIBUTION_METHODS.getDeviceSettingsContribution.output`.\n * Consumers treat it as immutable by convention — mutation is never\n * expected and would be a bug.\n */\n fields: ConfigFieldWithValue[]\n}\n\nexport interface ConfigUISchemaWithValues {\n /** See `ConfigSectionWithValues.fields` — kept mutable for Zod wire compat. */\n tabs?: ConfigTabDeclaration[]\n sections: ConfigSectionWithValues[]\n}\n\n// ---------------------------------------------------------------------------\n// `hydrateSchema` — backend-side helper\n// ---------------------------------------------------------------------------\n\n/**\n * Field types that never carry a value (separator, info, button). Used by\n * `hydrateSchema` to skip the `value` injection for structural-only fields.\n */\nfunction isValuelessField(\n field: ConfigField,\n): field is ConfigSeparatorField | ConfigInfoField | ConfigButtonField | ConfigObjectArrayField | ConfigWidgetField {\n return field.type === 'separator'\n || field.type === 'info'\n || field.type === 'button'\n || field.type === 'object-array'\n || field.type === 'widget'\n}\n\n/**\n * Merge a `ConfigUISchema` with a raw `values` record into a\n * `ConfigUISchemaWithValues`. Used by every `get*Settings` backend endpoint\n * before returning to the admin UI. Groups are walked recursively.\n *\n * For each leaf field:\n * - structural fields (`separator`, `info`, `button`) pass through unchanged\n * - other fields get `value = values[key] ?? field.default ?? null`\n *\n * Unknown keys in `values` (keys not declared in the schema) are silently\n * ignored — they don't contribute to the output. Missing keys fall back to\n * the schema default or `null`. This mirrors the old backend behaviour where\n * `FormBuilder` rendered `values[key] ?? field.default`.\n */\nexport function hydrateSchema(\n schema: ConfigUISchema,\n values: Record<string, unknown>,\n): ConfigUISchemaWithValues {\n return {\n ...(schema.tabs ? { tabs: [...schema.tabs] } : {}),\n sections: schema.sections.map((section) => ({\n ...section,\n fields: section.fields.map((field) => hydrateField(field, values)),\n })),\n }\n}\n\nfunction hydrateField(\n field: ConfigField,\n values: Record<string, unknown>,\n): ConfigFieldWithValue {\n // Structural fields (separator / info / button) pass through unchanged —\n // they carry no stored value.\n if (isValuelessField(field)) {\n return field\n }\n\n // Groups are recursive — hydrate their children but don't attach a top-level value.\n if (field.type === 'group') {\n const hydratedChildren = field.fields.map((child) => hydrateField(child, values))\n const out: ConfigGroupFieldWithValue = {\n ...field,\n fields: hydratedChildren,\n }\n return out\n }\n\n // Sub-tabs are recursive too — hydrate fields inside every sub-tab but\n // skip the top-level value (sub-tabs are layout, not a value).\n if (field.type === 'sub-tabs') {\n const hydratedTabs: ConfigSubTabDefinitionWithValue[] = field.tabs.map((tab) => ({\n ...tab,\n fields: tab.fields.map((child) => hydrateField(child, values)),\n }))\n const out: ConfigSubTabsFieldWithValue = {\n ...field,\n tabs: hydratedTabs,\n }\n return out\n }\n\n // Leaf valued field. After the guards above, `field` is narrowed to every\n // variant of ConfigField that extends ConfigFieldBase (i.e. has `key` +\n // optional `default`), so we can read them directly.\n const key: string = field.key\n const storedValue = Object.prototype.hasOwnProperty.call(values, key) ? values[key] : undefined\n const defaultValue = field.default\n\n // Multiple-mode: normalise to an array of `max(min, storedLen)` items.\n // Missing slots are padded with the field's `itemDefault` → `default`\n // → type-appropriate zero value so the renderer can always assume the\n // value is an array of exactly the right length.\n if (field.multiple) {\n const stored: readonly unknown[] = Array.isArray(storedValue)\n ? storedValue\n : (storedValue !== undefined && storedValue !== null ? [storedValue] : [])\n const itemFallback = field.multiple.itemDefault !== undefined\n ? field.multiple.itemDefault\n : (defaultValue !== undefined ? defaultValue : typeOf(field) === 'string' ? '' : null)\n const minCount = Math.max(field.multiple.min, stored.length)\n const items: unknown[] = []\n for (let i = 0; i < minCount; i++) {\n items.push(i < stored.length ? stored[i] : itemFallback)\n }\n return { ...field, value: items }\n }\n\n const rawValue: unknown = storedValue !== undefined\n ? storedValue\n : (defaultValue !== undefined ? defaultValue : null)\n // Textarea with `isJson: true` serialises the stored object/array as\n // pretty JSON so the input is human-editable. The save path is\n // expected to `JSON.parse` before forwarding the patch to the writer.\n const value = (field.type === 'textarea' && field.isJson && rawValue !== null && typeof rawValue === 'object')\n ? JSON.stringify(rawValue, null, 2)\n : rawValue\n // Spread-with-added-value preserves the discriminated-union variant.\n const hydrated = { ...field, value }\n return hydrated\n}\n\n/**\n * Rough \"value family\" classifier used by `hydrateField`'s multiple\n * fallback to pick a sensible zero-value when no `itemDefault` / no\n * field `default` / no stored value is available.\n */\nfunction typeOf(field: ConfigField): 'string' | 'number' | 'boolean' | 'other' {\n switch (field.type) {\n case 'text':\n case 'textarea':\n case 'password':\n case 'color':\n case 'probe':\n return 'string'\n case 'number':\n case 'slider':\n return 'number'\n case 'boolean':\n return 'boolean'\n default:\n return 'other'\n }\n}\n","import type { FrameResult, AudioResult } from '../types/detection.js'\nimport type { PipelineExecutionTrace } from '../types/pipeline-step.js'\nimport type { MotionRegion } from '../capabilities/motion-detection.cap.js'\nimport type { CameraPipelineConfig } from '../types/camera-pipeline.js'\nimport type { CameraMetrics } from './api-shared.js'\nimport type { RunnerLocalLoad } from './pipeline-runner-capability.js'\nimport type { BrokerStats } from './stream-broker.js'\nimport type { PipelineEngineChoice } from '../types/pipeline.js'\nimport type { NodeProcess, SystemResourceSnapshot } from './metrics-provider.js'\n\n// ---------------------------------------------------------------------------\n// Event source\n// ---------------------------------------------------------------------------\n\nexport interface EventSource {\n /** Primary source type: 'core', 'addon', 'device', 'pipeline', etc. */\n type: string\n /** Primary identifier — addonId when type='addon', deviceId when type='device', etc. */\n id: string | number\n /** Agent/node that originated the event (e.g. 'hub', 'agent-a1b2c3'). */\n nodeId?: string\n /** Addon that originated the event (populated even when type='device'). */\n addonId?: string\n /** Device the event relates to (populated even when type='addon'). */\n deviceId?: number\n}\n\n// ---------------------------------------------------------------------------\n// Detection event payloads\n// ---------------------------------------------------------------------------\n\n// MotionAnalysisRegion removed (2026-04-14) — consumers now use\n// `MotionRegion` from the motion-detection capability directly. The two\n// interfaces had identical shapes; keeping both was a duplication leak.\n\n/**\n * One detection entry emitted by a camera's firmware (not by the local\n * AI pipeline). Carried inside `detection.camera-native` events —\n * native providers fan out to this category for each ring/motion/AI\n * alarm push they receive from the camera.\n */\nexport interface CameraNativeDetection {\n /**\n * Firmware-reported class. Loose string to accommodate heterogeneous\n * firmwares (Reolink uses 'people'/'vehicle'/'animal'/…; ONVIF uses\n * 'PeopleDetect'; etc.). Common values: 'motion', 'person', 'vehicle',\n * 'animal', 'face', 'package', 'other', 'doorbell'.\n */\n readonly class: string\n /** Ms epoch when the server observed the push from the camera. */\n readonly timestamp: number\n /** Optional firmware-provided confidence [0..1]. Most firmwares don't expose it. */\n readonly confidence?: number\n /** Optional bbox [x, y, w, h] normalised [0..1]. Rare on native events. */\n readonly bbox?: readonly [number, number, number, number]\n}\n\nexport interface MotionAnalysisPayload {\n detected: boolean\n regionCount: number\n regions: readonly MotionRegion[]\n frameWidth: number\n frameHeight: number\n analysisMs: number\n [key: string]: unknown\n}\n\n/**\n * Motion phase transition payload. Single source of truth lives in\n * `motion.cap.ts` as `MotionOnMotionChangedDataSchema` — this alias\n * just re-exports the inferred type with the `[key: string]: unknown`\n * loose-index pattern the bus uses for forward-compat. Don't add\n * fields here; extend the schema in motion.cap.ts.\n */\nexport type MotionOnMotionChangedPayload =\n import('../capabilities/motion.cap.js').MotionOnMotionChangedData\n & { [key: string]: unknown }\n\n/** Raw motion zone from CCL (before minArea filter). */\nexport interface MotionRawZone {\n readonly bbox: readonly [number, number, number, number] // [x1, y1, x2, y2]\n readonly pixelCount: number\n readonly changeScore: number // 0-1 intensity\n}\n\n/** All raw motion zones — emitted for UI debug overlay. */\nexport interface MotionZonesRawPayload {\n readonly deviceId: number\n readonly zones: readonly MotionRawZone[]\n readonly frameSize: { readonly width: number; readonly height: number }\n readonly timestamp: number\n [key: string]: unknown\n}\n\nexport interface DetectionResultPayload {\n /**\n * The post-processed frame result the frontend consumes. Already\n * contains `width`/`height` + `detections[]` + optional debug. No\n * pipeline-raw wrapper — the new `FrameResult` shape IS the payload.\n */\n frame: FrameResult\n /** Events emitted by the analysis pipeline (tracking, scene state, face rec). */\n analysisResults: readonly unknown[]\n [key: string]: unknown\n}\n\n/**\n * Raw inference output emitted by `addon-pipeline-runner` per detection\n * frame. Carries the FrameResult produced by the runner — the hub-side\n * wiring service subscribes, applies the analysis pipeline +\n * notifications, and re-emits as `detection.result`.\n */\nexport interface PipelineInferenceResultPayload {\n readonly deviceId: number\n readonly frame: FrameResult\n /** The Moleculer node id of the runner that produced this result. */\n readonly nodeId: string\n readonly [key: string]: unknown\n}\n\n/**\n * Live per-audio-chunk output emitted by the pipeline-orchestrator for\n * each camera with audio analysis enabled. Mirrors `PipelineInferenceResultPayload`\n * but for audio: carries the canonical `AudioResult` produced by running\n * the audio-analyzer + audio-classifier inline on the hub.\n *\n * Replaces the legacy split `detection.audio.level` /\n * `detection.audio.classification` events — consumers should read\n * `frame.level` for dBFS/RMS and `frame.detections` for classifier\n * matches (both on the same single event).\n */\nexport interface PipelineAudioInferenceResultPayload {\n readonly deviceId: number\n readonly frame: AudioResult\n /** Node id of the host that ran the analyzer — always `'hub'` today\n * because audio runs inline on the hub, but the field is kept so the\n * event shape matches `PipelineInferenceResultPayload`. */\n readonly nodeId: string\n readonly [key: string]: unknown\n}\n\n/**\n * Camera assignment lifecycle payload emitted by `addon-pipeline-orchestrator`\n * when a camera is assigned to or unassigned from an agent runner. Used by\n * the UI / metrics dashboard. No frame data.\n */\nexport interface PipelineCameraAssignmentPayload {\n readonly deviceId: number\n readonly agentNodeId: string\n /** True when the assignment was set manually (preferredAgent setting), false when chosen by the load balancer. */\n readonly pinned: boolean\n readonly reason: 'manual' | 'capacity' | 'hardware-affinity' | 'failover' | 'rebalance' | 'unassigned'\n readonly [key: string]: unknown\n}\n\n/**\n * Capability binding change payload emitted whenever an operator picks\n * a different addon to implement a capability on a node. Each kernel\n * process subscribes to this event and updates its local\n * `preferredProviderRegistry` so subsequent capability lookups return\n * the newly chosen provider.\n *\n * The event lives under `capability.binding-changed` because binding\n * is a kernel-level concept used by any cap provider (not just the\n * pipeline flow). It was renamed from `pipeline.binding-changed` to\n * reflect that broader scope.\n */\nexport interface CapabilityBindingChangedPayload {\n readonly nodeId: string\n readonly capName: string\n /** New preferred addon id, or null when the binding was cleared. */\n readonly addonId: string | null\n readonly [key: string]: unknown\n}\n\nexport interface PhaseTransitionPayload {\n deviceId: number\n from: 'watching' | 'active'\n to: 'watching' | 'active'\n reason: 'motion_detected' | 'cooldown_expired'\n /** Motion source that armed the cooldown — present on both ON and OFF. */\n source?: 'onboard' | 'analyzer'\n /** Cooldown window in ms that was/is active for this transition. */\n cooldownMs?: number\n /** Ms epoch of the transition. */\n timestamp?: number\n [key: string]: unknown\n}\n\n// Legacy `AudioLevelPayload` / `AudioClassificationPayload` were removed\n// when the live audio path was migrated to the canonical `AudioResult`\n// shape — consumers now subscribe to `pipeline.audio-inference-result`\n// and read level + detections from the single payload.\n\n// ---------------------------------------------------------------------------\n// System readiness protocol — see docs/superpowers/specs/2026-04-19-system-readiness-design.md\n// ---------------------------------------------------------------------------\n\n/**\n * Scope of a readiness transition — the \"who does this ready/down apply to\".\n *\n * Two shapes today:\n * - `global` for singletons that are cluster-wide (there is only one hub).\n * - `node` for per-process providers (one readiness per broker nodeID).\n *\n * `device` scope covers per-device native caps registered via\n * `DeviceContext.registerNativeCap(cap, provider)`. Consumers of cross-\n * process per-device caps (stream-broker, orchestrator, snapshot, webrtc)\n * `awaitReady(capName, {type:'device', deviceId})` before calling the\n * native-cap bridge so they don't race the service-advertise window.\n * On worker disconnect the hub-side registry's `agent.offline` demux\n * synthesises `down` for every device-scoped cap whose `sourceNodeId`\n * matches the offline node — same pattern as node-scoped synthesis.\n */\nexport type ReadinessScope =\n | { readonly type: 'global' }\n | { readonly type: 'node'; readonly nodeId: string }\n | { readonly type: 'device'; readonly deviceId: number }\n\n/** States a capability provider transitions through. */\nexport type ReadinessState = 'starting' | 'ready' | 'down'\n\n/**\n * Payload for `system.ready-state` events.\n *\n * `generation` is a per-process random identifier that stays constant\n * for the producer's lifetime and changes whenever the producer process\n * is restarted. The kernel's local `ReadinessRegistry` derives a\n * monotonic `epoch` per `(capName, scope)` by counting generation\n * transitions — emitters never stamp epoch themselves. Consumers that\n * hold long-lived state compare `transition.epoch > lastSeenEpoch` to\n * decide whether to rebuild.\n *\n * Same-generation repeated `ready` events are idempotent keepalives\n * (e.g. re-emitted on every `$node.connected`) — the registry keeps\n * epoch stable.\n */\nexport interface SystemReadyStatePayload {\n readonly capName: string\n readonly scope: ReadinessScope\n readonly state: ReadinessState\n /** Per-process random id; changes on producer restart. */\n readonly generation: string\n readonly sourceNodeId: string\n readonly ts: number\n readonly [key: string]: unknown\n}\n\n// ---------------------------------------------------------------------------\n// Cluster topology snapshot shape — matches `nodes.topology` cap output\n// ---------------------------------------------------------------------------\n\n/** One service entry inside a topology process — addon + capabilities. */\nexport interface TopologyService {\n readonly addonId: string\n readonly capabilities: readonly string[]\n readonly status: string\n}\n\n/** One process under a topology node (main process + isolated workers). */\nexport interface TopologyProcess {\n readonly pid: number\n readonly name: string\n readonly state: string\n readonly cpuPercent: number\n readonly memoryRss: number\n readonly uptimeSeconds: number\n readonly services: readonly TopologyService[]\n readonly groupId?: string\n}\n\n/** Top-level cluster node — hub or remote agent. */\nexport interface TopologyNode {\n readonly id: string\n readonly name: string\n readonly hostname: string\n readonly platform: string\n readonly arch: string\n readonly cpuModel: string | null\n readonly cpuCores: number\n readonly memoryMB: number\n readonly engines: readonly string[]\n readonly isHub: boolean\n readonly isOnline: boolean\n readonly cpuPercent: number\n readonly memoryPercent: number\n readonly uptime: number\n readonly lastSeen: string\n /** Local IP addresses visible on the network (non-internal, IPv4/IPv6). */\n readonly localIps: readonly string[]\n readonly addons: ReadonlyArray<{ readonly id: string; readonly capabilities: readonly string[]; readonly status: string }>\n readonly processes: readonly TopologyProcess[]\n}\n\n// ---------------------------------------------------------------------------\n// Known event catalog — typed category → payload mapping\n// ---------------------------------------------------------------------------\n\n/** All known event categories with their typed payloads */\nexport interface EventCatalog {\n // ── System ──────────────────────────────────────────────────────────────\n 'system.boot': { mode: string }\n 'system.addons-ready': { activeAddons: readonly string[] }\n 'system.restarting': Record<string, never>\n 'system.ready-state': SystemReadyStatePayload\n\n // ── Addon lifecycle ─────────────────────────────────────────────────────\n 'addon.started': { addonId: string; packageName?: string; packageVersion?: string; agent?: string }\n 'addon.stopped': { addonId: string; packageName?: string; packageVersion?: string; agent?: string }\n 'addon.restarted': { addonId: string; packageName?: string; packageVersion?: string; agent?: string }\n 'addon.updated': { addonId: string; packageName?: string; packageVersion?: string; agent?: string; fromVersion?: string; toVersion?: string }\n 'addon.installed': { addonId: string; packageName?: string; packageVersion?: string; agent?: string }\n 'addon.uninstalled': { addonId: string; packageName?: string; packageVersion?: string; agent?: string }\n 'addon.crashed': { addonId: string; packageName?: string; packageVersion?: string; agent?: string; error?: string }\n 'addon.error': { addonId: string; packageName?: string; packageVersion?: string; agent?: string; error?: string; action?: string; phase?: string }\n\n // ── Device ──────────────────────────────────────────────────────────────\n 'device.registered': { deviceId: number; providerId: string; name?: string }\n 'device.unregistered': { deviceId: number; providerId: string }\n 'device.streams-registered': { deviceId: number; providerId: string }\n 'device.streams-unregistered': { deviceId: number }\n 'device.enabled': { deviceId: number; integrationId: string }\n 'device.disabled': { deviceId: number; integrationId: string }\n 'device.settings-updated': { deviceId: number; integrationId: string; keys: string[] }\n /**\n * Device online/offline aggregate. Emitted by the device's owning\n * provider (rtsp / reolink / onvif / frigate) when the union of its\n * stream-broker profile health flips. `online` fires when at least\n * one profile becomes healthy after all were offline; `offline` fires\n * when the last healthy profile goes stale (no packets for\n * STREAM_STALE_TIMEOUT_MS).\n */\n 'device.online': { deviceId: number; providerId: string; profileCount?: number; reason?: string }\n 'device.offline': { deviceId: number; providerId: string; reason?: string }\n 'device.awake': { deviceId: number; providerId: string; reason?: string }\n 'device.sleeping': { deviceId: number; providerId: string; reason?: string }\n /**\n * Emitted whenever the set of (device, capability) native providers or\n * wrapper activations changes. Hub subscribers use this to keep a\n * cross-process view of which addon/node currently serves each cap for\n * each device. `nodeId` is the broker nodeID where the provider lives;\n * 'hub' for hub-local. `addonId` is the provider (native or wrapper).\n */\n 'device.bindings-changed': {\n deviceId: number\n capName: string\n reason: 'native-registered' | 'native-unregistered' | 'wrapper-activated' | 'wrapper-deactivated'\n addonId: string\n nodeId: string\n }\n 'device.meta-changed': {\n deviceId: number\n field: 'name' | 'location' | 'disabled'\n value: string | null | boolean\n }\n\n // ── Integration ────────────────────────────────────────────────────────\n 'integration.enabled': { integrationId: string; addonId: string }\n 'integration.disabled': { integrationId: string; addonId: string }\n\n // ── Provider ────────────────────────────────────────────────────────────\n 'provider.started': { providerId: string; type?: string }\n 'provider.stopped': { providerId: string; reason?: string }\n\n // ── Process ─────────────────────────────────────────────────────────────\n 'process.crashed': { processId: string; exitCode?: number; signal?: string }\n 'process.restart_scheduled': { processId: string; delayMs: number }\n 'process.restarted': { processId: string }\n\n // ── Recording ───────────────────────────────────────────────────────────\n 'recording.started': { deviceId: number; streamId?: string }\n 'recording.stopped': { deviceId: number; reason?: string }\n 'recording.error': { deviceId: number; error: string }\n 'recording.health.degraded': { deviceId: number; message: string }\n 'recording.storage.critical': { deviceId: number; usagePercent?: number }\n 'recording.segment.written': { deviceId: number; path?: string; durationSec?: number; sizeMB?: number }\n 'recording.policy.fallback': { deviceId: number; reason: string }\n 'recording.retention.completed': { deletedCount?: number; freedMB?: number }\n\n // ── Detection & analysis ────────────────────────────────────────────────\n 'detection.event': { deviceId: number; detections?: unknown[]; [key: string]: unknown }\n 'detection.result': DetectionResultPayload\n 'detection.motion-analysis': MotionAnalysisPayload\n 'detection.motion-zones-raw': MotionZonesRawPayload\n 'motion.on-motion-changed': MotionOnMotionChangedPayload\n /**\n * On-board detection coming straight from the camera firmware (Reolink\n * AI alarms, ONVIF analytics, etc.) — as opposed to `detection.result`\n * which is produced by the pipeline running locally.\n *\n * `source` discriminates the origin when multiple pipelines coexist for\n * the same camera: `'onboard'` for native firmware events, `'camera-native'`\n * kept as an alias for backwards compatibility with pre-Reolink emitters.\n *\n * `detections` is tightened from `unknown[]` to a structured shape. Each\n * entry describes one firmware-reported class ('motion', 'person',\n * 'vehicle', 'animal', 'face', 'package', 'other', …) at a point in time.\n */\n 'detection.camera-native': {\n cameraId: number\n detections: readonly CameraNativeDetection[]\n source: 'onboard' | 'camera-native'\n }\n 'pipeline.audio-inference-result': PipelineAudioInferenceResultPayload\n 'detection.phase-transition': PhaseTransitionPayload\n /**\n * Emitted whenever a per-device override is written or cleared for any\n * pipeline-participating addon (pipeline-orchestrator, motion-wasm,\n * detection-pipeline, audio-analyzer, audio-classifier). The wiring\n * service subscribes to this event and restarts detection for the\n * affected camera so the new values take effect without a full reboot.\n * `addonId` is informational — most consumers only care about\n * `deviceId` and will rebuild the full RunnerCameraConfig anyway.\n */\n 'orchestration.settings-updated': { deviceId: number; addonId?: string }\n 'provider.motion': { active: boolean }\n 'provider.detection': { detections: unknown }\n\n // ── Session tracking ────────────────────────────────────────────────────\n 'session.track.new': { deviceId: number; trackId: string; label?: string }\n 'session.track.expired': { deviceId: number; trackId: string; durationMs?: number }\n\n // ── Benchmark ───────────────────────────────────────────────────────────\n /**\n * Progress from a running benchmark (pipeline image test, decoder perf test,\n * …). The payload is intentionally open (`kind` discriminator + free-form\n * additional fields) so different benchmark shapes share the same bus\n * category and a single UI subscriber can filter by `kind` + `sessionId`.\n */\n 'benchmark.progress': {\n kind: string\n sessionId: string\n phase?: string\n tSec?: number\n sample?: Record<string, unknown>\n message?: string\n }\n\n // ── Pipeline & inference ────────────────────────────────────────────────\n 'pipeline.progress': {\n /** Node that executed the pipeline step. Same value is also set on `event.source.nodeId`\n * but carried in the payload so admin-ui filters don't need to peek at the source shape. */\n nodeId: string\n /** Stable identifier per `runPipeline()` invocation — every progress event from the same\n * run shares this id so the UI can correlate a burst of messages into a single run card. */\n sessionId: string\n step: string\n addonId?: string\n modelId?: string\n ms?: number\n message?: string\n }\n /** Per-frame execution trace emitted by the pipeline executor for live observability. */\n 'pipeline.trace': PipelineExecutionTrace\n /** Raw inference output emitted by addon-pipeline-runner (no frame buffer). */\n 'pipeline.inference-result': PipelineInferenceResultPayload\n /** Camera assigned to an agent runner by addon-pipeline-orchestrator. */\n 'pipeline.camera-assigned': PipelineCameraAssignmentPayload\n /** Camera released from an agent runner. */\n 'pipeline.camera-unassigned': PipelineCameraAssignmentPayload\n /** Per-camera pipeline config changed — orchestrator hot-reloads the assigned runner. */\n 'pipeline.camera-updated': {\n readonly deviceId: number\n readonly config: CameraPipelineConfig\n }\n /**\n * Periodic per-runner load snapshot (~1 Hz). Replaces UI polling on\n * `pipelineRunner.getLocalLoad`. UI subscribes per agent node.\n */\n 'pipeline.runner-load-snapshot': {\n readonly nodeId: string\n readonly load: RunnerLocalLoad\n /** Wall-clock ms when the snapshot was sampled. */\n readonly timestamp: number\n }\n /**\n * Periodic per-camera metrics snapshot (~1 Hz). Replaces UI polling\n * on `pipelineOrchestrator.getCameraMetrics` /\n * `pipelineRunner.getCameraMetrics`. One event per attached camera\n * per tick. UI consumers filter by `deviceId`.\n */\n 'pipeline.camera-metrics-snapshot': {\n readonly deviceId: number\n readonly nodeId: string\n readonly metrics: CameraMetrics\n readonly timestamp: number\n }\n /**\n * Periodic per-broker stats snapshot (~1 Hz). Replaces polling on\n * `streamBroker.getBrokerStats` and `streamBroker.listAllProfileSlots`.\n * Carries the full `BrokerStats` payload so UI consumers can render\n * the panel directly from the event without round-tripping the cap.\n */\n 'stream-broker.metrics-snapshot': {\n readonly brokerId: string\n readonly deviceId: number\n readonly profile: string\n readonly nodeId: string\n readonly stats: BrokerStats\n readonly timestamp: number\n }\n /**\n * Cap event: stream-broker signals that a profile slot now has at\n * least one consumer. Camera-provider addons (Reolink Baichuan push,\n * etc.) start their underlying transport on receipt — see\n * `EventCategory.StreamBrokerOnCamStreamDemand`.\n */\n 'stream-broker.onCamStreamDemand': {\n readonly deviceId: number\n readonly camStreamId: string\n readonly profile: 'high' | 'mid' | 'low'\n }\n /**\n * Cap event: stream-broker signals the last consumer left. Providers\n * tear down their transport — see `EventCategory.StreamBrokerOnCamStreamIdle`.\n */\n 'stream-broker.onCamStreamIdle': {\n readonly deviceId: number\n readonly camStreamId: string\n }\n /**\n * Cap event: device's battery status changed (firmware push or\n * provider-side observation). Mirrors `batteryCapability.onStatusChanged`.\n * Payload shape duplicated inline (rather than importing from\n * `capabilities/battery.cap`) to avoid a cycle between the cap\n * definitions and the event bus typing — they're kept in lock-step\n * by hand (see also `BatteryStatus` in `capabilities/battery.cap.ts`).\n */\n 'battery.onStatusChanged': {\n readonly deviceId: number\n readonly status: {\n readonly percentage: number\n readonly charging: 'dc' | 'solar' | 'none'\n readonly sleeping: boolean\n readonly lastUpdated: number\n }\n }\n /**\n * Doorbell button press — emitted by every device that registers the\n * `doorbell` capability. Mirrors `doorbellCapability.events.onPressed`.\n * Subscribers (UI toast, advanced-notifier) react to physical rings\n * without holding a cap reference.\n */\n 'doorbell.onPressed': {\n readonly deviceId: number\n readonly timestamp: number\n }\n /**\n * Periodic per-node engine inventory snapshot (~0.2 Hz). Replaces\n * polling on `pipelineExecutor.listLoadedEngines`. One event per\n * detection-pipeline process per tick, carrying every loaded engine\n * with the same shape the cap returns.\n */\n 'pipeline.engine-metrics-snapshot': {\n readonly nodeId: string\n readonly engines: ReadonlyArray<{\n readonly engineKey: string\n readonly engine: PipelineEngineChoice\n readonly modelsLoaded: readonly string[]\n readonly inUseByCameras: readonly number[]\n readonly kind: 'runtime' | 'warm-override'\n readonly poolPid: number | null\n readonly idleMs: number | null\n readonly idleTtlMs: number | null\n }>\n readonly timestamp: number\n }\n /**\n * Cluster topology snapshot — same payload shape that\n * `nodes.topology` returns. Emitted by the hub on any agent /\n * addon lifecycle change (debounced ~200ms) plus a periodic safety\n * net. UI dashboards subscribe to drive their cluster view\n * directly from the event payload — zero round-trip.\n */\n 'cluster.topology-snapshot': {\n readonly nodes: ReadonlyArray<TopologyNode>\n readonly timestamp: number\n }\n /**\n * Periodic per-node system metrics snapshot. Carries the full\n * `SystemResourceSnapshot` returned by\n * `metricsProvider.getCached()` so dashboards render CPU /\n * memory / GPU / disk / network without polling.\n */\n 'metrics.node-resources-snapshot': {\n readonly nodeId: string\n readonly snapshot: SystemResourceSnapshot\n readonly timestamp: number\n }\n /**\n * Periodic per-node process-tree snapshot (`NodeProcess[]` —\n * camstack-related pids with ghost / managed / root classification).\n * One event per node per tick. Replaces polling on\n * `metricsProvider.listNodeProcesses`.\n */\n 'metrics.node-processes-snapshot': {\n readonly nodeId: string\n readonly processes: ReadonlyArray<NodeProcess>\n readonly timestamp: number\n }\n /**\n * Per-agent hwaccel override changed (set / cleared / re-probed). Payload\n * carries the new effective preference so UI consumers can toast or\n * refresh their pipeline view without re-fetching. Decoders still pull\n * from `pipeline-orchestrator.getAgentSettings` on session creation;\n * this event is additive observability.\n */\n 'pipeline.agent-hwaccel-changed': {\n readonly agentNodeId: string\n readonly userChoice: 'auto' | 'none' | string | null\n readonly probedBest: string\n readonly reason: 'user-set' | 'user-cleared' | 'reprobed' | 'seeded'\n }\n /** Capability binding changed for a node — kernels update their preferred-provider registry. */\n 'capability.binding-changed': CapabilityBindingChangedPayload\n 'model.download.progress': { modelId: string; progress: number; totalMB?: number }\n\n // ── Agent ───────────────────────────────────────────────────────────────\n 'agent.online': { agentId: string }\n 'agent.offline': { agentId: string }\n 'worker.online': { workerId: string }\n 'worker.offline': { workerId: string }\n 'agent.task.assigned': { agentId: string; taskId: string; taskType: string; payload?: unknown }\n\n // ── Enrichment ──────────────────────────────────────────────────────────\n 'enrichment.embedding.stored': {\n readonly deviceId: number\n readonly trackId: string\n readonly class: string\n readonly embeddingId: string\n readonly modelId: string\n readonly embeddingDim: number\n readonly inferenceMs: number\n readonly timestamp: number\n }\n 'enrichment.scene.state-changed': {\n readonly deviceId: number\n readonly monitorId: string\n readonly monitorLabel: string\n readonly previousState: string\n readonly currentState: string\n readonly confidence: number\n readonly timestamp: number\n }\n 'enrichment.activity.summary': {\n readonly deviceId: number\n readonly periodStart: number\n readonly periodEnd: number\n readonly objectCounts: Readonly<Record<string, number>>\n readonly zoneActivity: readonly { readonly zoneId: string; readonly entries: number; readonly exits: number; readonly avgDwellMs: number }[]\n readonly stateChanges: readonly { readonly monitorId: string; readonly from: string; readonly to: string; readonly timestamp: number }[]\n readonly activityLevel: 'none' | 'low' | 'medium' | 'high'\n }\n\n // ── Alerts ──────────────────────────────────────────────────────────────\n 'alert.created': { id: string; category: string; severity: string; title: string; status: string }\n 'alert.updated': { alertId: string; patch: Record<string, unknown> }\n\n // ── Stream broker health ────────────────────────────────────────────────\n /**\n * Per-broker stream health transition. Fired by the stream-broker\n * watchdog. `camStreamId` is the canonical identity of the source\n * (every broker is keyed by its cam stream now); `profile` is the\n * profile slot currently bound to it (or `null` if the broker is\n * only kept alive by a manual activation).\n */\n 'stream.online': {\n readonly deviceId: number\n readonly camStreamId: string\n readonly profile: 'high' | 'mid' | 'low' | null\n readonly brokerId: string\n readonly sourceType: string\n readonly lastPacketAt: number\n readonly reason?: string\n }\n 'stream.offline': {\n readonly deviceId: number\n readonly camStreamId: string\n readonly profile: 'high' | 'mid' | 'low' | null\n readonly brokerId: string\n readonly sourceType: string\n readonly lastPacketAt: number\n readonly reason?: string\n }\n\n // ── Retention ───────────────────────────────────────────────────────────\n 'retention.cleanup': {\n readonly deletedEvents?: number\n readonly deletedAudioRecords?: number\n readonly deletedSnapshots?: number\n readonly deletedCount?: number\n readonly freedMB?: number\n }\n}\n\n/** All known event category strings (derived from EventCatalog keys) */\nexport type KnownEventCategory = keyof EventCatalog\n\n// ---------------------------------------------------------------------------\n// SystemEvent — backward-compatible base type\n// ---------------------------------------------------------------------------\n\n/**\n * System event — `data` is `Record<string, unknown>` for backward compatibility.\n * Use `TypedSystemEvent<C>` or `narrowEvent()` for typed access to data.\n */\nexport interface SystemEvent {\n id: string\n timestamp: Date\n source: EventSource\n category: string\n data: Record<string, unknown>\n /**\n * Propagation chain when the event was re-emitted by the\n * `DeviceEventPropagator`. `via[0]` is the originating source (the\n * child that produced the event); subsequent entries walk up the\n * parent chain. Absent on the original emission and on events that\n * don't belong to a device-rooted source.\n *\n * Consumers that want ONLY direct events filter `ev.via === undefined`.\n * Consumers that want everything reaching a device (incl. children)\n * filter by `source.id === parentId` and accept any `via`.\n */\n via?: readonly EventSource[]\n}\n\n/**\n * A system event with a known category — `data` is typed.\n * Use this when you know the exact category at compile time.\n */\nexport type TypedSystemEvent<C extends KnownEventCategory> = {\n id: string\n timestamp: Date\n source: EventSource\n category: C\n data: EventCatalog[C]\n via?: readonly EventSource[]\n}\n\n// ---------------------------------------------------------------------------\n// Event filter\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Event filter — accepts known categories (strict) or strings (globs/custom)\n// ---------------------------------------------------------------------------\n\n/** A category filter value: a known category, a glob string, or an array of either */\nexport type EventCategoryFilter = KnownEventCategory | (string & {}) | readonly (KnownEventCategory | (string & {}))[]\n\nexport interface EventFilter {\n source?: EventSource\n /** Filter by top-level agent (e.g. 'hub', 'agent-a1b2c3'). Matches source.nodeId with prefix match so 'hub' includes 'hub/pipeline'. Same semantics as logs tags.agentId. */\n agentId?: string\n /** Filter by addon that originated the event. Matches source.addonId or source.id when type='addon'. */\n addonId?: string\n /** Filter by device the event relates to. Matches source.deviceId or source.id when type='device'. */\n deviceId?: number\n /** Category — known category (typed), glob (e.g. 'device.*'), or array */\n category?: EventCategoryFilter\n since?: Date\n}\n\n// ---------------------------------------------------------------------------\n// Typed event filter — for subscribe overloads\n// ---------------------------------------------------------------------------\n\nexport interface TypedEventFilter<C extends KnownEventCategory> {\n source?: EventSource\n category: C | readonly C[]\n since?: Date\n}\n\n// ---------------------------------------------------------------------------\n// IEventBus — emit and subscribe are typed when using known categories\n// ---------------------------------------------------------------------------\n\nexport interface IEventBus {\n /** Emit a known-category event with typed payload */\n emit<C extends KnownEventCategory>(event: TypedSystemEvent<C>): void\n /** Emit an arbitrary event (custom/unknown category) */\n emit(event: SystemEvent): void\n\n /** Subscribe to a known category — handler receives typed event */\n subscribe<C extends KnownEventCategory>(filter: TypedEventFilter<C>, handler: (event: TypedSystemEvent<C>) => void): () => void\n /** Subscribe with a generic filter — handler receives base SystemEvent */\n subscribe(filter: EventFilter, handler: (event: SystemEvent) => void): () => void\n\n /** Get recent events */\n getRecent(filter?: EventFilter, limit?: number): readonly SystemEvent[]\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Narrow a SystemEvent to a typed event by checking its category.\n * Returns `true` (and narrows the type) if the category matches.\n *\n * @example\n * ```typescript\n * eventBus.subscribe({ category: 'addon.started' }, (event) => {\n * if (isEvent(event, 'addon.started')) {\n * event.data.addonId // ✓ typed as string\n * }\n * })\n * ```\n */\nexport function isEvent<C extends KnownEventCategory>(\n event: SystemEvent,\n category: C,\n): event is TypedSystemEvent<C> {\n return event.category === category\n}\n\n/**\n * Create a typed event with less boilerplate.\n *\n * @example\n * ```typescript\n * eventBus.emit(createEvent('addon.started', { type: 'addon', id: 'pipeline' }, {\n * addonId: 'pipeline',\n * packageVersion: '0.1.8',\n * }))\n * ```\n */\nexport function createEvent<C extends KnownEventCategory>(\n category: C,\n source: EventSource,\n data: EventCatalog[C],\n): TypedSystemEvent<C> {\n return {\n id: typeof crypto !== 'undefined' && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2),\n timestamp: new Date(),\n source,\n category,\n data,\n }\n}\n\n// ---------------------------------------------------------------------------\n// System readiness protocol — low-level producer emission helper.\n// Consumers (kernel `ReadinessRegistry`) and their `awaitReady` /\n// `onReadyState` APIs live in `@camstack/kernel/src/readiness/`.\n// ---------------------------------------------------------------------------\n\n/**\n * Emit a `system.ready-state` event for a capability. Caller supplies a\n * per-process `generation` string — stable across a single process\n * lifetime, changes on restart — which consumer-side registries use to\n * derive a monotonic `epoch` without requiring the emitter to\n * coordinate.\n */\nexport function emitReadiness(\n bus: IEventBus,\n params: {\n readonly capName: string\n readonly scope: ReadinessScope\n readonly state: ReadinessState\n readonly generation: string\n readonly sourceNodeId: string\n readonly ts?: number\n },\n): void {\n const ts = params.ts ?? Date.now()\n bus.emit(createEvent(\n 'system.ready-state',\n { type: 'capability', id: params.capName, nodeId: params.sourceNodeId },\n {\n capName: params.capName,\n scope: params.scope,\n state: params.state,\n generation: params.generation,\n sourceNodeId: params.sourceNodeId,\n ts,\n },\n ))\n}\n","import type { AddonContext, AddonInitResult, CapabilitiesAccess, ProviderRegistration } from '../interfaces/addon.js'\nimport { EventCategory } from '../enums/event-category.js'\nimport type {\n ConfigUISchema, ConfigUISchemaWithValues,\n ConfigField, ConfigSection,\n} from '../interfaces/config-ui.js'\nimport { hydrateSchema } from '../interfaces/config-ui.js'\nimport { emitReadiness } from '../interfaces/event-bus.js'\n\nexport type { CapabilitiesAccess }\n\n// ── Typed field helper ──────────────────────────────────────────────────\n/**\n * Utility type that constrains a ConfigField's `key` to only accept\n * keys of TConfig. Usage inside schema builders:\n *\n * ```ts\n * protected globalSettingsSchema() {\n * return this.schema({\n * sections: [{\n * id: 'main',\n * title: 'Settings',\n * fields: [\n * this.field({ type: 'number', key: 'maxRetries', label: 'Max Retries' }),\n * // ^^^^^^^^^^^ — autocomplete + compile error if wrong\n * ],\n * }],\n * })\n * }\n * ```\n */\ntype TypedConfigField<TConfig extends object> =\n ConfigField extends infer F\n ? F extends { readonly key: string }\n ? Omit<F, 'key'> & { readonly key: keyof TConfig & string }\n : F // valueless fields (separator, info) pass through\n : never\n\n/**\n * A ConfigSection whose fields are key-constrained to TConfig.\n */\ninterface TypedConfigSection<TConfig extends object> extends Omit<ConfigSection, 'fields'> {\n readonly fields: ReadonlyArray<TypedConfigField<TConfig> | ConfigField>\n}\n\n/**\n * A ConfigUISchema whose sections use typed fields.\n */\ninterface TypedConfigUISchema<TConfig extends object> extends Omit<ConfigUISchema, 'sections'> {\n readonly sections: ReadonlyArray<TypedConfigSection<TConfig>>\n}\n\n// ── BaseAddon ───────────────────────────────────────────────────────────\n\n/**\n * Base class for CamStack addons. Eliminates settings boilerplate:\n *\n * - Typed `config` property with automatic resolution from store + defaults\n * - `getGlobalSettings()` / `updateGlobalSettings()` auto-implemented\n * - `getAddonSettings()` / `updateAddonSettings()` auto-implemented\n * - `getDeviceSettings()` / `updateDeviceSettings()` auto-implemented\n * - `ctx` accessor for the AddonContext (no manual `this.ctxRef` storage)\n * - `field()` helper that constrains field keys to TConfig keys\n * - `schema()` helper that validates the full schema structure\n *\n * Subclasses override:\n * - `onInitialize()` — addon-specific init logic, return ProviderRegistration[]\n * - `onShutdown()` — cleanup\n * - `globalSettingsSchema()` / `deviceSettingsSchema()` — UI schemas\n *\n * @example\n * ```ts\n * interface MyConfig {\n * maxRetries: number\n * endpoint: string\n * }\n *\n * export default class MyAddon extends BaseAddon<MyConfig> {\n * constructor() {\n * super({ maxRetries: 3, endpoint: 'http://localhost' })\n * }\n *\n * protected globalSettingsSchema() {\n * return this.schema({\n * sections: [{\n * id: 'main', title: 'Settings',\n * fields: [\n * this.field({ type: 'number', key: 'maxRetries', label: 'Max Retries', default: 3 }),\n * this.field({ type: 'text', key: 'endpoint', label: 'Endpoint' }),\n * ],\n * }],\n * })\n * }\n *\n * protected async onInitialize(): Promise<ProviderRegistration[]> {\n * const client = new Client(this.config.endpoint, this.config.maxRetries)\n * return [{ capability: 'my-feature', provider: client }]\n * }\n * }\n * ```\n */\nexport abstract class BaseAddon<TConfig extends object = Record<string, unknown>> {\n private _ctx: AddonContext | null = null\n private _config: TConfig\n /**\n * Per-process random id used as the `generation` stamp on every\n * `system.ready-state` event this addon emits. Constant for the\n * lifetime of this addon instance (== one process boot); consumer-\n * side registries derive a monotonic `epoch` by watching for\n * generation transitions.\n */\n private readonly _readinessGeneration: string =\n typeof crypto !== 'undefined' && crypto.randomUUID\n ? crypto.randomUUID()\n : Math.random().toString(36).slice(2, 14)\n /** Capability names this addon registered at init — used to emit matching `down` events on shutdown. */\n private _registeredCapNames: readonly string[] = []\n\n /** Default config values. Provided via constructor. */\n protected readonly defaults: TConfig\n\n constructor(defaults: TConfig) {\n this.defaults = defaults\n this._config = { ...defaults }\n }\n\n /**\n * Override to opt out of the automatic `system.ready-state` emission.\n * Returns `true` by default — addons that don't map cleanly to the\n * readiness protocol (e.g. pure collection providers whose readiness\n * is already reported per-device by upstream) can override to `false`\n * and emit manually.\n */\n protected get autoEmitReadiness(): boolean { return true }\n\n // ── Public accessors ──────────────────────────────────────────────────\n\n /** The AddonContext, available after initialize(). */\n get ctx(): AddonContext {\n if (!this._ctx) throw new Error(`${this.constructor.name}: ctx accessed before initialize()`)\n return this._ctx\n }\n\n /**\n * Non-throwing ctx accessor for code paths that can legitimately run\n * before `initialize()` has resolved — most commonly cap handlers the\n * hub invokes eagerly at page load (device-details aggregator pings\n * every addon's `getDeviceSettingsContribution` as soon as the page\n * mounts). Prefer `ctx` for the normal case; reach for this only in\n * capability methods that may be queried before the addon is wired up.\n */\n protected get ctxIfReady(): AddonContext | null {\n return this._ctx\n }\n\n /** Current resolved config (defaults merged with persisted store values). */\n get config(): Readonly<TConfig> {\n return this._config\n }\n\n // ── ICamstackAddon lifecycle ──────────────────────────────────────────\n\n async initialize(context: AddonContext): Promise<AddonInitResult | void> {\n this._ctx = context\n await this.resolveConfig()\n const result = await this.onInitialize()\n this.emitLifecycle(EventCategory.AddonStarted)\n const normalized = normalizeAddonInitResult(result)\n const providers: readonly ProviderRegistration[] =\n normalized && 'providers' in normalized && normalized.providers ? normalized.providers : []\n this._registeredCapNames = providers.map(p => p.capability.name)\n return normalized\n }\n\n /**\n * Called by the isolated-process runner AFTER `broker.start()`.\n * In-process addons never need this because the hub broker is already\n * running when `initialize()` fires. For forked children the broker\n * starts AFTER `initialize()`, so the readiness emit inside initialize()\n * fires before the broker can broadcast it. This method re-emits the\n * ready state once the transport is live.\n */\n postBrokerStart(): void {\n if (this.autoEmitReadiness && this._registeredCapNames.length > 0) {\n this.emitReadinessForProviders('ready')\n }\n }\n\n /**\n * Called by the isolated-process runner / agent bootstrap once the broker\n * has started AND the hub node is connected — the moment `ctx.api.*` calls\n * to hub-provided capabilities become safe. Wrap any bootstrap work that\n * must query the hub (device restore, settings fetch, initial sync) in\n * `onHubConnected()` rather than `onInitialize()` — during `initialize()`\n * on a worker the broker is not yet connected and remote cap calls either\n * time out or throw \"Service not found\".\n *\n * Default implementation is a no-op. Override in subclasses that need it.\n * Never fires on hub-local in-process addons (the hub is its own node).\n */\n async onHubReachable(): Promise<void> {\n // no-op — override in subclasses\n }\n\n async shutdown(): Promise<void> {\n this.emitLifecycle(EventCategory.AddonStopped)\n if (this.autoEmitReadiness) this.emitReadinessForProviders('down')\n await this.onShutdown()\n for (const unsub of this._subscriptions) unsub()\n this._subscriptions = []\n this._ctx = null\n }\n\n // ── Subclass hooks ────────────────────────────────────────────────────\n\n /**\n * Addon-specific initialization. Called after config is resolved.\n *\n * Subclasses may return:\n * - an array of `ProviderRegistration` (back-compat, most common),\n * - an `AddonInitResult` envelope to also declare `customActions`,\n * - `void` for pure consumers.\n */\n protected abstract onInitialize(): Promise<ProviderRegistration[] | AddonInitResult | void>\n\n /** Addon-specific cleanup. Override if needed. */\n protected async onShutdown(): Promise<void> { /* no-op by default */ }\n\n /**\n * Called after config is resolved during updateGlobalSettings/updateAddonSettings.\n * Override to react to config changes (e.g. restart a sampler, reconnect a service).\n * Not called during initialize() — use onInitialize() for initial setup.\n */\n protected async onConfigChanged(): Promise<void> { /* no-op by default */ }\n\n // ── Schema helpers (typed) ────────────────────────────────────────────\n\n /**\n * Create a ConfigField with `key` constrained to keys of TConfig.\n * Provides autocomplete and compile-time validation.\n */\n protected field<F extends ConfigField>(\n field: F extends { readonly key: string }\n ? Omit<F, 'key'> & { readonly key: keyof TConfig & string }\n : F\n ): ConfigField {\n return field as ConfigField\n }\n\n /**\n * Create a full ConfigUISchema with typed sections.\n * Fields created via `this.field()` get key validation automatically.\n */\n protected schema(schema: TypedConfigUISchema<TConfig>): ConfigUISchema {\n return schema as unknown as ConfigUISchema\n }\n\n // ── Settings schemas (override to provide UI) ─────────────────────────\n\n /** Override to provide global-level settings UI schema. */\n protected globalSettingsSchema(): ConfigUISchema | null { return null }\n\n /** Override to provide device-level settings UI schema. */\n protected deviceSettingsSchema(): ConfigUISchema | null { return null }\n\n // ── Two-level settings API (auto-implemented) ────────────────────────\n //\n // Note: the former three-level split (addon / global / device) collapsed\n // to two. `addon` and `global` both wrote to the same `writeAddonStore`\n // blob and every addon used exactly one of them; the distinction was\n // never semantically load-bearing. `global` won because it was the\n // widely-used one and the name reads naturally (per-node addon config).\n\n async getGlobalSettings(overlay?: Record<string, unknown>): Promise<ConfigUISchemaWithValues> {\n const schema = this.globalSettingsSchema()\n if (!schema) return { sections: [] }\n const raw = (await this._ctx?.settings?.readAddonStore()) ?? {}\n return hydrateSchema(schema, overlay ? { ...raw, ...overlay } : raw)\n }\n\n async updateGlobalSettings(patch: Partial<TConfig>): Promise<void> {\n await this._ctx?.settings?.writeAddonStore(patch as Record<string, unknown>)\n await this.resolveConfig()\n await this.onConfigChanged()\n this.emitLifecycle(EventCategory.AddonUpdated, { level: 'global' })\n this.maybeAutoRestart(patch, this.globalSettingsSchema())\n }\n\n /**\n * If any field in `patch` is marked `requiresRestart` in `schema`,\n * schedule an addon restart for the next tick. Deferred via\n * `setImmediate` so the tRPC mutation that triggered the write has\n * time to return its response before the addon is torn down and\n * re-initialised by `AddonRegistryService.restartAddon`.\n */\n private maybeAutoRestart(\n patch: Partial<TConfig>,\n schema: ConfigUISchema | null,\n ): void {\n if (!schema) return\n const restartKeys = new Set<string>()\n for (const section of schema.sections) {\n for (const field of section.fields) {\n if (field.type === 'separator' || field.type === 'info') continue\n if ((field as { readonly requiresRestart?: boolean }).requiresRestart) {\n restartKeys.add((field as { readonly key: string }).key)\n }\n }\n }\n if (restartKeys.size === 0) return\n const changed = Object.keys(patch).some((k) => restartKeys.has(k))\n if (!changed) return\n const ctx = this._ctx\n if (!ctx) return\n const addonId = ctx.id\n setImmediate(() => {\n const api = ctx.api as unknown as {\n addons?: { restartAddon?: { mutate: (input: { addonId: string }) => Promise<unknown> } }\n }\n api.addons?.restartAddon?.mutate({ addonId })\n .then(() => {\n ctx.logger.info('addon auto-restart triggered by restart-required setting change', {\n meta: { changedFields: Object.keys(patch).filter((k) => restartKeys.has(k)) },\n })\n })\n .catch((err: unknown) => {\n ctx.logger.error('addon auto-restart failed', {\n meta: { error: err instanceof Error ? err.message : String(err) },\n })\n })\n })\n }\n\n async getDeviceSettings(deviceId: number): Promise<ConfigUISchemaWithValues> {\n const schema = this.deviceSettingsSchema()\n if (!schema) return { sections: [] }\n const raw = (await this._ctx?.settings?.readDeviceStore(deviceId)) ?? {}\n return hydrateSchema(schema, raw)\n }\n\n async updateDeviceSettings(deviceId: number, patch: Record<string, unknown>): Promise<void> {\n await this._ctx?.settings?.writeDeviceStore(deviceId, patch)\n }\n\n // ── Event subscriptions (auto-cleanup on shutdown) ────────────────────\n\n private _subscriptions: Array<() => void> = []\n\n /**\n * Subscribe to an event bus category. The subscription is automatically\n * unsubscribed on shutdown — no manual cleanup needed.\n *\n * @example\n * ```ts\n * this.subscribe({ category: EventCategory.DeviceRegistered }, (event) => {\n * void this.handleDevice(event)\n * })\n * ```\n */\n /**\n * Subscribe to `system.ready-state` events for one or more capabilities.\n * Abstracts the boilerplate type-narrowing + nodeId extraction that every\n * resilience subscription duplicates. Cleanup is automatic (registered on\n * `_subscriptions` like a normal `subscribe` call).\n */\n protected watchCapability(\n capNames: string | readonly string[],\n handlers: {\n readonly onDown?: (nodeId: string, capName: string) => void\n readonly onReady?: (nodeId: string, capName: string) => void\n },\n ): void {\n const names = Array.isArray(capNames) ? capNames : [capNames]\n const nameSet = new Set<string>(names as string[])\n this.subscribe(\n { category: 'system.ready-state' },\n (event) => {\n const data = event.data as {\n readonly capName?: unknown\n readonly state?: unknown\n readonly scope?: { readonly type?: unknown; readonly nodeId?: unknown }\n }\n if (typeof data.capName !== 'string') return\n if (!nameSet.has(data.capName)) return\n if (data.scope?.type !== 'node') return\n const nodeId = data.scope.nodeId\n if (typeof nodeId !== 'string' || nodeId.length === 0) return\n const capName = data.capName\n if (data.state === 'down') {\n handlers.onDown?.(nodeId, capName)\n } else if (data.state === 'ready') {\n handlers.onReady?.(nodeId, capName)\n }\n },\n )\n }\n\n protected subscribe<C extends import('../interfaces/event-bus.js').KnownEventCategory>(\n filter: import('../interfaces/event-bus.js').TypedEventFilter<C>,\n handler: (event: import('../interfaces/event-bus.js').TypedSystemEvent<C>) => void,\n ): void\n protected subscribe(\n filter: import('../interfaces/event-bus.js').EventFilter,\n handler: (event: import('../interfaces/event-bus.js').SystemEvent) => void,\n ): void\n protected subscribe(\n filter: import('../interfaces/event-bus.js').EventFilter,\n handler: (event: import('../interfaces/event-bus.js').SystemEvent) => void,\n ): void {\n const unsub = this.ctx.eventBus.subscribe(filter, handler)\n this._subscriptions.push(unsub)\n }\n\n // ── Lifecycle event emission ────────────────────────────────────────────\n\n private emitLifecycle(category: EventCategory, data?: Record<string, unknown>): void {\n try {\n this._ctx?.eventBus.emit({\n id: `${this._ctx.id}-${Date.now()}`,\n timestamp: new Date(),\n source: { type: 'addon', id: this._ctx.id, nodeId: this._ctx.kernel.localNodeId ?? 'hub' },\n category,\n data: data ?? {},\n })\n } catch { /* best-effort — don't crash addon if event bus is unavailable */ }\n }\n\n /**\n * Emit a `system.ready-state` event for every capability this addon\n * registered at init. Scope is `{type:'node', nodeId}` — readiness is\n * tied to the node that hosts the provider. Consumers that care about\n * per-device readiness can subscribe with `{type:'device', ...}` if\n * the provider emits at finer granularity (collection addons may\n * opt-out via `autoEmitReadiness` and emit manually).\n */\n private emitReadinessForProviders(state: 'ready' | 'down'): void {\n const ctx = this._ctx\n if (!ctx) return\n if (this._registeredCapNames.length === 0) return\n // Forked child processes have a hierarchical nodeId (e.g. 'hub/detection-pipeline').\n // Readiness must be scoped to the logical parent node so orchestrators that\n // subscribe to 'hub' or 'dev-agent-0' receive the event from their children too.\n const rawNodeId = ctx.kernel?.localNodeId ?? 'hub'\n const nodeId = rawNodeId.includes('/') ? rawNodeId.split('/')[0]! : rawNodeId\n for (const capName of this._registeredCapNames) {\n try {\n emitReadiness(ctx.eventBus, {\n capName,\n scope: { type: 'node', nodeId },\n state,\n generation: this._readinessGeneration,\n sourceNodeId: nodeId,\n })\n } catch { /* best-effort — a broken bus must not take the addon down */ }\n }\n }\n\n // ── Common helpers ─────────────────────────────────────────────────────\n\n /**\n * Resolve the shared models directory path via the storage capability.\n * Falls back to `camstack-data/models` if storage is unavailable.\n * Used by inference addons (detection-pipeline, audio-classifier, embedding-encoder).\n */\n protected async resolveModelsDir(): Promise<string> {\n return this.ctx.api.storage.resolve.query({ location: 'models', relativePath: '' })\n .catch(() => 'camstack-data/models')\n }\n\n /**\n * Access the runtime capability registry for in-process provider lookups.\n * Returns null if the registry is not available (e.g. on agents).\n * Used by addons that consume other capabilities directly (snapshot, stream-broker, enrichment).\n */\n protected get capabilities(): CapabilitiesAccess | null {\n const capCtx = this.ctx as { capabilities?: CapabilitiesAccess }\n return capCtx.capabilities ?? null\n }\n\n // ── Config resolution ─────────────────────────────────────────────────\n\n /**\n * Resolve config by merging defaults with persisted store values.\n * Called automatically during initialize() and after every updateSettings().\n *\n * The merge is shallow: each key in `defaults` is checked against the store.\n * Only keys present in defaults are read — the store can contain extra keys\n * (e.g. from older versions) without polluting the typed config.\n */\n protected async resolveConfig(): Promise<void> {\n const stored = (await this._ctx?.settings?.readAddonStore()) ?? {}\n const resolved = { ...this.defaults }\n\n for (const key of Object.keys(this.defaults) as Array<keyof TConfig & string>) {\n const storedValue = stored[key]\n if (storedValue !== undefined && storedValue !== null) {\n const defaultType = typeof this.defaults[key]\n if (typeof storedValue === defaultType) {\n ;(resolved as Record<string, unknown>)[key] = storedValue\n }\n }\n }\n\n this._config = resolved\n }\n}\n\n/**\n * Normalize an `ICamstackAddon.initialize()` return value into the\n * `AddonInitResult` envelope. Arrays are wrapped into `{ providers }`;\n * envelopes pass through; void stays void.\n *\n * Exported so the kernel boot path and the backend addon registry can\n * share the same normalizer instead of duplicating the shim. Addons that\n * extend `BaseAddon` already emit the envelope, so this helper is only a\n * safety net for direct `ICamstackAddon` implementations (mostly tests).\n */\nexport function normalizeAddonInitResult(\n result: ProviderRegistration[] | AddonInitResult | void,\n): AddonInitResult | void {\n if (result == null) return\n if (Array.isArray(result)) return { providers: result }\n return result\n}\n\n","/**\n * ReadinessRegistry — kernel-side tracker for capability readiness\n * transitions. Spec: `docs/superpowers/specs/2026-04-19-system-readiness-design.md`.\n *\n * Each process owns one registry. The registry:\n * - Listens to `system.ready-state` events on the event bus.\n * - Maintains a `Map<key, ReadinessRecord>` snapshot of the most\n * recently observed state + generation + derived epoch.\n * - Exposes `emitReady` / `emitStarting` / `emitDown` helpers for\n * local producers (which stamp the process-wide `generation`).\n * - Exposes `awaitReady(capName, scope, {timeoutMs, signal})` and\n * `onReadyState(capName, scope, handler)` for consumers.\n *\n * Epoch derivation:\n * - First `ready` observed for a `(capName, scope)` → epoch = 1.\n * - `ready` received with a generation different from the last\n * `currentGeneration` → epoch++.\n * - Same-generation repeated `ready` events → epoch unchanged\n * (idempotent keepalive; e.g. re-emit on `$node.connected`).\n *\n * Not persisted. Rebuilt from the event stream + optional boot-time\n * snapshot rehydration by the caller.\n */\nimport type {\n IEventBus,\n SystemReadyStatePayload,\n ReadinessScope,\n ReadinessState,\n} from '../interfaces/event-bus.js'\nimport type { IScopedLogger } from '../interfaces/logging.js'\nimport type {\n IReadinessRegistry,\n IReadinessHandler,\n IAwaitReadyOptions,\n IReadinessTransition,\n} from '../interfaces/readiness.js'\nimport { createEvent } from '../interfaces/event-bus.js'\n\n/**\n * Concrete types live here; `interfaces/readiness.ts` declares the\n * matching narrow interfaces (`IReadinessTransition`,\n * `IReadinessHandler`, `IAwaitReadyOptions`) used by `AddonContext`\n * and other consumer-facing types.\n */\nexport type ReadinessTransition = IReadinessTransition\nexport type ReadinessHandler = IReadinessHandler\nexport type AwaitReadyOptions = IAwaitReadyOptions\n\nexport class ReadinessTimeoutError extends Error {\n readonly capName: string\n readonly scope: ReadinessScope\n readonly waitedMs: number\n constructor(capName: string, scope: ReadinessScope, waitedMs: number) {\n super(`Timed out waiting for ${capName} (${scopeKey(scope)}) to become ready after ${waitedMs}ms`)\n this.name = 'ReadinessTimeoutError'\n this.capName = capName\n this.scope = scope\n this.waitedMs = waitedMs\n }\n}\n\ninterface ReadinessRecord {\n capName: string\n scope: ReadinessScope\n state: ReadinessState\n generation: string\n epoch: number\n lastChange: number\n /**\n * Node that emitted the latest transition for this record. Needed for\n * `agent.offline` demux of `device`-scoped caps (scope itself carries\n * no node info). For `node`-scoped caps this matches `scope.nodeId`.\n */\n sourceNodeId: string\n}\n\ninterface Subscription {\n readonly capName: string\n readonly scope: ReadinessScope\n readonly handler: ReadinessHandler\n}\n\n/**\n * Build a canonical string key for a `(capName, scope)` pair. Used as\n * the snapshot map key and for log/debug output.\n */\nexport function readinessKey(capName: string, scope: ReadinessScope): string {\n return `${capName}|${scopeKey(scope)}`\n}\n\nfunction scopeKey(scope: ReadinessScope): string {\n switch (scope.type) {\n case 'global': return 'global'\n case 'node': return `node:${scope.nodeId}`\n case 'device': return `device:${scope.deviceId}`\n }\n}\n\nfunction scopesEqual(a: ReadinessScope, b: ReadinessScope): boolean {\n if (a.type !== b.type) return false\n if (a.type === 'global' || b.type === 'global') return true\n if (a.type === 'node' && b.type === 'node') return a.nodeId === b.nodeId\n if (a.type === 'device' && b.type === 'device') return a.deviceId === b.deviceId\n return false\n}\n\nexport interface ReadinessRegistryOptions {\n readonly eventBus: IEventBus\n readonly sourceNodeId: string\n /**\n * Per-process generation id — stamped on every emit made via this\n * registry's `emitReady`/`emitStarting`/`emitDown` helpers. Caller\n * owns the value so it can survive across subsystem re-bindings\n * within the same process. Default: a random 12-char id.\n */\n readonly generation?: string\n readonly logger?: IScopedLogger\n /**\n * Clock source. Injectable for tests.\n */\n readonly now?: () => number\n}\n\nexport class ReadinessRegistry implements IReadinessRegistry {\n private readonly bus: IEventBus\n private readonly sourceNodeId: string\n private readonly logger: IScopedLogger | undefined\n private readonly now: () => number\n private readonly generation: string\n private readonly snapshot = new Map<string, ReadinessRecord>()\n private readonly subscriptions = new Set<Subscription>()\n private readonly unsubscribeBus: () => void\n private readonly unsubscribeAgentOffline: () => void\n\n constructor(options: ReadinessRegistryOptions) {\n this.bus = options.eventBus\n this.sourceNodeId = options.sourceNodeId\n this.logger = options.logger\n this.now = options.now ?? (() => Date.now())\n this.generation = options.generation ?? randomGeneration()\n\n this.unsubscribeBus = this.bus.subscribe(\n { category: 'system.ready-state' },\n (event) => this.ingest(event.data as SystemReadyStatePayload),\n )\n // Auto-heal on agent disconnect: when `agent.offline` fires, walk\n // our own snapshot and synthesize `down` transitions for every\n // node-scoped cap bound to the disconnected nodeId. This covers\n // ungraceful producer deaths (process crash, network blip,\n // SIGKILL) where the producer's own shutdown hook never fires —\n // subscribers would otherwise keep waiting on a stale `ready`.\n // Synthesized transitions are local-only (we don't re-emit on the\n // bus) — every registry reacts independently to the same agent.offline.\n this.unsubscribeAgentOffline = this.bus.subscribe(\n { category: 'agent.offline' },\n (event) => this.synthesizeDownForNode((event.data as { agentId: string }).agentId),\n )\n // Hydrate from recent bus events so a late-starting registry\n // (e.g. an addon subscribed mid-session, or a hub reboot where\n // producers haven't re-emitted yet) picks up already-fired\n // readiness transitions. Safe to run after subscribe: ingest()\n // is idempotent for same-generation replays.\n if (typeof this.bus.getRecent === 'function') {\n try {\n const recent = this.bus.getRecent({ category: 'system.ready-state' })\n for (const event of recent) {\n this.ingest(event.data as SystemReadyStatePayload)\n }\n } catch {\n // getRecent is optional — a minimal test bus may not support it.\n }\n }\n }\n\n /** Release the event-bus subscription. Idempotent. */\n close(): void {\n this.unsubscribeBus()\n this.unsubscribeAgentOffline()\n this.subscriptions.clear()\n }\n\n /** Current snapshot for a `(capName, scope)` pair, or `null` if never seen. */\n get(capName: string, scope: ReadinessScope): ReadinessRecord | null {\n return this.snapshot.get(readinessKey(capName, scope)) ?? null\n }\n\n /**\n * Serializable snapshot for cross-process transport. Returns an array\n * of `ReadinessRecord` plain objects — safe for MsgPack / JSON\n * transport. Used by the hub's `$readiness.getSnapshot` Moleculer\n * action; consumers hydrate their local registry from the result.\n */\n getSnapshotForTransport(): readonly ReadinessRecord[] {\n return Array.from(this.snapshot.values())\n }\n\n /**\n * Hydrate the snapshot from an authoritative source. Entries already\n * present locally are skipped — live deltas (received via the event\n * bus subscription) always take precedence over the snapshot. For\n * each newly hydrated entry, a one-shot transition is dispatched to\n * matching subscriptions so pending `awaitReady` callers unblock\n * without having to wait for a fresh event.\n *\n * Local `epoch` is reset to 1 per entry — consumer-side epoch is\n * derived from observed generation transitions, so this mirrors the\n * value that would have been assigned had the consumer observed the\n * first `ready` event directly.\n */\n hydrate(records: readonly ReadinessRecord[]): void {\n const now = this.now()\n for (const record of records) {\n const key = readinessKey(record.capName, record.scope)\n if (this.snapshot.has(key)) continue\n const hydrated: ReadinessRecord = {\n capName: record.capName,\n scope: record.scope,\n state: record.state,\n generation: record.generation,\n epoch: 1,\n lastChange: now,\n sourceNodeId: record.sourceNodeId,\n }\n this.snapshot.set(key, hydrated)\n if (this.logger) {\n this.logger.debug(\n `readiness: ${record.capName} (${scopeKey(record.scope)}) → ${record.state} (hydrated, gen=${record.generation.slice(0, 6)})`,\n )\n }\n const transition: ReadinessTransition = {\n capName: record.capName,\n scope: record.scope,\n state: record.state,\n epoch: 1,\n generation: record.generation,\n sourceNodeId: 'hydrated',\n ts: now,\n durationInPrevState: 0,\n }\n for (const sub of this.subscriptions) {\n if (sub.capName !== record.capName) continue\n if (!scopesEqual(sub.scope, record.scope)) continue\n try {\n sub.handler(transition)\n } catch (err) {\n this.logger?.warn(\n `readiness hydrate handler threw for ${record.capName}: ${(err as Error).message ?? String(err)}`,\n )\n }\n }\n }\n }\n\n /** Shallow copy of the full snapshot — mainly for diagnostics/tests. */\n getAll(): ReadonlyMap<string, ReadinessRecord> {\n return new Map(this.snapshot)\n }\n\n /**\n * Emit a `ready` transition for a locally-owned capability. The\n * payload carries this registry's `generation` so remote registries\n * can derive their own `epoch`.\n */\n emitReady(capName: string, scope: ReadinessScope): void {\n this.emitTransition(capName, scope, 'ready')\n }\n\n emitStarting(capName: string, scope: ReadinessScope): void {\n this.emitTransition(capName, scope, 'starting')\n }\n\n emitDown(capName: string, scope: ReadinessScope): void {\n this.emitTransition(capName, scope, 'down')\n }\n\n /**\n * One-shot: resolve once the cap is `ready`. Reads the snapshot\n * first — if already ready, resolves synchronously on the next tick.\n *\n * Default behaviour is **wait indefinitely** (timeoutMs = `Infinity`):\n * the orchestrator and other callers never want to attach a camera\n * with empty steps just because a cap took longer than 30s to come\n * up. Pass an explicit finite `timeoutMs` to bound the wait, or an\n * `AbortSignal` to cancel externally. `Infinity` is honoured natively\n * — no `setTimeout` is registered (Node's setTimeout silently clamps\n * values above ~24.8d, so we must skip the timer entirely).\n */\n awaitReady(capName: string, scope: ReadinessScope, opts: AwaitReadyOptions = {}): Promise<void> {\n const timeoutMs = opts.timeoutMs ?? Number.POSITIVE_INFINITY\n const start = this.now()\n const current = this.get(capName, scope)\n if (current?.state === 'ready') {\n return Promise.resolve()\n }\n if (opts.signal?.aborted) {\n return Promise.reject(opts.signal.reason ?? new Error('aborted'))\n }\n return new Promise<void>((resolve, reject) => {\n let settled = false\n const unsubscribe = this.onReadyState(capName, scope, (t) => {\n if (t.state !== 'ready') return\n if (settled) return\n settled = true\n cleanup()\n resolve()\n })\n const isInfinite = !Number.isFinite(timeoutMs)\n const timer: ReturnType<typeof setTimeout> | null = isInfinite\n ? null\n : setTimeout(() => {\n if (settled) return\n settled = true\n cleanup()\n reject(new ReadinessTimeoutError(capName, scope, this.now() - start))\n }, timeoutMs)\n const onAbort = (): void => {\n if (settled) return\n settled = true\n cleanup()\n reject(opts.signal?.reason ?? new Error('aborted'))\n }\n opts.signal?.addEventListener('abort', onAbort, { once: true })\n function cleanup(): void {\n unsubscribe()\n if (timer !== null) clearTimeout(timer)\n opts.signal?.removeEventListener('abort', onAbort)\n }\n })\n }\n\n /**\n * Observable: every transition (starting/ready/down) dispatches to\n * `handler`. On subscription, if the snapshot has a current state,\n * the handler fires ONCE asynchronously with that state as the\n * initial transition (duration = 0) so late subscribers can pick up\n * current state without racing the next transition.\n *\n * Returns an unsubscribe function.\n */\n onReadyState(capName: string, scope: ReadinessScope, handler: ReadinessHandler): () => void {\n const sub: Subscription = { capName, scope, handler }\n this.subscriptions.add(sub)\n const current = this.get(capName, scope)\n if (current !== null) {\n queueMicrotask(() => {\n if (!this.subscriptions.has(sub)) return\n handler({\n capName,\n scope,\n state: current.state,\n epoch: current.epoch,\n generation: current.generation,\n sourceNodeId: this.sourceNodeId,\n ts: current.lastChange,\n durationInPrevState: 0,\n })\n })\n }\n return () => { this.subscriptions.delete(sub) }\n }\n\n // ── Internals ─────────────────────────────────────────────────────────\n\n private emitTransition(capName: string, scope: ReadinessScope, state: ReadinessState): void {\n const ts = this.now()\n this.bus.emit(createEvent(\n 'system.ready-state',\n { type: 'capability', id: capName, nodeId: this.sourceNodeId },\n {\n capName,\n scope,\n state,\n generation: this.generation,\n sourceNodeId: this.sourceNodeId,\n ts,\n },\n ))\n }\n\n /**\n * Update snapshot + dispatch to subscribers. Idempotent: same\n * `generation + state` replay is a no-op for both snapshot and\n * subscribers.\n *\n * Defensive against malformed payloads (legal reason: a mock bus's\n * `getRecent` may ignore the category filter and replay unrelated\n * events when we hydrate at construction time).\n */\n private ingest(payload: SystemReadyStatePayload): void {\n if (typeof payload?.capName !== 'string') return\n if (payload.state !== 'ready' && payload.state !== 'starting' && payload.state !== 'down') return\n if (typeof payload.generation !== 'string') return\n if (payload.scope?.type !== 'global' && payload.scope?.type !== 'node' && payload.scope?.type !== 'device') return\n\n const key = readinessKey(payload.capName, payload.scope)\n const prev = this.snapshot.get(key) ?? null\n const now = this.now()\n\n let epoch: number\n if (prev === null) {\n epoch = payload.state === 'ready' ? 1 : 0\n } else if (prev.generation !== payload.generation && payload.state === 'ready') {\n epoch = prev.epoch + 1\n } else {\n epoch = prev.epoch\n }\n\n // Idempotent replay: same generation + same state + we've already\n // recorded it — skip both snapshot write and dispatch.\n if (prev !== null && prev.generation === payload.generation && prev.state === payload.state) {\n return\n }\n\n const durationInPrevState = prev === null ? 0 : Math.max(0, now - prev.lastChange)\n const next: ReadinessRecord = {\n capName: payload.capName,\n scope: payload.scope,\n state: payload.state,\n generation: payload.generation,\n epoch,\n lastChange: now,\n sourceNodeId: payload.sourceNodeId,\n }\n this.snapshot.set(key, next)\n\n const transition: ReadinessTransition = {\n capName: payload.capName,\n scope: payload.scope,\n state: payload.state,\n epoch,\n generation: payload.generation,\n sourceNodeId: payload.sourceNodeId,\n ts: payload.ts,\n durationInPrevState,\n }\n\n if (this.logger) {\n this.logger.debug(\n `readiness: ${payload.capName} (${scopeKey(payload.scope)}) → ${payload.state} epoch=${epoch} gen=${payload.generation.slice(0, 6)} (prev ${durationInPrevState}ms)`,\n )\n }\n\n for (const sub of this.subscriptions) {\n if (sub.capName !== payload.capName) continue\n if (!scopesEqual(sub.scope, payload.scope)) continue\n try {\n sub.handler(transition)\n } catch (err) {\n this.logger?.warn(`readiness handler threw for ${payload.capName}: ${(err as Error).message ?? String(err)}`)\n }\n }\n }\n\n /**\n * `agent.offline` demux. When an agent disconnects ungracefully,\n * its BaseAddon's shutdown hook doesn't fire — consumers would\n * otherwise keep waiting on a stale `ready`. Walk the snapshot and\n * synthesize a `down` transition for every node-scoped record bound\n * to the disconnected `nodeId`, skipping records already `down`.\n *\n * Synthesis is LOCAL: we don't re-emit on the bus. Every registry\n * (one per process) receives the same `agent.offline` and reacts\n * independently, which means no duplicated downs and no central\n * supervisor required.\n */\n private synthesizeDownForNode(offlineNodeId: string): void {\n const now = this.now()\n for (const [key, record] of this.snapshot) {\n if (record.state === 'down') continue\n // Node-scoped records: match on scope.nodeId.\n // Device-scoped records: match on sourceNodeId (which node emitted\n // the latest ready) because the scope itself carries no node info.\n // Global-scoped records are skipped — they're not tied to a node.\n const matchesOfflineNode =\n (record.scope.type === 'node' && record.scope.nodeId === offlineNodeId) ||\n (record.scope.type === 'device' && record.sourceNodeId === offlineNodeId)\n if (!matchesOfflineNode) continue\n\n const durationInPrevState = Math.max(0, now - record.lastChange)\n const next: ReadinessRecord = {\n ...record,\n state: 'down',\n lastChange: now,\n }\n this.snapshot.set(key, next)\n\n const transition: ReadinessTransition = {\n capName: record.capName,\n scope: record.scope,\n state: 'down',\n epoch: record.epoch,\n generation: record.generation,\n sourceNodeId: this.sourceNodeId,\n ts: now,\n durationInPrevState,\n }\n if (this.logger) {\n this.logger.debug(\n `readiness: ${record.capName} (${scopeKey(record.scope)}) → down (synthesized from agent.offline ${offlineNodeId})`,\n )\n }\n for (const sub of this.subscriptions) {\n if (sub.capName !== record.capName) continue\n if (!scopesEqual(sub.scope, record.scope)) continue\n try {\n sub.handler(transition)\n } catch (err) {\n this.logger?.warn(`readiness handler threw during agent.offline demux for ${record.capName}: ${(err as Error).message ?? String(err)}`)\n }\n }\n }\n }\n}\n\nfunction randomGeneration(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID()\n }\n return Math.random().toString(36).slice(2, 14)\n}\n\n// ---------------------------------------------------------------------------\n// Helpers for `$node.disconnected` demultiplexing\n// ---------------------------------------------------------------------------\n\n/**\n * Given a list of `(capName, scope)` pairs that a just-disconnected\n * node owned, emit a `down` transition for each. Callers (kernel\n * supervisor, hub `$node.disconnected` handler) wire this up once they\n * know which caps the node held.\n */\nexport function emitDownForOwnedCaps(\n registry: ReadinessRegistry,\n owned: ReadonlyArray<{ readonly capName: string; readonly scope: ReadinessScope }>,\n): void {\n for (const { capName, scope } of owned) {\n registry.emitDown(capName, scope)\n }\n}\n\n// Re-export the scope key helper for consumers that want to\n// collate by key in their own maps (e.g. debug UIs).\nexport { scopeKey }\n","import type { StreamSourceEntry } from '../../device/camera-device.js'\n\n// ---------------------------------------------------------------------------\n// Stream metadata — probed (ffprobe) or declared by provider\n// ---------------------------------------------------------------------------\n\nexport interface StreamMetadata {\n width?: number // e.g. 1920\n height?: number // e.g. 1080\n codec?: string // e.g. 'h264', 'h265', 'mjpeg', 'vp8', 'vp9', 'av1'\n fps?: number // e.g. 25\n bitrateKbps?: number // e.g. 4000\n /** Probed audio track. Undefined when stream carries no audio. */\n audio?: StreamAudioMetadata\n}\n\nexport interface StreamAudioMetadata {\n /** Codec name as reported by the demuxer (e.g. 'aac', 'pcm_mulaw', 'opus'). */\n codec?: string\n /** Sample rate in Hz (e.g. 8000, 16000, 44100, 48000). */\n sampleRate?: number\n /** Channel count (1 = mono, 2 = stereo). */\n channels?: number\n /** Stated bitrate in kbps when the demuxer reports one. */\n bitrateKbps?: number\n /** Codec profile/aac-mode (e.g. 'LC', 'HE-AAC') when known. */\n profile?: string\n}\n\n// ---------------------------------------------------------------------------\n// Stream quality — computed from metadata\n// ---------------------------------------------------------------------------\n\nexport type StreamQuality = 'high' | 'mid' | 'low'\n\n/** Friendly display labels for stream quality IDs. */\nexport const STREAM_QUALITY_LABELS: Readonly<Record<string, string>> = {\n high: 'High',\n mid: 'Mid',\n low: 'Low',\n}\n\n/** Get a friendly label for a stream ID. Falls back to capitalised id. */\nexport function streamQualityLabel(id: string): string {\n return STREAM_QUALITY_LABELS[id] ?? (id.charAt(0).toUpperCase() + id.slice(1))\n}\n\n/**\n * Compute pixel count for sorting. Returns w*h, or 0 if unknown.\n */\nexport function streamPixels(meta: StreamMetadata): number {\n return (meta.width ?? 0) * (meta.height ?? 0)\n}\n\n/**\n * Classify streams relative to each other.\n * Highest resolution → high, lowest → low, everything else → mid.\n * With 1 stream: high. With 2: high + low.\n */\nexport function classifyStreams<T extends { metadata?: StreamMetadata }>(\n streams: readonly T[],\n): Array<T & { quality: StreamQuality }> {\n if (streams.length === 0) return []\n\n // Sort by pixel count descending\n const sorted = streams\n .map((s, i) => ({ s, i, px: streamPixels(s.metadata ?? {}) }))\n .sort((a, b) => b.px - a.px)\n\n const result: Array<T & { quality: StreamQuality }> = Array.from<T & { quality: StreamQuality }>({ length: streams.length })\n\n for (let rank = 0; rank < sorted.length; rank++) {\n const { s, i } = sorted[rank]!\n let quality: StreamQuality\n if (rank === 0) quality = 'high'\n else if (rank === sorted.length - 1) quality = 'low'\n else quality = 'mid'\n result[i] = { ...s, quality }\n }\n\n return result\n}\n\n/**\n * Classify a single stream in isolation (no relative context).\n * Use classifyStreams() when you have the full set.\n */\nexport function classifyStream(meta: StreamMetadata): StreamQuality {\n const h = meta.height ?? 0\n const w = meta.width ?? 0\n if (h >= 1080 || w >= 1920) return 'high'\n if (h >= 480 || w >= 640) return 'mid'\n return 'low'\n}\n\n// ---------------------------------------------------------------------------\n// Stream protocol — how to consume a stream\n// ---------------------------------------------------------------------------\n\nexport type StreamProtocolType = 'rtsp' | 'rtmp' | 'http' | 'flv' | 'rtp' | 'raw'\n\nexport interface StreamProtocol {\n type: StreamProtocolType\n /** Source URL. undefined for 'raw' (push-based, e.g. Reolink Baichuan). */\n url?: string\n}\n\n// ---------------------------------------------------------------------------\n// AvailableStream — a physical stream exposed by a camera\n// ---------------------------------------------------------------------------\n\nexport interface AvailableStream {\n /** Unique identifier within the device (e.g. 'main', 'sub', 'ch0_0') */\n id: string\n /** Ways to consume this stream */\n protocols: StreamProtocol[]\n /** Probed or provider-declared stream characteristics */\n metadata?: StreamMetadata\n /** Computed from metadata via classifyStream() */\n quality: StreamQuality\n /** Optional display hint */\n label?: string\n}\n\n/** Convert AvailableStream to StreamSourceEntry for stream-broker consumers. */\nexport function toStreamSourceEntry(stream: AvailableStream): StreamSourceEntry {\n // Pick first URL-bearing protocol, prefer rtsp\n const urlProto = stream.protocols.find((p) => p.type === 'rtsp' && p.url)\n ?? stream.protocols.find((p) => p.url)\n\n const protocolRaw = urlProto?.type\n const protocol: StreamSourceEntry['protocol'] =\n protocolRaw === 'rtsp' ? 'rtsp'\n : protocolRaw === 'http' || protocolRaw === 'flv' ? 'http-mjpeg'\n : 'custom'\n\n return {\n id: stream.id,\n label: stream.label ?? stream.id,\n protocol,\n url: urlProto?.url,\n profileHint: stream.quality,\n }\n}\n\n\n// ---------------------------------------------------------------------------\n// Camera stream settings — stored in device settings by providers\n// ---------------------------------------------------------------------------\n\n/** A single stream entry in device settings. */\nexport interface CameraStreamEntry {\n readonly url: string\n readonly label?: string\n}\n\nexport interface CameraStreamConfig {\n readonly streams: readonly CameraStreamEntry[]\n /**\n * Snapshot source URL (JPEG).\n * Used internally by the provider to implement ICamera.getSnapshot().\n * Clients should call snapshot.getSnapshot() instead of hitting this URL directly.\n */\n readonly snapshot_url?: string\n}\n\nfunction isString(v: unknown): v is string {\n return typeof v === 'string'\n}\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v)\n}\n\nfunction parseStreamEntry(v: unknown): CameraStreamEntry | null {\n // \"rtsp://...\" → { url }\n if (isString(v) && v.trim()) return { url: v }\n // { url: \"rtsp://...\", label?: \"Main\" } → { url, label }\n if (isRecord(v) && isString(v['url']) && v['url'].trim()) {\n return {\n url: v['url'],\n label: isString(v['label']) ? v['label'] : undefined,\n }\n }\n return null\n}\n\n/** Extract CameraStreamConfig from untyped settings record. */\nexport function parseCameraStreamConfig(raw: Record<string, unknown>): CameraStreamConfig {\n const snapshotUrl = isString(raw['snapshot_url']) ? raw['snapshot_url'] : undefined\n\n // Array format: [\"url\"] or [{url, label}]\n if (Array.isArray(raw['streams'])) {\n const streams: CameraStreamEntry[] = []\n for (const item of raw['streams']) {\n const entry = parseStreamEntry(item)\n if (entry) streams.push(entry)\n }\n return { streams, snapshot_url: snapshotUrl }\n }\n\n // Legacy key-based format: main_stream_url, sub_stream_url, third_stream_url\n const streams: CameraStreamEntry[] = []\n\n const mainUrl = isString(raw['main_stream_url']) ? raw['main_stream_url'] : undefined\n if (mainUrl) streams.push({ url: mainUrl, label: isString(raw['main_stream_name']) ? raw['main_stream_name'] : undefined })\n\n const subUrl = isString(raw['sub_stream_url']) ? raw['sub_stream_url'] : undefined\n if (subUrl) streams.push({ url: subUrl, label: isString(raw['sub_stream_name']) ? raw['sub_stream_name'] : undefined })\n\n const thirdUrl = isString(raw['third_stream_url']) ? raw['third_stream_url'] : undefined\n if (thirdUrl) streams.push({ url: thirdUrl, label: isString(raw['third_stream_name']) ? raw['third_stream_name'] : undefined })\n\n return {\n streams,\n snapshot_url: snapshotUrl,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Stream Profile Assignment\n// ---------------------------------------------------------------------------\n\n/**\n * Per-device mapping of quality profile → streamId.\n * Cameras expose N physical streams; the user assigns which stream\n * serves each of the 3 standard CamStack profiles.\n */\nexport interface StreamProfileMap {\n high?: string\n mid?: string\n low?: string\n}\n\n/**\n * Auto-assign profiles based on quality classification.\n * With 1 stream: all profiles point to it.\n * With 2: high + low. With 3+: high + mid + low.\n */\nexport function autoAssignProfiles(streams: readonly AvailableStream[]): StreamProfileMap {\n if (streams.length === 0) return {}\n\n const classified = classifyStreams(streams)\n const map: StreamProfileMap = {}\n\n // Assign by quality label, not array position (classifyStreams preserves original order)\n const high = classified.find((s) => s.quality === 'high')\n const mid = classified.find((s) => s.quality === 'mid')\n const low = classified.find((s) => s.quality === 'low')\n\n if (high) map.high = high.id\n if (mid) map.mid = mid.id\n if (low) map.low = low.id\n\n // Fallback: fill missing profiles from what's available\n const fallback = high ?? mid ?? low ?? classified[0]\n if (fallback) {\n if (!map.high) map.high = fallback.id\n if (!map.mid) map.mid = fallback.id\n if (!map.low) map.low = fallback.id\n }\n\n return map\n}\n\n// ---------------------------------------------------------------------------\n","export interface FeatureManifest {\n streaming: boolean\n notifications: boolean\n objectDetection: boolean\n remoteAccess: boolean\n agentCluster: boolean\n smartHome: boolean\n recordings: boolean\n backup: boolean\n repl: boolean\n}\n\nexport type FeatureFlag = keyof FeatureManifest\n\nexport const DEFAULT_FEATURES: FeatureManifest = {\n streaming: true,\n notifications: true,\n objectDetection: false,\n remoteAccess: true,\n agentCluster: false,\n smartHome: true,\n recordings: true,\n backup: true,\n repl: true,\n}\n","/**\n * Detection Analysis Pipeline -- types for tracked detections, sub-detections,\n * recognition results, and audio classification.\n */\n\nimport type { VideoFrame } from './camera-pipeline.js'\n\n/**\n * A single detection entry consumed by the analysis pipeline (tracking,\n * zones, session aggregation).\n *\n * Intentionally DIFFERENT from `SpatialDetection` (the engine-level\n * detector output in `types/detection.ts`):\n * - `SpatialDetection` is raw model output: `{class, bbox:{x,y,w,h},\n * landmarks?, mask?}`.\n * - `AnalysisDetection` is the pipeline's view: tuple-bbox\n * `[x1,y1,x2,y2]`, optional enrichment (`id`, `label`, `zones`,\n * `previousZones`) added by upstream stages.\n *\n * Renamed from the ambiguous `Detection` on 2026-04-14 to disambiguate\n * from the other Detection types in the codebase (`ObjectDetection`\n * for UI payloads, `SpatialDetection` for engine output).\n */\nexport interface AnalysisDetection {\n className: string\n score: number\n boundingBox?: [number, number, number, number]\n id?: string\n label?: string\n labelScore?: number\n zones?: string[]\n previousZones?: string[]\n}\n\n// --- Detection type const unions ---\n\nexport const SUB_DETECTION_TYPES = ['face', 'plate'] as const\nexport type SubDetectionType = typeof SUB_DETECTION_TYPES[number]\n\nexport const RECOGNITION_TYPES = ['face', 'plate', 'clip', 'custom'] as const\nexport type RecognitionType = typeof RECOGNITION_TYPES[number]\n\n// --- Analysis Context ---\n\nexport interface AnalysisContext {\n readonly deviceId: string\n readonly frame: VideoFrame\n readonly timestamp: number\n readonly rawDetections: readonly AnalysisDetection[]\n readonly trackedDetections: readonly ServerTrackedDetection[]\n readonly events: readonly AnalysisEvent[]\n readonly metadata: Readonly<Record<string, unknown>>\n}\n\n// --- Tracked Detection ---\n\nexport interface ServerTrackedDetection {\n readonly trackId: string\n readonly detection: AnalysisDetection\n readonly crop?: Buffer\n readonly tracking: TrackingInfo\n readonly subDetections: readonly SubDetection[]\n readonly recognitions: readonly RecognitionResult[]\n readonly zones: readonly string[]\n readonly previousZones: readonly string[]\n}\n\nexport interface TrackingInfo {\n readonly age: number\n readonly state: 'moving' | 'stationary' | 'new' | 'lost'\n readonly stationaryDuration: number\n readonly velocity: { readonly dx: number; readonly dy: number }\n readonly positionHistory: ReadonlyArray<{ readonly x: number; readonly y: number; readonly t: number }>\n}\n\n// --- Sub-Detection ---\n\nexport interface SubDetection {\n readonly detectionType: SubDetectionType\n readonly boundingBox: readonly [number, number, number, number]\n readonly score: number\n readonly crop?: Buffer\n}\n\n// --- Recognition ---\n\nexport interface RecognitionResult {\n readonly recognitionType: RecognitionType\n readonly label: string\n readonly score: number\n readonly embedding?: readonly number[]\n readonly metadata?: Readonly<Record<string, unknown>>\n}\n\n// --- Analysis Events ---\n\nexport interface AnalysisEvent {\n readonly category: string\n readonly severity: 'info' | 'warning' | 'alert'\n readonly detection: ServerTrackedDetection\n readonly description: string\n readonly data: Readonly<Record<string, unknown>>\n}\n\n// --- Audio Classifier ---\n//\n// The canonical `IAudioClassifier` lives in `./audio-analyzer.ts` and is\n// derived from the capability definition. The legacy interface that lived\n// here had a different shape (readonly ready + release()) and was never\n// actually consumed outside of this file — removed to avoid confusion.\n","\nimport { z } from 'zod'\nimport type { FrameFormat } from '../types/io.js'\n\n// ── Zod schemas for wire-serializable decoder cap methods ──────────\n\nexport const DecoderStatsSchema = z.object({\n inputFps: z.number(),\n outputFps: z.number(),\n avgDecodeTimeMs: z.number(),\n droppedFrames: z.number(),\n})\n\nexport const DecoderSessionConfigSchema = z.object({\n codec: z.string(),\n maxFps: z.number().default(0),\n outputFormat: z.enum(['jpeg', 'rgb', 'bgr', 'yuv420', 'gray']).default('jpeg'),\n scale: z.number().default(1),\n width: z.number().optional(),\n height: z.number().optional(),\n /**\n * Identifier of the camera this decoder session serves. Optional\n * because the cap is generic (any caller could request decode), but\n * stream-broker passes it so decoder logs include `deviceId` for\n * per-camera filtering when diagnosing failures (e.g. node-av\n * sendPacket errors on a single hung camera).\n */\n deviceId: z.number().int().nonnegative().optional(),\n /**\n * Free-form tag for log scoping. Stream-broker uses\n * `broker:<deviceId>/<profile>`. Decoder session logger surfaces it\n * on every line so `grep tag=broker:5/high` filters one camera\n * profile cleanly.\n */\n tag: z.string().optional(),\n})\n\nexport type Unsubscribe = () => void\n\n/**\n * Discriminator for `StreamSource.type`. Values that the broker\n * understands today:\n *\n * - `'rtsp'` — pull mode. Broker connects to a `rtsp://` URL,\n * demuxes RTP, exposes raw RTP via `onVideoRtp`.\n * - `'rtmp'` — pull mode. Broker connects to a `rtmp://` URL,\n * demuxes flv into AnnexB packets. No source RTP\n * available (RTMP carries no RTP), so the WebRTC\n * path falls back to AnnexB → writeVideoNals.\n * Reserved — implementation pending.\n * - `'push'` — push mode. Provider addon delivers AnnexB packets\n * via `pushEncodedPacket()` (Reolink Baichuan,\n * Frigate event streams, etc.).\n * - `'push-rtp'` — push mode with raw RTP packets. Provider addon\n * delivers source RTP via `pushVideoRtp()` AND\n * AnnexB-equivalents via `pushEncodedPacket()` so\n * downstream consumers (decoder, restreamer) keep\n * working. Lets the WebRTC path use the H.265\n * repacketizer for push-mode H.265 streams. Reserved\n * — implementation pending.\n * - `'placeholder'` — silent black-image placeholder reader.\n *\n * String type instead of a literal union so addons remain free to\n * add new source types — the broker's switch statement falls through\n * to \"data is pushed externally\" for unknown values.\n */\nexport type StreamSourceType = 'rtsp' | 'rtmp' | 'push' | 'push-rtp' | 'rfc4571' | 'placeholder' | (string & {})\n\nexport interface StreamSource {\n readonly type: StreamSourceType\n /** Stream URL — required for pull-based sources (rtsp, rtmp). Not used for push sources. */\n readonly url: string\n readonly videoCodec?: string\n readonly audioCodec?: string\n readonly metadata?: Readonly<Record<string, unknown>>\n /**\n * Push-source flag — when true, a stall in the input stream is\n * treated as a valid suspension (battery cameras intentionally go\n * silent between motion events) rather than an error. The broker\n * stops emitting the black-image placeholder and pauses the watchdog\n * until the next packet arrives. Default: false (legacy behaviour —\n * stall is an error).\n */\n readonly allowStall?: boolean\n}\n\nexport interface StreamSourceOption {\n readonly id: string\n readonly label: string\n readonly source: StreamSource\n readonly resolution?: { readonly width: number; readonly height: number }\n readonly primary?: boolean\n}\n\nexport interface EncodedPacket {\n readonly type: 'video' | 'audio'\n readonly data: Buffer\n readonly pts: number\n readonly dts: number\n readonly keyframe: boolean\n readonly codec: string\n /**\n * `true` when the packet was synthesized by the broker's placeholder\n * pump (state-aware \"RECONNECTING\" / \"SLEEPING\" / etc. keyframes\n * pushed at 1Hz while no real RTP is flowing). Consumers that\n * accumulate per-stream codec state (sticky SPS/PPS, decoder config)\n * MUST treat these as throwaway: the placeholder is a different\n * resolution and parameter set than the live camera, so caching its\n * SPS/PPS and prepending them to real keyframes silently corrupts\n * the decoder state and freezes the WebRTC viewer on the last\n * placeholder until the consumer is re-created. Absent on packets\n * produced from real source data.\n */\n readonly isPlaceholder?: boolean\n}\n\n/**\n * Audio metadata declared by push-source providers before they emit the\n * first audio `EncodedPacket`. Mirrors the slice of an SDP audio track\n * the broker actually consumes — `codec` is canonical lowercase\n * ('aac' | 'opus' | 'pcmu' | 'pcma' | ...).\n *\n * `extraData` carries codec-specific config bytes (e.g. AAC\n * AudioSpecificConfig) when the codec needs them at decoder-init time.\n */\nexport interface PushAudioInfo {\n readonly codec: string\n readonly sampleRate: number\n readonly channels: number\n readonly extraData?: Uint8Array\n}\n\nexport interface DecodedFrame {\n readonly data: Buffer\n readonly width: number\n readonly height: number\n readonly format: FrameFormat\n readonly timestamp: number\n}\n\nexport interface DecodedAudioChunk {\n readonly data: Buffer\n readonly sampleRate: number\n readonly channels: number\n readonly timestamp: number\n}\n\nexport interface DecodeOptions {\n readonly maxFps?: number\n readonly format?: FrameFormat\n readonly scale?: number\n /**\n * Caller identity tag (Phase 10). Surfaced by `listClients` so\n * operators can tell who's holding the broker open. Short and stable:\n * `motion`, `detection`, `snapshot`, `webrtc:<sessionId>`,\n * `benchmark`. Missing tag → recorded as `'unknown'` with a broker-\n * side warn log.\n */\n readonly tag?: string\n}\n\nexport interface AudioSubscribeOptions {\n /** Caller identity tag. See DecodeOptions.tag. */\n readonly tag?: string\n}\n\nexport type BrokerStatus = 'idle' | 'connecting' | 'streaming' | 'error' | 'stopped'\n\nexport interface BrokerStats {\n readonly status: BrokerStatus\n readonly inputFps: number\n readonly decodeFps: number\n readonly encodedSubscribers: number\n readonly decodedSubscribers: number\n readonly uptimeMs: number\n /** Measured bitrate in kbps (averaged over 2s window) */\n readonly bitrateKbps: number\n /** Time between last two keyframes in ms (IDR interval) */\n readonly idrIntervalMs: number\n /** Detected video codec (h264, h265) */\n readonly codec?: string\n /** Total bytes received since broker start */\n readonly totalBytes: number\n /** Total encoded packets received since broker start */\n readonly packetCount: number\n /** Number of connected RTSP restream clients */\n readonly rtspClients: number\n /** Number of connected TCP pipe clients */\n readonly pipeClients: number\n /** Pre-buffer configured duration in seconds */\n readonly preBufferSec: number\n /** Pre-buffer actual buffered duration in ms */\n readonly preBufferMs: number\n /** Pre-buffer packet count */\n readonly preBufferPackets: number\n /**\n * Moleculer node id of the decoder provider currently servicing this\n * stream's decoded subscribers. `null` until the deferred decoder is\n * created (no decoded clients yet, or codec not detected).\n */\n readonly decoderNodeId: string | null\n /**\n * Detected audio track parameters from the RTSP DESCRIBE / SDP. Null\n * when the stream has no audio track or the broker is still in cold\n * start. `supported` reflects whether the local native + ffmpeg-based\n * decoder pipeline can produce PCM chunks for downstream consumers\n * (audio-analyzer). When `false`, the codec is detected but skipped.\n */\n readonly audio?: {\n readonly codec: string\n readonly sampleRate: number\n readonly channels: number\n readonly supported: boolean\n } | null\n}\n\nexport interface IStreamBroker {\n readonly deviceId: string\n readonly status: BrokerStatus\n readonly suspended: boolean\n start(source: StreamSource): Promise<void>\n stop(): Promise<void>\n /**\n * Push an encoded packet into the broker from an external source.\n *\n * Used by camera provider addons that deliver media data directly\n * (e.g. Reolink Baichuan protocol, Frigate event streams) instead\n * of exposing an RTSP URL for the broker to pull from.\n *\n * The broker fans out the packet to all consumers: pre-buffer, RTSP\n * restreamer, TCP pipe, decoder sessions, and encoded subscribers.\n */\n pushEncodedPacket(packet: EncodedPacket): void\n /**\n * Push-source audio metadata. Push providers (Reolink Baichuan,\n * Frigate, etc.) call this BEFORE the first audio EncodedPacket so\n * the broker can wire the audio-codec capability — RTSP sources get\n * the same data from the SDP audio track. Repeat calls update the\n * declared codec; calling with `null` retracts (broker tears down\n * any audio decode session).\n *\n * Typical Reolink Baichuan audio: AAC-LC 16 kHz mono. Cameras that\n * push G.711 should still call this so the broker can bypass the\n * codec cap for the supported native codecs.\n */\n pushAudioInfo?(info: PushAudioInfo | null): void\n /**\n * Push a raw video RTP packet from an external source (used by\n * `'push-rtp'`-typed sources, e.g. Reolink Baichuan adapter that\n * synthesizes RTP from its packetizer-friendly access units). The\n * broker fans out to `onVideoRtp` subscribers, including the\n * WebRTC server's H.265 repacketizer path.\n *\n * Sources that don't carry per-packet RTP MAY ignore this entirely\n * and call only `pushEncodedPacket`. Implementations are free to\n * be a no-op when no RTP subscribers exist.\n */\n pushVideoRtp?(rtpData: Buffer): void\n onEncodedData(callback: (packet: EncodedPacket) => void): Unsubscribe\n /**\n * Subscribe to source video RTP packets (raw on-wire bytes, before\n * depacketization). Used by the WebRTC server's H.265 path to feed\n * a packet-level repacketizer that preserves the original RTP header\n * layout — Chrome's HEVC depacketizer is sensitive to it.\n *\n * Sources that don't have an underlying RTP wire (e.g. Frigate event\n * streams that call `pushEncodedPacket`) MAY register zero callbacks\n * and emit nothing.\n */\n onVideoRtp(callback: (rtpData: Buffer) => void): Unsubscribe\n /**\n * Codec parameter sets harvested from the camera's SDP (sprop-vps /\n * sprop-sps / sprop-pps). Cameras like Reolink high-profile streams\n * publish VPS/SPS/PPS only via SDP — Chrome's HEVC decoder needs them\n * to initialise. Returns null when the broker hasn't connected yet\n * or the camera ships param sets in-band.\n */\n getSdpParameterSets(): ReadonlyArray<Buffer> | null\n /**\n * Subscribe to SDP-derived VPS/SPS/PPS deliveries. Fires once\n * synchronously if the broker already has them (late-subscriber\n * shape), and again every time `onVideoTrack` repopulates them on a\n * reader rebuild. Used by the WebRTC server's H.265 path so a\n * session created during the wake-up window — when\n * `getSdpParameterSets()` still returns null — can seed its\n * `H265Repacketizer` once the camera's first RTP+SDP arrive.\n */\n onSdpParameterSets(callback: (ps: ReadonlyArray<Buffer>) => void): Unsubscribe\n /**\n * Source type as configured at `start()` — see `StreamSourceType`\n * for the supported values. `null` before `start()` resolves.\n */\n getSourceType(): StreamSourceType | null\n /**\n * True when the broker can emit source RTP packets via\n * `onVideoRtp` — i.e. the source is RTSP (pull) or push-rtp.\n * RTMP and bare push (AnnexB-only) sources return false.\n * Routing decisions in the WebRTC server (e.g. \"use the H.265\n * repacketizer\") should consult this rather than string-comparing\n * the source type.\n */\n isRtpSource(): boolean\n /**\n * Subscribe to decoded frames. Phase 10 added `options.tag` — a short\n * caller-identity string (`motion`, `detection`, `snapshot`,\n * `webrtc:<sessionId>`, `benchmark`) used by `listClients` so\n * operators can see who is holding the broker open. Omitted tag\n * yields a `'unknown'` entry with a warn log — not silently accepted.\n */\n onDecodedFrame(callback: (frame: DecodedFrame) => void, options?: DecodeOptions): Unsubscribe\n /** Subscribe to decoded audio chunks. `options.tag` mirrors `onDecodedFrame`. */\n onDecodedAudioChunk(callback: (chunk: DecodedAudioChunk) => void, options?: AudioSubscribeOptions): Unsubscribe\n getStats(): BrokerStats\n getLocalStreamUrl(): string\n /** Get the pre-buffer: recent encoded packets starting from last keyframe. */\n getPreBuffer(): readonly EncodedPacket[]\n /** Set the pre-buffer duration in seconds (0 to disable, max 30). */\n setPreBufferDuration(seconds: number): void\n /** Get the current pre-buffer duration in seconds. */\n getPreBufferDuration(): number\n setPreBufferEnabled(enabled: boolean): void\n}\n\n/**\n * Manager for stream brokers — the server interacts with this interface,\n * while the concrete implementation lives in the addon-stream-broker package.\n */\n/** Per-broker RTSP restream entry (absorbed from the former rtsp-restream capability). */\nexport interface RtspRestreamEntry {\n readonly brokerId: string\n readonly url: string\n readonly mutedUrl: string\n readonly enabled: boolean\n}\n\n/** Flat cap-shaped broker record returned by `listBrokers()`. */\nexport interface BrokerListEntry {\n readonly brokerId: string\n readonly status: string\n readonly inputFps: number\n readonly decodeFps: number\n readonly encodedSubscribers: number\n readonly decodedSubscribers: number\n readonly uptimeMs: number\n readonly bitrateKbps: number\n readonly idrIntervalMs: number\n readonly codec?: string\n readonly totalBytes: number\n readonly packetCount: number\n readonly rtspClients: number\n readonly pipeClients: number\n readonly preBufferSec: number\n readonly preBufferMs: number\n readonly preBufferPackets: number\n}\n\n\n/**\n * Phase the runner's per-camera state machine occupies. `'idle'` is the\n * `detectionMode === 'disabled'` resting state — runner registered the\n * camera but never subscribed to detection frames. The other 4 are the\n * historical motion-gated states; their transitions are now driven by\n * `detectionMode` ('always-on' starts in 'active', 'on-motion' starts\n * in 'watching').\n */\nexport type CameraPhase = 'idle' | 'watching' | 'active' | 'paused' | 'load-shed'\n\nexport interface CameraDetectionConfig {\n readonly enabled: boolean\n readonly pipelineEnabled: boolean\n\n /** Motion sources that activate this camera's pipeline. At least one. */\n readonly motionSources: import('./pipeline-orchestrator-capability.js').OrchestrationMotionSources\n\n readonly motionStreamId: string\n readonly detectionStreamId: string\n\n readonly motionFps: number\n readonly detectionFps: number\n readonly motionCooldownMs: number\n\n readonly audioStreamId?: string\n\n /**\n * Operator-facing scheduling modes. Forwarded to `RunnerCameraConfig`;\n * the runner uses these to gate its substream subscribers + phase\n * machine. See `PipelinePhaseMode` for the semantics.\n */\n readonly detectionMode: import('../device/device-profile.js').PipelinePhaseMode\n readonly audioMode: import('../device/device-profile.js').PipelinePhaseMode\n}\n","/**\n * Analysis Persistence Types — interfaces for event persistence, track trails,\n * retention, session tracking, and known faces.\n *\n * These interfaces define the contracts used by the server; concrete\n * implementations live in addon-analytics and are received via CapabilityRegistry.\n */\n\nimport type { ServerTrackedDetection } from './server-analysis.js'\n\n// ---------------------------------------------------------------------------\n// Event Persistence\n// ---------------------------------------------------------------------------\n\nexport interface ObjectSnapshotResult {\n readonly trackId: string\n readonly thumbnail?: Buffer\n readonly fullCrop?: Buffer\n}\n\nexport interface AnnotatedSnapshotResult {\n readonly thumbnail: Buffer\n readonly full: Buffer\n}\n\nexport interface PersistableEvent {\n readonly id: string\n readonly timestamp: number\n readonly deviceId: string\n readonly category: string\n readonly className: string\n readonly score: number\n readonly trackId: string\n readonly severity: string\n readonly description: string\n readonly data: Record<string, unknown>\n readonly mediaFiles: readonly string[]\n}\n\nexport interface EventBufferStatus {\n readonly eventCount: number\n readonly mediaCount: number\n readonly mediaSizeMB: number\n}\n\nexport type TrackMediaType =\n | 'crop-thumb'\n | 'crop-full'\n | 'debug-annotated-thumb'\n | 'debug-annotated-full'\n | 'original'\n | 'original-thumb'\n | 'inline-crop'\n | 'unknown'\n\nexport interface TrackMediaFile {\n readonly path: string\n readonly type: TrackMediaType\n readonly data: Buffer\n readonly source: 'buffer' | 'storage'\n}\n\n// ---------------------------------------------------------------------------\n// Track Trail\n// ---------------------------------------------------------------------------\n\n// F15c: `enabled` removed — trail capture on/off lives on the\n// `track-trail` wrapper binding. See capabilities/track-trail.cap.ts.\nexport interface TrackCaptureConfig {\n readonly snapshotIntervalMs: number\n readonly maxTrailLength: number\n readonly saveThumbnails: boolean\n readonly thumbnailSize: { readonly width: number; readonly height: number }\n}\n\nexport interface TrackPosition {\n readonly x: number\n readonly y: number\n readonly timestamp: number\n readonly bbox: [number, number, number, number]\n}\n\nexport interface TrackSnapshot {\n readonly timestamp: number\n readonly position: TrackPosition\n readonly thumbnailPath: string\n}\n\nexport interface TrackTrail {\n readonly trackId: string\n readonly deviceId: number\n readonly className: string\n readonly label?: string\n readonly firstSeen: number\n readonly lastSeen: number\n readonly positions: readonly TrackPosition[]\n readonly snapshots: readonly TrackSnapshot[]\n readonly totalDistance: number\n readonly zonesVisited: readonly string[]\n readonly active: boolean\n}\n\n// ---------------------------------------------------------------------------\n// Retention\n// ---------------------------------------------------------------------------\n\nexport interface RetentionConfig {\n readonly cleanupIntervalMs: number\n readonly detectionEventsDays: number\n readonly audioLevelsDays: number\n /** @deprecated — snapshots are tied to events, use detectionEventsDays */\n readonly snapshotsDays: number\n readonly deviceOverrides?: Readonly<Record<string, Partial<Pick<RetentionConfig, 'detectionEventsDays' | 'audioLevelsDays' | 'snapshotsDays'>>>>\n}\n\nexport const DEFAULT_RETENTION: RetentionConfig = {\n cleanupIntervalMs: 60 * 60 * 1000,\n detectionEventsDays: 30,\n audioLevelsDays: 7,\n snapshotsDays: 14,\n}\n\nexport interface RetentionReport {\n readonly deletedEvents: number\n readonly deletedAudioRecords: number\n readonly deletedSnapshots: number\n}\n\n// ---------------------------------------------------------------------------\n// Session Tracker\n// ---------------------------------------------------------------------------\n\nexport interface SessionTrack {\n readonly trackId: string\n readonly deviceId: string\n readonly className: string\n readonly label?: string\n readonly firstSeen: number\n readonly lastSeen: number\n readonly totalFrames: number\n readonly lastDetection: ServerTrackedDetection\n readonly state: string\n readonly positions: ReadonlyArray<{ readonly x: number; readonly y: number; readonly t: number }>\n readonly embedding?: Float32Array\n readonly globalId?: string\n readonly bestCrop?: Buffer\n}\n\nexport interface GlobalIdentity {\n readonly globalId: string\n readonly embedding: Float32Array\n readonly label?: string\n readonly firstSeen: number\n readonly lastSeen: number\n readonly deviceIds: ReadonlyArray<string>\n}\n\n// ---------------------------------------------------------------------------\n// Known Faces\n// ---------------------------------------------------------------------------\n\nexport interface ClipRecognizer {\n getEmbedding(imageBuffer: Buffer): Promise<Float32Array>\n}\n\nexport interface KnownFaceEntry {\n readonly id: string\n readonly label: string\n readonly group?: string\n readonly embedding: readonly number[]\n readonly cropBase64: string\n readonly createdAt: number\n readonly updatedAt: number\n readonly source?: string\n readonly metadata?: Readonly<Record<string, unknown>>\n}\n\n// ---------------------------------------------------------------------------\n// Recording Addon (generic interface for recording engine access)\n// ---------------------------------------------------------------------------\n\n/**\n * Interface for the recording addon — the server uses this instead of\n * importing RecordingAddon directly from addon-recording.\n */\nexport interface IRecordingAddon {\n getCoordinator(): IRecordingCoordinator\n getRecordingDb(): IRecordingDb\n}\n\n/**\n * Minimal coordinator interface for the server's recording router.\n */\nexport interface IRecordingCoordinator {\n enableRecording(deviceId: string, options: {\n policy: unknown\n ffmpegOverrides?: unknown\n }): Promise<void>\n disableRecording(deviceId: string): Promise<void>\n isRecording(deviceId: string): boolean\n readonly playlistGenerator: {\n generate(\n deviceId: string,\n streamId: string,\n startTime: number,\n endTime: number,\n options?: { live?: boolean },\n ): unknown\n }\n readonly storageEstimator: {\n estimateForDevice(\n deviceId: string,\n motionInput?: { avgEventsPerDay: number; avgDurationSec: number },\n ): { totalEstimatedGb: number; [key: string]: unknown }\n }\n}\n\n/**\n * Minimal recording database interface for the server's recording router.\n */\nexport interface IRecordingDb {\n upsertStorageConfig(config: {\n deviceId: string\n dataCategory: string\n storageName: string\n subDirectory: string\n retentionDays: number | null\n retentionGb: number | null\n }): void\n getPolicy(deviceId: string): { readonly enabled: boolean; readonly mode: string; [key: string]: unknown } | null\n getEnabledPolicies(): Array<{ deviceId: string; [key: string]: unknown }>\n querySegments(deviceId: string, streamId: string, startTime: number, endTime: number): unknown\n getAvailability(deviceId: string, startTime: number, endTime: number): unknown\n getStorageUsage(deviceId: string, streamId: string): unknown\n upsertPolicy(policy: unknown): void\n findNearestThumbnail(deviceId: string, timestamp: number, category: string): unknown\n getMotionStats(deviceId: string, startTime: number, endTime: number): {\n avgEventsPerDay: number\n avgDurationSec: number\n dutyCyclePercent: number\n totalEvents: number\n }\n resolveStorageConfig(deviceId: string, dataCategory: string): unknown\n}\n\n// ---------------------------------------------------------------------------\n// Sub-service interfaces — used by the server's thin NestJS wrappers\n// to receive delegates via CapabilityRegistry.\n// ---------------------------------------------------------------------------\n\nexport interface IEventPersistence {\n start(): void\n stop(): void\n saveDetectionCrops(eventId: string, crops: readonly ObjectSnapshotResult[]): void\n saveAnnotatedFrame(eventId: string, result: AnnotatedSnapshotResult): void\n saveOriginalFrame(eventId: string, frame: import('./camera-pipeline.js').VideoFrame): Promise<void>\n getEventMedia(eventId: string): Promise<readonly TrackMediaFile[]>\n getTrackMedia(trackId: string): Promise<readonly TrackMediaFile[]>\n getDeviceMedia(deviceId: string, since?: number, until?: number): Promise<readonly TrackMediaFile[]>\n getBufferStatus(): { pendingEvents: number; pendingMedia: number; lastFlush?: number }\n flush(): Promise<void>\n}\n\nexport interface ITrackTrail {\n setConfig(deviceId: string, config: Partial<TrackCaptureConfig>): void\n getConfig(deviceId: string): TrackCaptureConfig\n recordFrame(ctx: unknown): Promise<void>\n getActiveTrail(trackId: string): TrackTrail | null\n getActiveTrails(deviceId: string): readonly TrackTrail[]\n getPersistedTrail(trackId: string): Promise<TrackTrail | null>\n getTrail(trackId: string): Promise<TrackTrail | null>\n listTrails(deviceId: string, options?: {\n since?: number\n until?: number\n limit?: number\n className?: string\n }): Promise<readonly TrackTrail[]>\n}\n\nexport interface IRetention {\n start(): void\n stop(): void\n runCleanup(): Promise<unknown>\n setConfig(update: Partial<RetentionConfig>): void\n getConfig(): unknown\n forceCleanup(): Promise<unknown>\n}\n\nexport interface ISessionTracker {\n updateFromAnalysis(deviceId: string, ctx: unknown): void\n getActiveTracks(deviceId: string): readonly SessionTrack[]\n getAllActiveTracks(): readonly SessionTrack[]\n getTrack(deviceId: string, trackId: string): SessionTrack | undefined\n getTrackCounts(): Record<string, number>\n clearDevice(deviceId: string): void\n clearAll(): void\n getGlobalPool(): unknown\n}\n\nexport interface KnownFaceSummary {\n readonly id: string\n readonly label: string\n readonly group?: string\n readonly cropBase64: string\n readonly createdAt: number\n readonly updatedAt: number\n readonly source?: string\n readonly sourceType?: string\n readonly count?: number\n}\n\nexport interface IKnownFaces {\n register(entry: KnownFaceEntry): Promise<void>\n listAll(): Promise<readonly KnownFaceSummary[]>\n delete(id: string): Promise<void>\n update(id: string, updates: Partial<Pick<KnownFaceEntry, 'label' | 'group'>>): Promise<void>\n recalculateEmbedding(id: string, clipRecognizer: ClipRecognizer): Promise<void>\n findMatch(embedding: Float32Array, threshold: number): Promise<unknown>\n batchRegister(\n entries: ReadonlyArray<{ readonly label: string; readonly cropBase64: string; readonly group?: string }>,\n clipRecognizer: ClipRecognizer,\n ): Promise<unknown>\n}\n\n/**\n * Composite interface exposed via CapabilityRegistry as the\n * 'analysis-data-persistence' singleton. Each sub-service is wired\n * individually to the corresponding NestJS wrapper service.\n */\nexport interface IAnalysisDataPersistence {\n readonly eventPersistence: IEventPersistence\n readonly knownFaces: IKnownFaces\n readonly sessionTracker: ISessionTracker\n readonly retention: IRetention\n readonly trackTrail: ITrackTrail\n}\n\n// ---------------------------------------------------------------------------\n// Provider Connection Testing\n// ---------------------------------------------------------------------------\n\nexport interface TestConnectionResult {\n readonly success: boolean\n readonly version?: string\n readonly cameraCount?: number\n readonly error?: string\n}\n\n/**\n * Generic interface for testing provider connections.\n * Each provider addon can expose a connection tester.\n */\nexport interface IProviderConnectionTester {\n testConnection(): Promise<TestConnectionResult>\n}\n","export enum EventSourceType {\n Addon = 'addon',\n Core = 'core',\n Device = 'device',\n Provider = 'provider',\n System = 'system',\n}\n","export const HF_REPO = 'camstack/camstack-models'\nexport const HF_BASE_URL = `https://huggingface.co/${HF_REPO}/resolve/main`\n\n/**\n * Shape of {@link RUNTIME_DEFAULTS}. Every key/value is typed explicitly so\n * consumers (ConfigManager.raw, feature accessors, settings-store seeder)\n * can read fields without `as` casts.\n *\n * Iteration via `Object.entries` still yields `[string, RuntimeDefaultsShape[keyof RuntimeDefaultsShape]]`\n * which is assignable to `[string, unknown]` — no change for consumers that\n * only need the iteration behaviour.\n */\nexport interface RuntimeDefaultsProvider {\n id: string\n type: string\n name: string\n}\n\nexport interface RuntimeDefaultsShape {\n /** Index signature for dynamic string-path lookups (e.g. ConfigManager.get).\n * Explicit keys below override this with their precise types. */\n [key: string]: unknown\n 'features.streaming': boolean\n 'features.notifications': boolean\n 'features.objectDetection': boolean\n 'features.remoteAccess': boolean\n 'features.agentCluster': boolean\n 'features.smartHome': boolean\n 'features.recordings': boolean\n 'features.backup': boolean\n 'features.repl': boolean\n 'retention.detectionEventsDays': number\n 'retention.audioLevelsDays': number\n 'logging.level': string\n 'logging.retentionDays': number\n 'eventBus.ringBufferSize': number\n 'storage.provider': string\n 'storage.locations': Record<string, string>\n 'providers': RuntimeDefaultsProvider[]\n 'recording.segmentDurationSeconds': number\n 'recording.defaultRetentionDays': number\n 'ffmpeg.binaryPath': string\n 'ffmpeg.hwAccel': string\n 'ffmpeg.threadCount': number\n 'auth.tokenExpiry': string\n}\n\n/**\n * Runtime defaults -- used by ConfigManager.get() for backward compatibility\n * until Plan B wires all runtime settings to the system_settings SQL table.\n *\n * Moved from @camstack/kernel/config-schema to @camstack/types so that\n * @camstack/core can reference it without a cross-package kernel import.\n */\nexport const RUNTIME_DEFAULTS: RuntimeDefaultsShape = {\n 'features.streaming': true,\n 'features.notifications': true,\n 'features.objectDetection': false,\n 'features.remoteAccess': true,\n 'features.agentCluster': false,\n 'features.smartHome': true,\n 'features.recordings': true,\n 'features.backup': true,\n 'features.repl': true,\n 'retention.detectionEventsDays': 30,\n 'retention.audioLevelsDays': 7,\n 'logging.level': 'info',\n 'logging.retentionDays': 30,\n 'eventBus.ringBufferSize': 10000,\n 'storage.provider': 'sqlite-storage',\n 'storage.locations': {\n data: 'camstack-data/data',\n media: 'camstack-data/media',\n recordings: 'camstack-data/recordings',\n cache: '/tmp/camstack-cache',\n logs: 'camstack-data/logs',\n models: 'camstack-data/models',\n },\n 'providers': [],\n // Recording\n 'recording.segmentDurationSeconds': 4,\n 'recording.defaultRetentionDays': 30,\n // Streaming ports are addon-specific (go2rtc owns its defaults)\n // FFmpeg\n 'ffmpeg.binaryPath': 'ffmpeg',\n 'ffmpeg.hwAccel': 'auto',\n 'ffmpeg.threadCount': 0,\n // Detection / motion / audio settings are owned by their respective addons\n // (pipeline-orchestrator, motion-wasm, audio-analyzer/classifier, detection-pipeline\n // step schemas). No detection defaults at this level.\n // Backup retention is addon-specific (local-backup owns its default)\n // Auth (runtime)\n 'auth.tokenExpiry': '24h',\n}\n","/**\n * Type-safe JSON parsing helpers.\n *\n * `JSON.parse` is typed as `any` in lib.es5.d.ts, which triggers\n * `no-unsafe-*` ESLint rules and destroys downstream inference. These\n * wrappers return `unknown` — callers narrow structurally via type\n * guards, `typeof` checks, or helpers like `asRecord`/`asString`.\n */\n\n/**\n * Parse JSON and return it as `unknown` — the only entry point for untrusted JSON.\n *\n * The optional generic overload `parseJsonUnknown<T>(text)` returns `T` for\n * call sites that know the shape at parse time (e.g. MQTT payloads with a\n * known protocol schema). This is a **type-level bridge only** — no runtime\n * validation is performed. Callers that need runtime validation should parse\n * as `unknown` and narrow via Zod or structural guards.\n */\nexport function parseJsonUnknown<T = unknown>(text: string): T {\n // Isolate JSON.parse's `any` to this single statement.\n const parsed: unknown = JSON.parse(text)\n return parsed as T\n}\n\n/** Narrow an unknown value to a plain `Record<string, unknown>` or return null. */\nexport function asJsonObject(value: unknown): Record<string, unknown> | null {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n return null\n }\n return { ...value }\n}\n\n/** Narrow an unknown value to a `readonly unknown[]` or return an empty array. */\nexport function asJsonArray(value: unknown): readonly unknown[] {\n return Array.isArray(value) ? value : []\n}\n\n/** Safe string extraction from an unknown record field. */\nexport function asString(value: unknown, fallback = ''): string {\n return typeof value === 'string' ? value : fallback\n}\n\n/** Safe number extraction from an unknown record field. */\nexport function asNumber(value: unknown, fallback = 0): number {\n return typeof value === 'number' ? value : fallback\n}\n\n/** Safe boolean extraction from an unknown record field. */\nexport function asBoolean(value: unknown, fallback = false): boolean {\n return typeof value === 'boolean' ? value : fallback\n}\n\n/** Parse JSON + narrow to object in one step. */\nexport function parseJsonObject(text: string): Record<string, unknown> | null {\n try {\n return asJsonObject(parseJsonUnknown(text))\n } catch {\n return null\n }\n}\n\n/** Parse JSON + narrow to array in one step. */\nexport function parseJsonArray(text: string): readonly unknown[] | null {\n try {\n const parsed = parseJsonUnknown(text)\n return Array.isArray(parsed) ? parsed : null\n } catch {\n return null\n }\n}\n","export function hfModelUrl(repo: string, path: string): string {\n return `https://huggingface.co/${repo}/resolve/main/${path}`\n}\n","/** Cosine similarity between two embedding vectors */\nexport function cosineSimilarity(a: Float32Array, b: Float32Array): number {\n if (a.length !== b.length) return 0\n let dotProduct = 0\n let normA = 0\n let normB = 0\n for (let i = 0; i < a.length; i++) {\n dotProduct += a[i]! * b[i]!\n normA += a[i]! * a[i]!\n normB += b[i]! * b[i]!\n }\n const denom = Math.sqrt(normA) * Math.sqrt(normB)\n return denom === 0 ? 0 : dotProduct / denom\n}\n","import type { IElementConfig } from '../interfaces/context.js'\nimport type { ISettingsBackend } from '../interfaces/storage.js'\n\n/**\n * Persisted config store for a single element.\n * Reads/writes to the element's scoped storage under the 'config' collection.\n * Notifies listeners on every change.\n */\nexport class ElementConfigStore implements IElementConfig {\n private cache: Record<string, unknown> = {}\n private listeners: Set<(config: Record<string, unknown>) => void> = new Set()\n private loaded = false\n\n private readonly getBackend: () => ISettingsBackend | null\n\n constructor(\n private readonly elementId: string,\n settingsBackend: ISettingsBackend | (() => ISettingsBackend | null) | null,\n ) {\n // Accept either a direct backend or a lazy getter for late-wired backends\n this.getBackend = typeof settingsBackend === 'function'\n ? settingsBackend\n : () => settingsBackend\n }\n\n /** Load config from storage into cache. Called once on first access. */\n private async ensureLoaded(): Promise<void> {\n if (this.loaded) return\n const backend = this.getBackend()\n if (!backend) {\n throw new Error(`ElementConfigStore(${this.elementId}): settings backend not available`)\n }\n\n const records = await backend.query({ collection: 'config', filter: {\n where: { id: this.elementId },\n limit: 1,\n } })\n if (records.length > 0) {\n this.cache = records[0]!.data ?? {}\n }\n this.loaded = true\n }\n\n getAll(): Record<string, unknown> {\n return { ...this.cache }\n }\n\n get<T = unknown>(key: string): T | undefined {\n const parts = key.split('.')\n let current: unknown = this.cache\n for (const part of parts) {\n if (current === null || typeof current !== 'object' || Array.isArray(current)) return undefined\n current = Reflect.get(current, part)\n }\n // Type-level bridge: callers supply T based on their knowledge of the\n // stored schema — the runtime has no way to prove the shape matches.\n return current as T | undefined\n }\n\n async set(key: string, value: unknown): Promise<void> {\n await this.ensureLoaded()\n setNestedValue(this.cache, key, value)\n await this.persist()\n this.notifyListeners()\n }\n\n async setAll(config: Record<string, unknown>): Promise<void> {\n await this.ensureLoaded()\n this.cache = { ...config }\n await this.persist()\n this.notifyListeners()\n }\n\n onChange(callback: (config: Record<string, unknown>) => void): () => void {\n this.listeners.add(callback)\n return () => { this.listeners.delete(callback) }\n }\n\n /** Initialize from storage — called by ContextFactory after creation */\n async load(): Promise<void> {\n await this.ensureLoaded()\n }\n\n /** Initialize with default values (doesn't overwrite existing) */\n async loadDefaults(defaults: Record<string, unknown>): Promise<void> {\n await this.ensureLoaded()\n if (Object.keys(this.cache).length === 0) {\n this.cache = { ...defaults }\n await this.persist()\n }\n }\n\n private async persist(): Promise<void> {\n const backend = this.getBackend()\n if (!backend) {\n throw new Error(`ElementConfigStore(${this.elementId}): settings backend not available — cannot persist config`)\n }\n\n // Use set() for upsert semantics — avoids race condition where two\n // concurrent persist() calls both see \"no existing row\" and both insert.\n await backend.set({ collection: 'config', key: this.elementId, value: this.cache })\n }\n\n private notifyListeners(): void {\n const snapshot = this.getAll()\n for (const listener of this.listeners) {\n try {\n listener(snapshot)\n } catch {\n // Don't let one bad listener kill others\n }\n }\n }\n}\n\nfunction setNestedValue(obj: Record<string, unknown>, path: string, value: unknown): void {\n const parts = path.split('.')\n let current: Record<string, unknown> = obj\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]!\n const existing = current[part]\n if (existing === null || typeof existing !== 'object' || Array.isArray(existing)) {\n const fresh: Record<string, unknown> = {}\n current[part] = fresh\n current = fresh\n } else {\n current = existing as Record<string, unknown>\n }\n }\n current[parts[parts.length - 1]!] = value\n}\n","/**\n * Canonical runtime/backend/format mapping utilities.\n *\n * This is the SINGLE SOURCE OF TRUTH for mapping between:\n * - Pipeline config (runtime: 'node'|'python', backend: 'cpu'|'coreml'|'cuda'|...)\n * - DetectionRuntime ('onnx'|'coreml'|'pytorch'|'openvino'|'tflite')\n * - ModelFormat ('onnx'|'coreml'|'openvino'|'tflite'|'pt')\n *\n * Import from '@camstack/types' — do NOT duplicate these mappings anywhere.\n */\nimport type { ModelFormat } from '../types/models.js'\nimport type { DetectionRuntime } from '../types/config.js'\n\n// ---------------------------------------------------------------------------\n// Pipeline runtime: the two-level abstraction used in pipeline config\n// ---------------------------------------------------------------------------\n\n/** Pipeline-level runtime: 'node' (ONNX Runtime in Node.js) or 'python' (Python inference) */\nexport type PipelineRuntime = 'node' | 'python'\n\n// ---------------------------------------------------------------------------\n// Backend → Format: what model file format does a backend require?\n// ---------------------------------------------------------------------------\n\n/**\n * Map a backend ID to the model format it requires.\n *\n * Node.js backends (cpu, coreml, cuda, tensorrt) all use ONNX format\n * because onnxruntime-node loads .onnx and uses execution providers internally.\n *\n * Python backends use their native format.\n */\nconst BACKEND_TO_FORMAT: Readonly<Record<string, ModelFormat>> = {\n // Node.js backends — all ONNX (onnxruntime-node execution providers)\n cpu: 'onnx',\n coreml: 'onnx', // onnxruntime CoreML EP loads .onnx, not .mlpackage\n cuda: 'onnx',\n tensorrt: 'onnx',\n 'onnx-py': 'onnx',\n // Python native backends\n pytorch: 'pt',\n openvino: 'openvino',\n}\n\n/**\n * Map DetectionRuntime to ModelFormat.\n * Used when the addon receives an explicit runtime (not 'auto').\n */\nconst RUNTIME_TO_FORMAT: Readonly<Record<DetectionRuntime, ModelFormat>> = {\n onnx: 'onnx',\n coreml: 'coreml',\n openvino: 'openvino',\n tflite: 'tflite',\n pytorch: 'pt',\n}\n\n/**\n * Map a Python backend to the Python inference script name.\n */\nconst PYTHON_SCRIPT: Readonly<Record<string, string>> = {\n coreml: 'coreml_inference.py',\n pytorch: 'pytorch_inference.py',\n openvino: 'openvino_inference.py',\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve pipeline config (runtime + backend) to a DetectionRuntime.\n *\n * Pipeline config uses two levels:\n * runtime: 'node' | 'python'\n * backend: 'cpu' | 'coreml' | 'cuda' | 'openvino' | 'pytorch' | ...\n *\n * Addons expect a DetectionRuntime:\n * 'onnx' | 'coreml' | 'pytorch' | 'openvino' | 'tflite'\n *\n * Mapping rules:\n * node + any backend → 'onnx' (onnxruntime-node handles backend via EP)\n * python + coreml → 'coreml' (native .mlpackage via coremltools)\n * python + openvino → 'openvino'\n * python + pytorch → 'pytorch'\n * python + onnx-py → 'onnx'\n * python + <other> → backend as-is\n */\nexport function resolveDetectionRuntime(\n pipelineRuntime: PipelineRuntime | string,\n backend: string,\n): DetectionRuntime {\n if (pipelineRuntime === 'node') return 'onnx'\n // Python: backend IS the runtime (coreml, openvino, pytorch, etc.)\n const map: Record<string, DetectionRuntime> = {\n coreml: 'coreml',\n openvino: 'openvino',\n pytorch: 'pytorch',\n 'onnx-py': 'onnx',\n cpu: 'onnx',\n }\n return map[backend] ?? (backend as DetectionRuntime)\n}\n\n/**\n * Resolve pipeline config (runtime + backend) to a ModelFormat.\n *\n * Determines which model file format is needed (.onnx, .mlpackage, etc.)\n */\nexport function resolveModelFormat(\n pipelineRuntime: PipelineRuntime | string,\n backend: string,\n): ModelFormat {\n if (pipelineRuntime === 'node') {\n return BACKEND_TO_FORMAT[backend] ?? 'onnx'\n }\n // Python: derive format from backend\n const map: Record<string, ModelFormat> = {\n coreml: 'coreml',\n openvino: 'openvino',\n pytorch: 'pt',\n 'onnx-py': 'onnx',\n cpu: 'onnx',\n }\n return map[backend] ?? 'onnx'\n}\n\n/**\n * Resolve pipeline runtime string to 'auto' | DetectionRuntime for addon consumption.\n * Used when building addon addonConfig from pipeline step config.\n *\n * 'python' + 'coreml' → 'coreml'\n * 'node' + 'coreml' → 'onnx'\n * 'node' + 'cpu' → 'onnx'\n * 'auto' → 'auto'\n */\nexport function resolveAddonRuntime(\n pipelineRuntime: string | undefined,\n backend: string | undefined,\n): DetectionRuntime | 'auto' {\n if (!pipelineRuntime || pipelineRuntime === 'auto') return 'auto'\n return resolveDetectionRuntime(pipelineRuntime, backend ?? 'cpu')\n}\n\n/**\n * Get the model format needed for a given backend.\n * Convenience wrapper for backend-only lookup (e.g., UI components).\n */\nexport function formatForBackend(backend: string): ModelFormat {\n return BACKEND_TO_FORMAT[backend] ?? 'onnx'\n}\n\n/**\n * Get the model format for a given DetectionRuntime.\n */\nexport function formatForRuntime(runtime: DetectionRuntime): ModelFormat {\n return RUNTIME_TO_FORMAT[runtime]\n}\n\n/**\n * Get the Python inference script name for a backend.\n * Returns undefined if no Python script is needed (e.g., 'cpu' uses ONNX).\n */\nexport function pythonScriptForBackend(backend: string): string | undefined {\n return PYTHON_SCRIPT[backend]\n}\n\n/**\n * Check if a DetectionRuntime requires a Python binary.\n * 'coreml', 'pytorch', 'openvino' need Python; 'onnx' and 'tflite' don't.\n */\nexport function requiresPython(runtime: DetectionRuntime | string): boolean {\n return runtime === 'coreml' || runtime === 'pytorch' || runtime === 'openvino'\n}\n\n// Re-export constants for consumers that need the raw maps (e.g., UI filtering)\nexport { BACKEND_TO_FORMAT, RUNTIME_TO_FORMAT, PYTHON_SCRIPT }\n","/**\nimport { errMsg } from '@camstack/types'\n * Extract a human-readable message from an unknown error value.\n * Replaces the ubiquitous `errMsg(err)` pattern.\n */\nexport function errMsg(err: unknown): string {\n if (err instanceof Error) return err.message\n if (typeof err === 'string') return err\n return String(err)\n}\n","import { errMsg } from './err-msg.js'\n\n/**\n * runInferenceStep — shared utility for executing a single inference call\n * with timing, error capture, and optional timeout.\n *\n * Used by: pipeline-executor, benchmark-executor, benchmark.service,\n * inference-engine-adapter — eliminating duplicated timing/error patterns.\n */\n\nexport interface InferenceStepResult<T> {\n /** The inference output, or undefined if the call failed */\n readonly output: T | undefined\n /** Wall-clock duration in ms (rounded to 2 decimals) */\n readonly durationMs: number\n /** True if the call succeeded */\n readonly ok: boolean\n /** Error message if the call failed */\n readonly error?: string\n}\n\n/**\n * Execute an inference function with timing and error capture.\n *\n * @param fn - The inference call (e.g. `() => engine.infer(frame)`)\n * @param timeoutMs - Optional timeout in ms. If exceeded, rejects with timeout error.\n * @returns InferenceStepResult with output, timing, and error info\n */\nexport async function runInferenceStep<T>(\n fn: () => Promise<T>,\n timeoutMs?: number,\n): Promise<InferenceStepResult<T>> {\n const t0 = performance.now()\n\n try {\n const output = timeoutMs !== undefined\n ? await withTimeout(fn(), timeoutMs)\n : await fn()\n\n return {\n output,\n durationMs: roundMs(performance.now() - t0),\n ok: true,\n }\n } catch (err) {\n return {\n output: undefined,\n durationMs: roundMs(performance.now() - t0),\n ok: false,\n error: errMsg(err),\n }\n }\n}\n\n/** Round to 2 decimal places */\nfunction roundMs(ms: number): number {\n return Math.round(ms * 100) / 100\n}\n\n/** Reject a promise if it exceeds the given timeout */\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(`Inference timeout after ${ms}ms`)), ms)\n promise\n .then((v) => { clearTimeout(timer); resolve(v) })\n .catch((e: unknown) => { clearTimeout(timer); reject(e) })\n })\n}\n","import type { LabelDefinition, ClassMapDefinition } from '../types/labels.js'\n\nexport const COCO_80_LABELS: readonly LabelDefinition[] = [\n { id: 'person', name: 'Person' },\n { id: 'bicycle', name: 'Bicycle' },\n { id: 'car', name: 'Car' },\n { id: 'motorcycle', name: 'Motorcycle' },\n { id: 'airplane', name: 'Airplane' },\n { id: 'bus', name: 'Bus' },\n { id: 'train', name: 'Train' },\n { id: 'truck', name: 'Truck' },\n { id: 'boat', name: 'Boat' },\n { id: 'traffic light', name: 'Traffic Light' },\n { id: 'fire hydrant', name: 'Fire Hydrant' },\n { id: 'stop sign', name: 'Stop Sign' },\n { id: 'parking meter', name: 'Parking Meter' },\n { id: 'bench', name: 'Bench' },\n { id: 'bird', name: 'Bird' },\n { id: 'cat', name: 'Cat' },\n { id: 'dog', name: 'Dog' },\n { id: 'horse', name: 'Horse' },\n { id: 'sheep', name: 'Sheep' },\n { id: 'cow', name: 'Cow' },\n { id: 'elephant', name: 'Elephant' },\n { id: 'bear', name: 'Bear' },\n { id: 'zebra', name: 'Zebra' },\n { id: 'giraffe', name: 'Giraffe' },\n { id: 'backpack', name: 'Backpack' },\n { id: 'umbrella', name: 'Umbrella' },\n { id: 'handbag', name: 'Handbag' },\n { id: 'tie', name: 'Tie' },\n { id: 'suitcase', name: 'Suitcase' },\n { id: 'frisbee', name: 'Frisbee' },\n { id: 'skis', name: 'Skis' },\n { id: 'snowboard', name: 'Snowboard' },\n { id: 'sports ball', name: 'Sports Ball' },\n { id: 'kite', name: 'Kite' },\n { id: 'baseball bat', name: 'Baseball Bat' },\n { id: 'baseball glove', name: 'Baseball Glove' },\n { id: 'skateboard', name: 'Skateboard' },\n { id: 'surfboard', name: 'Surfboard' },\n { id: 'tennis racket', name: 'Tennis Racket' },\n { id: 'bottle', name: 'Bottle' },\n { id: 'wine glass', name: 'Wine Glass' },\n { id: 'cup', name: 'Cup' },\n { id: 'fork', name: 'Fork' },\n { id: 'knife', name: 'Knife' },\n { id: 'spoon', name: 'Spoon' },\n { id: 'bowl', name: 'Bowl' },\n { id: 'banana', name: 'Banana' },\n { id: 'apple', name: 'Apple' },\n { id: 'sandwich', name: 'Sandwich' },\n { id: 'orange', name: 'Orange' },\n { id: 'broccoli', name: 'Broccoli' },\n { id: 'carrot', name: 'Carrot' },\n { id: 'hot dog', name: 'Hot Dog' },\n { id: 'pizza', name: 'Pizza' },\n { id: 'donut', name: 'Donut' },\n { id: 'cake', name: 'Cake' },\n { id: 'chair', name: 'Chair' },\n { id: 'couch', name: 'Couch' },\n { id: 'potted plant', name: 'Potted Plant' },\n { id: 'bed', name: 'Bed' },\n { id: 'dining table', name: 'Dining Table' },\n { id: 'toilet', name: 'Toilet' },\n { id: 'tv', name: 'TV' },\n { id: 'laptop', name: 'Laptop' },\n { id: 'mouse', name: 'Mouse' },\n { id: 'remote', name: 'Remote' },\n { id: 'keyboard', name: 'Keyboard' },\n { id: 'cell phone', name: 'Cell Phone' },\n { id: 'microwave', name: 'Microwave' },\n { id: 'oven', name: 'Oven' },\n { id: 'toaster', name: 'Toaster' },\n { id: 'sink', name: 'Sink' },\n { id: 'refrigerator', name: 'Refrigerator' },\n { id: 'book', name: 'Book' },\n { id: 'clock', name: 'Clock' },\n { id: 'vase', name: 'Vase' },\n { id: 'scissors', name: 'Scissors' },\n { id: 'teddy bear', name: 'Teddy Bear' },\n { id: 'hair drier', name: 'Hair Drier' },\n { id: 'toothbrush', name: 'Toothbrush' },\n] as const\n\nexport const MACRO_LABELS: readonly LabelDefinition[] = [\n { id: 'person', name: 'Person' },\n { id: 'vehicle', name: 'Vehicle' },\n { id: 'animal', name: 'Animal' },\n] as const\n\nexport const COCO_TO_MACRO: ClassMapDefinition = {\n mapping: {\n person: 'person',\n bicycle: 'vehicle',\n car: 'vehicle',\n motorcycle: 'vehicle',\n airplane: 'vehicle',\n bus: 'vehicle',\n train: 'vehicle',\n truck: 'vehicle',\n boat: 'vehicle',\n bird: 'animal',\n cat: 'animal',\n dog: 'animal',\n horse: 'animal',\n sheep: 'animal',\n cow: 'animal',\n elephant: 'animal',\n bear: 'animal',\n zebra: 'animal',\n giraffe: 'animal',\n },\n // Today the pipeline only supports the three macro classes. Any other\n // COCO class (carrot, umbrella, spoon, …) is dropped upstream in the\n // executor instead of leaking through as a `macroClass: \"carrot\"`\n // detection with no child routing. When support for additional COCO\n // classes lands, either add them to `mapping` (mapped to a new macro)\n // or flip this back to `true` and teach `matchesMacroFilter` to handle\n // the raw-COCO case.\n preserveOriginal: false,\n}\n","/**\n * Audio classification macro classes — maps 521 YAMNet labels into ~25 actionable categories.\n * Same pattern as COCO_TO_MACRO for video detection.\n *\n * Each macro class aggregates related fine-grained labels so the user\n * sees a manageable set of event types in settings, timelines, and notifications.\n */\nimport type { LabelDefinition, ClassMapDefinition } from '../types/labels.js'\n\n// ---------------------------------------------------------------------------\n// Macro class definitions\n// ---------------------------------------------------------------------------\n\nexport const AUDIO_MACRO_LABELS: readonly LabelDefinition[] = [\n { id: 'speech', name: 'Speech', icon: '🗣️' },\n { id: 'scream', name: 'Scream / Shout', icon: '😱' },\n { id: 'crying', name: 'Crying / Baby', icon: '😢' },\n { id: 'laughter', name: 'Laughter', icon: '😂' },\n { id: 'music', name: 'Music', icon: '🎵' },\n { id: 'dog', name: 'Dog', icon: '🐕' },\n { id: 'cat', name: 'Cat', icon: '🐈' },\n { id: 'bird', name: 'Bird', icon: '🐦' },\n { id: 'animal', name: 'Animal (other)', icon: '🐾' },\n { id: 'alarm', name: 'Alarm / Siren', icon: '🚨' },\n { id: 'doorbell', name: 'Doorbell / Knock', icon: '🔔' },\n { id: 'glass_breaking', name: 'Glass Breaking', icon: '💥' },\n { id: 'gunshot', name: 'Gunshot / Explosion', icon: '💣' },\n { id: 'vehicle', name: 'Vehicle', icon: '🚗' },\n { id: 'siren', name: 'Emergency Siren', icon: '🚑' },\n { id: 'fire', name: 'Fire / Smoke', icon: '🔥' },\n { id: 'water', name: 'Water', icon: '💧' },\n { id: 'wind', name: 'Wind / Weather', icon: '🌬️' },\n { id: 'door', name: 'Door', icon: '🚪' },\n { id: 'footsteps', name: 'Footsteps', icon: '👣' },\n { id: 'crowd', name: 'Crowd / Chatter', icon: '👥' },\n { id: 'telephone', name: 'Telephone', icon: '📞' },\n { id: 'engine', name: 'Engine / Motor', icon: '⚙️' },\n { id: 'tools', name: 'Tools / Construction', icon: '🔨' },\n { id: 'silence', name: 'Silence', icon: '🤫' },\n] as const\n\n// ---------------------------------------------------------------------------\n// YAMNet label → macro class mapping (by label name, case-insensitive)\n// ---------------------------------------------------------------------------\n\nexport const YAMNET_TO_MACRO: ClassMapDefinition = {\n mapping: {\n // Speech\n 'Speech': 'speech',\n 'Child speech, kid speaking': 'speech',\n 'Conversation': 'speech',\n 'Narration, monologue': 'speech',\n 'Babbling': 'speech',\n 'Whispering': 'speech',\n 'Speech synthesizer': 'speech',\n 'Humming': 'speech',\n 'Rapping': 'speech',\n 'Singing': 'speech',\n 'Choir': 'speech',\n 'Child singing': 'speech',\n\n // Scream / Shout\n 'Shout': 'scream',\n 'Bellow': 'scream',\n 'Yell': 'scream',\n 'Screaming': 'scream',\n 'Children shouting': 'scream',\n 'Whoop': 'scream',\n\n // Crying\n 'Crying, sobbing': 'crying',\n 'Baby cry, infant cry': 'crying',\n 'Whimper': 'crying',\n 'Wail, moan': 'crying',\n 'Groan': 'crying',\n\n // Laughter\n 'Laughter': 'laughter',\n 'Baby laughter': 'laughter',\n 'Giggle': 'laughter',\n 'Snicker': 'laughter',\n 'Belly laugh': 'laughter',\n 'Chuckle, chortle': 'laughter',\n\n // Music\n 'Music': 'music',\n 'Musical instrument': 'music',\n 'Guitar': 'music',\n 'Piano': 'music',\n 'Drum': 'music',\n 'Drum kit': 'music',\n 'Violin, fiddle': 'music',\n 'Flute': 'music',\n 'Saxophone': 'music',\n 'Trumpet': 'music',\n 'Synthesizer': 'music',\n 'Pop music': 'music',\n 'Rock music': 'music',\n 'Hip hop music': 'music',\n 'Classical music': 'music',\n 'Jazz': 'music',\n 'Electronic music': 'music',\n 'Background music': 'music',\n\n // Dog\n 'Dog': 'dog',\n 'Bark': 'dog',\n 'Yip': 'dog',\n 'Howl': 'dog',\n 'Bow-wow': 'dog',\n 'Growling': 'dog',\n 'Whimper (dog)': 'dog',\n\n // Cat\n 'Cat': 'cat',\n 'Purr': 'cat',\n 'Meow': 'cat',\n 'Hiss': 'cat',\n 'Caterwaul': 'cat',\n\n // Bird\n 'Bird': 'bird',\n 'Bird vocalization, bird call, bird song': 'bird',\n 'Chirp, tweet': 'bird',\n 'Squawk': 'bird',\n 'Crow': 'bird',\n 'Owl': 'bird',\n 'Pigeon, dove': 'bird',\n\n // Animal (other)\n 'Animal': 'animal',\n 'Domestic animals, pets': 'animal',\n 'Livestock, farm animals, working animals': 'animal',\n 'Horse': 'animal',\n 'Cattle, bovinae': 'animal',\n 'Pig': 'animal',\n 'Sheep': 'animal',\n 'Goat': 'animal',\n 'Frog': 'animal',\n 'Insect': 'animal',\n 'Cricket': 'animal',\n\n // Alarm / Siren\n 'Alarm': 'alarm',\n 'Alarm clock': 'alarm',\n 'Smoke detector, smoke alarm': 'alarm',\n 'Fire alarm': 'alarm',\n 'Buzzer': 'alarm',\n 'Civil defense siren': 'alarm',\n 'Car alarm': 'alarm',\n\n // Emergency Siren\n 'Siren': 'siren',\n 'Police car (siren)': 'siren',\n 'Ambulance (siren)': 'siren',\n 'Fire engine, fire truck (siren)': 'siren',\n 'Emergency vehicle': 'siren',\n 'Foghorn': 'siren',\n\n // Doorbell / Knock\n 'Doorbell': 'doorbell',\n 'Ding-dong': 'doorbell',\n 'Knock': 'doorbell',\n 'Tap': 'doorbell',\n\n // Glass Breaking\n 'Glass': 'glass_breaking',\n 'Shatter': 'glass_breaking',\n 'Chink, clink': 'glass_breaking',\n\n // Gunshot / Explosion\n 'Gunshot, gunfire': 'gunshot',\n 'Machine gun': 'gunshot',\n 'Explosion': 'gunshot',\n 'Fireworks': 'gunshot',\n 'Firecracker': 'gunshot',\n 'Artillery fire': 'gunshot',\n 'Cap gun': 'gunshot',\n 'Boom': 'gunshot',\n\n // Vehicle\n 'Vehicle': 'vehicle',\n 'Car': 'vehicle',\n 'Truck': 'vehicle',\n 'Bus': 'vehicle',\n 'Motorcycle': 'vehicle',\n 'Car passing by': 'vehicle',\n 'Vehicle horn, car horn, honking': 'vehicle',\n 'Traffic noise, roadway noise': 'vehicle',\n 'Train': 'vehicle',\n 'Aircraft': 'vehicle',\n 'Helicopter': 'vehicle',\n 'Bicycle': 'vehicle',\n 'Skateboard': 'vehicle',\n\n // Fire / Smoke\n 'Fire': 'fire',\n 'Crackle': 'fire',\n\n // Water\n 'Water': 'water',\n 'Rain': 'water',\n 'Raindrop': 'water',\n 'Rain on surface': 'water',\n 'Stream': 'water',\n 'Waterfall': 'water',\n 'Ocean': 'water',\n 'Waves, surf': 'water',\n 'Splash, splatter': 'water',\n\n // Wind / Weather\n 'Wind': 'wind',\n 'Thunderstorm': 'wind',\n 'Thunder': 'wind',\n 'Wind noise (microphone)': 'wind',\n 'Rustling leaves': 'wind',\n\n // Door\n 'Door': 'door',\n 'Sliding door': 'door',\n 'Slam': 'door',\n 'Cupboard open or close': 'door',\n\n // Footsteps\n 'Walk, footsteps': 'footsteps',\n 'Run': 'footsteps',\n 'Shuffle': 'footsteps',\n\n // Crowd\n 'Crowd': 'crowd',\n 'Chatter': 'crowd',\n 'Cheering': 'crowd',\n 'Applause': 'crowd',\n 'Children playing': 'crowd',\n 'Hubbub, speech noise, speech babble': 'crowd',\n\n // Telephone\n 'Telephone': 'telephone',\n 'Telephone bell ringing': 'telephone',\n 'Ringtone': 'telephone',\n 'Telephone dialing, DTMF': 'telephone',\n 'Busy signal': 'telephone',\n\n // Engine / Motor\n 'Engine': 'engine',\n 'Engine starting': 'engine',\n 'Idling': 'engine',\n 'Accelerating, revving, vroom': 'engine',\n 'Light engine (high frequency)': 'engine',\n 'Medium engine (mid frequency)': 'engine',\n 'Heavy engine (low frequency)': 'engine',\n 'Lawn mower': 'engine',\n 'Chainsaw': 'engine',\n\n // Tools / Construction\n 'Hammer': 'tools',\n 'Jackhammer': 'tools',\n 'Sawing': 'tools',\n 'Power tool': 'tools',\n 'Drill': 'tools',\n 'Sanding': 'tools',\n\n // Silence\n 'Silence': 'silence',\n },\n preserveOriginal: false,\n}\n\n// ---------------------------------------------------------------------------\n// Apple SoundAnalysis identifier → macro class mapping\n// Apple uses snake_case identifiers (e.g. 'dog_bark', 'siren')\n// ---------------------------------------------------------------------------\n\nexport const APPLE_SA_TO_MACRO: ClassMapDefinition = {\n mapping: {\n 'speech': 'speech', 'child_speech': 'speech', 'conversation': 'speech',\n 'whispering': 'speech', 'singing': 'speech', 'humming': 'speech',\n 'shout': 'scream', 'yell': 'scream', 'screaming': 'scream',\n 'crying': 'crying', 'baby_crying': 'crying', 'sobbing': 'crying',\n 'laughter': 'laughter', 'baby_laughter': 'laughter', 'giggling': 'laughter',\n 'music': 'music', 'guitar': 'music', 'piano': 'music', 'drums': 'music',\n 'dog_bark': 'dog', 'dog_bow_wow': 'dog', 'dog_growling': 'dog', 'dog_howl': 'dog',\n 'cat_meow': 'cat', 'cat_purr': 'cat', 'cat_hiss': 'cat',\n 'bird': 'bird', 'bird_chirp': 'bird', 'bird_squawk': 'bird',\n 'animal': 'animal', 'horse': 'animal', 'cow_moo': 'animal', 'insect': 'animal',\n 'alarm': 'alarm', 'smoke_alarm': 'alarm', 'fire_alarm': 'alarm', 'car_alarm': 'alarm',\n 'siren': 'siren', 'police_siren': 'siren', 'ambulance_siren': 'siren',\n 'doorbell': 'doorbell', 'door_knock': 'doorbell', 'knocking': 'doorbell',\n 'glass_breaking': 'glass_breaking', 'glass_shatter': 'glass_breaking',\n 'gunshot': 'gunshot', 'explosion': 'gunshot', 'fireworks': 'gunshot',\n 'car': 'vehicle', 'truck': 'vehicle', 'motorcycle': 'vehicle',\n 'car_horn': 'vehicle', 'vehicle_horn': 'vehicle', 'traffic': 'vehicle',\n 'fire': 'fire', 'fire_crackle': 'fire',\n 'water': 'water', 'rain': 'water', 'ocean': 'water', 'splash': 'water',\n 'wind': 'wind', 'thunder': 'wind', 'thunderstorm': 'wind',\n 'door': 'door', 'door_slam': 'door', 'sliding_door': 'door',\n 'footsteps': 'footsteps', 'walking': 'footsteps', 'running': 'footsteps',\n 'crowd': 'crowd', 'chatter': 'crowd', 'cheering': 'crowd', 'applause': 'crowd',\n 'telephone_ring': 'telephone', 'ringtone': 'telephone',\n 'engine': 'engine', 'engine_starting': 'engine', 'lawn_mower': 'engine', 'chainsaw': 'engine',\n 'hammer': 'tools', 'jackhammer': 'tools', 'drill': 'tools', 'power_tool': 'tools',\n 'silence': 'silence',\n },\n preserveOriginal: false,\n}\n\n// ---------------------------------------------------------------------------\n// Unified lookup — merges YAMNet + Apple SA mappings\n// ---------------------------------------------------------------------------\n\nconst _macroLookup = new Map<string, string>()\nfor (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) {\n _macroLookup.set(k.toLowerCase(), v)\n}\nfor (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) {\n _macroLookup.set(k.toLowerCase(), v)\n}\n\n/** Map a raw audio label (YAMNet or Apple SoundAnalysis) to its macro class. Returns null if unmapped. */\nexport function mapAudioLabelToMacro(label: string): string | null {\n return _macroLookup.get(label.toLowerCase()) ?? null\n}\n\n/** Get all macro class IDs */\nexport function getAudioMacroClassIds(): readonly string[] {\n return AUDIO_MACRO_LABELS.map(l => l.id)\n}\n","/**\n * @deprecated Use DeviceType from '@camstack/types/device' instead.\n * This file is kept for backwards compatibility during migration.\n */\n\n/* eslint-disable @typescript-eslint/no-deprecated */\n\nexport enum DeviceType {\n Camera = 'camera',\n}\n\nexport interface DeviceTypeInfo {\n readonly type: DeviceType\n readonly label: string\n readonly icon: string // lucide icon name\n}\n\nexport const DEVICE_TYPE_INFO: Record<DeviceType, DeviceTypeInfo> = {\n [DeviceType.Camera]: { type: DeviceType.Camera, label: 'Camera', icon: 'camera' },\n}\n","export enum DeviceType {\n Camera = 'camera',\n Hub = 'hub',\n Light = 'light',\n Siren = 'siren',\n Switch = 'switch',\n Sensor = 'sensor',\n Thermostat = 'thermostat',\n Button = 'button',\n Generic = 'generic',\n}\n\nexport enum DeviceFeature {\n BatteryOperated = 'battery-operated',\n Rebootable = 'rebootable',\n NativeSnapshot = 'native-snapshot',\n DoorbellButton = 'doorbell-button',\n TwoWayAudio = 'two-way-audio',\n PanTiltZoom = 'pan-tilt-zoom',\n /**\n * Camera supports the on-firmware autotrack subsystem (subject-\n * following). Distinct from `PanTiltZoom` because not every PTZ\n * camera ships autotrack — the admin UI uses this flag to gate\n * the autotrack toggle / settings card without re-deriving from\n * the cap registry. Mirrors `ptz-autotrack` cap registration:\n * driver sets this feature when probe confirms the firmware\n * surface, and registers the cap in the same code path.\n */\n PtzAutotrack = 'ptz-autotrack',\n /**\n * Accessory exposes a \"trigger on motion\" toggle — the parent camera's\n * motion detection automatically activates this device. Mirrors\n * `motion-trigger` cap registration: drivers set this feature in the\n * same code path that calls `ctx.registerNativeCap(motionTriggerCapability, ...)`.\n *\n * Used by admin UI (gate the in-hero `MotionTriggerToggle` against a\n * fast scalar without binding fetch), notifier rules, and `listAll`\n * filters that want \"all devices with on-motion behaviour\".\n */\n MotionTrigger = 'motion-trigger',\n}\n\nexport enum ChargingStatus {\n ChargingDC = 'charging-dc',\n ChargingSolar = 'charging-solar',\n NotCharging = 'not-charging',\n}\n\n/**\n * Semantic role a device plays within its parent. Populated by driver\n * addons when creating accessory devices (Reolink siren/floodlight/\n * PIR/chime/autotrack/doorbell, ONVIF relay outputs, …). Used by the\n * admin UI to pick icons, labels, and widgets — a `Switch` with\n * `role: Floodlight` renders as a bulb with a brightness slider,\n * whereas a `Switch` with `role: Siren` renders as a klaxon.\n *\n * Undefined for top-level devices (cameras, NVRs, hubs). Persisted in\n * sqlite as a nullable TEXT column — old rows keep working unchanged.\n */\nexport enum DeviceRole {\n // ── Switch-type accessories ──────────────────────────────\n Siren = 'siren',\n Floodlight = 'floodlight',\n Spotlight = 'spotlight',\n PirSensor = 'pir-sensor',\n Chime = 'chime',\n Autotrack = 'autotrack',\n Nightvision = 'nightvision',\n PrivacyMask = 'privacy-mask',\n\n // ── Button-type accessories ──────────────────────────────\n Doorbell = 'doorbell',\n}\n","/**\n * Accessory device helpers — shared across drivers.\n *\n * Many vendor-specific drivers register accessory child devices on\n * top of a parent (Reolink: siren / floodlight / PIR / autotrack /\n * chime; ONVIF: relay outputs; future: Tapo Hub child devices). Each\n * driver picks the right `DeviceType` + `DeviceRole` explicitly when\n * spawning, builds a name derived from the parent, and produces a\n * stableId tied to the parent so boot-restore can reconstruct the\n * relationship.\n *\n * Centralised `(kind → DeviceType)` mapping was dropped on purpose:\n * drivers may reasonably disagree on the right type for an accessory\n * (a Reolink PIR exposes a switch on/off + sensitivity, while a hypothetical\n * read-only motion-only sensor might be `DeviceType.Sensor`). Forcing\n * one canonical mapping was over-prescriptive and added a layer of\n * indirection without saving meaningful code at call sites — the\n * driver knows its own hardware best.\n */\nimport { DeviceRole } from './device-type.js'\n\n/**\n * Subset of `DeviceRole` values that drivers register as child\n * accessories of a parent device. Sourced verbatim from `DeviceRole`\n * — `AccessoryKind` is the alias drivers use when building accessory\n * children, so the call site reads as\n * `accessoryStableId(parent, AccessoryKind.Siren)` rather than\n * `accessoryStableId(parent, DeviceRole.Siren)` (which would imply\n * any role works, including non-accessory ones like Doorbell).\n */\nexport const AccessoryKind = {\n Siren: DeviceRole.Siren,\n Floodlight: DeviceRole.Floodlight,\n Spotlight: DeviceRole.Spotlight,\n PirSensor: DeviceRole.PirSensor,\n Chime: DeviceRole.Chime,\n Autotrack: DeviceRole.Autotrack,\n Nightvision: DeviceRole.Nightvision,\n PrivacyMask: DeviceRole.PrivacyMask,\n} as const\n\nexport type AccessoryKindValue = typeof AccessoryKind[keyof typeof AccessoryKind]\n\n/**\n * Default English label for each accessory kind. Drivers append this\n * to the parent's name — e.g. `\"Living Room Siren\"` for a camera named\n * `\"Living Room\"`. Localisation lives in the UI layer; the driver only\n * has to surface a stable English name.\n */\nexport const ACCESSORY_LABEL: Record<AccessoryKindValue, string> = {\n [AccessoryKind.Siren]: 'Siren',\n [AccessoryKind.Floodlight]: 'Floodlight',\n [AccessoryKind.Spotlight]: 'Spotlight',\n [AccessoryKind.PirSensor]: 'PIR',\n [AccessoryKind.Chime]: 'Chime',\n [AccessoryKind.Autotrack]: 'Autotracking',\n [AccessoryKind.Nightvision]: 'Night Vision',\n [AccessoryKind.PrivacyMask]: 'Privacy Mask',\n}\n\n/**\n * Canonical stableId for an accessory child. Format: `${parent}:${role}`\n * for single-instance accessories; drivers that need multiple instances\n * of the same kind (e.g. wireless chimes) pass an extra `index` token\n * which the helper appends as `:${index}`.\n *\n * The stableId is the persistence key the device-manager uses to\n * resolve `(addonId, stableId) → numeric id` across reboots, so it\n * MUST be stable across runs. Using the parent's stableId + the role\n * meets this — a driver can re-create children deterministically as\n * long as the parent's stableId is also stable (which the platform\n * already guarantees).\n */\nexport function accessoryStableId(\n parentStableId: string,\n kind: AccessoryKindValue,\n index?: number,\n): string {\n const base = `${parentStableId}:${kind}`\n return typeof index === 'number' ? `${base}:${index}` : base\n}\n","/**\n * Bindings × Modes contract\n * ─────────────────────────\n *\n * Two independent layers gate every analyzer phase (detection / audio):\n *\n * 1. **Bindings** (low-level wiring, escape hatch)\n * The cap-router decides whether the addon is MOUNTED for a\n * device at all. `setWrapperActive(deviceId, capName, false)`\n * fully dismounts the cap; nothing the cap exposes (provider\n * methods, runtime-state, events) is reachable. The operator\n * rarely touches this from the UI — it's the \"uninstall this\n * addon for this device\" button. Default: every wrapper bound.\n *\n * 2. **Modes** (operator-facing scheduling)\n * The `detectionMode` / `audioMode` selectors decide WHEN the\n * mounted cap actually fires. `'disabled'` is the runtime-level\n * off switch — the cap stays mounted, schema present, RPCs\n * callable, but the runner / orchestrator skip the substream\n * subscriber. The other 2 modes (`'always-on'`, `'on-motion'`)\n * drive when the subscribe + analyze cycle runs.\n *\n * **AND-gate semantics**: a phase fires iff `(binding bound) AND\n * (mode != 'disabled')`. Either layer disables → cap inactive.\n * Neither layer overrides the other; the operator picks whichever\n * lever maps to their intent.\n *\n * - \"I never want SW detection on this camera\" → unbind via\n * bindings UI (extreme — also disables the cap surface).\n * - \"Pause detection for now, keep wired\" → set\n * `detectionMode = 'disabled'`. Settings still surface; no\n * substream demand.\n * - \"Detection only when motion fires\" → `detectionMode = 'on-motion'`,\n * binding stays bound.\n *\n * Profile defaults populate modes when the operator hasn't picked.\n * Bindings are bound by their wrappers' `defaultActive: true` flag,\n * unaffected by the profile.\n *\n * ─────────────────────────\n *\n * DeviceProfile — declarative defaults applied to devices that match a\n * feature predicate.\n *\n * Solves the \"battery cams shouldn't run continuous analyzers\" problem\n * (and adjacent policy questions like low-bandwidth fallback) by\n * centralising the operator-facing defaults in ONE place. The profile\n * does NOT touch capability bindings — those stay as the low-level\n * wiring escape hatch. Instead the profile drives the per-device\n * pipeline behaviour through three operator-visible \"mode\" knobs that\n * the runner / orchestrator interpret directly.\n *\n * - `motionSources` — already a per-device setting today; the profile\n * just supplies a sensible default (`['onboard']` when firmware\n * motion is available; `[]` otherwise so a battery cam with no PIR\n * and no firmware push gates everything off until the operator opts\n * into `'analyzer'` SW motion).\n *\n * - `audioMode` (NEW) — selects when the audio classifier runs:\n * `'disabled'`, `'always-on'`, `'on-motion'`. Replaces the implicit\n * \"audio runs when wrapper bound\" behaviour. Wrappers stay bound;\n * the addon reads this mode at runtime to decide whether to\n * subscribe to the audio decoded stream.\n *\n * - `detectionMode` (NEW) — selects when object detection runs:\n * `'disabled'`, `'always-on'`, `'on-motion'`. Mirrors `audioMode`\n * and replaces the legacy `priority: 'default'|'always-on'` toggle\n * with explicit semantics.\n *\n * ─── Sticky-by-construction ───────────────────────────────────────────\n *\n * Nothing in the runtime re-applies a profile. Operator changes always\n * win because the persistence layer captures them as concrete entries\n * (config blob value); the profile is consulted only when no entry\n * exists yet. If a setting is absent from the blob the resolver falls\n * back to the profile's default, then the schema's static default.\n */\nimport type { DeviceFeature } from './device-type.js'\nimport { DeviceFeature as Feature } from './device-type.js'\n\n/**\n * Match clause: the profile applies to a device iff its `features`\n * array contains `hasFeature`. Single-feature gate keeps matching\n * cheap; the profile-stack iterates in order and the first match wins.\n */\nexport interface DeviceProfileMatch {\n readonly hasFeature: DeviceFeature\n}\n\n/**\n * When-mode selector for analyzer phases (audio classification, object\n * detection). `'disabled'` keeps the addon idle; `'always-on'` runs\n * continuously; `'on-motion'` activates only when the motion-gate is\n * open (firmware motion event OR analyzer-derived motion).\n */\nexport type PipelinePhaseMode =\n | 'disabled'\n | 'always-on'\n | 'on-motion'\n\n/**\n * Operator-facing settings the profile populates at creation time +\n * resolver fallback time. These are NOT tightly bound to a single\n * config schema field — the resolver (in pipeline-orchestrator) reads\n * them when computing the runner config, and persists operator changes\n * back to the same keys via the existing per-device store.\n */\nexport interface DeviceProfileDefaults {\n /** Default `motionSources` array when the operator hasn't picked\n * one. Empty array means \"no motion source\" — useful for battery\n * cams without firmware motion (operator opts into `'analyzer'`\n * explicitly to enable SW motion). PIR-sourced motion currently\n * flows through `'onboard'` because Reolink's accessory PIRs feed\n * the parent camera's firmware motion event channel. */\n readonly motionSources?: readonly ('onboard' | 'analyzer')[]\n readonly audioMode?: PipelinePhaseMode\n readonly detectionMode?: PipelinePhaseMode\n}\n\nexport interface DeviceProfile {\n readonly id: string\n readonly label: string\n readonly when: DeviceProfileMatch\n /**\n * Default phase modes + motion-source pick. Resolver reads these\n * when no operator value is persisted; profile never overrides a\n * concrete operator choice.\n */\n readonly defaults: DeviceProfileDefaults\n /**\n * Generic settings overrides (snapshot interval, pre-buffer flag,\n * etc.). Same sticky semantics as defaults — applied on first read,\n * operator override wins. Keys are dot-paths interpreted by the\n * per-driver / per-addon config schema.\n */\n readonly settings: Readonly<Record<string, unknown>>\n}\n\n/**\n * Heuristic check — `device.features?.includes(profile.when.hasFeature)`.\n */\nexport function deviceMatchesProfile(\n features: readonly string[] | undefined,\n profile: DeviceProfile,\n): boolean {\n if (!features || features.length === 0) return false\n return features.includes(profile.when.hasFeature)\n}\n\n/**\n * Battery-operated cameras default policy. The substream stays dialed\n * only when there's something for the runner to actually process —\n * audio is off, detection only runs on motion.\n *\n * `motionSources` is NOT in the profile defaults: the orchestrator's\n * resolver already prefers `'onboard'` whenever the device exposes a\n * native motion cap (firmware-driven motion), independent of profile.\n * Battery cams without firmware motion fall back to `[]` (no source) —\n * the operator must opt into `'analyzer'` SW motion explicitly.\n *\n * Object detection on motion: when motion fires, the runner attaches\n * the substream + runs detection until the motion gate closes, then\n * releases. Firmware idle-disconnect fires shortly after, the camera\n * goes back to sleep.\n */\nexport const BATTERY_DEVICE_PROFILE: DeviceProfile = {\n id: 'battery',\n label: 'Battery-operated camera',\n when: { hasFeature: Feature.BatteryOperated },\n defaults: {\n audioMode: 'disabled',\n detectionMode: 'on-motion',\n },\n settings: {\n 'snapshot.minRefreshIntervalSec': 3600,\n 'streamBroker.preBufferEnabled': false,\n },\n}\n\n/**\n * Profile registry — order matters when multiple profiles match the\n * same device (first match wins). Today there's only one entry.\n */\nexport const DEVICE_PROFILES: readonly DeviceProfile[] = [\n BATTERY_DEVICE_PROFILE,\n]\n\n/**\n * Resolve the profile that matches a device's features, or `null` when\n * no profile matches. First-match-wins.\n */\nexport function resolveDeviceProfile(\n features: readonly string[] | undefined,\n): DeviceProfile | null {\n for (const profile of DEVICE_PROFILES) {\n if (deviceMatchesProfile(features, profile)) return profile\n }\n return null\n}\n","import { z } from 'zod'\n\n/**\n * Optional callback invoked when `fromSchema` had to drop one or\n * more persisted fields to recover from a Zod validation failure.\n * Used by `BaseDevice` to surface the action via the device logger.\n */\nexport type ConfigRecoveryListener = (info: {\n droppedKeys: readonly string[]\n issues: readonly z.core.$ZodIssue[]\n}) => void\n\nexport class DeviceConfig<T extends z.ZodObject<z.core.$ZodLooseShape>> {\n readonly schema: T\n private data: z.infer<T>\n private readonly persistFn: (data: z.infer<T>) => Promise<void>\n\n private constructor(\n schema: T,\n data: z.infer<T>,\n persist: (data: z.infer<T>) => Promise<void>,\n ) {\n this.schema = schema\n this.data = data\n this.persistFn = persist\n }\n\n /**\n * Build a `DeviceConfig` from a persisted blob, with automatic\n * recovery from schema-validation failures. Boot must never be\n * blocked by stale persisted values: if Zod rejects the blob,\n * we drop every offending top-level field, retry, and persist\n * the cleaned blob so the bad value is healed in the DB on next\n * write. The most common trigger is a tightened range constraint\n * (e.g. `max(100) → max(50)`) on a field that already has an\n * out-of-range value persisted from the previous schema. Without\n * this safety net, the device would fail to instantiate and end\n * up with no caps registered — exactly the failure mode that\n * stranded device 15 when `motionSensitivity: 90` no longer fit\n * the new `1..50` schema.\n *\n * Recovery rules:\n * 1. Try `safeParse(initialData)`. If it succeeds, done.\n * 2. On failure, walk `error.issues`, collect the top-level path\n * of each issue, and drop those keys from `initialData`.\n * 3. Re-run `safeParse`. If the cleaned blob now passes (Zod\n * fills the missing keys with schema defaults / undefined for\n * `.optional()`), persist it via `persist()` so the bad\n * values disappear from the DB, and return the device.\n * 4. If the cleaned blob STILL fails (very rare — would require\n * a non-recoverable required field), fall back to\n * `schema.parse({})` so the device still boots with pure\n * schema defaults. Persist nothing in that path so the next\n * successful `setAll` still writes a coherent blob.\n */\n static fromSchema<T extends z.ZodObject<z.core.$ZodLooseShape>>(\n schema: T,\n persist: (data: z.infer<T>) => Promise<void>,\n initialData: Record<string, unknown> = {},\n onRecover?: ConfigRecoveryListener,\n ): DeviceConfig<T> {\n const first = schema.safeParse(initialData)\n if (first.success) {\n return new DeviceConfig(schema, first.data as z.infer<T>, persist)\n }\n\n const droppedKeys = new Set<string>()\n for (const issue of first.error.issues) {\n const top = issue.path[0]\n if (typeof top === 'string') droppedKeys.add(top)\n }\n\n const cleaned: Record<string, unknown> = { ...initialData }\n for (const k of droppedKeys) delete cleaned[k]\n const second = schema.safeParse(cleaned)\n\n onRecover?.({\n droppedKeys: [...droppedKeys],\n issues: first.error.issues,\n })\n\n if (second.success) {\n // Heal the DB: persist the cleaned blob asynchronously so the\n // offending fields are gone on next read. Best-effort — a\n // persist failure here doesn't block boot, the device still\n // runs from the in-memory cleaned data.\n void persist(second.data as z.infer<T>).catch(() => { /* swallow */ })\n return new DeviceConfig(schema, second.data as z.infer<T>, persist)\n }\n\n // Last-resort fallback: pure schema defaults. This branch should\n // be unreachable for well-formed schemas (every required field\n // must already be in `initialData`, and `.optional()` fields\n // accept undefined), but is here so a malformed blob can't\n // strand the device.\n const defaults = schema.parse({}) as z.infer<T>\n return new DeviceConfig(schema, defaults, persist)\n }\n\n get values(): z.infer<T> {\n return this.data\n }\n\n get<K extends keyof z.infer<T>>(key: K): z.infer<T>[K] {\n return this.data[key]\n }\n\n async set<K extends keyof z.infer<T>>(key: K, value: z.infer<T>[K]): Promise<void> {\n const next = this.schema.parse({ ...this.data, [key]: value })\n this.data = next\n await this.persistFn(this.data)\n }\n\n /**\n * Merge an untyped patch onto the current config and persist. Accepts\n * `Record<string, unknown>` because the patch typically comes from the\n * UI form layer (a `ConfigField.key → value` map) where the caller\n * doesn't hold the Zod schema's static type. Runtime validation is\n * authoritative: `this.schema.parse` rejects unknown keys or invalid\n * shapes before touching storage.\n */\n async setAll(partial: Record<string, unknown>): Promise<void> {\n const next = this.schema.parse({ ...this.data, ...partial })\n this.data = next\n await this.persistFn(this.data)\n }\n\n async deleteKey<K extends keyof z.infer<T>>(key: K): Promise<void> {\n const { [key as string]: _, ...rest } = this.data as Record<string, unknown>\n const next = this.schema.parse(rest)\n this.data = next\n await this.persistFn(this.data)\n }\n\n entries(): Array<{\n key: string\n schema: z.ZodType\n value: unknown\n description?: string\n }> {\n const shape = this.schema.shape as Record<string, z.ZodType>\n return Object.entries(shape).map(([key, fieldSchema]) => ({\n key,\n schema: fieldSchema,\n value: this.data[key as keyof z.infer<T>],\n description: fieldSchema.description,\n }))\n }\n}\n","import { z } from 'zod'\n\n/**\n * Per-device runtime state — cap-keyed. Mutable signals discovered\n * after boot live here, separate from `DeviceConfig` (operator\n * intent) and from `deviceCache` (immutable autodetect / abilities).\n *\n * Shape: `Record<capName, capStateSlice>`. Each slice's schema is\n * declared by the capability itself (`CapabilityDefinition.runtimeState`)\n * so that any provider implementing the cap inherits the same shape —\n * the BatteryStatus shape a Reolink cam emits is the same a Frigate or\n * ONVIF cam emits, no driver-specific re-declaration.\n *\n * Schemas are registered DYNAMICALLY as the device's caps are\n * installed (see `BaseDevice.registerNativeCap`). A slice without a\n * registered schema is rejected on write — the cap must be wired\n * first. Reads return `undefined` for unknown slices.\n *\n * Persistence: only registered slices round-trip to disk. The kernel\n * layer debounces writes; explicit `flush()` awaits in-flight saves\n * (used by the shutdown hook).\n */\nexport interface IDeviceRuntimeState {\n /**\n * Read the slice for `capName`. Three overloads, picked by\n * argument shape:\n *\n * 1. Pass a known cap-name literal (`'battery'`, `'motion'`, …)\n * → return type is auto-inferred from\n * `CapNameToRuntimeStateMap` (codegen output). No generic\n * argument, no `as`-cast.\n * 2. Pass a cap-name with an explicit generic\n * (`getCapState<MyShape>('custom-cap')`) → return that\n * shape. Used for caps the codegen doesn't see (test-only,\n * addon-private).\n * 3. Pass a cap-name with no generic (default `Record<string,\n * unknown>`) → permissive untyped fallback.\n *\n * Returns `undefined` if no slice has been written yet.\n */\n getCapState<K extends keyof import('../generated/device-local-state.js').CapNameToRuntimeStateMap>(\n capName: K,\n ): Readonly<import('../generated/device-local-state.js').CapNameToRuntimeStateMap[K]> | undefined\n getCapState<T extends Record<string, unknown> = Record<string, unknown>>(\n capName: string,\n ): Readonly<T> | undefined\n\n /** Read a single key inside a slice. Convenience for the common\n * case of reading a primitive (`battery.percentage`). */\n getCapField(capName: string, key: string): unknown\n\n /**\n * Replace the slice for `capName`. The schema bound to `capName`\n * (via `installCapSchema`) validates `value`; throws on mismatch.\n * Listeners fire synchronously after the write applies.\n */\n setCapState(capName: string, value: Record<string, unknown>): void\n\n /**\n * Shallow-merge `partial` into the current slice for `capName`.\n * Re-validates the merged result against the cap's schema.\n */\n patchCapState(capName: string, partial: Record<string, unknown>): void\n\n /** Subscribe to ALL state changes. Receives the cap names whose\n * slices changed and the full snapshot. */\n subscribe(cb: (changedCaps: ReadonlyArray<string>, snapshot: Snapshot) => void): () => void\n\n /** Subscribe to a single cap's slice changes. Fires only when that\n * cap's slice is touched; ignores writes against other caps. */\n subscribeCap<T extends Record<string, unknown> = Record<string, unknown>>(\n capName: string,\n cb: (slice: Readonly<T> | undefined) => void,\n ): () => void\n\n /** Frozen snapshot of every cap's slice. Cap names without a\n * written slice are omitted (sparse). */\n snapshot(): Snapshot\n\n /** Flush any pending debounced disk writes. */\n flush(): Promise<void>\n\n /**\n * Register a cap's runtime-state schema. Called by the kernel\n * when `ctx.registerNativeCap(cap, …)` runs and `cap.runtimeState`\n * is defined. Idempotent — repeat installs with the same schema\n * are no-ops; mismatched schemas throw to surface a config bug.\n *\n * Lazily validates any existing in-memory slice for `capName` so\n * a slice loaded from disk before the cap was wired is checked\n * the moment the cap shows up.\n */\n installCapSchema(capName: string, schema: z.ZodObject<z.core.$ZodLooseShape>): void\n}\n\nexport type Snapshot = Readonly<Record<string, Readonly<Record<string, unknown>>>>\n\n/**\n * Concrete implementation. Routes every successful write through\n * `writer(capName, slice)` — the kernel hooks this up to\n * `device-state.setCapSlice`, the canonical cross-layer write\n * entrypoint, which handles disk persistence (debounced on the hub)\n * and mirror updates.\n *\n * Schema validation runs in-process before the writer is called —\n * the round-trip should never carry an invalid slice. `flush()`\n * awaits any in-flight writer promises so shutdown is lossless.\n *\n * `initial` is the persisted blob loaded at boot. Slices for caps\n * whose schema hasn't been installed yet are kept in-memory verbatim\n * and validated when the cap registers later.\n */\nexport class DeviceRuntimeState implements IDeviceRuntimeState {\n private readonly writer: (capName: string, slice: Record<string, unknown>) => Promise<void>\n /** In-flight writer promises tracked so `flush()` can await them. */\n private readonly pendingWrites = new Set<Promise<unknown>>()\n /** Per-cap committed slice — after schema validation when known. */\n private slices: Map<string, Record<string, unknown>>\n /** Per-cap registered schema (set by `installCapSchema`). */\n private readonly schemas = new Map<string, z.ZodObject<z.core.$ZodLooseShape>>()\n private readonly listeners = new Set<(changed: ReadonlyArray<string>, snap: Snapshot) => void>()\n private readonly capListeners = new Map<string, Set<(slice: Readonly<Record<string, unknown>> | undefined) => void>>()\n\n private constructor(\n initial: Record<string, unknown>,\n writer: (capName: string, slice: Record<string, unknown>) => Promise<void>,\n ) {\n this.writer = writer\n // Hydrate slices: every top-level key in `initial` is a cap name,\n // its value should be an object. Non-object values are dropped\n // with no error — the persisted blob is owned by us, so a\n // garbage shape is a kernel bug we'd rather surface elsewhere.\n this.slices = new Map()\n for (const [k, v] of Object.entries(initial)) {\n if (v && typeof v === 'object' && !Array.isArray(v)) {\n this.slices.set(k, { ...v as Record<string, unknown> })\n }\n }\n }\n\n static fromInitial(\n initial: Record<string, unknown>,\n writer: (capName: string, slice: Record<string, unknown>) => Promise<void>,\n ): DeviceRuntimeState {\n return new DeviceRuntimeState(initial, writer)\n }\n\n installCapSchema(capName: string, schema: z.ZodObject<z.core.$ZodLooseShape>): void {\n const existing = this.schemas.get(capName)\n if (existing) {\n // Idempotent: caps register multiple times during the device's\n // lifetime (constructor + post-login retroactive registration).\n // Ignore identical re-registrations; a different schema for the\n // same cap is a programming error worth throwing on.\n if (existing !== schema) {\n throw new Error(\n `[DeviceRuntimeState] capability \"${capName}\" registered a different runtime-state schema; `\n + `each cap must declare ONE shape across every provider`,\n )\n }\n return\n }\n this.schemas.set(capName, schema)\n // Validate any pre-loaded slice now that we have the schema.\n // Reject silently and clear: the persisted blob shouldn't crash\n // the device on boot, just lose stale data the schema rejects.\n const stored = this.slices.get(capName)\n if (stored) {\n const result = schema.safeParse(stored)\n if (result.success) {\n this.slices.set(capName, result.data as Record<string, unknown>)\n } else {\n this.slices.delete(capName)\n }\n }\n }\n\n getCapState<T extends Record<string, unknown> = Record<string, unknown>>(\n capName: string,\n ): Readonly<T> | undefined {\n const slice = this.slices.get(capName)\n if (!slice) return undefined\n return Object.freeze({ ...slice }) as unknown as Readonly<T>\n }\n\n getCapField(capName: string, key: string): unknown {\n return this.slices.get(capName)?.[key]\n }\n\n setCapState(capName: string, value: Record<string, unknown>): void {\n this.applyCapWrite(capName, value, /* merge */ false)\n }\n\n patchCapState(capName: string, partial: Record<string, unknown>): void {\n this.applyCapWrite(capName, partial, /* merge */ true)\n }\n\n /**\n * Internal worker. `merge` controls whether `value` replaces or\n * shallow-merges into the existing slice. Schema validation runs\n * on the FINAL composed object regardless.\n */\n private applyCapWrite(capName: string, value: Record<string, unknown>, merge: boolean): void {\n const schema = this.schemas.get(capName)\n if (!schema) {\n // Refuse: a cap without a registered schema can't have its\n // slice written. Drivers that legitimately need extra\n // ad-hoc state should attach a `runtimeState` schema to the\n // cap definition. The strict refusal catches typos\n // (`'batery'` vs `'battery'`) loudly.\n throw new Error(\n `[DeviceRuntimeState] no schema registered for cap \"${capName}\" — `\n + `did the device register it via ctx.registerNativeCap before writing?`,\n )\n }\n const current = this.slices.get(capName) ?? {}\n const next = merge ? { ...current, ...value } : { ...value }\n const parsed = schema.parse(next) as Record<string, unknown>\n // Equality check before commit — back-to-back identical writes\n // (e.g. battery push every minute with the same percentage)\n // should NOT churn listeners or disk.\n if (shallowEqual(current, parsed)) return\n this.slices.set(capName, parsed)\n this.fireListeners([capName])\n // Kick off the write asynchronously — schema validation already\n // ran, so failure here means a transport / hub issue. We log\n // and drop the error rather than throwing, mirroring the\n // fire-and-forget contract `setCapState` had with the legacy\n // debounced persister.\n const writePromise = this.writer(capName, { ...parsed }).catch(() => {\n /* transport error — caller can re-issue if it cares */\n })\n this.pendingWrites.add(writePromise)\n void writePromise.finally(() => { this.pendingWrites.delete(writePromise) })\n }\n\n private fireListeners(changed: ReadonlyArray<string>): void {\n const snap = this.snapshot()\n for (const cb of this.listeners) {\n try { cb(changed, snap) } catch { /* listener errors don't break the writer */ }\n }\n for (const capName of changed) {\n const subs = this.capListeners.get(capName)\n if (!subs) continue\n const slice = this.getCapState(capName)\n for (const cb of subs) {\n try { cb(slice) } catch { /* idem */ }\n }\n }\n }\n\n subscribe(cb: (changed: ReadonlyArray<string>, snap: Snapshot) => void): () => void {\n this.listeners.add(cb)\n return () => { this.listeners.delete(cb) }\n }\n\n subscribeCap<T extends Record<string, unknown> = Record<string, unknown>>(\n capName: string,\n cb: (slice: Readonly<T> | undefined) => void,\n ): () => void {\n let subs = this.capListeners.get(capName)\n if (!subs) {\n subs = new Set()\n this.capListeners.set(capName, subs)\n }\n const adapter = (slice: Readonly<Record<string, unknown>> | undefined): void => {\n cb(slice as Readonly<T> | undefined)\n }\n subs.add(adapter)\n return () => {\n const set = this.capListeners.get(capName)\n if (!set) return\n set.delete(adapter)\n if (set.size === 0) this.capListeners.delete(capName)\n }\n }\n\n snapshot(): Snapshot {\n const out: Record<string, Record<string, unknown>> = {}\n for (const [k, v] of this.slices) out[k] = Object.freeze({ ...v })\n return Object.freeze(out) as Snapshot\n }\n\n async flush(): Promise<void> {\n if (this.pendingWrites.size === 0) return\n // Snapshot the current set so writes added while we await\n // (e.g. listeners that re-trigger setCapState) settle in a\n // separate flush round if the caller wants strict drainage.\n const inflight = [...this.pendingWrites]\n await Promise.allSettled(inflight)\n }\n}\n\nfunction shallowEqual(a: Record<string, unknown>, b: Record<string, unknown>): boolean {\n const ak = Object.keys(a)\n const bk = Object.keys(b)\n if (ak.length !== bk.length) return false\n for (const k of ak) {\n if (a[k] !== b[k]) return false\n }\n return true\n}\n","import type { z } from 'zod'\nimport type { CapabilityDefinition } from '../capabilities/capability-definition.js'\nimport type { IDeviceRuntimeState } from './device-runtime-state.js'\n\nconst LAST_FETCHED_FIELD = 'lastFetchedAt'\n\n/**\n * Bridge a cap's `runtimeState` slice to its read-side methods.\n *\n * Pattern: provider keeps the camera fetch / write path, but delegates\n * stale-check + slice read + cold-start fallback to this helper. Cuts\n * the boilerplate that every provider would otherwise repeat across\n * `getStatus`, `getSettings`, and any other read-side cap method.\n *\n * Convention: the cap's `runtimeState` schema must include a numeric\n * `lastFetchedAt` field (ms epoch) so the helper can drive the\n * stale-check. The field is stripped from the value returned by\n * `getStatus` so the cap's status schema (which doesn't carry it)\n * still parses cleanly.\n *\n * Usage in a provider:\n * ```ts\n * const bridge = createRuntimeStateBridge({\n * runtimeState: this.runtimeState,\n * cap: ptzAutotrackCapability,\n * ownDeviceId: this.id,\n * refresh: () => this.refreshAutotrackFromCamera(),\n * staleMs: 10_000,\n * empty: () => emptyAutotrackStatus(),\n * })\n *\n * const provider: InferNativeProvider<typeof ptzAutotrackCapability> = {\n * getStatus: bridge.getStatus,\n * getSettings: async ({ deviceId }) => {\n * if (deviceId !== this.id) return null\n * await bridge.ensureFresh()\n * return this.runtimeState.getCapState<...>(...)?.currentSettings ?? null\n * },\n * setEnabled: async (...) => { ... ; await this.refreshAutotrackFromCamera() },\n * setSettings: async (...) => { ... ; await this.refreshAutotrackFromCamera() },\n * }\n * ```\n *\n * Single-flight (collapsing concurrent `refresh()` invocations) lives\n * INSIDE `refresh` — the camera client owns its own promise slot. This\n * helper stays thin so a single provider can host multiple cap-bridged\n * readers without fighting over a shared promise.\n */\nexport interface RuntimeStateBridge<TStatus> {\n /** Run a stale-check; if the slice is missing or older than\n * `staleMs`, await `refresh()`. Idempotent within the freshness\n * window — back-to-back calls touch zero camera I/O. */\n readonly ensureFresh: () => Promise<void>\n /** Drop-in `getStatus` provider method. Includes the cross-device\n * guard + freshness check + status projection from the slice. */\n readonly getStatus: (input: { readonly deviceId: number }) => Promise<TStatus>\n}\n\nexport function createRuntimeStateBridge<\n TCap extends CapabilityDefinition & { status: { schema: z.ZodType } },\n>(params: {\n readonly runtimeState: IDeviceRuntimeState\n readonly cap: TCap\n readonly ownDeviceId: number\n readonly refresh: () => Promise<void>\n readonly staleMs: number\n readonly empty: () => z.infer<TCap['status']['schema']>\n}): RuntimeStateBridge<z.infer<TCap['status']['schema']>> {\n const { runtimeState, cap, ownDeviceId, refresh, staleMs, empty } = params\n\n const ensureFresh = async (): Promise<void> => {\n const slice = runtimeState.getCapState<Record<string, unknown>>(cap.name)\n const fetchedAt = typeof slice?.[LAST_FETCHED_FIELD] === 'number'\n ? (slice[LAST_FETCHED_FIELD] as number)\n : 0\n if (!slice || Date.now() - fetchedAt > staleMs) await refresh()\n }\n\n const projectStatus = (): z.infer<TCap['status']['schema']> => {\n const slice = runtimeState.getCapState<Record<string, unknown>>(cap.name)\n if (!slice) return empty()\n // Strip lastFetchedAt (and any future helper-only fields) before\n // returning. Status schemas don't carry this field; runtime-state\n // schemas extend status with it for stale tracking.\n const { [LAST_FETCHED_FIELD]: _omit, ...rest } = slice\n return rest as z.infer<TCap['status']['schema']>\n }\n\n const getStatus = async ({ deviceId }: { readonly deviceId: number }): Promise<z.infer<TCap['status']['schema']>> => {\n if (deviceId !== ownDeviceId) {\n throw new Error(`${cap.name}: deviceId mismatch, expected ${ownDeviceId}, got ${deviceId}`)\n }\n await ensureFresh()\n return projectStatus()\n }\n\n return { ensureFresh, getStatus }\n}\n","import { z } from 'zod'\nimport { type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n/**\n * Generic device-level status snapshot. Auto-registered by `BaseDevice`\n * for every device, regardless of provider — the kernel needs a uniform\n * cap-keyed slice for the basic device flags every consumer expects to\n * read across processes (the `online` flag in particular). Driver-specific\n * caps (`battery`, `doorbell`, …) carry their domain-specific state on\n * their own slices.\n *\n * Pattern is identical to `battery`: schema-bearing `runtimeState`,\n * empty `methods`, single change event. Reads land at\n * `runtimeState.getCapState('device-status')`; writes at\n * `runtimeState.setCapState('device-status', …)`. Cross-process\n * consumers reach the same data via the `device-state` cap router\n * (`getCapSlice({deviceId, capName: 'device-status'})`).\n */\nexport const DeviceStatusSchema = z.object({\n /**\n * Device-level liveness. Drivers flip via `markOnline(boolean)` on\n * `BaseDevice`. Provider semantics vary — RTSP aggregates broker\n * stream-health, Reolink reads firmware push events, ONVIF tracks\n * ping responses. This cap intentionally does NOT prescribe which\n * signal drives the flag.\n */\n online: z.boolean(),\n /** Ms epoch of the last `online` transition. Lets consumers tell\n * apart \"just came online\" from \"still online\". */\n lastChangedAt: z.number(),\n})\n\nexport type DeviceStatus = z.infer<typeof DeviceStatusSchema>\n\nexport const deviceStatusCapability = {\n name: 'device-status',\n scope: 'device',\n mode: 'singleton',\n methods: {},\n events: {\n /** Emitted when `online` transitions. Mirrors the semantics of\n * `battery.onStatusChanged`. */\n onStatusChanged: { data: z.object({\n deviceId: z.number(),\n status: DeviceStatusSchema,\n })},\n },\n status: {\n schema: DeviceStatusSchema,\n kind: 'push',\n },\n runtimeState: DeviceStatusSchema,\n} as const satisfies CapabilityDefinition\n\nexport type IDeviceStatusProvider = InferProvider<typeof deviceStatusCapability>\n","import { z } from 'zod'\nimport { type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n/**\n * Per-device feature/identity probe slice. Holds the runtime-resolved\n * truth about what a device CAN do — which the kernel uses to:\n * 1. Reconcile accessory children (hub-children spawn siren/floodlight/PIR\n * based on what the firmware actually advertises).\n * 2. Compute the public `features: DeviceFeature[]` array surfaced via\n * `device-manager.listAll`.\n * 3. Decide which optional caps (PTZ, intercom, doorbell, battery, …)\n * to register on the device's capability surface.\n *\n * Auto-registered by `BaseDevice` for every device. Drivers populate the\n * slice from `onProbe()` (kernel calls it once after register, before\n * accessory reconciliation). Consumers read via:\n * `runtimeState.getCapState<FeatureProbeStatus>('feature-probe')`\n *\n * `flags` is an open record so each driver carries its own keys without\n * a centralized schema bottleneck — Reolink writes `hasPtz/hasIntercom`,\n * Hikvision writes `hasSupplementalLight/hasAlarmIo`, etc.\n *\n * Replaces the older driver-local `deviceCache.has*` blob: the per-device\n * config is for operator-edited overrides + UI snapshots; runtime probe\n * results belong in runtime-state where the kernel handles persistence,\n * cross-process mirroring, and reactive updates.\n */\nexport const FeatureProbeStatusSchema = z.object({\n /**\n * Driver-specific flag bag. Each driver picks its own key names — the\n * cap deliberately does NOT enforce a closed enum here. Reolink keys:\n * `hasPtz`, `hasIntercom`, `hasDoorbell`, `hasFloodlight`, `hasSiren`,\n * `hasPirSensor`, `hasAutotrack`, `hasBattery`. Hikvision keys:\n * `hasSupplementalLight`, `lightHasWhiteLight`, `hasAlarmIo`, `hasPtz`.\n */\n flags: z.record(z.string(), z.unknown()),\n /**\n * Coarse driver-classification — lets cross-process consumers tell apart\n * cameras / battery-cams / NVRs without re-running the probe. `null`\n * before the first probe completes.\n */\n deviceType: z.string().nullable(),\n /** Camera/firmware model string. `null` when the firmware doesn't expose it. */\n model: z.string().nullable(),\n /** Channel count for NVR/Hub devices; `1` for standalone cameras; `null` pre-probe. */\n channelCount: z.number().nullable(),\n /**\n * Ms epoch of the last SUCCESSFUL probe. `0` before the first probe\n * completes — drivers' `getAccessoryChildren()` should treat zero as\n * \"probe not done yet, return empty\" so accessories aren't spawned\n * before the firmware is queried.\n */\n lastProbedAt: z.number(),\n /**\n * Framework convention: every runtime-state slice carries this for the\n * createRuntimeStateBridge stale-check helper. We keep it in sync with\n * `lastProbedAt` on every write.\n */\n lastFetchedAt: z.number(),\n})\n\nexport type FeatureProbeStatus = z.infer<typeof FeatureProbeStatusSchema>\n\nexport const featureProbeCapability = {\n name: 'feature-probe',\n scope: 'device',\n mode: 'singleton',\n methods: {},\n events: {\n /** Fires whenever a fresh probe completes (kernel-driven `reprobe()`\n * or driver-initiated re-detect after a state change). */\n onProbeChanged: { data: z.object({\n deviceId: z.number(),\n status: FeatureProbeStatusSchema,\n })},\n },\n status: {\n schema: FeatureProbeStatusSchema,\n kind: 'push',\n },\n runtimeState: FeatureProbeStatusSchema,\n} as const satisfies CapabilityDefinition\n\nexport type IFeatureProbeProvider = InferProvider<typeof featureProbeCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * Per-class audio metrics aggregated over a sliding window.\n */\nconst AudioClassSummarySchema = z.object({\n className: z.string(),\n /** Number of windows (chunks) where this class was the top hit. */\n hits: z.number().int().nonnegative(),\n /** Mean score across those hits, clamped to [0,1]. */\n avgScore: z.number().min(0).max(1),\n /** Peak score in the window. */\n peakScore: z.number().min(0).max(1),\n})\n\n/**\n * Per-camera audio metrics snapshot — emitted by the analytics frame\n * handler on every `pipeline.audio-inference-result` event and\n * mirrored into the `audio-metrics` device-state slice. Symmetric\n * with `zone-analytics` snapshots for video — every consumer\n * (admin UI panel, automations, alert rules) reads via the\n * canonical `device.state.audioMetrics.value` reactive handle.\n *\n * Aggregates are computed over a rolling `windowSec` window\n * (default 60s). Past that window, classes drop out of `byClass`\n * and the level history shifts forward.\n */\nconst AudioMetricsSnapshotSchema = z.object({\n /** Wall-clock timestamp (ms) of the most recent audio window. */\n ts: z.number().int(),\n /** Sliding-window length (seconds) used for aggregation. */\n windowSec: z.number().int().positive(),\n /** Latest level reading from the most recent window. */\n level: z.object({\n rms: z.number(),\n dbfs: z.number(),\n }),\n /** Peak dBFS observed across the rolling window. */\n peakDbfs: z.number(),\n /** Mean dBFS across the rolling window. */\n avgDbfs: z.number(),\n /** Most recent above-threshold classification, or null on silence. */\n current: z.object({\n className: z.string(),\n score: z.number().min(0).max(1),\n timestamp: z.number().int(),\n }).nullable(),\n /** Per-class summary across the rolling window — keys are\n * `macroClass` strings (e.g. `dog_bark`, `speech`, `glass_break`). */\n byClass: z.array(AudioClassSummarySchema).readonly(),\n})\nexport type AudioMetricsSnapshot = z.infer<typeof AudioMetricsSnapshotSchema>\nexport type AudioClassSummary = z.infer<typeof AudioClassSummarySchema>\n\n/**\n * One sample on the audio-metrics history time-series. Captures the\n * subset of the live snapshot useful for charting: dB level, peak/avg\n * over the rolling window, and the dominant above-threshold class\n * (when any). Per-class hit breakdown lives on the snapshot but is\n * elided from the history sample to keep the buffer compact —\n * consumers needing class drill-down should pull `getCurrentSnapshot`.\n */\nconst AudioMetricsHistoryPointSchema = z.object({\n /** Wall-clock ms when this sample was recorded. */\n ts: z.number().int(),\n /** Instantaneous dBFS level at sample time. `null` for windows where\n * the source had no level reading (rare; happens at decode startup). */\n dbfs: z.number().nullable(),\n /** Rolling-window peak dBFS at sample time. Same window the live\n * snapshot reports. */\n peakDbfs: z.number(),\n /** Rolling-window mean dBFS at sample time. */\n avgDbfs: z.number(),\n /** Dominant above-threshold class at sample time, or null on silence. */\n topClass: z.string().nullable(),\n /** Score of the dominant class (`null` whenever `topClass` is null). */\n topScore: z.number().min(0).max(1).nullable(),\n})\nexport type AudioMetricsHistoryPoint = z.infer<typeof AudioMetricsHistoryPointSchema>\n\n/**\n * Audio-metrics history payload — a series of `AudioMetricsHistoryPoint`\n * samples capped at `maxPoints` (default 1024). When the requested\n * `windowSec / sampleEveryMs` would exceed the cap, the provider\n * subsamples by bucketed averaging and reports the effective sample\n * spacing on `effectiveSampleEveryMs` so the UI can label the x-axis.\n */\nconst AudioMetricsHistorySchema = z.object({\n points: z.array(AudioMetricsHistoryPointSchema).readonly(),\n /** Actual ms between adjacent samples after any subsampling. */\n effectiveSampleEveryMs: z.number().int().positive(),\n /** Wall-clock window covered by `points` (`points[N-1].ts - points[0].ts`),\n * or `0` when there's fewer than 2 samples. */\n windowMsActual: z.number().int().nonnegative(),\n})\nexport type AudioMetricsHistory = z.infer<typeof AudioMetricsHistorySchema>\n\n/**\n * Audio Metrics capability — sliding-window aggregates over the\n * pipeline audio inference results. Hosted by `addon-pipeline-analytics`\n * (same addon that owns `zone-analytics`); the runtime-state slice\n * gives operators a live read on dB level + dominant classes without\n * a custom event subscription.\n */\nexport const audioMetricsCapability = {\n name: 'audio-metrics',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n methods: {\n /** Latest snapshot for this device. Null until the analytics\n * pipeline has processed at least one audio window. */\n getCurrentSnapshot: method(\n z.object({ deviceId: z.number() }),\n AudioMetricsSnapshotSchema.nullable(),\n ),\n /**\n * Time-series view of recent audio-metrics samples. The provider\n * keeps an in-memory ring of ~1Hz samples (matching the slice-\n * write rate) capped at `MAX_HISTORY_POINTS_KEPT` (provider-side).\n * `windowSec` selects how far back to read; `sampleEveryMs`\n * downsamples by bucketed averaging when finer than the kept\n * granularity. Empty `points` array on freshly-booted providers\n * with no audio yet — same convention as `getCurrentSnapshot`.\n */\n getHistory: method(\n z.object({\n deviceId: z.number(),\n /** History window in seconds. Default 300 (5 minutes).\n * Provider clamps to its retention cap if larger. */\n windowSec: z.number().int().positive().optional(),\n /** Target sample interval in ms. Default 1000 (1 sample/second).\n * Provider clamps to natural sample rate if smaller, and\n * bucket-averages when bigger than the requested window\n * would produce more than `maxPoints` samples. */\n sampleEveryMs: z.number().int().positive().optional(),\n }),\n AudioMetricsHistorySchema,\n ),\n },\n /** Reactive runtime-state mirror — live `device.state.audioMetrics.value`. */\n runtimeState: AudioMetricsSnapshotSchema,\n} as const satisfies CapabilityDefinition\n\nexport type IAudioMetricsProvider = InferProvider<typeof audioMetricsCapability>\n\nexport {\n AudioMetricsSnapshotSchema,\n AudioClassSummarySchema,\n AudioMetricsHistoryPointSchema,\n AudioMetricsHistorySchema,\n}\n","/**\n * Generic types for capability definitions.\n *\n * A capability is defined with Zod schemas for methods, events, and settings.\n * TypeScript types are inferred via z.infer<> — zero duplication.\n *\n * Pattern:\n * 1. Define Zod schemas for data, methods, settings\n * 2. Export const capabilityDef = { ... } satisfies CapabilityDefinition\n * 3. Export type IProvider = InferProvider<typeof capabilityDef>\n * 4. Addon implements IProvider\n * 5. Registry auto-mounts tRPC router from definition.methods\n */\n\nimport { z } from 'zod'\nimport { DeviceType } from '../device/device-type.js'\nimport type { ConfigUISchemaWithValues } from '../interfaces/config-ui.js'\n\n// ── Method & Event Schemas ───────────────────────────────────────────\n\n/**\n * tRPC procedure kind.\n * - 'query': read-only, no side effects\n * - 'mutation': write operation, side effects\n * - 'subscription': push-based real-time stream via WebSocket\n */\nexport type CapabilityMethodKind = 'query' | 'mutation' | 'subscription'\n\n/** Auth level required to call a capability method. */\nexport type CapabilityMethodAuth = 'public' | 'protected' | 'admin' | 'superAdmin'\n\n/** Schema pair for a single capability method: input + output + routing metadata. */\nexport interface CapabilityMethodSchema<\n TInput extends z.ZodType = z.ZodType,\n TOutput extends z.ZodType = z.ZodType,\n TKind extends CapabilityMethodKind = CapabilityMethodKind,\n> {\n readonly input: TInput\n readonly output: TOutput\n /** tRPC procedure kind. Default: 'query'. */\n readonly kind: TKind\n /** Auth level. Default: 'protected'. */\n readonly auth: CapabilityMethodAuth\n /** Moleculer action timeout override (ms). Overrides broker global requestTimeout for this action only. */\n readonly timeoutMs?: number\n}\n\n/** Schema for a capability event (emitted to EventBus) */\nexport interface CapabilityEventSchema<\n TData extends z.ZodType = z.ZodType,\n> {\n readonly data: TData\n}\n\n// ── Status (live readable machine-state per device) ─────────────────\n//\n// A cap can declare a `status` block describing the MACHINE-READABLE\n// snapshot of the device's current state for this capability (battery\n// percentage, PTZ position, intercom talking flag, …). When present,\n// the provider interface gains `getStatus({ deviceId })` auto-injected\n// via `InferProvider`. Distinct from `getDeviceSettingsContribution`\n// which is the UI-schema for human-editable settings.\n\nexport type CapabilityStatusKind = 'push' | 'poll' | 'command-driven'\n\nexport interface CapabilityStatusSchema<TStatus extends z.ZodType = z.ZodType> {\n readonly schema: TStatus\n /** Documentation hint on update cadence — used by the aggregator and UI. */\n readonly kind?: CapabilityStatusKind\n}\n\n// ── Declarative settings bindings ───────────────────────────────────\n//\n// A cap's `settings.bindings` spec lets the device-manager auto-derive\n// both `getDeviceSettingsContribution` (UI schema with live values) and\n// `applyDeviceSettingsPatch` (patch → cap method dispatch) without the\n// provider implementing a single line of FormBuilder code. The provider\n// only implements the imperative cap methods; the framework wires up\n// the admin-UI form from these bindings.\n\n/** Supported field kinds in settings bindings. Deliberately limited — mirror FormBuilder primitives. */\nexport type CapSettingsFieldKind = 'boolean' | 'text' | 'number' | 'select'\n\n/** Scalar (single value) binding — target a single scalar path inside `status`. */\nexport interface CapSettingsScalarBinding {\n readonly kind: 'scalar'\n /** Dot-path into `status` where the current value lives. */\n readonly statusPath: string\n /** Cap method invoked when the field changes. Must exist in `methods`. */\n readonly method: string\n /** Name of the method's input arg that receives the new value. */\n readonly valueArg: string\n readonly field: {\n readonly label: string\n readonly kind: CapSettingsFieldKind\n readonly options?: readonly string[]\n }\n /** Optional section override (default: capability name). */\n readonly sectionId?: string\n readonly sectionTitle?: string\n}\n\n/** Array binding — target an array path in `status`, render one row per item. */\nexport interface CapSettingsArrayBinding {\n readonly kind: 'array'\n /** Dot-path into `status` pointing at an array. */\n readonly statusPath: string\n /** Field on each array item used as stable id (e.g. 'id'). */\n readonly idField: string\n /** Cap method invoked on any per-item field change. */\n readonly method: string\n /** Method input arg that receives the item id (e.g. 'overlayId'). */\n readonly idArg: string\n /** Method input arg that receives the patch object. */\n readonly patchArg: string\n readonly sectionId: string\n readonly sectionTitle: string\n readonly itemFields: Readonly<Record<string, CapSettingsItemField>>\n}\n\nexport interface CapSettingsItemField {\n /** Static string or per-item resolver (runs server-side at contribution time). */\n readonly label: string | ((item: Record<string, unknown>) => string)\n readonly kind: CapSettingsFieldKind\n /** Select options — static array or per-item resolver. */\n readonly options?: readonly string[] | ((item: Record<string, unknown>) => readonly string[])\n /** Visibility predicate — hide the field for items returning false. */\n readonly when?: (item: Record<string, unknown>) => boolean\n}\n\nexport type CapSettingsBinding = CapSettingsScalarBinding | CapSettingsArrayBinding\n\nexport interface CapabilitySettingsSpec {\n readonly bindings: readonly CapSettingsBinding[]\n}\n\n// ── Capability Definition ────────────────────────────────────────────\n\n/**\n * Full definition of a capability — the single source of truth for the\n * functional contract (methods + events).\n *\n * Settings are NOT part of the capability definition — they belong to\n * the addon implementation. Each addon defines its own settings schema\n * via ICamstackAddon.getConfigSchema(), stored per-addon with optional\n * per-device overrides.\n */\nexport interface CapabilityDefinition<\n TName extends string = string,\n TMethods extends Record<string, CapabilityMethodSchema> = Record<string, CapabilityMethodSchema>,\n TEvents extends Record<string, CapabilityEventSchema> | undefined = Record<string, CapabilityEventSchema> | undefined,\n> {\n /** Unique capability name (kebab-case) */\n readonly name: TName\n /** system = global singleton/collection. device = per-device resolution. */\n readonly scope: 'system' | 'device'\n /**\n * Cardinality of active providers:\n * - `singleton` — exactly one active provider cluster-wide\n * (e.g. admin-ui, device-manager). User config can pick which addon\n * is active when multiple are registered.\n * - `collection` — every registered provider stays active\n * (e.g. decoder, notification-output).\n * - `per-node` — one active provider per node/agent. Every node that\n * hosts an addon for this cap runs its own independent provider;\n * consumers query `getProviderForNode(capName, nodeId)` instead of\n * `getSingleton(capName)`. Used for node-local probes\n * (platform-probe, metrics-provider, hwaccel-probe).\n */\n readonly mode: 'singleton' | 'collection' | 'per-node'\n /** Method definitions: name → { input, output } Zod schemas */\n readonly methods: TMethods\n /** Event definitions: name → { data } Zod schema (optional) */\n readonly events?: TEvents\n /**\n * Typed machine-readable status snapshot. When present, the provider\n * interface gains `getStatus({ deviceId })` auto-injected via\n * `InferProvider`. Consumers poll via this method or subscribe via\n * `device-manager.subscribeDeviceStatusAggregate`. Distinct from\n * `getDeviceSettingsContribution` — that serves the UI editable-form\n * schema; `status` is the live readable state.\n */\n readonly status?: CapabilityStatusSchema\n\n /**\n * Per-device runtime-state slice owned by THIS cap. Persisted across\n * restarts under `device.state[capName]`. Every provider that\n * implements the cap inherits the same shape — drivers don't\n * redeclare it, they just write through `this.runtimeState\n * .setCapState('<capName>', value)`. Examples:\n *\n * - `batteryCapability.runtimeState`: `{ percentage, charging,\n * sleeping, lastUpdated }`. A Reolink Argus, a Frigate sensor\n * proxy, an ONVIF battery cam — every provider stores the\n * same shape under `state.battery`.\n * - `ptzCapability.runtimeState`: `{ pan, tilt, zoom }`.\n *\n * Caps without runtime state (pure-RPC like `reboot`) leave this\n * undefined; setCapState refuses to write to those slices.\n */\n readonly runtimeState?: import('zod').ZodObject<import('zod').core.$ZodLooseShape>\n /**\n * Declarative settings spec. When present, the device-manager's\n * settings aggregator auto-derives the ConfigUISchema and routes\n * patches back to the referenced imperative methods. The provider\n * implements ONLY the imperative methods — no manual FormBuilder\n * contribution code. Colocated with the cap for single-source-of-\n * truth ergonomics.\n */\n readonly settings?: CapabilitySettingsSpec\n /** For `scope: 'device'` caps — allowed device types. Omit → applies to every type. */\n readonly deviceTypes?: readonly DeviceType[]\n /**\n * When `true`, every provider of this capability MUST implement the\n * device-settings contribution surface — three extra methods appearing\n * automatically on the provider interface via `InferProvider`:\n *\n * - `getDeviceSettingsContribution({ deviceId })` → schema + values\n * for the device-details page (cached, slow cadence). Returns null\n * when the provider has nothing to contribute for the given device.\n * - `getDeviceLiveContribution({ deviceId })` → readonly live data\n * (status, counters). Returns null when not applicable. Polled ~2-3s.\n * - `applyDeviceSettingsPatch({ deviceId, patch })` → single-entry\n * mutation for field values returned by `getDeviceSettingsContribution`.\n * The provider owns the storage.\n *\n * The naming is intentionally distinct from the three-level addon API\n * (`getGlobalSettings` / `getDeviceSettings` / `getAddonSettings`) to\n * avoid collisions when an addon implements both surfaces on the same\n * class. The words \"Contribution\" and \"Patch\" signal these are aggregator\n * hooks, not persistent settings accessors.\n *\n * The `device-manager` aggregator enumerates bindings for the target\n * device, picks providers whose cap has this flag, and concatenates\n * the per-provider contributions into the single aggregate consumed\n * by `deviceManager.getDeviceSettingsAggregate`.\n */\n readonly exposesDeviceSettings?: boolean\n\n /**\n * Server-internal cap — registered for in-process consumption only.\n * NOT exposed via the SDK `System` proxy and NOT exposed via the\n * generated React hooks. Use this for collection caps whose\n * contributions are aggregated by another singleton cap (for example\n * `addon-pages-source` walked by the `addon-pages` aggregator) or for\n * declarative slots (`addon-routes`, `admin-ui`, `log-destination`,\n * `restreamer`, `streaming-engine`, `webrtc`) consumed by hub\n * builtins/addons via `capabilities.getCollection()` /\n * `getSingleton()`.\n *\n * Behaviour:\n * - cap-router codegen still emits a `createCapRouter_<Cap>` so the\n * router stays available for opt-in mounting (e.g. test harnesses);\n * `trpc.router.ts` simply does not reference it.\n * - system-proxy codegen skips it — `system.<cap>` is not minted.\n * - system-hooks codegen skips it — no `use<Cap><Method>` exports.\n * - The cap is still consumable internally via\n * `ctx.capabilities.getCollection()` / `getSingleton()` from\n * inside an addon.\n *\n * Default: `false` (cap is publicly mounted and exposed on the SDK\n * surface).\n */\n readonly internal?: boolean\n\n /**\n * How the generated tRPC cap-router treats an input field named\n * `nodeId`:\n *\n * - `'routing'` (default): extract `nodeId` from the input and\n * route to that node via `createRemoteProxy`. Use when the cap\n * has a provider registered on every target node.\n *\n * - `'data'`: forward `nodeId` untouched to the local provider\n * as part of the method's input. Use when the cap has a\n * hub-centric provider that dispatches internally\n * (`broker.call('<addonId>.settings.<method>', ..., {nodeID})`).\n * `addon-settings` is the canonical example — one singleton on\n * the hub resolves `addonId` → worker nodeId by consulting the\n * cluster roster.\n */\n readonly nodeIdMode?: 'routing' | 'data'\n}\n\n/** Contract for the three methods added by `exposesDeviceSettings: true`. */\nexport interface DeviceSettingsContribution {\n readonly getDeviceSettingsContribution: (input: { readonly deviceId: number }) => Promise<ConfigUISchemaWithValues | null>\n readonly getDeviceLiveContribution: (input: { readonly deviceId: number }) => Promise<ConfigUISchemaWithValues | null>\n readonly applyDeviceSettingsPatch: (input: { readonly deviceId: number; readonly patch: Record<string, unknown> }) => Promise<{ readonly success: true }>\n}\n\n// ── DeviceSettingsContribution Zod schemas ──────────────────────────\n//\n// Zod-level counterparts to the TS interface above. Exposed so every\n// layer that walks a cap def's methods (Moleculer service factory,\n// tRPC cap-router codegen, remote-provider proxy builder) can treat\n// `exposesDeviceSettings: true` the same way it treats any other\n// method — just auto-spread these three into the methods map. The\n// interface stops being an implicit \"invisible surface\": every\n// provider of an `exposesDeviceSettings` cap exposes these three\n// actions as regular cap methods, reachable through Moleculer and\n// tRPC like everything else. No hidden in-process-only shortcuts.\n\n/**\n * Output schema shared by the contribution + live methods.\n *\n * Mirrors the `ConfigUISchemaWithValues` shape (sections[] + optional\n * tabs[]) without importing from `../interfaces/config-ui.js` — a\n * concrete-but-lenient Zod object keeps tRPC output inference happy\n * (using `z.unknown()` here collapses unrelated router branches to\n * `unknown` when the generator re-inlines the huge AppRouter type).\n *\n * `.passthrough()` on sections/fields accepts whatever FormBuilder\n * extensions the caller adds (showWhen, displayScale, …) without\n * rebuilding every time a new field kind is introduced.\n */\nconst ContributionSectionSchema = z.object({\n id: z.string(),\n title: z.string(),\n description: z.string().optional(),\n style: z.enum(['card', 'accordion']).optional(),\n defaultCollapsed: z.boolean().optional(),\n columns: z.union([z.literal(1), z.literal(2), z.literal(3), z.literal(4)]).optional(),\n tab: z.string().optional(),\n // Hoist the section into a top-level device tab (DeviceDetail\n // discovers these and renders one tab per unique `tab` id). Default\n // 'settings' keeps the section under the Config tab.\n location: z.enum(['settings', 'top-tab']).optional(),\n order: z.number().optional(),\n fields: z.array(z.any()),\n})\n\nconst ContributionTabSchema = z.object({\n id: z.string(),\n label: z.string(),\n icon: z.string(),\n order: z.number().optional(),\n})\n\nconst ContributionSchema = z.object({\n tabs: z.array(ContributionTabSchema).optional(),\n sections: z.array(ContributionSectionSchema),\n})\n\nconst ContributionOutputSchema = ContributionSchema.nullable()\n\nexport const DEVICE_SETTINGS_CONTRIBUTION_METHODS = {\n getDeviceSettingsContribution: {\n input: z.object({ deviceId: z.number() }),\n output: ContributionOutputSchema,\n kind: 'query',\n auth: 'protected',\n },\n getDeviceLiveContribution: {\n input: z.object({ deviceId: z.number() }),\n output: ContributionOutputSchema,\n kind: 'query',\n auth: 'protected',\n },\n applyDeviceSettingsPatch: {\n input: z.object({ deviceId: z.number(), patch: z.record(z.string(), z.unknown()) }),\n output: z.object({ success: z.literal(true) }),\n kind: 'mutation',\n auth: 'admin',\n },\n} as const satisfies Record<string, CapabilityMethodSchema>\n\n/**\n * Schema for the `getStatus` method auto-injected when a cap declares\n * `status`. The runtime shape of the output is the cap's own\n * `status.schema` — but at codegen time we need a concrete Zod to emit\n * a typed tRPC route, so we keep the output as `z.unknown().nullable()`\n * here and tighten it on the client side via the generated\n * `CapStatusTypeMap` (see `scripts/generate-cap-status-types.ts`).\n */\nexport const DEVICE_STATUS_METHOD = {\n getStatus: {\n input: z.object({ deviceId: z.number() }),\n output: z.unknown().nullable(),\n kind: 'query',\n auth: 'protected',\n },\n} as const satisfies Record<string, CapabilityMethodSchema>\n\n/**\n * Expand a cap def's methods map with every auto-injected method:\n * - `exposesDeviceSettings: true` → 3 contribution methods\n * - `status: {...}` → `getStatus`\n *\n * Callers walk `expandCapMethods(def)` instead of `def.methods` when\n * they need the effective runtime method surface (Moleculer actions,\n * proxy shape, tRPC router entries). The cap def stays the single\n * source of truth. Providers still declare their concrete `methods`\n * block; the expansion happens at every consumption point, so there's\n * no accidental divergence between the declared surface and what's\n * actually mounted.\n */\nexport function expandCapMethods(def: CapabilityDefinition): Record<string, CapabilityMethodSchema> {\n let out: Record<string, CapabilityMethodSchema> = def.methods\n if (def.exposesDeviceSettings) {\n out = { ...DEVICE_SETTINGS_CONTRIBUTION_METHODS, ...out }\n }\n if (def.status) {\n out = { ...DEVICE_STATUS_METHOD, ...out }\n }\n return out\n}\n\n// ── Type Inference Helpers ───────────────────────────────────────────\n\n/**\n * Infer the provider interface from a capability definition.\n *\n * All query/mutation methods return Promise<T> — this ensures consumers\n * can transparently call local or Moleculer-remote providers.\n * Providers may still implement methods as sync (return T); the Moleculer\n * action handler and tRPC router await the result either way.\n */\n/** Extract the status output type — or `never` when the cap has no status block. */\nexport type InferStatus<T extends CapabilityDefinition> =\n T extends { status: CapabilityStatusSchema<infer S> } ? z.infer<S> : never\n\n/** Contract for the `getStatus` method auto-injected when `status: {...}` is set. */\nexport interface DeviceStatusContribution<TStatus> {\n readonly getStatus: (input: { readonly deviceId: number }) => Promise<TStatus | null>\n}\n\nexport type InferProvider<T extends CapabilityDefinition> = {\n readonly [K in keyof T['methods']]: T['methods'][K] extends CapabilityMethodSchema<infer TIn, infer TOut>\n ? T['methods'][K]['kind'] extends 'subscription'\n ? (input: z.infer<TIn>, push: (value: z.infer<TOut>) => void) => (() => void) | void\n : (input: z.infer<TIn>) => Promise<z.infer<TOut>>\n : never\n} & (T['exposesDeviceSettings'] extends true ? DeviceSettingsContribution : Record<never, never>)\n & (T extends { status: CapabilityStatusSchema } ? DeviceStatusContribution<InferStatus<T>> : Record<never, never>)\n\n/**\n * Interface for native (per-device) providers — strips the\n * `DeviceSettingsContribution` surface that `exposesDeviceSettings: true`\n * bolts onto the system-level `InferProvider`.\n *\n * Native providers are registered via `DeviceContext.registerNativeCap`\n * and only serve the cap's device-scoped runtime methods for that single\n * device. They do NOT own per-device settings — those flow through the\n * addon's system-level provider's `applyDeviceSettingsPatch`, not\n * through the camera driver's native hook. Keeping the two surfaces\n * separate stops every device class (RtspCamera, OnvifCamera, …) from\n * having to stub out three unused methods.\n */\nexport type InferNativeProvider<T extends CapabilityDefinition> = {\n readonly [K in keyof T['methods']]: T['methods'][K] extends CapabilityMethodSchema<infer TIn, infer TOut>\n ? T['methods'][K]['kind'] extends 'subscription'\n ? (input: z.infer<TIn>, push: (value: z.infer<TOut>) => void) => (() => void) | void\n : (input: z.infer<TIn>) => Promise<z.infer<TOut>>\n : never\n} & (T extends { status: CapabilityStatusSchema }\n // Optional on native providers: not every driver can report status\n // (e.g. snapshot providers that only expose the fetch call). When\n // present the server-side aggregator uses it; when absent the cap's\n // status entry is reported as `null` in `getDeviceStatusAggregate`.\n ? Partial<DeviceStatusContribution<InferStatus<T>>>\n : Record<never, never>\n)\n\n/**\n * Infer event data types from a capability definition.\n * Returns a map of event name → data type.\n */\nexport type InferEvents<T extends CapabilityDefinition> =\n T['events'] extends Record<string, CapabilityEventSchema>\n ? { readonly [K in keyof T['events']]: T['events'][K] extends CapabilityEventSchema<infer TData> ? z.infer<TData> : never }\n : never\n\n/**\n * Infer the device-proxy facade interface for a device-scoped capability.\n *\n * Strips `deviceId` from every method's input so consumers of the client-side\n * proxy (bound to a specific device) don't have to pass it. The proxy layer\n * injects `deviceId` before forwarding to the tRPC/Moleculer action.\n *\n * Query/Mutation methods always return Promise<T>. Subscription methods keep\n * the push-based shape, without `deviceId` in the input payload.\n */\nexport type InferDeviceProxyCap<T extends CapabilityDefinition> = {\n readonly [K in keyof T['methods']]: T['methods'][K] extends CapabilityMethodSchema<infer TIn, infer TOut>\n ? T['methods'][K]['kind'] extends 'subscription'\n ? (input: Omit<z.infer<TIn>, 'deviceId'>, push: (value: z.infer<TOut>) => void) => (() => void) | void\n : (input: Omit<z.infer<TIn>, 'deviceId'>) => Promise<z.infer<TOut>>\n : never\n} & (T['status'] extends { schema: infer S }\n // Auto-injected `getStatus` mirrors the runtime emitted by the proxy\n // generator (see `scripts/generate-device-proxy.ts`). The schema is\n // tightened to the cap's status shape — `S` is the Zod schema, so\n // we resolve `z.infer<S>` here so consumers don't have to cast.\n ? { readonly getStatus: (input?: { deviceId?: number }) => Promise<S extends z.ZodType ? z.infer<S> | null : unknown> }\n : Record<never, never>)\n // When `exposesDeviceSettings: true`, mirror the three contribution\n // methods that `expandCapMethods()` injects at runtime + the cap-router\n // codegen surfaces. Without these here, the device-proxy codegen\n // (which textually parses the cap and includes those methods in its\n // `Pick<>` over `InferDeviceProxyCap`) hits a constraint mismatch.\n & (T['exposesDeviceSettings'] extends true\n ? {\n readonly getDeviceSettingsContribution: (input?: { deviceId?: number }) => Promise<unknown>\n readonly getDeviceLiveContribution: (input?: { deviceId?: number }) => Promise<unknown>\n readonly applyDeviceSettingsPatch: (input: { deviceId?: number; patch: Record<string, unknown> }) => Promise<{ readonly success: true }>\n }\n : Record<never, never>)\n\n/** Extract the capability name as a string literal type. */\nexport type InferName<T extends CapabilityDefinition> = T['name']\n\n/**\n * Infer the runtime-state slice TS shape from a cap definition.\n *\n * Lives inside the types package on purpose: `z.infer<>` is resolved\n * against THIS package's Zod version (built with Zod 4), so consumers\n * that resolve a different Zod major (e.g. core resolving Zod 3 from\n * the workspace root) still see the correct concrete shape — they\n * never need to call `z.infer` themselves.\n *\n * Falls back to `unknown` for caps without `runtimeState:` so call sites\n * can't accidentally narrow to `never` and lose property-access type\n * checking.\n */\nexport type InferRuntimeState<T extends CapabilityDefinition> =\n T extends { readonly runtimeState: infer R }\n ? R extends z.ZodType<infer Out>\n ? Out\n : R extends { readonly _output: infer Out }\n ? Out\n : unknown\n : unknown\n\n// ── Helpers ─────────────────────────────────────────────────────────\n\n/** Options for a capability method definition. */\nexport interface CapabilityMethodOptions<TKind extends CapabilityMethodKind = CapabilityMethodKind> {\n /** tRPC procedure kind. Default: 'query'. */\n readonly kind?: TKind\n /** Auth level. Default: 'protected'. */\n readonly auth?: CapabilityMethodAuth\n /** Moleculer action timeout override (ms). Overrides broker global requestTimeout for this action only. */\n readonly timeoutMs?: number\n}\n\n/** Shorthand to define a method schema */\nexport function method<TIn extends z.ZodType, TOut extends z.ZodType, TKind extends CapabilityMethodKind = 'query'>(\n input: TIn,\n output: TOut,\n options?: CapabilityMethodOptions<TKind>,\n): CapabilityMethodSchema<TIn, TOut, TKind> {\n return {\n input,\n output,\n kind: (options?.kind ?? 'query') as TKind,\n auth: options?.auth ?? 'protected',\n timeoutMs: options?.timeoutMs,\n }\n}\n\n/** Shorthand to define an event schema */\nexport function event<TData extends z.ZodType>(\n data: TData,\n): CapabilityEventSchema<TData> {\n return { data }\n}\n","import { z } from 'zod'\nimport { type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * Battery status snapshot. Emitted by providers whose device is\n * battery-operated (cameras with `DeviceFeature.BatteryOperated`,\n * future sensor/button accessories). Consumers build their own \"low\n * battery\" alerting on top — the cap deliberately does NOT enforce a\n * threshold.\n */\nexport const BatteryStatusSchema = z.object({\n /** 0..100 inclusive. Firmware-reported. */\n percentage: z.number().min(0).max(100),\n /**\n * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is\n * Reolink-specific for the Solar Panel 2 accessory (will become\n * common on other battery cams). `'none'` means running on battery\n * alone.\n */\n charging: z.enum(['dc', 'solar', 'none']),\n /**\n * True when the camera firmware has gone into low-power mode. Battery\n * providers MUST avoid polling during sleep — reading the battery\n * wakes the camera up and drains charge.\n */\n sleeping: z.boolean(),\n /** Ms epoch of the last observation. Lets consumers reason about freshness. */\n lastUpdated: z.number(),\n})\n\nexport type BatteryStatus = z.infer<typeof BatteryStatusSchema>\n\nexport const batteryCapability = {\n name: 'battery',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch],\n methods: {},\n events: {\n /**\n * Emitted whenever the cached status changes (firmware push OR\n * poll observes a delta). The DeviceEventPropagator mirrors this\n * event on the parent chain — subscribing to a camera's source\n * receives battery events from child accessories automatically.\n */\n onStatusChanged: { data: z.object({\n deviceId: z.number(),\n status: BatteryStatusSchema,\n })},\n },\n status: {\n schema: BatteryStatusSchema,\n kind: 'push',\n },\n /**\n * Runtime-state slice — every provider that registers this cap\n * stores the same shape under `device.runtimeState[battery]`.\n * Cross-provider uniformity: a Reolink Argus, a Frigate sensor\n * proxy, an ONVIF battery cam all read/write the same keys.\n * Consumers (BatteryBadge, snapshot wrapper sleep gate) read once\n * via `device.runtimeState.getCapState('battery')` regardless of\n * the underlying driver.\n */\n runtimeState: BatteryStatusSchema,\n} as const satisfies CapabilityDefinition\n\nexport type IBatteryProvider = InferProvider<typeof batteryCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * Dimmable-light brightness control. Co-exists with `switch` on the\n * same device — the switch toggles on/off, this cap sets the level\n * applied when the light is on. Modeled after Scrypted's `Brightness`\n * interface so drivers can map their per-vendor dim controls cleanly.\n *\n * The cap is intentionally minimal: a single `setBrightness({deviceId,\n * percentage})` mutation plus the auto-injected `getStatus`. Drivers\n * that expose richer controls (color temperature, scenes, schedules)\n * should surface those via the device's `getSettingsUISchema()`\n * instead of bloating this cap.\n */\nexport const BrightnessStatusSchema = z.object({\n /** Current level as 0..100 inclusive. Firmware-reported. */\n percentage: z.number().min(0).max(100),\n /** Ms epoch of the last operator-driven change. Useful for UI freshness. */\n lastChangedAt: z.number(),\n})\n\nexport type BrightnessStatus = z.infer<typeof BrightnessStatusSchema>\n\nexport const brightnessCapability = {\n name: 'brightness',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Light],\n methods: {\n setBrightness: method(\n z.object({\n deviceId: z.number().int().nonnegative(),\n percentage: z.number().min(0).max(100),\n }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n events: {\n /**\n * Emitted whenever the brightness changes — operator action OR\n * firmware push. Subscribers (UI sliders, automation engines) react\n * without polling.\n */\n onBrightnessChanged: { data: z.object({\n deviceId: z.number(),\n percentage: z.number().min(0).max(100),\n lastChangedAt: z.number(),\n })},\n },\n status: {\n schema: BrightnessStatusSchema,\n kind: 'command-driven',\n },\n /**\n * Runtime-state slice — the last applied brightness level, mirrored\n * by the kernel. Read via `device.state.brightness.value` so UI\n * sliders surface the current level without polling the provider.\n */\n runtimeState: BrightnessStatusSchema,\n} as const satisfies CapabilityDefinition\n\nexport type IBrightnessProvider = InferProvider<typeof brightnessCapability>\n","import { z } from 'zod'\nimport { method, event, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\nimport { CameraStreamSchema, ProfileSlotSchema, ProfileSlotStatusSchema } from './schemas/streaming-shared.js'\nimport { RtspRestreamEntrySchema } from './stream-broker.cap.js'\n\n\n/**\n * Camera streams — device-scoped facade over the system `stream-broker`.\n *\n * Mirrors the slice of broker state relevant to a single device:\n * - `getCameraStreams()`: the pool of physical streams published for\n * this device. UI uses it to populate the \"Camera Stream\" dropdown\n * under each quality section.\n * - `getBrokerStreams()`: the (up to 3) profile slots `high/mid/low`\n * with their current assignment + runtime status. UI uses it for\n * the WebRTC quality picker, recording target selection, etc.\n *\n * Registered for every camera device that has at least one published\n * cam stream. The provider is owned by the stream-broker addon; reads\n * go against the broker's in-memory registries. Mutations (assign /\n * unassign / publish / retract) do NOT live here — they stay on the\n * system `stream-broker` cap so cross-device / addon-driven flows keep\n * a single namespace.\n */\nexport const cameraStreamsCapability = {\n name: 'camera-streams',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n methods: {\n getCameraStreams: method(\n z.object({ deviceId: z.number().int().nonnegative() }),\n z.array(CameraStreamSchema).readonly(),\n ),\n getBrokerStreams: method(\n z.object({ deviceId: z.number().int().nonnegative() }),\n z.array(ProfileSlotSchema).readonly(),\n ),\n /**\n * Per-device RTSP restream entries. Returns the broker's published\n * RTSP URLs (one per `${deviceId}/${profile}`) for THIS device only,\n * including the rendered `url` field with the RTSP token applied.\n * Consumers (snapshot wrapper, recording, external probes) use this\n * to pick a stream URL without scanning the whole cluster.\n *\n * The system `stream-broker.getAllRtspEntries({hostname?})` still\n * exists for whole-cluster use cases (admin dashboard, settings\n * exports). This device-scoped accessor is the supported handle for\n * code that already has a `deviceId` in hand — keeps device-keyed\n * filtering server-side and rides the DeviceProxy auto-injection.\n */\n getRtspEntries: method(\n z.object({\n deviceId: z.number().int().nonnegative(),\n /** Override hostname embedded in returned URLs. Defaults to the broker's bound address. */\n hostname: z.string().optional(),\n }),\n z.array(RtspRestreamEntrySchema).readonly(),\n ),\n },\n events: {\n /** Fires on publishCameraStream / retractCameraStream. */\n onCamStreamsChanged: event(z.object({\n deviceId: z.number().int().nonnegative(),\n camStreams: z.array(CameraStreamSchema).readonly(),\n })),\n /** Fires on assignProfile / unassignProfile / runtime status change. */\n onProfileSlotsChanged: event(z.object({\n deviceId: z.number().int().nonnegative(),\n profileSlots: z.array(ProfileSlotSchema).readonly(),\n })),\n },\n /**\n * Per-device live stream-broker state. Persistent settings (RTSP\n * tokens, profile assignments, pre-buffer config, RTSP-enabled toggles,\n * streamingDebug) stay in the broker's addon store — they survive\n * restarts. The slice below carries ONLY what's truly runtime:\n *\n * - `online` — at least one profile slot is currently `'streaming'`.\n * Drivers without a firmware liveness signal (RTSP, ONVIF…) can\n * subscribe and mirror this into `state.deviceStatus.online`.\n * - `slotStatuses` — current `ProfileSlotStatus` per profile,\n * mirroring the runtime-mutable subset of `ProfileSlot`.\n * - `slotErrors` — last error message per profile (only set when the\n * corresponding slot is in `'error'`).\n * - `lastChangedAt` — freshness signal for consumers that want to\n * reason about how stale the slice is.\n *\n * Written by the stream-broker manager on every transition that\n * affects these aggregates. Read via `device.state.cameraStreams.<field>`\n * (BaseDevice proxy) or, cross-process, via\n * `device-state.getCapSlice({deviceId, capName: 'camera-streams'})`.\n * The cap's `onChanged` event fires automatically on each write so\n * subscribers get push semantics for free.\n */\n runtimeState: z.object({\n online: z.boolean(),\n slotStatuses: z.object({\n high: ProfileSlotStatusSchema.optional(),\n mid: ProfileSlotStatusSchema.optional(),\n low: ProfileSlotStatusSchema.optional(),\n }),\n slotErrors: z.object({\n high: z.string().optional(),\n mid: z.string().optional(),\n low: z.string().optional(),\n }),\n lastChangedAt: z.number(),\n }),\n} as const satisfies CapabilityDefinition\n\nexport type ICameraStreamsProvider = InferProvider<typeof cameraStreamsCapability>\n","/** Shared Zod schemas used across streaming capabilities. */\n\nimport { z } from 'zod'\n\n// ── Broker profile slots ─────────────────────────────────────────────\n//\n// Camstack supports at most 3 system-wide quality profiles per device:\n// `high`, `mid`, `low`. Valid combinations: {high,mid,low}, {high,low},\n// {mid}. Every consumer (WebRTC, recording, pipeline, detection, frame\n// transport) addresses a device's stream via `${deviceId}/${profile}`;\n// the camera's physical cam-stream ids never leak past the broker.\n\nexport const CamProfileSchema = z.enum(['high', 'mid', 'low'])\nexport type CamProfile = z.infer<typeof CamProfileSchema>\n\n/** Canonical ordering. Hard-coded; never sorted. */\nexport const CAM_PROFILE_ORDER = ['high', 'mid', 'low'] as const\n\n// ── Published cam stream (broker-owned registry) ─────────────────────\n//\n// A camera's physical stream, published to the broker via\n// `streamBroker.publishCameraStream(...)`. The provider owns the\n// lifecycle (re-publishes on boot, retracts on removal). The broker\n// owns the registry: each entry is the pool of options an operator or\n// addon can assign to a profile slot.\n//\n// Two kinds:\n// - `pull-*`: the broker dials the URL (RTSP / RTMP / HTTP).\n// - `push-annexb`: the provider emits Annex-B packets. The broker\n// signals demand via `stream-broker.onCamStreamDemand` events so\n// push-capable cams (e.g. Reolink Baichuan) only wake when a\n// profile is actively consuming them.\n\nexport const CamStreamKindSchema = z.enum([\n 'pull-rtsp',\n 'pull-rtmp',\n 'pull-http',\n 'pull-rfc4571',\n 'push-annexb',\n])\nexport type CamStreamKind = z.infer<typeof CamStreamKindSchema>\n\nexport const CamStreamResolutionSchema = z.object({\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n})\n\nexport const CameraStreamSchema = z.object({\n /** Stable, provider-assigned id unique within the (deviceId) scope. */\n camStreamId: z.string().min(1),\n deviceId: z.number().int().nonnegative(),\n kind: CamStreamKindSchema,\n /** Required for pull-* kinds. Ignored for push-annexb. */\n url: z.string().optional(),\n codec: z.string().optional(),\n resolution: CamStreamResolutionSchema.optional(),\n fps: z.number().positive().optional(),\n /** Human label surfaced in the Admin UI \"Camera Stream\" dropdown. */\n label: z.string().optional(),\n /**\n * Device-level features the publisher advertised (e.g. `battery-operated`).\n * The broker, snapshot orchestrator, and prebuffer manager all consult\n * this list to derive policy — relaxed stall watchdog for battery\n * cams, prebuffer off by default, longer snapshot rate-limit, etc.\n *\n * Single source of truth replacing per-stream flags like the\n * historical `allowStall`: if the publisher knows the camera is\n * battery-powered, every downstream service derives the right policy\n * from this list.\n */\n deviceFeatures: z.array(z.string()).optional(),\n /**\n * Whether this stream participates in the broker's automatic profile\n * assignment (`computeInitialAssignment`). Defaults to `true`. Publishers\n * use `false` when they want a stream to be SELECTABLE in the UI but not\n * picked by default — e.g. Reolink publishes its native Baichuan streams\n * as `autoEligible: true` (the recommended path) and its RTSP / RTMP\n * mirrors as `autoEligible: false` (still pickable per slot, just not\n * the auto choice). Manual `assignProfile` calls remain valid for\n * non-eligible streams.\n */\n autoEligible: z.boolean().optional(),\n /**\n * Transport-specific opaque metadata. The broker passes it through to\n * the source reader without inspecting it. Currently used by\n * `pull-rfc4571` streams to carry the upstream SDP (so the reader can\n * route RTP packets to the right depacketizer without an in-band\n * DESCRIBE phase). Other kinds typically leave it undefined.\n */\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\nexport type CameraStream = z.infer<typeof CameraStreamSchema>\n\n// ── Profile slot view ────────────────────────────────────────────────\n//\n// Returned by the broker's `listAllProfileSlots` / the device-scoped\n// `camera-streams.getBrokerStreams`. Describes one of the up-to-3\n// system profile slots for a device: which cam stream is its source,\n// runtime status, and public addressing info.\n\nexport const ProfileSlotStatusSchema = z.enum([\n 'unassigned',\n 'idle',\n 'connecting',\n 'streaming',\n 'error',\n])\nexport type ProfileSlotStatus = z.infer<typeof ProfileSlotStatusSchema>\n\nexport const ProfileSlotSchema = z.object({\n deviceId: z.number().int().nonnegative(),\n profile: CamProfileSchema,\n /** Broker id the rest of the system addresses: `${deviceId}/${profile}`. */\n brokerId: z.string(),\n /** `null` when the profile is unassigned. */\n sourceCamStreamId: z.string().nullable(),\n status: ProfileSlotStatusSchema,\n resolution: CamStreamResolutionSchema.optional(),\n codec: z.string().optional(),\n preBufferSec: z.number().nonnegative().optional(),\n errorMessage: z.string().optional(),\n})\nexport type ProfileSlot = z.infer<typeof ProfileSlotSchema>\n\n/**\n * Zod schema for StreamSourceEntry — the canonical stream descriptor\n * exposed by ICameraDevice.getStreamSources() and consumed by the broker.\n */\nexport const StreamSourceEntrySchema = z.object({\n id: z.string(),\n label: z.string(),\n protocol: z.enum(['rtsp', 'rtmp', 'annexb', 'http-mjpeg', 'webrtc', 'custom']),\n url: z.string().optional(),\n resolution: z.object({ width: z.number(), height: z.number() }).readonly().optional(),\n fps: z.number().optional(),\n bitrate: z.number().optional(),\n codec: z.string().optional(),\n profileHint: z.enum(['high', 'mid', 'low']).optional(),\n})\n\nexport const StreamSourceSchema = z.object({\n type: z.string(),\n url: z.string(),\n videoCodec: z.string().optional(),\n audioCodec: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).readonly().optional(),\n})\n\nexport const EncodedPacketSchema = z.object({\n type: z.enum(['video', 'audio']),\n data: z.instanceof(Uint8Array),\n pts: z.number(),\n dts: z.number(),\n keyframe: z.boolean(),\n codec: z.string(),\n})\n\nexport const DecodedFrameSchema = z.object({\n data: z.instanceof(Uint8Array),\n width: z.number(),\n height: z.number(),\n format: z.enum(['jpeg', 'rgb', 'bgr', 'yuv420', 'gray']),\n timestamp: z.number(),\n})\n\nexport const BrokerStatusSchema = z.enum(['idle', 'connecting', 'streaming', 'error', 'stopped'])\n\nexport const BrokerStatsSchema = z.object({\n status: BrokerStatusSchema,\n inputFps: z.number(),\n decodeFps: z.number(),\n encodedSubscribers: z.number(),\n decodedSubscribers: z.number(),\n uptimeMs: z.number(),\n bitrateKbps: z.number(),\n idrIntervalMs: z.number(),\n codec: z.string().optional(),\n totalBytes: z.number(),\n packetCount: z.number(),\n rtspClients: z.number(),\n pipeClients: z.number(),\n preBufferSec: z.number(),\n preBufferMs: z.number(),\n preBufferPackets: z.number(),\n /**\n * Moleculer node id of the decoder provider currently servicing this\n * stream's decoded subscribers. `null` until the deferred decoder is\n * created (no decoded clients yet, or codec not detected). Surfaces the\n * runtime decoder placement so the UI can show \"Decoder: <agent>\" without\n * a separate cap call per broker.\n */\n decoderNodeId: z.string().nullable(),\n /**\n * Detected audio track parameters from the RTSP DESCRIBE / SDP. `null`\n * when the stream has no audio track or the broker is in cold start.\n * `supported = false` means the codec was detected but the local\n * decoder pipeline cannot produce PCM chunks (e.g. AAC without the\n * AAC pipeline wired). Surfaced in the UI device-overview so operators\n * can pre-pick the audio-analysis model that matches the codec.\n */\n audio: z.object({\n codec: z.string(),\n sampleRate: z.number(),\n channels: z.number(),\n supported: z.boolean(),\n }).nullable().optional(),\n})\n\n","import { z } from 'zod'\nimport { method, event, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport {\n CameraStreamSchema, CamStreamKindSchema, CamStreamResolutionSchema,\n CamProfileSchema, ProfileSlotSchema, BrokerStatsSchema,\n} from './schemas/streaming-shared.js'\nimport { StreamFormatSchema } from './streaming-engine.cap.js'\nimport type { IStreamBroker } from '../interfaces/stream-broker.js'\n\n/**\n * Per-broker RTSP restream entry. The broker exposes the public RTSP\n * restream URL for every active profile slot — consumers read the URL\n * here instead of constructing it from broker internals.\n */\nconst RtspRestreamEntrySchema = z.object({\n brokerId: z.string(),\n url: z.string(),\n mutedUrl: z.string(),\n enabled: z.boolean(),\n})\n\n/**\n * Individual-client shapes for the `listClients` roster. One row per\n * consumer of the chosen broker slot (profile) — RTSP sessions,\n * decoded-frame subscribers, audio chunks.\n */\nexport const BrokerRtspClientSchema = z.object({\n sessionId: z.string(),\n remoteAddr: z.string(),\n playing: z.boolean(),\n muted: z.boolean(),\n connectedAt: z.number(),\n lastRtpAt: z.number(),\n bytesSent: z.number(),\n})\n\nexport const BrokerDecodedClientSchema = z.object({\n tag: z.string(),\n subscribedAt: z.number(),\n maxFps: z.number(),\n framesDelivered: z.number(),\n framesDropped: z.number(),\n})\n\nexport const BrokerAudioClientSchema = z.object({\n tag: z.string(),\n subscribedAt: z.number(),\n chunksDelivered: z.number(),\n})\n\nexport const BrokerClientsSchema = z.object({\n rtsp: z.array(BrokerRtspClientSchema).readonly(),\n decoded: z.array(BrokerDecodedClientSchema).readonly(),\n audio: z.array(BrokerAudioClientSchema).readonly(),\n pipeClients: z.number(),\n encodedSubscribers: z.number(),\n})\n\nexport type BrokerRtspClient = z.infer<typeof BrokerRtspClientSchema>\nexport type BrokerDecodedClient = z.infer<typeof BrokerDecodedClientSchema>\nexport type BrokerAudioClient = z.infer<typeof BrokerAudioClientSchema>\nexport type BrokerClients = z.infer<typeof BrokerClientsSchema>\n\n/**\n * Reason rendered by the broker's placeholder image while no live RTP\n * is flowing. Each value maps 1:1 to a pre-encoded H.264 keyframe in\n * `addon-stream-broker/.../placeholder-frames.ts`. Keep aligned with\n * `PlaceholderKind` over there — the union here is the public surface\n * (cap input + provider type) and is the single source of truth.\n */\nexport const PlaceholderReasonSchema = z.enum([\n 'reconnecting',\n 'sleeping',\n 'offline',\n 'disabled',\n 'waking',\n])\nexport type PlaceholderReason = z.infer<typeof PlaceholderReasonSchema>\n\n/**\n * Stream broker — system-wide singleton cap.\n *\n * Owns two registries per device:\n * - `cameraStreams`: the pool of physical streams published by device\n * providers (and potentially third-party addons, e.g. an RTMP\n * discovery addon). Ephemeral: each provider re-publishes in its\n * own `onInitialize`.\n * - `profileMap`: persistent operator-intent mapping\n * `{high?, mid?, low?} -> camStreamId`. Persisted in the broker's\n * own storage, not in `device.config`.\n *\n * Up to 3 brokers per device keyed `${deviceId}/${profile}`. Each\n * broker ingests from the URL of the cam stream currently assigned via\n * `profileMap[profile]`. Changing the assignment tears down the broker\n * and rebuilds it against the new source — stream id seen by consumers\n * never changes.\n *\n * Per-device reads (what's published, what's assigned) live on the\n * device-scoped `camera-streams` cap, surfaced via `fetchDevice()`. The\n * methods below are either mutations or system-wide dumps.\n */\nexport const streamBrokerCapability = {\n name: 'stream-broker',\n scope: 'system',\n mode: 'singleton',\n exposesDeviceSettings: true,\n methods: {\n // ── Cam stream lifecycle (publish / retract) ─────────────────────\n /**\n * Register a physical camera stream as an input option. Idempotent\n * for (deviceId, camStreamId) — re-publishing updates metadata\n * without disturbing profile assignments. The provider calls this\n * in `onInitialize` for each stream it offers. Third-party addons\n * may also publish (e.g. an RTMP discovery layer) — camstack has\n * no notion of \"owner\" beyond the (deviceId, camStreamId) key.\n */\n /* — see STREAM_BROKER_CAP_EVENTS below for cap-event category strings — */\n\n publishCameraStream: method(\n z.object({\n deviceId: z.number().int().nonnegative(),\n camStreamId: z.string().min(1),\n kind: CamStreamKindSchema,\n url: z.string().optional(),\n codec: z.string().optional(),\n resolution: CamStreamResolutionSchema.optional(),\n fps: z.number().positive().optional(),\n label: z.string().optional(),\n /**\n * Device-level features that the broker / manager / snapshot\n * orchestrator consult to derive per-stream policy (e.g.\n * `BatteryOperated` → relax stall watchdog, default pre-buffer\n * to off, raise snapshot rate-limit). Single source of truth —\n * publishers no longer set per-stream flags like `allowStall`.\n */\n deviceFeatures: z.array(z.string()).optional(),\n /**\n * Whether this stream participates in the broker's automatic\n * profile assignment. Defaults `true`. Publishers set `false` for\n * streams that should be SELECTABLE but not auto-picked — e.g.\n * Reolink publishes native Baichuan as eligible and RTSP/RTMP\n * mirrors as ineligible (still assignable manually via\n * `assignProfile`).\n */\n autoEligible: z.boolean().optional(),\n /**\n * Transport-specific opaque metadata stashed alongside the stream\n * record. `pull-rfc4571` publishers put the SDP here so the broker\n * reader can route packets without an in-band DESCRIBE phase.\n */\n metadata: z.record(z.string(), z.unknown()).optional(),\n }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n retractCameraStream: method(\n z.object({\n deviceId: z.number().int().nonnegative(),\n camStreamId: z.string().min(1),\n }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n // ── Profile assignment ───────────────────────────────────────────\n /**\n * Assign a cam stream to a profile slot. Tears down any existing\n * broker for that slot and rebuilds against the new source. Persists\n * the choice — survives reboots.\n */\n assignProfile: method(\n z.object({\n deviceId: z.number().int().nonnegative(),\n profile: CamProfileSchema,\n camStreamId: z.string().min(1),\n }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n unassignProfile: method(\n z.object({\n deviceId: z.number().int().nonnegative(),\n profile: CamProfileSchema,\n }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n // ── System-wide views ────────────────────────────────────────────\n /**\n * Full dump of every published cam stream across every device.\n * For dashboards and cross-device tooling; per-device reads go\n * through the `camera-streams` cap on the device proxy.\n */\n listAllCameraStreams: method(\n z.void(),\n z.array(CameraStreamSchema).readonly(),\n ),\n listAllProfileSlots: method(\n z.void(),\n z.array(ProfileSlotSchema).readonly(),\n ),\n\n // ── Broker runtime (stats + client inventory) ────────────────────\n getBrokerStats: method(\n z.object({ brokerId: z.string() }),\n BrokerStatsSchema,\n ),\n listClients: method(\n z.object({ brokerId: z.string() }),\n BrokerClientsSchema,\n ),\n killClient: method(\n z.object({\n brokerId: z.string(),\n channel: z.enum(['rtsp', 'decoded', 'audio']),\n handle: z.string(),\n }),\n z.object({ killed: z.boolean() }),\n { kind: 'mutation', auth: 'admin' },\n ),\n /** Rebuild the broker for a profile slot in place (re-dial source). */\n restartProfile: method(\n z.object({\n deviceId: z.number().int().nonnegative(),\n profile: CamProfileSchema,\n }),\n z.object({ success: z.boolean() }),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n // ── Stream URLs ──────────────────────────────────────────────────\n getStreamUrl: method(\n z.object({ streamId: z.string(), format: StreamFormatSchema }),\n z.object({ url: z.string() }),\n ),\n\n // ── In-process broker access ─────────────────────────────────────\n /**\n * Return the live IStreamBroker instance for a given brokerId. Same\n * LOCAL-ONLY contract as before: callers (pipeline-runner) must be\n * co-located. BrokerId is `${deviceId}/${camStreamId}` — profile\n * lookup goes through `assignments` if a caller starts from a\n * profile.\n */\n getBroker: method(\n z.object({ brokerId: z.string() }),\n z.custom<IStreamBroker | null>(),\n ),\n\n // ── Pre-buffer ───────────────────────────────────────────────────\n setPreBufferDuration: method(\n z.object({ brokerId: z.string(), seconds: z.number().min(0).max(30) }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n getPreBufferInfo: method(\n z.object({ brokerId: z.string() }),\n z.object({ configuredSec: z.number(), bufferedMs: z.number(), packetCount: z.number() }),\n ),\n\n // ── RTSP restream ────────────────────────────────────────────────\n getRtspPort: method(z.void(), z.number()),\n getAllRtspEntries: method(\n z.object({ hostname: z.string().optional() }),\n z.array(RtspRestreamEntrySchema).readonly(),\n ),\n getRtspEntry: method(\n z.object({ brokerId: z.string(), hostname: z.string().optional() }),\n RtspRestreamEntrySchema.nullable(),\n ),\n regenerateRtspToken: method(\n z.object({ brokerId: z.string() }),\n z.string().nullable(),\n { kind: 'mutation', auth: 'admin' },\n ),\n setRtspEnabled: method(\n z.object({ brokerId: z.string(), enabled: z.boolean() }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n isRtspEnabled: method(\n z.object({ brokerId: z.string() }),\n z.boolean(),\n ),\n },\n events: {\n /**\n * Emitted when a profile starts consuming a push-kind cam stream.\n * Push-kind providers (e.g. Reolink Baichuan native streams)\n * subscribe and begin emitting packets only on demand — battery\n * cams stay asleep until someone actually watches.\n */\n onCamStreamDemand: event(z.object({\n deviceId: z.number().int().nonnegative(),\n camStreamId: z.string(),\n profile: CamProfileSchema,\n })),\n /**\n * Emitted when the last profile consuming a push-kind cam stream\n * releases it. Providers tear down upstream connections on this\n * signal.\n */\n onCamStreamIdle: event(z.object({\n deviceId: z.number().int().nonnegative(),\n camStreamId: z.string(),\n })),\n /**\n * Emitted by a broker that failed to dial a managed-loopback\n * source (today: `pull-rfc4571`). The publisher's transport (e.g.\n * the Reolink lib's RFC 4571 TCP server) idle-tears-down after\n * ~15s with no clients and may rebind to a different port on\n * recreate, leaving the URL the broker has cached stale. The owning\n * camera provider re-runs its publish pipeline on receipt — that\n * call self-heals the loopback server (`ensureRfc4571Server`) and\n * `publishCameraStream` propagates the fresh URL back into the\n * broker's source resolver.\n */\n onRequestStreamSourceRefresh: event(z.object({\n deviceId: z.number().int().nonnegative(),\n camStreamId: z.string(),\n brokerId: z.string(),\n })),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IStreamBrokerProvider = InferProvider<typeof streamBrokerCapability>\n\nexport { RtspRestreamEntrySchema }\n\n/* Cap event categories live in `EventCategory` enum\n * (`StreamBrokerOnCamStreamDemand`, `StreamBrokerOnCamStreamIdle`) so\n * subscribers/emitters share typed identifiers across the cluster. */\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\nconst StreamFormatSchema = z.enum(['webrtc', 'hls', 'mjpeg', 'rtsp'])\n\nconst StreamInfoSchema = z.object({\n streamId: z.string(),\n format: StreamFormatSchema,\n url: z.string().nullable(),\n active: z.boolean(),\n})\n\nexport const streamingEngineCapability = {\n name: 'streaming-engine',\n scope: 'system',\n mode: 'singleton',\n internal: true,\n methods: {\n registerStream: method(\n z.object({ streamId: z.string(), sourceUrl: z.string(), codec: z.string().optional() }),\n z.void(),\n { kind: 'mutation' },\n ),\n unregisterStream: method(z.object({ streamId: z.string() }), z.void(), { kind: 'mutation' }),\n getStreamUrl: method(\n z.object({ streamId: z.string(), format: StreamFormatSchema }),\n z.string().nullable(),\n ),\n listStreams: method(z.void(), z.array(StreamInfoSchema)),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IStreamingEngineProvider = InferProvider<typeof streamingEngineCapability>\n\nexport { StreamFormatSchema, StreamInfoSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider, type InferNativeProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * device-discovery — device-scoped capability for parents that host /\n * enumerate child devices (Reolink Hub / NVR, ONVIF gateway, future\n * integrations). Mirrors Scrypted's `DeviceDiscovery` interface\n * (`scrypted-reolink-native/src/nvr.ts:42-44`): the parent advertises\n * a list of discoverable children, and the operator promotes a subset\n * to real devices via `adoptDevice`. Child lifecycle (kernel device\n * create/remove, parent reference) is owned by the framework so a\n * single shared `<DiscoveryPanel />` can drive any integration.\n *\n * Boundaries:\n * - The cap exposes ENUMERATION + ADOPT/RELEASE only. The protocol\n * used to discover children (CGI poll, mDNS, push from hub, ...)\n * is the integration's business; results land in `runtimeState`\n * so the panel can render without a fresh round-trip.\n * - `childNativeId` is integration-defined and must be stable across\n * reboots so re-discovery doesn't duplicate adopted children.\n * - `adoptDevice` returns the new `deviceId` so the UI can navigate\n * directly to the freshly-created child's settings page.\n */\n\n/**\n * Status enum for a discovered device. Mirrors the Reolink simpleEvent\n * lifecycle (`online` / `sleeping` / `offline`) — generic enough for\n * battery cams, awake cams, and unreachable cams alike.\n */\nexport const DiscoveredChildStatusSchema = z.enum(['online', 'sleeping', 'offline', 'unknown'])\nexport type DiscoveredChildStatus = z.infer<typeof DiscoveredChildStatusSchema>\n\n/**\n * Single discovered child entry. `metadata` is integration-defined\n * but intentionally typed as a closed shape with the most-common\n * camera knobs — keeps the panel renderer dumb without forcing every\n * integration to invent a custom UI.\n */\nexport const DiscoveredChildDeviceSchema = z.object({\n /** Stable, integration-defined identifier. Mirrors Scrypted's `nativeId`. */\n childNativeId: z.string(),\n /** Friendly name as reported by the source (Reolink camera name, ONVIF profile, ...). */\n name: z.string(),\n /** DeviceType the child should be created with on adopt. */\n type: z.enum(DeviceType),\n status: DiscoveredChildStatusSchema,\n /** Free-form integration-specific metadata surfaced in the panel. */\n metadata: z.object({\n model: z.string().optional(),\n serialNumber: z.string().optional(),\n uid: z.string().optional(),\n /** Reolink: 0-based channel index inside the parent NVR/Hub. */\n rtspChannel: z.number().int().nonnegative().optional(),\n isBattery: z.boolean().optional(),\n isDoorbell: z.boolean().optional(),\n isMultifocal: z.boolean().optional(),\n }).default({}),\n /**\n * `true` when the framework already created a child device for this\n * `childNativeId` under the current parent. The panel uses it to\n * gate the Add/Remove button and surface the existing `deviceId`.\n */\n alreadyAdopted: z.boolean(),\n /** When `alreadyAdopted=true`, the framework-assigned child device id. */\n adoptedDeviceId: z.number().int().nonnegative().nullable(),\n})\nexport type DiscoveredChildDevice = z.infer<typeof DiscoveredChildDeviceSchema>\n\n/**\n * Status block — populated by the integration after each\n * `refreshDiscovery` (or push-driven update). The runtime-state slice\n * is what the panel reads via the per-device proxy; `getStatus`\n * returns the same payload via the codegen'd auto-injection.\n */\nexport const DeviceDiscoveryStatusSchema = z.object({\n discovered: z.array(DiscoveredChildDeviceSchema),\n /** Wall-clock ms of the last successful enumeration. */\n lastDiscoveryAt: z.number().int().nonnegative().nullable(),\n /** Last error surfaced from the source (rendered as a banner). */\n lastError: z.string().nullable(),\n})\nexport type DeviceDiscoveryStatus = z.infer<typeof DeviceDiscoveryStatusSchema>\n\nexport const deviceDiscoveryCapability = {\n name: 'device-discovery',\n scope: 'device',\n mode: 'singleton',\n // Hub is the canonical parent. Other integrations (gateway-style)\n // can register against the cap by also targeting their root type.\n deviceTypes: [DeviceType.Hub],\n status: {\n schema: DeviceDiscoveryStatusSchema,\n kind: 'poll',\n },\n // Mirror status into the per-device runtime-state slice so the panel\n // hydrates from the kernel cache without a round-trip on every open.\n runtimeState: DeviceDiscoveryStatusSchema.extend({\n lastFetchedAt: z.number().int().nonnegative(),\n }),\n methods: {\n /**\n * Snapshot of the current `discovered` list. Returns the\n * runtime-state cache — call `refreshDiscovery` first if a\n * fresh round-trip to the source is required.\n */\n listDiscovered: method(\n z.object({ deviceId: z.number().int().nonnegative() }),\n z.array(DiscoveredChildDeviceSchema).readonly(),\n ),\n /**\n * Force the integration to re-enumerate and update the\n * runtime-state slice. Returns the freshly-enumerated list (also\n * available via `listDiscovered` post-call).\n */\n refreshDiscovery: method(\n z.object({ deviceId: z.number().int().nonnegative() }),\n z.array(DiscoveredChildDeviceSchema).readonly(),\n { kind: 'mutation', auth: 'admin' },\n ),\n /**\n * Promote a discovered entry to a real child device. The framework\n * creates the child via `kernel.devices.create()` with\n * `parentDeviceId = parent.id` and seeds the child's config from\n * `childInitialConfig` (driver-defined; usually carries channel +\n * uid + parent reference). Returns the kernel-assigned numeric id.\n */\n adoptDevice: method(\n z.object({\n deviceId: z.number().int().nonnegative(),\n childNativeId: z.string(),\n /** Optional override for the child's display name. */\n name: z.string().optional(),\n }),\n z.object({\n deviceId: z.number().int().nonnegative(),\n stableId: z.string(),\n }),\n { kind: 'mutation', auth: 'admin' },\n ),\n /**\n * Inverse of `adoptDevice`: removes the child device from the\n * kernel registry. The discovered entry remains in the\n * enumeration (status updates resume) so the operator can re-adopt\n * it later without a fresh refresh.\n */\n releaseDevice: method(\n z.object({\n deviceId: z.number().int().nonnegative(),\n childDeviceId: z.number().int().nonnegative(),\n }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IDeviceDiscoveryProvider = InferProvider<typeof deviceDiscoveryCapability>\nexport type IDeviceDiscoveryNativeProvider = InferNativeProvider<typeof deviceDiscoveryCapability>\n","import { z } from 'zod'\nimport { type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * Doorbell button cap. Installed on a `DeviceType.Button` accessory\n * with `role: DeviceRole.Doorbell`. Emits an `onPressed` event every\n * time the firmware pushes a ring; status tracks the last press and\n * a pressCount since start (diagnostic).\n *\n * The DeviceEventPropagator re-emits `onPressed` on the camera parent\n * — subscribers listening at the camera level receive ring events\n * with `via[]` populated. No code on the parent needed.\n */\nexport const DoorbellStatusSchema = z.object({\n /** Ms epoch of the last press. null = never observed since this provider started. */\n lastPressedAt: z.number().nullable(),\n /** Counter since provider start. Resets on reboot. Useful for metrics/debug. */\n pressCountSinceStart: z.number(),\n})\n\nexport type DoorbellStatus = z.infer<typeof DoorbellStatusSchema>\n\nexport const DoorbellPressEventSchema = z.object({\n deviceId: z.number(),\n timestamp: z.number(),\n})\n\nexport type DoorbellPressEvent = z.infer<typeof DoorbellPressEventSchema>\n\nexport const doorbellCapability = {\n name: 'doorbell',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Button],\n methods: {},\n events: {\n /**\n * Fires once per physical press. Reolink delivers via Baichuan\n * push (`ReolinkSimpleEvent.type === 'doorbell'`). There is no\n * release/duration — it's a pulse.\n */\n onPressed: { data: DoorbellPressEventSchema },\n },\n status: {\n schema: DoorbellStatusSchema,\n kind: 'push',\n },\n /**\n * Runtime-state slice — last press timestamp + lifetime press count.\n * Mirrored by the kernel and readable via\n * `device.state.doorbell.value`. UIs can show \"last ring 5m ago\"\n * without subscribing.\n */\n runtimeState: DoorbellStatusSchema,\n} as const satisfies CapabilityDefinition\n\nexport type IDoorbellProvider = InferProvider<typeof doorbellCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\nimport { MotionRegionSchema } from './motion-detection.cap.js'\nimport { MotionSourceEnum } from './pipeline-runner.cap.js'\n\n/**\n * Hardware / firmware motion sensor cap — binary detected state plus\n * a timestamp of the last observation. Distinct from\n * `motion-detection.cap.ts` which owns the LOCAL ML motion pipeline;\n * `motion` is the lightweight readout from on-camera motion (Reolink\n * `GetMdState`, Baichuan push `type: motion`, ONVIF analytics).\n *\n * Native-motion providers also fan out to `detection.camera-native`\n * with `source: 'onboard'` so cross-cutting system services\n * (alert-center, advanced-notifier) can subscribe once and receive\n * motion from every camera.\n */\nexport const MotionStatusSchema = z.object({\n detected: z.boolean(),\n /** Ms epoch of the last detected-true observation. Null if never detected. */\n lastDetectedAt: z.number().nullable(),\n /**\n * Ms after which `detected` auto-reverts to false if no fresh push\n * arrives. Mirrors the scrypted-reolink-native default. Null means\n * the provider leaves detected state until a native \"clear\" event.\n */\n autoClearAfterMs: z.number().nullable(),\n})\n\nexport type MotionStatus = z.infer<typeof MotionStatusSchema>\n\n/**\n * Payload of `motion.onMotionChanged` event + the corresponding bus\n * event `EventCategory.MotionOnMotionChanged`. Single source of truth\n * — both the cap event surface and the bus payload type alias to this\n * schema.\n */\nexport const MotionOnMotionChangedDataSchema = z.object({\n deviceId: z.number(),\n detected: z.boolean(),\n timestamp: z.number(),\n source: MotionSourceEnum,\n regions: z.array(MotionRegionSchema).readonly().optional(),\n})\nexport type MotionOnMotionChangedData = z.infer<typeof MotionOnMotionChangedDataSchema>\n\nexport const motionCapability = {\n name: 'motion',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera, DeviceType.Sensor],\n methods: {\n /**\n * Pull the current motion state synchronously. Convenience shortcut\n * for consumers that don't need the full status object; equivalent\n * to `getStatus()?.detected ?? false`. Will likely be folded into\n * `getStatus` once the auto-injected status surface lands in every\n * consumer.\n */\n isDetected: method(\n z.object({ deviceId: z.number() }),\n z.boolean(),\n ),\n },\n events: {\n /**\n * Fires every time the runner transitions a camera between\n * `watching` and `active` phases. `source` carries which motion\n * path drove the transition; `regions` is populated only for\n * `source: 'analyzer'` (frame-diff regions from the ML motion\n * detector) — onboard sources don't carry per-frame regions\n * here (camera-provided zones / AI metadata live in dedicated\n * channels: `detection.camera-native`, future zone capability).\n *\n * Consumers that want all motion pushes (even with `detected`\n * unchanged) should subscribe to the status subscription via\n * `device-manager.subscribeDeviceStatusAggregate` instead.\n */\n onMotionChanged: { data: MotionOnMotionChangedDataSchema },\n },\n status: {\n schema: MotionStatusSchema,\n kind: 'push',\n },\n /**\n * Runtime-state slice — the last observed motion snapshot, mirrored\n * by the kernel and readable cross-process via\n * `device.state.motion.value`. Reads never invoke the provider, so\n * UIs and other addons can poll the cached state safely.\n */\n runtimeState: MotionStatusSchema,\n} as const satisfies CapabilityDefinition\n\nexport type IMotionProvider = InferProvider<typeof motionCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { FrameInputSchema, BoundingBoxSchema } from './schemas/detection-shared.js'\n\nconst MotionRegionSchema = z.object({\n bbox: BoundingBoxSchema,\n pixelCount: z.number(),\n intensity: z.number(),\n})\n\nconst MotionAnalysisResultSchema = z.object({\n detected: z.boolean(),\n regionCount: z.number(),\n /** Regions passing minArea filter — used for pipeline triggering. */\n regions: z.array(MotionRegionSchema).readonly(),\n /** All raw regions from CCL before minArea filter — used for UI debug overlay. */\n rawRegions: z.array(MotionRegionSchema).readonly(),\n frameWidth: z.number(),\n frameHeight: z.number(),\n analysisMs: z.number(),\n})\n\nexport const motionDetectionCapability = {\n name: 'motion-detection',\n scope: 'device',\n mode: 'singleton',\n exposesDeviceSettings: true,\n methods: {\n analyze: method(\n z.object({ deviceId: z.number(), frame: FrameInputSchema }),\n MotionAnalysisResultSchema,\n { kind: 'mutation' },\n ),\n removeCamera: method(z.object({ deviceId: z.number() }), z.void(), { kind: 'mutation' }),\n reset: method(z.void(), z.void(), { kind: 'mutation' }),\n },\n events: {\n onMotion: { data: z.object({\n deviceId: z.number(),\n detected: z.boolean(),\n regionCount: z.number(),\n })},\n },\n} as const satisfies CapabilityDefinition\n\nexport type IMotionDetectionProvider = InferProvider<typeof motionDetectionCapability>\nexport type MotionRegion = z.infer<typeof MotionRegionSchema>\nexport type MotionAnalysisResult = z.infer<typeof MotionAnalysisResultSchema>\n\nexport { MotionRegionSchema, MotionAnalysisResultSchema }\n","/** Shared Zod schemas used across detection capabilities. */\n\nimport { z } from 'zod'\n\n/**\n * Canonical frame-format enum mirrored on `FrameFormat` in\n * `packages/types/src/types/io.ts`. Kept inline (vs imported) so the\n * Zod runtime schema and TypeScript type stay in sync at the call site\n * — adding a new format requires changing both this enum and the\n * `FrameFormat` type alias together.\n */\nexport const FrameFormatSchema = z.enum(['jpeg', 'rgb', 'bgr', 'yuv420', 'gray'])\n\nexport const FrameInputSchema = z.object({\n data: z.custom<Uint8Array>(),\n format: FrameFormatSchema,\n width: z.number(),\n height: z.number(),\n timestamp: z.number(),\n})\n\nexport const BoundingBoxSchema = z.object({\n x: z.number(),\n y: z.number(),\n w: z.number(),\n h: z.number(),\n})\n\nexport const SpatialDetectionSchema = z.object({\n class: z.string(),\n originalClass: z.string(),\n score: z.number(),\n bbox: BoundingBoxSchema,\n})\n\nexport const AudioChunkInputSchema = z.object({\n data: z.instanceof(Float32Array),\n sampleRate: z.number(),\n channels: z.number(),\n timestamp: z.number(),\n /** Originating device id — used by the classifier for per-camera concurrency tracking. */\n deviceId: z.number().optional(),\n})\n\nexport const AudioLevelSchema = z.object({\n rms: z.number(),\n dbfs: z.number(),\n})\n\nexport const AudioClassificationLabelSchema = z.object({\n /**\n * Primary display class. Depending on how the label was produced\n * this is either the macro category (e.g. `dog`) or the raw\n * backend label (e.g. `Dog bark`). Mirrors `class` on\n * `SpatialDetection`.\n */\n className: z.string(),\n /**\n * Raw backend-native label the classifier actually emitted (e.g.\n * `Dog bark` for YAMNet, `dog_bark` for Apple SoundAnalysis). For\n * macro-aggregated entries this is the top raw contributor. Mirrors\n * `originalClass` on `SpatialDetection`.\n */\n originalClass: z.string().optional(),\n score: z.number(),\n})\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { CameraMetricsSchema, CameraMetricsWithDeviceIdSchema } from './schemas/orchestrator-metrics.js'\nimport { PipelineEngineChoiceSchema, PipelineStepInputSchema } from './pipeline-executor.cap.js'\nimport { MotionRegionSchema } from './motion-detection.cap.js'\nimport { ZoneSchema } from './zones.cap.js'\nimport type { ConfigField } from '../interfaces/config-ui.js'\n\n/**\n * Per-camera tunable ranges + defaults. Single source of truth used\n * by both the Zod data schema (validation + default fallback) and\n * the device settings UI (slider min/max/step). Touch one place and\n * both sides stay aligned.\n */\nconst motionCooldownMsField = { min: 0, max: 60_000, default: 30_000, step: 500 } as const\nconst motionFpsField = { min: 1, max: 30, default: 4, step: 1 } as const\nconst detectionFpsField = { min: 1, max: 30, default: 10, step: 1 } as const\n\n/**\n * Source enum for motion signals fed to the runner. Extensible — add\n * new variants here when new motion-trigger paths are wired in\n * (`wasm-cross-camera`, `event-bus-relay`, etc.). The runner uses\n * the variant for diagnostics + to route the cap-state event payload\n * (analyzer attaches detected `regions[]`; onboard does not — the\n * camera typically only reports a binary signal plus an optional\n * channel/AI class which lives in dedicated event channels).\n */\nexport const MotionSourceEnum = z.enum(['onboard', 'analyzer'])\nexport type MotionSource = z.infer<typeof MotionSourceEnum>\n\n/**\n * List of motion sources active on a camera. Empty array is valid:\n * \"no source\" — happens for battery cams without firmware motion when\n * the operator hasn't opted into the SW analyzer (would hold the\n * substream open continuously and defeat the sleep cycle). The runner\n * accepts the empty list as \"no motion-driven phase transitions\" and\n * relies on the operator-set `detectionMode` to drive activation\n * (`'always-on'`) — `'on-motion'` with no source effectively pins the\n * phase to `'watching'`, which is the desired battery-cam-without-\n * firmware behaviour.\n *\n * Single source of truth for the array shape — every consumer\n * (orchestrator, runner, settings UI, dispatch) imports from here.\n */\nexport const MotionSourcesSchema = z.array(MotionSourceEnum)\nexport type MotionSources = z.infer<typeof MotionSourcesSchema>\n\n/**\n * Input shape for `pipeline-runner.reportMotion` cap method. Exported\n * so cap-side consumers (the orchestrator forward, the runner addon's\n * cap implementation, tests) can reuse the type instead of redeclaring\n * the field set.\n */\nexport const ReportMotionInputSchema = z.object({\n deviceId: z.number(),\n detected: z.boolean(),\n source: MotionSourceEnum.default('analyzer'),\n regions: z.array(MotionRegionSchema).readonly().optional(),\n})\nexport type ReportMotionInput = z.infer<typeof ReportMotionInputSchema>\n\n/**\n * Camera assignment payload sent by `addon-pipeline-orchestrator` to a\n * specific runner instance via `attachCamera`. Carries everything the\n * runner needs to subscribe to the local broker and execute inference.\n *\n * Stateless-pipeline model: the full pipeline content (`engine`, `steps`,\n * optional `audio`) travels with the attach payload. The runner keeps it\n * in RAM for the lifetime of the attach — on rebalance, edit, or\n * restart the orchestrator re-sends the latest snapshot.\n *\n * `engine`/`steps`/`audio` are optional during the additive migration\n * window; once orchestrator + UI are migrated they become required.\n */\nconst RunnerCameraConfigSchema = z.object({\n deviceId: z.number(),\n /**\n * Operator-facing scheduling mode for the SW object detection\n * pipeline. Replaces the legacy 2-state `priority` toggle.\n *\n * - `'disabled'` — runner never subscribes to the substream for\n * detection; phase stays idle. Bindings stay\n * bound; this is the runtime-level off switch.\n * - `'always-on'` — phase starts in `'active'` and never falls\n * back to `'watching'`.\n * - `'on-motion'` — phase starts in `'watching'`; transitions to\n * `'active'` when a motion source fires; falls\n * back to `'watching'` after `motionCooldownMs`.\n */\n detectionMode: z.enum(['disabled', 'always-on', 'on-motion']).default('on-motion'),\n /** Audio scheduling mode — same values as `detectionMode`. The\n * audio-analyzer addon reads this to decide whether to subscribe\n * to the audio decoded stream. */\n audioMode: z.enum(['disabled', 'always-on', 'on-motion']).default('always-on'),\n motionCooldownMs: z.number().min(motionCooldownMsField.min).default(motionCooldownMsField.default),\n motionFps: z.number().min(motionFpsField.min).max(motionFpsField.max).default(motionFpsField.default),\n detectionFps: z.number().min(detectionFpsField.min).max(detectionFpsField.max).default(detectionFpsField.default),\n motionStreamId: z.string(),\n detectionStreamId: z.string(),\n /**\n * Motion sources that can activate the pipeline. At least one must\n * be present. Multiple sources OR-ed: any one firing arms the\n * cooldown timer and transitions watching → active. The same\n * `motionCooldownMs` applies to whichever source(s) fire — the\n * timer rearms on every `reportMotion(true)` and expires after the\n * window, returning the runner to `watching`.\n *\n * - `analyzer`: ML/frame-diff motion detection (motion-wasm or other\n * analyzer providers) running on decoded frames in this runner.\n * - `onboard`: camera-native motion pushes (Reolink Baichuan, ONVIF\n * analytics, Frigate motion). The provider emits ProviderMotion\n * events; the orchestrator forwards to `reportMotion`.\n */\n motionSources: MotionSourcesSchema.default(['analyzer']),\n pipelineEnabled: z.boolean().default(true),\n // ── Stateless-pipeline: content carried with the attach ───────────\n /** Engine choice for video steps (runtime+backend+format). */\n engine: PipelineEngineChoiceSchema.optional(),\n /** Ordered tree of video steps. Absent → runner skips video detection. */\n steps: z.array(PipelineStepInputSchema).readonly().optional(),\n /** Audio classification branch. `enabled:false` disables, null skips. */\n audio: z.object({\n engine: PipelineEngineChoiceSchema,\n modelId: z.string(),\n enabled: z.boolean(),\n }).nullable().optional(),\n /**\n * Per-camera detection zones (user + onboard) snapshot at dispatch\n * time. Forwarded so motion-wasm + pipeline-executor running on the\n * runner can apply include/exclude/monitor logic without an extra\n * round-trip to the hub. The orchestrator re-dispatches the camera\n * whenever its `zones` device-state slice changes, so the runner's\n * copy stays in sync. Empty array → no zone filtering.\n */\n zones: z.array(ZoneSchema).readonly().default([]),\n})\n\n/**\n * Per-device settings UI fields the runner cap owns. Co-located with\n * the Zod data schema so a single change to defaults / ranges /\n * options propagates to both the wire contract AND the rendered UI.\n *\n * Consumers spread this into their own ConfigUISchema sections\n * (e.g. orchestrator's deviceSettingsSchema) instead of redeclaring\n * the fields. The ranges are read from the `*Field` constants above\n * so values stay in sync with `RunnerCameraConfigSchema`.\n *\n * Fields NOT included here are intentional — they're either internal\n * wire (motionStreamId, detectionStreamId) or live in a different\n * config surface (priority, motionStreamProfile/detectionStreamProfile\n * — the orchestrator transforms them into stream IDs before dispatch).\n */\nexport const RunnerCameraDeviceUIFields: readonly ConfigField[] = [\n {\n key: 'motionSources',\n type: 'multiselect',\n label: 'Motion Sources',\n default: ['analyzer'],\n options: [\n { value: 'analyzer', label: 'Frame-diff Analyzer (motion addon)' },\n { value: 'onboard', label: 'Camera Onboard Sensor' },\n ],\n },\n // Analyzer-only knobs — gated on `motionSources` containing the\n // `analyzer` (frame-diff) source. When the operator picks\n // `onboard`-only (camera-native VMD), running an analyzer pipeline\n // would burn CPU for no signal, so we hide the FPS / cooldown /\n // stream-profile tuning entirely. The dependent section header in\n // the orchestrator reads \"Frame-diff Analyzer\" → these fields\n // disappear together when the source isn't selected.\n {\n key: 'motionFps',\n type: 'slider',\n label: 'Motion FPS (analyzer)',\n min: motionFpsField.min,\n max: motionFpsField.max,\n step: motionFpsField.step,\n default: motionFpsField.default,\n showValue: true,\n unit: 'fps',\n showWhen: { field: 'motionSources', includes: 'analyzer' },\n },\n {\n key: 'detectionFps',\n type: 'slider',\n label: 'Detection FPS',\n min: detectionFpsField.min,\n max: detectionFpsField.max,\n step: detectionFpsField.step,\n default: detectionFpsField.default,\n showValue: true,\n unit: 'fps',\n },\n // Motion cooldown applies to BOTH analyzer and onboard sources —\n // every reportMotion(true) re-arms the cooldown regardless of the\n // emitting source, so the operator must be able to tune it for\n // onboard-only cameras too. Without this the field silently\n // disappeared when the user picked \"Camera Onboard Sensor\" only.\n {\n key: 'motionCooldownMs',\n type: 'slider',\n label: 'Motion Cooldown',\n description: 'Time without a fresh motion event before the active phase ends. Applies to all motion sources — every motion event re-arms the timer.',\n min: motionCooldownMsField.min,\n max: motionCooldownMsField.max,\n step: motionCooldownMsField.step,\n default: motionCooldownMsField.default,\n showValue: true,\n unit: 's',\n displayScale: 1000,\n },\n] as const\n\n/**\n * Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's\n * load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide\n * which agent should receive a new camera assignment.\n */\nconst RunnerLocalLoadSchema = z.object({\n /** Moleculer node id of this runner instance. */\n nodeId: z.string(),\n /** Total cameras currently attached (regardless of phase). */\n attachedCameras: z.number(),\n /** Cameras currently in `active` phase (running detection inference). */\n activeCameras: z.number(),\n /** Average inference FPS across all attached cameras. */\n avgInferenceFps: z.number(),\n /** Average inference latency in ms across all attached cameras. */\n avgInferenceTimeMs: z.number(),\n /** Total queue depth across motion + detection queues. */\n queueDepthTotal: z.number(),\n /** Hardware capability flags reported by this node. */\n hardware: z.object({\n hasGpu: z.boolean(),\n inferenceBackend: z.string().optional(),\n cpuCores: z.number().optional(),\n }),\n})\n\n/**\n * Aggregate runtime metrics for the runner's whole local pool. Mirrors the\n * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep\n * working unchanged when they switch to reading from the runner cap.\n */\nconst RunnerLocalMetricsSchema = z.object({\n nodeId: z.string(),\n activeCameras: z.number(),\n throttledCameras: z.number(),\n avgInferenceTimeMs: z.number(),\n queueDepth: z.number(),\n})\n\n/**\n * Pipeline Runner capability — runtime detection workhorse.\n *\n * One instance per node. Receives camera assignments from\n * `addon-pipeline-orchestrator`, subscribes to the local stream-broker for\n * decoded frames, drains motion + detection queues, calls the local\n * `motion-detection` and `pipeline-executor` capabilities, and emits typed\n * `pipeline.inference-result` and `detection.motion-analysis` events on\n * the bus.\n *\n * Distinct from `pipeline-orchestrator` (the hub-side load balancer) — the\n * runner has zero knowledge of other agents, no global state, and never\n * makes assignment decisions itself.\n */\nexport const pipelineRunnerCapability = {\n name: 'pipeline-runner',\n scope: 'system',\n mode: 'singleton',\n methods: {\n // ── Camera lifecycle (called by orchestrator) ────────────────────\n /** Attach a camera to this runner. Subscribes to local broker. */\n attachCamera: method(RunnerCameraConfigSchema, z.object({ success: z.literal(true) }), { kind: 'mutation' }),\n /** Detach a camera. Unsubscribes from local broker, clears queues. */\n detachCamera: method(z.object({ deviceId: z.number() }), z.object({ success: z.literal(true) }), { kind: 'mutation' }),\n /**\n * Report an external motion event for a camera. Drives the runner's\n * phase machine: every `detected: true` clears + rearms the\n * cooldown timer (`motionCooldownMs`); when the timer expires the\n * camera returns to `watching`. `detected: false` is a no-op —\n * onboard sources never send an explicit clear, the timer is the\n * single closure path.\n *\n * `source` discriminates which motion path triggered the event so\n * the runner can attach the right metadata to the cap-state event\n * (analyzer carries `regions[]`, onboard does not). `regions` is\n * populated only for `source: 'analyzer'` — the analyzer's\n * frame-diff result. Always-on cameras silently ignore\n * reportMotion calls.\n */\n reportMotion: method(\n ReportMotionInputSchema,\n z.object({ success: z.literal(true) }),\n { kind: 'mutation' },\n ),\n\n // ── Observability (called by orchestrator + dashboards) ──────────\n /** Return load summary used by the orchestrator's load balancer. */\n getLocalLoad: method(z.void(), RunnerLocalLoadSchema),\n /** Return aggregate runtime metrics for this runner instance. */\n getLocalMetrics: method(z.void(), RunnerLocalMetricsSchema),\n /** Per-camera metrics for cameras attached to this runner. */\n getCameraMetrics: method(z.object({ deviceId: z.number() }), CameraMetricsSchema.nullable()),\n /** All per-camera metrics in one round-trip. */\n getAllCameraMetrics: method(z.void(), z.array(CameraMetricsWithDeviceIdSchema).readonly()),\n /** List the deviceIds currently attached to this runner. */\n getLocalCameras: method(z.void(), z.array(z.number()).readonly()),\n\n // NOTE: Phase 6 (settings redesign) removed `getTuning` / `setTuning`.\n // The four tuning fields are now exposed via the addon-level settings\n // API (`pipeline-runner.getAddonSettings / updateAddonSettings`) and\n // rendered in the admin UI via `NodeAddonsSettingsPanel` instead of\n // the dedicated `NodeTuningTab` that used to call these cap methods.\n },\n} as const satisfies CapabilityDefinition\n\nexport type IPipelineRunnerProvider = InferProvider<typeof pipelineRunnerCapability>\n\nexport { RunnerCameraConfigSchema, RunnerLocalLoadSchema, RunnerLocalMetricsSchema }\n","/** Shared Zod schemas for the runtime pipeline orchestrator metrics. */\n\nimport { z } from 'zod'\n\nexport const OrchestratorMetricsSchema = z.object({\n activeCameras: z.number(),\n throttledCameras: z.number(),\n avgInferenceTimeMs: z.number(),\n queueDepth: z.number(),\n})\n\nexport const CameraMetricsSchema = z.object({\n detectionMode: z.enum(['disabled', 'always-on', 'on-motion']),\n configuredFps: z.number(),\n actualFps: z.number(),\n queueDepth: z.number(),\n avgInferenceTimeMs: z.number(),\n droppedFrames: z.number(),\n phase: z.enum(['idle', 'watching', 'active']),\n})\n\nexport const CameraMetricsWithDeviceIdSchema = CameraMetricsSchema.extend({\n deviceId: z.number(),\n})\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { FrameInputSchema, SpatialDetectionSchema } from './schemas/detection-shared.js'\nimport type { ConfigUISchema, ConfigField } from '../interfaces/config-ui.js'\nimport type { InferenceCapabilities, ModelAvailability } from '../interfaces/inference-capabilities.js'\nimport type { PipelineConfig } from '../types/pipeline.js'\nimport type { FrameResult, AudioResult } from '../types/detection.js'\n\n// ── Engine & device ──────────────────────────────────────────────\nconst ModelFormatSchema = z.enum(['onnx', 'coreml', 'openvino', 'tflite', 'pt'])\nconst PipelineSlotSchema = z.enum(['detector', 'cropper', 'classifier', 'refiner', 'audio-classifier'])\n\nconst PipelineEngineChoiceSchema = z.object({\n runtime: z.enum(['node', 'python']),\n backend: z.string(),\n format: ModelFormatSchema,\n device: z.string().optional(),\n})\n\nconst EngineDeviceInfoSchema = z.object({\n id: z.string(),\n label: z.string(),\n description: z.string().optional(),\n})\n\nconst AvailableEngineSchema = z.object({\n engine: PipelineEngineChoiceSchema,\n devices: z.array(EngineDeviceInfoSchema).readonly(),\n defaultDevice: z.string(),\n})\n\n// ── Pipeline step (recursive) ──\n// Zod v4's `ZodType` is invariant over its `Input`/`Output` generics, so the\n// canonical `z.lazy()` recursive pattern does not type-check cleanly against\n// the full `PipelineDefaultStep` TS interface. Use a zod-inferred type\n// instead — the resulting shape is structurally identical and still fully\n// typed for callers via `z.infer<typeof PipelineDefaultStepSchema>`.\n// Phase 7 (settings redesign): removed generic `confidence: number` field.\n// Each step declares its own thresholds via `configSchema` and persists\n// them inside `settings`. The runtime executor reads\n// `StepDefinition.defaultConfidence` from the step registry as the\n// hard-coded fallback threshold.\nexport type PipelineDefaultStepOutput = {\n readonly addonId: string\n readonly addonName: string\n readonly slot: 'detector' | 'cropper' | 'classifier' | 'refiner' | 'audio-classifier'\n readonly inputClasses: readonly string[]\n readonly outputClasses: readonly string[]\n readonly enabled: boolean\n readonly modelId: string\n readonly children: readonly PipelineDefaultStepOutput[]\n readonly engine?: {\n readonly runtime: 'node' | 'python'\n readonly backend: string\n readonly format: 'onnx' | 'coreml' | 'openvino' | 'tflite' | 'pt'\n readonly device?: string\n }\n readonly group?: string\n readonly settings?: Readonly<Record<string, unknown>>\n}\n\nconst PipelineDefaultStepSchema: z.ZodType<PipelineDefaultStepOutput> = z.lazy(() =>\n z.object({\n addonId: z.string(),\n addonName: z.string(),\n slot: PipelineSlotSchema,\n inputClasses: z.array(z.string()).readonly(),\n outputClasses: z.array(z.string()).readonly(),\n enabled: z.boolean(),\n modelId: z.string(),\n children: z.array(PipelineDefaultStepSchema).readonly(),\n engine: PipelineEngineChoiceSchema.optional(),\n group: z.string().optional(),\n settings: z.record(z.string(), z.unknown()).optional(),\n }),\n)\n\n// ── PipelineTemplate step (recursive) ──\n// Phase 7: same reasoning as `PipelineDefaultStepOutput` — no generic\n// `confidence` field. Templates created before Phase 7 are migrated on\n// load by `provider.ts::loadTemplates` which strips the obsolete key.\nexport type PipelineTemplateStepOutput = {\n readonly addonId: string\n readonly enabled: boolean\n readonly modelId: string\n readonly children: readonly PipelineTemplateStepOutput[]\n readonly settings?: Readonly<Record<string, unknown>>\n}\n\nconst PipelineTemplateStepSchema: z.ZodType<PipelineTemplateStepOutput> = z.lazy(() =>\n z.object({\n addonId: z.string(),\n enabled: z.boolean(),\n modelId: z.string(),\n children: z.array(PipelineTemplateStepSchema).readonly(),\n settings: z.record(z.string(), z.unknown()).optional(),\n }),\n)\n\nconst PipelineTemplateSchema = z.object({\n id: z.string(),\n name: z.string(),\n createdAt: z.string(),\n updatedAt: z.string(),\n engine: PipelineEngineChoiceSchema,\n steps: z.array(PipelineTemplateStepSchema).readonly(),\n})\n\n// ── PipelineSchema (returned by getSchema) ──\nconst PipelineModelOptionSchema = z.object({\n id: z.string(),\n name: z.string(),\n formats: z.record(\n z.string(),\n z.object({ downloaded: z.boolean(), sizeMB: z.number() }),\n ),\n})\n\nconst ConfigFieldBridge = z.custom<ConfigField>()\n\nconst PipelineAddonSchemaSchema = z.object({\n id: z.string(),\n name: z.string(),\n slot: PipelineSlotSchema,\n inputClasses: z.array(z.string()).readonly(),\n outputClasses: z.array(z.string()).readonly(),\n childSlots: z.array(PipelineSlotSchema).readonly(),\n models: z.array(PipelineModelOptionSchema).readonly(),\n defaultModelId: z.string(),\n // Per-format model override. Lets an addon declare \"on `coreml` prefer\n // apple-soundanalysis, on `onnx` prefer yamnet-onnx\". The orchestrator's\n // agent-seed routine uses this to pick a modelId that matches the\n // agent's active engine format.\n defaultModelIdByFormat: z.record(z.string(), z.string()).optional(),\n // Whether a freshly-seeded agent starts with this addon `enabled: true`.\n // Absent = true. Operator-controlled after first seed.\n enabledByDefault: z.boolean().optional(),\n defaultConfidence: z.number(),\n group: z.string().optional(),\n configSchema: z.array(ConfigFieldBridge).readonly().optional(),\n})\n\nconst PipelineSlotSchemaSchema = z.object({\n id: PipelineSlotSchema,\n label: z.string(),\n priority: z.number(),\n parentSlot: PipelineSlotSchema.nullable(),\n addons: z.array(PipelineAddonSchemaSchema).readonly(),\n})\n\nconst PipelineSchemaSchema = z.object({\n availableEngines: z.array(AvailableEngineSchema).readonly(),\n selectedEngine: PipelineEngineChoiceSchema,\n slots: z.array(PipelineSlotSchemaSchema).readonly(),\n})\n\n// ── Detection / inference ──\nconst DetectorOutputSchema = z.object({\n detections: z.array(SpatialDetectionSchema).readonly(),\n inferenceMs: z.number(),\n modelId: z.string(),\n})\n\n// ── Pipeline run input (UI-facing) ──\n// Phase 7: dropped generic `confidence`. Per-step thresholds live in\n// `settings` (each step declares its own field in `configSchema`); the\n// runtime executor falls back to `StepDefinition.defaultConfidence`\n// when settings don't override.\nexport type PipelineStepInputOutput = {\n readonly addonId: string\n readonly modelId: string\n readonly enabled: boolean\n readonly children?: readonly PipelineStepInputOutput[]\n readonly settings?: Readonly<Record<string, unknown>>\n}\n\nexport const PipelineStepInputSchema: z.ZodType<PipelineStepInputOutput> = z.lazy(() =>\n z.object({\n addonId: z.string(),\n modelId: z.string(),\n enabled: z.boolean().default(true),\n children: z.array(PipelineStepInputSchema).optional(),\n settings: z.record(z.string(), z.unknown()).optional(),\n }),\n)\n\n// ── Reference media ──\nconst ReferenceImageEntrySchema = z.object({\n filename: z.string(),\n stepIds: z.array(z.string()).readonly().optional(),\n})\n\nconst ReferenceImageBodySchema = z.object({\n base64: z.string(),\n filename: z.string(),\n})\n\nconst ReferenceAudioEntrySchema = z.object({\n filename: z.string(),\n sizeKb: z.number(),\n})\n\nconst ReferenceAudioBodySchema = z.object({\n base64: z.string(),\n})\n\n// Benchmark schemas (BenchmarkInputSchema, BenchmarkResultSchema,\n// BenchmarkHistoryEntrySchema, BenchmarkHistoryEntryInputSchema,\n// BenchmarkLatencyStatsSchema, PipelineRunInputSchema) moved to\n// `@camstack/addon-benchmark/src/benchmark-schemas.ts` (2026-04-14).\n// They describe a surface that belongs to the benchmark addon, not the\n// core pipeline-executor cap. `PipelineEngineChoiceSchema` below remains\n// exported because it's still referenced by other cap methods (runPipeline\n// output, getSelectedEngine).\n\nconst AudioBackendSchema = z.object({\n id: z.string(),\n name: z.string(),\n description: z.string(),\n available: z.boolean(),\n /**\n * Raw classifier labels this backend can emit (e.g. YAMNet's\n * 521-class set or Apple SoundAnalysis's 303-class set). Used by\n * the benchmark UI to populate the `enabledMicroClasses` filter\n * specific to the selected backend without a separate fetch.\n */\n rawLabels: z.array(z.string()).readonly().optional(),\n})\n\nconst AudioCapabilitiesSchema = z.object({\n activeBackend: z.string(),\n availableBackends: z.array(AudioBackendSchema).readonly(),\n sampleRate: z.number(),\n chunkDurationMs: z.number(),\n})\n\n// ── Download model result ────────────────────────────────────────────\nconst DownloadModelResultSchema = z.object({\n filePath: z.string(),\n sizeMB: z.number(),\n durationMs: z.number(),\n})\n\n/**\n * Wrapper carrying a single test run's result. Replaces the legacy\n * ad-hoc `{labels: [{className, originalClass, score}]}` shape with the\n * canonical `AudioResult` from the Phase 6 output rework: one\n * `AudioDetection` per class above `minScore`, top-N candidates in\n * `debug.alternateLabels['audio-classifier']`, per-source timings in\n * `debug.stepTimings`. The outer `success`/`error` fields stay so the\n * benchmark UI can still report a clean failure when the classifier\n * cap isn't available.\n */\nconst AudioTestResultSchema = z.object({\n success: z.boolean(),\n error: z.string().optional(),\n frame: z.custom<AudioResult>().optional(),\n})\n\n// ── Typed bridges to complex TS interfaces defined in `@camstack/types` ──\n// Use `z.custom<T>()` when the target interface is a deeply-nested discriminated\n// union (ConfigUISchema) or a recursive graph (PipelineConfig, PipelineRunResult,\n// InferenceCapabilities). `z.custom<T>()` provides full TS inference on the\n// client without forcing a duplicate Zod definition that would drift from the\n// canonical TS interface. Validation is structural at the tRPC transport layer\n// and the server-side provider guarantees the shape at emission time.\nconst PipelineConfigBridge = z.custom<PipelineConfig | null>()\nconst ConfigUISchemaBridge = z.custom<ConfigUISchema>()\nconst ConfigUISchemaNullableBridge = z.custom<ConfigUISchema | null>()\nconst InferenceCapabilitiesBridge = z.custom<InferenceCapabilities>()\nconst ModelAvailabilityListBridge = z.custom<readonly ModelAvailability[]>()\nexport const PipelineRunResultBridge = z.custom<FrameResult>()\n\n/**\n * Pipeline executor — detection engine + configuration + inference API.\n *\n * Merged from: pipeline-executor, pipeline-config, inference, detection-config.\n * Implemented by the detection-pipeline addon.\n *\n * Per-device surface (DeviceSettingsContribution + the \"is detection\n * enabled for this camera?\" toggle) lives on the paired\n * `detection-pipeline` cap (device-scoped, singleton, wrapper\n * defaultActive) — same split pattern used by stream-broker /\n * camera-streams and audio-analyzer / audio-analysis.\n */\nexport const pipelineExecutorCapability = {\n name: 'pipeline-executor',\n scope: 'system',\n mode: 'singleton',\n methods: {\n // ── Engine selection ─────────────────────────────────────────────\n // `setEngine` removed in Phase 6c — the stateless-pipeline model\n // picks engine per-camera, not per-node. `getSelectedEngine` is\n // kept read-only so the benchmark + models-page can still show the\n // executor's bootstrap engine; its semantics degrade to \"what the\n // executor would pick by default\" in the stateless world.\n getAvailableEngines: method(z.void(), z.array(PipelineEngineChoiceSchema)),\n getSelectedEngine: method(z.void(), PipelineEngineChoiceSchema),\n getDefaultSteps: method(PipelineEngineChoiceSchema, z.array(PipelineDefaultStepSchema)),\n /**\n * Re-run the platform probe for the inference engine and write the\n * detected runtime / backend / device back into the addon's own\n * global settings store. Returns the engine that was picked so the\n * UI can confirm without a second round-trip. Triggers the standard\n * `requiresRestart` auto-restart flow because all three fields are\n * marked restart-required. Replaces the legacy per-agent\n * `pipeline-orchestrator.reprobeAgentHwAccel` surface for the\n * engine dimension — each addon now owns its own probe.\n */\n reprobeEngine: method(z.void(), PipelineEngineChoiceSchema, { kind: 'mutation', auth: 'admin' }),\n\n // ── Video pipeline step configuration (phase 2c) ─────────────────\n // Per-addonId config the operator tunes on the Pipeline → agent\n // page. Replaces the orchestrator's per-agent\n // `setAgentAddonDefaults` mutation. No `enabled` flag — the cap\n // binding system (wrapper caps + setWrapperActive) decides whether\n // a step runs.\n getVideoPipelineSteps: method(\n z.void(),\n z.record(z.string(), z.object({\n modelId: z.string(),\n settings: z.record(z.string(), z.unknown()).readonly(),\n })),\n ),\n setVideoPipelineSteps: method(\n z.object({\n steps: z.record(z.string(), z.object({\n modelId: z.string(),\n settings: z.record(z.string(), z.unknown()).readonly(),\n })),\n }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n // ── Global pipeline configuration ────────────────────────────────\n // `setGlobalSteps` removed in Phase 6c — there is no \"global\n // pipeline\" in the stateless model (each camera carries its own\n // steps via the orchestrator's `pipelines/<deviceId>`).\n // `getGlobalSteps` is kept read-only as a benchmark fallback;\n // it returns null in fresh stateless deploys.\n getSchema: method(z.void(), PipelineSchemaSchema),\n getGlobalSteps: method(z.void(), z.array(PipelineDefaultStepSchema).readonly().nullable()),\n getGlobalPipelineConfig: method(z.void(), PipelineConfigBridge),\n getOrchestratorConfigSchema: method(z.void(), ConfigUISchemaBridge),\n\n // ── Templates ────────────────────────────────────────────────────\n listTemplates: method(z.void(), z.array(PipelineTemplateSchema).readonly()),\n saveTemplate: method(\n z.object({\n name: z.string(),\n steps: z.array(PipelineTemplateStepSchema).readonly(),\n engine: PipelineEngineChoiceSchema,\n }),\n PipelineTemplateSchema,\n { kind: 'mutation' },\n ),\n updateTemplate: method(\n z.object({\n id: z.string(),\n name: z.string().optional(),\n steps: z.array(PipelineTemplateStepSchema).readonly().optional(),\n }),\n PipelineTemplateSchema,\n { kind: 'mutation' },\n ),\n deleteTemplate: method(z.object({ id: z.string() }), z.void(), { kind: 'mutation' }),\n\n // ── Inference / detection ────────────────────────────────────────\n getCapabilities: method(z.void(), InferenceCapabilitiesBridge),\n getAddonModels: method(z.object({ addonId: z.string() }), ModelAvailabilityListBridge),\n downloadModel: method(\n z.object({ addonId: z.string(), modelId: z.string(), format: ModelFormatSchema }),\n DownloadModelResultSchema,\n { kind: 'mutation' },\n ),\n deleteModel: method(\n z.object({ addonId: z.string(), modelId: z.string(), format: ModelFormatSchema }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation' },\n ),\n // NOTE: onDownloadProgress / onPipelineProgress removed in Fase H.4.\n // Consumers subscribe via the generic `live.onEvent` core router with\n // `{category: 'model.download.progress'}` or `{category: 'pipeline.progress'}`\n // — the event bus already handles category filtering, no dedicated\n // pipeline-executor method needed.\n detect: method(\n z.object({ addonId: z.string(), frame: FrameInputSchema, config: z.record(z.string(), z.unknown()).optional() }),\n DetectorOutputSchema,\n ),\n // `runFrame` removed in Phase 4 — runtime dispatch now goes through\n // the stateless `runPipeline({engine, steps, frame, deviceId})` path.\n // The runner hydrates `steps` from the orchestrator's attach payload\n // (`pipelines[deviceId]`), so there is no longer an executor-side\n // global \"current pipeline\" for a legacy `runFrame` call to target.\n /**\n * Stateless single-frame execution. Callers (runner, benchmark) pass\n * the complete `engine` + `steps` tree; the executor holds no state\n * about cameras or saved pipelines.\n *\n * `engine` is optional during the migration window to preserve the\n * legacy call shape used by existing benchmark code; once all\n * callers pass it explicitly we make it required.\n *\n * Exactly one of `frame`, `imageBase64`, `referenceImage` must be\n * provided:\n * - `frame`: runtime dispatch path (runner → decoded broker frame).\n * Carries the raw buffer, dimensions, and format; the executor\n * uses it directly without base64 round-tripping.\n * - `imageBase64`: one-shot test path (benchmark ImageTab).\n * - `referenceImage`: named file from the reference-image store.\n */\n runPipeline: method(\n z.object({\n engine: PipelineEngineChoiceSchema.optional(),\n steps: z.array(PipelineStepInputSchema).min(1),\n frame: FrameInputSchema.optional(),\n imageBase64: z.string().optional(),\n /**\n * Binary JPEG bytes — preferred over `imageBase64` on internal\n * hops (hub → forked worker via Moleculer MsgPack) because it\n * skips the 33% base64 overhead + the per-call base64 decode on\n * the detection-pipeline worker. Callers can pass either; exactly\n * one of `frame`/`image`/`imageBase64`/`referenceImage` is required.\n */\n image: z.instanceof(Uint8Array).optional(),\n referenceImage: z.string().optional(),\n deviceId: z.number().optional(),\n sessionId: z.string().optional(),\n }),\n PipelineRunResultBridge,\n { kind: 'mutation' },\n ),\n\n /**\n * Batched run — N raw frames packed into one cap call. The provider\n * routes the batch through `SharedInferencePool.inferBatch`\n * (`MSG_INFER_BATCH = 0x03`) so the IPC framing and JSON response\n * envelope cost is amortised N:1 vs N concurrent `runPipeline`\n * calls. Single root step + uniform model assumed; trees with crop\n * children fall back to sequential execution.\n *\n * Used by `scripts/bench-scrypted-style.mts` to mirror Scrypted's\n * `detectObjects(media, {batch})` semantics for fair comparison.\n */\n runPipelineBatch: method(\n z.object({\n engine: PipelineEngineChoiceSchema.optional(),\n steps: z.array(PipelineStepInputSchema).min(1),\n frames: z.array(FrameInputSchema).min(1).max(255),\n deviceId: z.number().optional(),\n sessionId: z.string().optional(),\n }),\n z.object({\n results: z.array(PipelineRunResultBridge).readonly(),\n }),\n { kind: 'mutation' },\n ),\n\n // ── Bench frame cache (Python pool-side) ──────────────────────────\n\n /**\n * Cache a raw frame inside the Python inference pool's memory.\n * Returns a numeric `frameId` that `inferCached` references —\n * subsequent calls send only 5 bytes through the pipe instead of\n * 1.2MB raw data, eliminating the pipe transfer bottleneck.\n */\n cacheFrameInPool: method(\n z.object({\n data: z.instanceof(Uint8Array),\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n format: z.enum(['rgb', 'bgr', 'gray']),\n }),\n z.object({\n frameId: z.number(),\n width: z.number(),\n height: z.number(),\n }),\n { kind: 'mutation' },\n ),\n\n /**\n * Run inference on a previously cached frame. Sends only 5 bytes\n * (model_idx + frameId) through the IPC pipe — eliminates the\n * ~35ms per-call overhead of transferring 1.2MB raw data.\n */\n inferCached: method(\n z.object({\n stepId: z.string(),\n frameId: z.number().int(),\n }),\n z.record(z.string(), z.unknown()),\n { kind: 'mutation' },\n ),\n\n /**\n * Release a cached frame from the Python pool's memory.\n */\n uncacheFrame: method(\n z.object({ frameId: z.number().int() }),\n z.void(),\n { kind: 'mutation' },\n ),\n\n /** Returns the effective pool tuning (resolved from user overrides + backend defaults). */\n getEffectiveTuning: method(\n z.void(),\n z.object({\n batchMode: z.string(),\n windowMs: z.number(),\n maxBatchSize: z.number(),\n concurrency: z.number(),\n }),\n ),\n // ── Engine registry / management (stateless-pipeline spec) ────────\n /**\n * List every EngineFactory currently loaded in this executor's RAM,\n * with the models resident and a coarse \"in use\" marker derived from\n * ongoing inference activity. Used by the Pipeline page Engines tab.\n */\n listLoadedEngines: method(\n z.void(),\n z.array(z.object({\n engineKey: z.string(),\n engine: PipelineEngineChoiceSchema,\n modelsLoaded: z.array(z.string()).readonly(),\n inUseByCameras: z.array(z.number()).readonly(),\n /**\n * Origin of this resident factory.\n * - `runtime` — main camera-serving engine (no idle TTL).\n * - `warm-override` — benchmark/test override held in the warm\n * cache; auto-disposed after the idle TTL.\n */\n kind: z.enum(['runtime', 'warm-override']),\n /** Native pid of the underlying Python pool (null when no pool). */\n poolPid: z.number().nullable(),\n /** ms since this factory was last used (null when not warm-tracked). */\n idleMs: z.number().nullable(),\n /** Idle TTL after which `warm-override` factories self-evict (null when not applicable). */\n idleTtlMs: z.number().nullable(),\n })).readonly(),\n ),\n /** Warm up an engine without running a frame. No-op if already loaded. */\n spinEngine: method(\n z.object({ engine: PipelineEngineChoiceSchema }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n /**\n * Unload an engine from RAM. `force:true` unloads even when cameras\n * are actively using it (they re-spin on next frame). Default is\n * gated — returns `{success:false, reason}` when in use.\n */\n killEngine: method(\n z.object({\n engine: PipelineEngineChoiceSchema,\n force: z.boolean().optional(),\n }),\n z.object({ success: z.boolean(), reason: z.string().optional() }),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n // ── Benchmarks & testing ─────────────────────────────────────────\n // Moved to `@camstack/addon-benchmark` as customActions (2026-04-14).\n // The addon exposes runBenchmark / runPipelineTest / listBenchmarkHistory /\n // saveBenchmarkResult / deleteBenchmarkResult / clearBenchmarkHistory via\n // `api.addons.custom.mutate({addonId: 'benchmark', action, input})` and\n // delegates the actual pipeline execution back to this cap's runPipeline.\n\n // ── Reference media ──────────────────────────────────────────────\n listReferenceImages: method(z.void(), z.array(ReferenceImageEntrySchema).readonly()),\n getReferenceImage: method(z.object({ filename: z.string() }), ReferenceImageBodySchema.nullable()),\n getReferenceAudioFiles: method(z.void(), z.array(ReferenceAudioEntrySchema).readonly()),\n getReferenceAudio: method(z.object({ filename: z.string() }), ReferenceAudioBodySchema.nullable()),\n getAudioCapabilities: method(z.void(), AudioCapabilitiesSchema),\n runAudioTest: method(\n z.object({\n addonId: z.string(),\n modelId: z.string(),\n filename: z.string().optional(),\n // Per-step settings (e.g. `enabledClasses`) sourced from the\n // audio-classifier step's `getConfigSchema()`. The provider\n // applies them to the classification result before returning.\n settings: z.record(z.string(), z.unknown()).optional(),\n }),\n AudioTestResultSchema,\n { kind: 'mutation' },\n ),\n\n // ── Detection wiring / metrics (from detection-config) ───────────\n getDetectionConfigSchema: method(z.void(), ConfigUISchemaNullableBridge),\n // NOTE: orchestratorStatus / cameraDetectionStatus removed in the\n // pipeline page redesign — UI reads runner metrics directly via\n // perNodePipeline.getLocalMetrics / getCameraMetrics, which forward\n // to the pipeline-runner cap on the target node.\n //\n // NOTE: listBrokers / brokerStatus used to live here too — removed in\n // Fase H.3. Frontends now call `streamBroker.listBrokers` directly and\n // filter by deviceId client-side (brokerId prefix match). The broker\n // collection lives in the stream-broker capability and there is no\n // reason for pipeline-executor to mirror it.\n //\n // NOTE: subscribeLive / subscribeAudioLive removed in Fase H.4.\n // Consumers use the generic `live.onEvent` / `live.onDeviceEvent`\n // with `{category: 'pipeline.progress' | 'pipeline.inference-result'\n // | 'pipeline.audio-inference-result'}`.\n\n // Per-device pipeline step CRUD (`getDevicePipelineSteps` /\n // `setDevicePipelineSteps` / `clearDevicePipelineSteps`) removed in\n // Phase 4b. The orchestrator owns per-camera pipeline content now\n // (`pipelineOrchestrator.{get,set}CameraPipeline` +\n // `pipelines/<deviceId>` in its addon store). The executor is\n // stateless w.r.t. cameras — it receives `steps` inline on every\n // `runPipeline` call.\n },\n} as const satisfies CapabilityDefinition\n\nexport type IPipelineExecutorProvider = InferProvider<typeof pipelineExecutorCapability>\n\nexport {\n PipelineEngineChoiceSchema,\n PipelineDefaultStepSchema,\n DetectorOutputSchema,\n // Schema types — consumed by pipeline-schema.ts to derive TS types\n PipelineSchemaSchema,\n PipelineAddonSchemaSchema,\n PipelineSlotSchemaSchema,\n PipelineModelOptionSchema,\n AvailableEngineSchema,\n PipelineTemplateSchema,\n PipelineTemplateStepSchema,\n EngineDeviceInfoSchema,\n}\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * Zone — pure geometry + identity. NO filtering behaviour.\n *\n * Zones describe **where** in the frame the operator wants to flag\n * something; consumer-owned {@link ZoneRule} arrays describe **how**\n * each pipeline stage uses them. Splitting the two means a single\n * polygon \"Driveway\" can simultaneously back a motion-exclude rule,\n * a detection-include rule on `['car']`, and an occupancy aggregate\n * — without three duplicated polygons.\n *\n * Owned by the orchestrator addon (provider) and mirrored into the\n * `zones` device-state slice on every mutation. Consumers\n * (motion-wasm, pipeline-executor, analytics, admin UI) read either\n * via `api.zones.listZones` (one-shot) or via `dev.state.zones` (live\n * mirror with `onChanged`).\n *\n * Coordinates are normalised fractions of the frame (0–1) so zones\n * survive resolution changes and stream profile switches.\n *\n * `kind` discriminates between full polygons (closed regions used\n * for intrusion / occupancy filters) and tripwires (open 2-point\n * line segments used for cross events). Onboard / firmware-reported\n * zones (Reolink, ONVIF) are out of scope for now — see the deferred\n * task list.\n */\nexport const ZoneKindEnum = z.enum(['polygon', 'tripwire'])\nexport type ZoneKind = z.infer<typeof ZoneKindEnum>\n\n/** Polygon vertex in fraction-of-frame coordinates (0–1). */\nexport const PolygonPointSchema = z.object({\n x: z.number(),\n y: z.number(),\n})\nexport type PolygonPoint = z.infer<typeof PolygonPointSchema>\n\n/** A camera detection zone — pure geometry/identity. */\nexport const ZoneSchema = z.object({\n id: z.string(),\n name: z.string(),\n kind: ZoneKindEnum.default('polygon'),\n /** Polygon vertices, fraction of frame (0–1). */\n polygon: z.array(PolygonPointSchema).readonly(),\n /** Visual color for UI rendering. */\n color: z.string().default('#3b82f6'),\n})\nexport type Zone = z.infer<typeof ZoneSchema>\n\n/**\n * Zones capability — per-camera CRUD over polygon detection zones.\n *\n * Provider lives in `addon-pipeline-orchestrator` (hub-only). Persists\n * to per-device settings and mirrors into the `zones` device-state\n * slice on every mutation, so downstream consumers can subscribe via\n * `dev.state.zones.onChanged`.\n *\n * The cap surface only handles geometry + identity; filtering\n * behaviour (per-class, include/exclude, threshold) lives in the\n * consumer addons' rule arrays — see `ZoneRuleSchema` exported from\n * `capabilities/schemas/zone-rule.js`.\n */\nexport const zonesCapability = {\n name: 'zones',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n methods: {\n listZones: method(\n z.object({ deviceId: z.number() }),\n z.array(ZoneSchema).readonly(),\n ),\n addZone: method(\n z.object({ deviceId: z.number(), zone: ZoneSchema }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n removeZone: method(\n z.object({ deviceId: z.number(), zoneId: z.string() }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n updateZone: method(\n z.object({ deviceId: z.number(), zone: ZoneSchema }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n /**\n * Runtime-state slice — the live zone catalogue mirrored by the\n * orchestrator on every CRUD mutation. Consumers read via\n * `device.state.zones.value` / `.watch(...)` without round-tripping\n * the cap, and the codegen DeviceProxy auto-wires the reactive\n * handle. Slice shape is `{ zones: Zone[] }` so future extensions\n * (e.g. zone groupings) can sit alongside the polygon list.\n */\n runtimeState: z.object({\n zones: z.array(ZoneSchema).readonly(),\n }),\n} as const satisfies CapabilityDefinition\n\nexport type IZonesProvider = InferProvider<typeof zonesCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * Motion-trigger toggle for accessory devices.\n *\n * \"Motion trigger\" means: when the parent camera detects motion, the\n * accessory activates automatically. The cap exposes a single boolean\n * — `enabled` — that drivers map to the vendor-specific firmware\n * action (Reolink: `setSirenOnMotion`, `setFloodlightOnMotion`; ONVIF\n * relay: schedule binding; …).\n *\n * The accessory still has its own `switch` cap for direct on/off; this\n * cap is independent. Toggling motion-trigger on does NOT necessarily\n * toggle the switch on — it just instructs the firmware to flip the\n * switch when motion fires.\n *\n * Driver-specific knobs (motion duration window, brightness while\n * triggered, schedule windows) live in the device's\n * `getSettingsUISchema()` instead of bloating this cap — same\n * principle as `switch` and `brightness` keeping their surface\n * minimal.\n */\nexport const MotionTriggerStatusSchema = z.object({\n enabled: z.boolean(),\n /** Ms epoch of the last operator-driven change. */\n lastChangedAt: z.number(),\n})\n\nexport type MotionTriggerStatus = z.infer<typeof MotionTriggerStatusSchema>\n\n/**\n * Persistent slice mirrored across restarts. The provider writes here\n * on every successful firmware fetch / setMotionTrigger push; the cap\n * router and admin-ui hero read straight from this snapshot via\n * `device.state.motionTrigger.value` instead of re-issuing a firmware\n * round-trip on every UI mount. `lastFetchedAt` lets the framework\n * helper (`createRuntimeStateBridge`) stale-check before deciding\n * whether to refresh from the camera.\n */\nexport const MotionTriggerRuntimeStateSchema = MotionTriggerStatusSchema.extend({\n /** Ms epoch of the last successful camera fetch (0 = never). */\n lastFetchedAt: z.number(),\n})\n\nexport type MotionTriggerRuntimeState = z.infer<typeof MotionTriggerRuntimeStateSchema>\n\nexport const motionTriggerCapability = {\n name: 'motion-trigger',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Light, DeviceType.Siren, DeviceType.Switch],\n methods: {\n setMotionTrigger: method(\n z.object({\n deviceId: z.number().int().nonnegative(),\n enabled: z.boolean(),\n }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n events: {\n onMotionTriggerChanged: { data: z.object({\n deviceId: z.number(),\n enabled: z.boolean(),\n lastChangedAt: z.number(),\n })},\n },\n status: {\n schema: MotionTriggerStatusSchema,\n kind: 'command-driven',\n },\n runtimeState: MotionTriggerRuntimeStateSchema,\n} as const satisfies CapabilityDefinition\n\nexport type IMotionTriggerProvider = InferProvider<typeof motionTriggerCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * `ptz-autotrack` — sibling cap of `ptz` that exposes the on-camera\n * smart-tracking subsystem (subject-following). Modeled separately\n * from `ptz` because:\n * - Not every PTZ-capable camera has autotrack (Reolink: yes;\n * Hikvision: model-dependent), so a single combined cap would\n * force every PTZ provider to surface `Unsupported` stubs on\n * half the methods.\n * - The cap's lifecycle is \"registered when probed-true\" — the\n * binding system can show / hide the UI affordance cleanly via\n * the standard `provider-registered` signal.\n * - Autotrack on/off is a device-state toggle (status), distinct\n * from PTZ's continuous control surface — a status-driven cap\n * fits the existing `setStatus` / `onStatusChanged` pattern\n * better than `ptz`'s discrete-action surface.\n *\n * Settings (cross-vendor consolidation, sourced from Reolink's\n * `setAutotrackingSettings` shape; expandable as Hikvision /\n * Dahua / others land):\n * - `targetType` — vendor target string (people /\n * vehicle / pet / `''` = camera default)\n * - `stopDelaySeconds` — how long to keep tracking a\n * stationary target before stopping\n * (0..300, default 30)\n * - `disappearDelaySeconds` — how long to wait before releasing a\n * target that has left the frame\n * (0..300, default 15)\n *\n * The driver is the source of truth for which settings keys it\n * actually honours; unsupported keys silently fall back to the\n * camera's defaults. Adding a new vendor's setting (e.g. Hikvision's\n * `trackingDuration`) extends the schema below and the\n * `setSettings` payload.\n */\n\nconst AutotrackTargetTypeSchema = z.string()\n .describe('Vendor target string (people/vehicle/pet); empty = camera default')\n\nexport const PtzAutotrackSettingsSchema = z.object({\n targetType: AutotrackTargetTypeSchema,\n stopDelaySeconds: z.number().int().min(0).max(300),\n disappearDelaySeconds: z.number().int().min(0).max(300),\n})\n\nexport type PtzAutotrackSettings = z.infer<typeof PtzAutotrackSettingsSchema>\n\n/**\n * One option the camera advertises as a valid `targetType`. Drivers\n * harvest this from their probe data; the UI renders these as the\n * `targetType` select options. Empty array = the camera doesn't\n * expose a target-type selector (auto-only).\n *\n * The `value` is the canonical wire string the cap accepts in\n * `setSettings({targetType})` — drivers use it verbatim when pushing\n * to firmware. The `label` is operator-facing English (translated\n * client-side if the UI supports i18n).\n */\nexport const PtzAutotrackTargetOptionSchema = z.object({\n value: z.string(),\n label: z.string(),\n})\n\nexport type PtzAutotrackTargetOption = z.infer<typeof PtzAutotrackTargetOptionSchema>\n\nexport const PtzAutotrackStatusSchema = z.object({\n /** True when autotrack is currently armed on the camera. */\n enabled: z.boolean(),\n /** Ms epoch of the last on/off transition (0 if never observed). */\n lastChangedAt: z.number(),\n /** Currently-applied settings the camera reports. Drivers fill\n * this from the firmware GET so the UI can echo what's *really*\n * active vs the operator-typed values in the settings form. */\n currentSettings: PtzAutotrackSettingsSchema.nullable(),\n /**\n * Target types the camera advertises. Driver-supplied — Reolink\n * exposes `people` / `vehicle` / `pet`, Hikvision exposes\n * `auto` / `human` / `vehicle` when the `<smartTrackingType>` knob\n * is supported. Empty array = vendor doesn't expose a selector\n * (treat as auto-only). The UI renders these as the `targetType`\n * field options without hardcoding a vendor-specific list.\n */\n supportedTargetTypes: z.array(PtzAutotrackTargetOptionSchema),\n})\n\nexport type PtzAutotrackStatus = z.infer<typeof PtzAutotrackStatusSchema>\n\n/**\n * Runtime-state slice owned by this cap. Persists the last-known\n * camera-derived snapshot across restarts, so cold-start callers\n * have a meaningful baseline even before the first refresh round-trip.\n *\n * Adds `lastFetchedAt` on top of the status shape so the framework\n * (or the provider) can stale-check before deciding whether to\n * round-trip the camera again.\n */\nexport const PtzAutotrackRuntimeStateSchema = PtzAutotrackStatusSchema.extend({\n /** Ms epoch of the last successful camera fetch (0 = never). */\n lastFetchedAt: z.number(),\n})\n\nexport type PtzAutotrackRuntimeState = z.infer<typeof PtzAutotrackRuntimeStateSchema>\n\nexport const ptzAutotrackCapability = {\n name: 'ptz-autotrack',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n methods: {\n /**\n * Read the current on/off state + last-applied settings.\n * Drivers may serve from a cache + refresh on a schedule —\n * callers should NOT poll faster than ~5s.\n */\n getStatus: method(\n z.object({ deviceId: z.number() }),\n PtzAutotrackStatusSchema,\n ),\n /**\n * Arm or disarm autotrack. Resolves once the camera has\n * acknowledged the transition; the `onStatusChanged` event\n * fires shortly after with the live state.\n */\n setEnabled: method(\n z.object({ deviceId: z.number(), enabled: z.boolean() }),\n z.void(),\n { kind: 'mutation' },\n ),\n /**\n * Read settings (target type + delays). Mirrors the\n * `getStatus().currentSettings` payload but exposes it as a\n * standalone read for callers that want settings without the\n * status surface around them. `null` until the driver has\n * harvested the firmware state at least once.\n */\n getSettings: method(\n z.object({ deviceId: z.number() }),\n PtzAutotrackSettingsSchema.nullable(),\n ),\n /**\n * Update one or more settings. Partial — keys that aren't\n * supplied keep their last persisted value. The driver is\n * responsible for clamping vendor-specific ranges if narrower\n * than the cross-vendor max declared on the schema.\n */\n setSettings: method(\n z.object({\n deviceId: z.number(),\n settings: PtzAutotrackSettingsSchema.partial(),\n }),\n z.void(),\n { kind: 'mutation' },\n ),\n },\n events: {\n onStatusChanged: { data: z.object({\n deviceId: z.number(),\n status: PtzAutotrackStatusSchema,\n })},\n },\n status: {\n schema: PtzAutotrackStatusSchema,\n kind: 'command-driven',\n },\n /**\n * Persistent slice mirrored across restarts. The provider writes\n * here on every successful firmware fetch / settings push;\n * `getStatus` and `getSettings` then read this snapshot synchronously\n * with a stale-driven async refresh in the background. Keeps the\n * fetch / cache / fallback logic out of the four cap methods —\n * they become trampolines over `runtimeState`.\n */\n runtimeState: PtzAutotrackRuntimeStateSchema,\n} as const satisfies CapabilityDefinition\n\nexport type IPtzAutotrackProvider = InferProvider<typeof ptzAutotrackCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * Generic on/off switch cap for accessory children (siren, floodlight,\n * spotlight, PIR toggle, chime silencer, autotrack enable, …). The cap\n * owns ONLY the boolean state — driver-specific settings (brightness,\n * sensitivity, schedule, duration) live on the device's own\n * `getSettingsUISchema()` surface.\n */\nexport const SwitchStatusSchema = z.object({\n on: z.boolean(),\n /** Ms epoch of the last state change. Useful for UI \"X minutes ago\". */\n lastChangedAt: z.number(),\n})\n\nexport type SwitchStatus = z.infer<typeof SwitchStatusSchema>\n\nexport const switchCapability = {\n name: 'switch',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Switch, DeviceType.Siren, DeviceType.Light],\n methods: {\n setState: method(\n z.object({ deviceId: z.number(), on: z.boolean() }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n events: {\n onStateChanged: { data: z.object({\n deviceId: z.number(),\n on: z.boolean(),\n lastChangedAt: z.number(),\n })},\n },\n status: {\n schema: SwitchStatusSchema,\n kind: 'command-driven',\n },\n /**\n * Runtime-state slice — the last applied on/off state, mirrored by\n * the kernel. Read via `device.state.switch.value`; UI toggles do\n * not need to re-query the provider after a setState mutation.\n */\n runtimeState: SwitchStatusSchema,\n settings: {\n bindings: [{\n kind: 'scalar',\n statusPath: 'on',\n method: 'setState',\n valueArg: 'on',\n field: { label: 'On', kind: 'boolean' },\n }],\n },\n} as const satisfies CapabilityDefinition\n\nexport type ISwitchProvider = InferProvider<typeof switchCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * Per-zone occupancy aggregation produced by the analytics frame\n * processor on every inference result. Covers the full combinatorial\n * matrix the operator UI needs: total objects everywhere, total\n * objects per zone, single class everywhere, single class per zone,\n * objects outside any zone.\n *\n * Counts are derived from the analytics tracker (tracked detections\n * with stable trackIds), not raw detector hits — this filters out\n * one-off detector flickers and gives counts that match what the user\n * sees on the live overlay.\n *\n * Overlap policy: a detection that intersects two zones counts in\n * BOTH zones' `byClass` and `totalObjects` (count-in-each). The\n * `frame` aggregate de-duplicates trivially since it's frame-wide.\n * `unzoned` counts only detections that landed in zero zones.\n */\nconst PerScopeBreakdownSchema = z.object({\n /** Total tracked objects in this scope (frame / zone / unzoned). */\n totalObjects: z.number().int().nonnegative(),\n /** Per-class count. Keys are macro class names (e.g. `person`, `car`). */\n byClass: z.record(z.string(), z.number().int().nonnegative()),\n})\n\nconst ZoneScopeBreakdownSchema = PerScopeBreakdownSchema.extend({\n zoneId: z.string(),\n zoneName: z.string(),\n /** TrackIds of objects currently inside this zone — for cross-reference\n * with the per-track detail panel and live overlay. */\n trackIds: z.array(z.string()).readonly(),\n})\n\nexport const CameraOccupancySnapshotSchema = z.object({\n /** Frame timestamp of the inference result that produced this snapshot. */\n ts: z.number().int(),\n /** Frame width/height in pixels — let the UI normalize bbox coords. */\n frameWidth: z.number().int().nonnegative(),\n frameHeight: z.number().int().nonnegative(),\n /** Per-zone breakdown — one entry per defined zone (user + onboard). */\n zones: z.array(ZoneScopeBreakdownSchema).readonly(),\n /** Frame-wide aggregate (everywhere, regardless of zone membership). */\n frame: PerScopeBreakdownSchema,\n /** Detections that landed outside every zone. Empty when no zones defined. */\n unzoned: PerScopeBreakdownSchema,\n})\nexport type CameraOccupancySnapshot = z.infer<typeof CameraOccupancySnapshotSchema>\nexport type ZoneScopeBreakdown = z.infer<typeof ZoneScopeBreakdownSchema>\nexport type PerScopeBreakdown = z.infer<typeof PerScopeBreakdownSchema>\n\n/**\n * Time-series resolution. The history methods return one bucket per\n * step over the requested range. Smaller resolutions cost more\n * memory + bandwidth; bound to discrete steps so caller cannot ask\n * for arbitrary fractional buckets.\n */\nconst HistoryResolutionEnum = z.enum(['minute', '5min', 'hour'])\nexport type HistoryResolution = z.infer<typeof HistoryResolutionEnum>\n\nconst HistoryRangeSchema = z.object({\n /** Range start (epoch ms, inclusive). */\n from: z.number().int(),\n /** Range end (epoch ms, inclusive). Defaults to \"now\" at query time. */\n to: z.number().int(),\n resolution: HistoryResolutionEnum,\n})\n\nconst HistoryPointSchema = z.object({\n /** Bucket midpoint (epoch ms). */\n ts: z.number().int(),\n /** Object count averaged over the bucket (rounded to nearest integer). */\n count: z.number().int().nonnegative(),\n})\nexport type HistoryPoint = z.infer<typeof HistoryPointSchema>\n\n/**\n * Zone Analytics capability — spatial occupancy aggregations over\n * tracked detections. Hosted by `addon-pipeline-analytics`.\n *\n * Live snapshot is mirrored into the `zone-occupancy` device-state\n * slice on every frame; the cap method `getCurrentSnapshot` is a\n * direct read for callers that don't want to subscribe.\n *\n * History methods are sourced from a 60-minute rolling in-memory\n * ring of frame-level samples (sub-second resolution). Queries\n * outside the ring window return empty arrays — durable storage\n * is a follow-up (Step 4b: persisted samples → SQL store).\n *\n * Every history method takes an optional `className` filter:\n * - omitted → bucket count includes ALL classes in scope\n * - present → bucket count restricted to that class\n *\n * The `getZoneHistory` / `getCameraHistory` / `getUnzonedHistory`\n * triple covers the three spatial scopes (per-zone, frame-wide,\n * outside-any-zone). Crossing them with `className?` gives the full\n * combinatorial coverage the operator UI requested.\n */\nexport const zoneAnalyticsCapability = {\n name: 'zone-analytics',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n methods: {\n /** Latest computed occupancy snapshot for this camera. Null when\n * the analytics pipeline hasn't seen a frame for this device yet\n * (no inference result emitted since boot or since binding was\n * activated). */\n getCurrentSnapshot: method(\n z.object({ deviceId: z.number() }),\n CameraOccupancySnapshotSchema.nullable(),\n ),\n /** Time-series object count inside one zone. `className` optional —\n * omit to count every class in the zone. */\n getZoneHistory: method(\n z.object({\n deviceId: z.number(),\n zoneId: z.string(),\n className: z.string().optional(),\n }).extend(HistoryRangeSchema.shape),\n z.array(HistoryPointSchema).readonly(),\n ),\n /** Time-series frame-wide object count (everywhere). */\n getCameraHistory: method(\n z.object({\n deviceId: z.number(),\n className: z.string().optional(),\n }).extend(HistoryRangeSchema.shape),\n z.array(HistoryPointSchema).readonly(),\n ),\n /** Time-series count of objects outside every zone. */\n getUnzonedHistory: method(\n z.object({\n deviceId: z.number(),\n className: z.string().optional(),\n }).extend(HistoryRangeSchema.shape),\n z.array(HistoryPointSchema).readonly(),\n ),\n },\n /**\n * Runtime-state slice — the latest occupancy snapshot mirrored by\n * the analytics frame processor on every inference result. Consumers\n * read via `device.state.zoneAnalytics.value` and stay in sync\n * automatically; the explicit `getCurrentSnapshot` cap method is\n * still useful for one-off polls without a subscription.\n */\n runtimeState: CameraOccupancySnapshotSchema,\n} as const satisfies CapabilityDefinition\n\nexport type IZoneAnalyticsProvider = InferProvider<typeof zoneAnalyticsCapability>\n\nexport {\n CameraOccupancySnapshotSchema as _CameraOccupancySnapshotSchema,\n HistoryResolutionEnum,\n HistoryPointSchema,\n HistoryRangeSchema,\n ZoneScopeBreakdownSchema,\n PerScopeBreakdownSchema,\n}\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\nimport { ZoneRuleSchema } from './schemas/zone-rule.js'\n\n/**\n * Stages a {@link ZoneRule} can apply to. Discriminator on the rules\n * cap so a single CRUD surface backs every consumer; each stage has\n * its own dev-state mirror slice (`motion-zone-rules`,\n * `detection-zone-rules`, …) so consumer addons subscribe independently.\n *\n * Extend the enum here when a new gating consumer comes online (audio\n * gating, alert filtering, …) — no other surface needs to change.\n */\nexport const ZoneRuleStageEnum = z.enum(['motion', 'detection'])\nexport type ZoneRuleStage = z.infer<typeof ZoneRuleStageEnum>\n\n/**\n * Zone rules capability — per-camera CRUD over the {@link ZoneRule}\n * arrays that decide how each pipeline stage uses the polygon zones.\n *\n * Hosted by `addon-pipeline-orchestrator` alongside the zones provider\n * so the operator has a single hub-side source of truth for both\n * geometry and behaviour. Per-stage rules are stored under the\n * `zoneRules.<stage>` key in the orchestrator's per-device store and\n * mirrored to the device-state slice `<stage>-zone-rules` on every\n * mutation; consumer addons (analytics, motion-wasm, pipeline-executor)\n * subscribe to that slice and refresh their gating without\n * round-tripping the cap.\n *\n * Sets are bulk-replace — the operator UI sends the new rule list\n * wholesale, so reordering / batch enable-toggle / drag-drop CRUD lives\n * naturally in the rule editor without per-rule mutation chatter.\n */\nexport const zoneRulesCapability = {\n name: 'zone-rules',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n methods: {\n /** Read the full rule list for a given stage (empty when no rules\n * are defined yet). */\n listRules: method(\n z.object({ deviceId: z.number(), stage: ZoneRuleStageEnum }),\n z.array(ZoneRuleSchema).readonly(),\n ),\n /** Bulk-replace the rule list for one stage. The provider validates\n * each entry against {@link ZoneRuleSchema} (zoneIds non-empty,\n * thresholds in range) and rejects the whole patch if any entry\n * is invalid — partial writes are a configuration footgun. */\n setRules: method(\n z.object({\n deviceId: z.number(),\n stage: ZoneRuleStageEnum,\n rules: z.array(ZoneRuleSchema).readonly(),\n }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n /**\n * Runtime-state slice — both stages mirrored together so consumers\n * see one reactive handle (`device.state.zoneRules.value`) instead\n * of two. Bulk-replace mutations on either stage write the full\n * `{motion, detection}` shape, so subscribers always get the\n * complete current set. Consumers that only care about one stage\n * just read the matching property.\n */\n runtimeState: z.object({\n motion: z.array(ZoneRuleSchema).readonly(),\n detection: z.array(ZoneRuleSchema).readonly(),\n }),\n} as const satisfies CapabilityDefinition\n\nexport type IZoneRulesProvider = InferProvider<typeof zoneRulesCapability>\n","import { z } from 'zod'\n\n/**\n * Per-stage gating mode applied to the zones a rule references.\n *\n * - `include`: the rule contributes to a **whitelist** for its stage.\n * When at least one `include` rule fires for a stage, only entities\n * inside one of those zones pass that stage.\n * - `exclude`: the rule contributes to a **blacklist** for its stage.\n * Entities inside one of those zones are dropped at that stage.\n *\n * `monitor`-style observation (count without filtering) is not a rule\n * mode — zones without any matching rule are observed naturally by\n * `zone-analytics` (live snapshot + history), so an \"I just want to\n * count, not filter\" use case needs no rule at all.\n */\nexport const ZoneRuleModeEnum = z.enum(['include', 'exclude'])\nexport type ZoneRuleMode = z.infer<typeof ZoneRuleModeEnum>\n\n/**\n * Per-consumer rule that references existing zones (geometry) and\n * defines how a specific pipeline stage should treat them. Each\n * consumer addon owns its own `ZoneRule[]` array in its per-device\n * settings:\n *\n * - `addon-motion-wasm` → `motionZoneRules: ZoneRule[]` (motion stage)\n * - `addon-detection-pipeline` → `detectionZoneRules: ZoneRule[]` (detection stage)\n * - future: notification rules, audio gating, etc.\n *\n * One rule applies to N zones (`zoneIds[]`) so the operator can\n * express \"ignore motion in ALL of {garden, street}\" with a single\n * rule. `classFilter` narrows the rule to specific object classes —\n * \"drop person detections in the street, but keep cars\" is one\n * `exclude` rule with `classFilter: ['person']`.\n *\n * `enabled` is a soft toggle — the operator can keep the rule\n * configured but inert without deleting it.\n */\nexport const ZoneRuleSchema = z.object({\n /** Stable rule id — survives edits, used by the UI for diffing. */\n id: z.string(),\n /** Optional human-readable label rendered in the rule editor. */\n name: z.string().optional(),\n /** Zones this rule targets. The rule's `mode` applies to ALL\n * listed zones (OR-set: a detection in any one of them counts).\n * At least one zone id required — a rule with no targets is a\n * configuration mistake and the form validator rejects it. */\n zoneIds: z.array(z.string()).min(1).readonly(),\n mode: ZoneRuleModeEnum,\n /**\n * Class names this rule applies to. Empty / undefined ⇒ rule\n * applies to every class. Class strings match the `macroClass`\n * field on detections (e.g. `person`, `car`, `dog`).\n */\n classFilter: z.array(z.string()).readonly().optional(),\n /**\n * Minimum bbox/mask overlap (0–1) with any of the rule's zones\n * required to consider an entity \"in the zone\". Defaults to the\n * consumer's stage default when omitted. Kept for back-compat with\n * existing per-rule overrides; new operators pick the value via\n * `bboxInclusionPct` (operator-friendly 0–100). Whichever field is\n * set, the lower-level engine reads it as a 0–1 fraction.\n */\n overlapThreshold: z.number().min(0).max(1).optional(),\n /**\n * Operator-friendly version of `overlapThreshold` — the percentage\n * of the detection's bbox that must lie inside the zone for the\n * rule to match. Documented default is 85%; the engine substitutes\n * that when the field is omitted (kept optional so existing rules\n * stored without it stay valid).\n *\n * When BOTH `overlapThreshold` and `bboxInclusionPct` are set on a\n * rule, the engine prefers `bboxInclusionPct` because it's the\n * field exposed in the UI. Internally both feed the same gate.\n */\n bboxInclusionPct: z.number().min(0).max(100).optional(),\n /**\n * When `true` and a detection has a segmentation mask, use the\n * mask for overlap instead of the bbox. Detection-stage only;\n * motion rules ignore this field.\n */\n preferMask: z.boolean().optional(),\n /**\n * Soft-toggle: `false` disables the rule without deleting it.\n * Defaults to `true` so operators creating a rule via the UI\n * see it active immediately.\n */\n enabled: z.boolean().default(true),\n})\nexport type ZoneRule = z.infer<typeof ZoneRuleSchema>\n\n/**\n * Convenience array schema — used by addon device-settings\n * contributions and runtime payloads (e.g. `RunnerCameraConfig`).\n */\nexport const ZoneRulesArraySchema = z.array(ZoneRuleSchema).readonly()\nexport type ZoneRules = z.infer<typeof ZoneRulesArraySchema>\n","// AUTO-GENERATED — do not edit manually.\n// Regenerate with: npx tsx scripts/generate-device-proxy.ts\n/* eslint-disable */\n\nimport type { CapabilityDefinition, InferRuntimeState } from '../capabilities/capability-definition.js'\nimport { audioMetricsCapability } from '../capabilities/audio-metrics.cap.js'\nimport { batteryCapability } from '../capabilities/battery.cap.js'\nimport { brightnessCapability } from '../capabilities/brightness.cap.js'\nimport { cameraStreamsCapability } from '../capabilities/camera-streams.cap.js'\nimport { deviceDiscoveryCapability } from '../capabilities/device-discovery.cap.js'\nimport { deviceStatusCapability } from '../capabilities/device-status.cap.js'\nimport { doorbellCapability } from '../capabilities/doorbell.cap.js'\nimport { featureProbeCapability } from '../capabilities/feature-probe.cap.js'\nimport { motionCapability } from '../capabilities/motion.cap.js'\nimport { motionTriggerCapability } from '../capabilities/motion-trigger.cap.js'\nimport { ptzAutotrackCapability } from '../capabilities/ptz-autotrack.cap.js'\nimport { switchCapability } from '../capabilities/switch.cap.js'\nimport { zoneAnalyticsCapability } from '../capabilities/zone-analytics.cap.js'\nimport { zoneRulesCapability } from '../capabilities/zone-rules.cap.js'\nimport { zonesCapability } from '../capabilities/zones.cap.js'\n\n/**\n * Server-side, write-capable per-cap state shape for any device that\n * extends `BaseDevice`. One entry per cap with `runtimeState:` declared.\n *\n * Drivers access via `this.state.<capName>.<field>` — both reads and\n * writes route through the device's runtime-state slice (validate,\n * persist, fire `<cap>.onChanged`). No string keys, no manual generic.\n *\n * Adding a new cap with `runtimeState:` auto-extends this interface —\n * regenerate with `npm run codegen`.\n */\nexport interface DeviceLocalState {\n audioMetrics: InferRuntimeState<typeof audioMetricsCapability>\n battery: InferRuntimeState<typeof batteryCapability>\n brightness: InferRuntimeState<typeof brightnessCapability>\n cameraStreams: InferRuntimeState<typeof cameraStreamsCapability>\n deviceDiscovery: InferRuntimeState<typeof deviceDiscoveryCapability>\n deviceStatus: InferRuntimeState<typeof deviceStatusCapability>\n doorbell: InferRuntimeState<typeof doorbellCapability>\n featureProbe: InferRuntimeState<typeof featureProbeCapability>\n motion: InferRuntimeState<typeof motionCapability>\n motionTrigger: InferRuntimeState<typeof motionTriggerCapability>\n ptzAutotrack: InferRuntimeState<typeof ptzAutotrackCapability>\n switch: InferRuntimeState<typeof switchCapability>\n zoneAnalytics: InferRuntimeState<typeof zoneAnalyticsCapability>\n zoneRules: InferRuntimeState<typeof zoneRulesCapability>\n zones: InferRuntimeState<typeof zonesCapability>\n}\n\n/**\n * Runtime registry: cap-property-name → cap definition. `BaseDevice`'s\n * `state` getter looks up the cap definition here to construct a\n * `sliceProxy()` lazily on first access. Generated alongside the type\n * so type and runtime registry can never drift apart.\n */\nexport const DEVICE_LOCAL_STATE_CAPS: Record<keyof DeviceLocalState, CapabilityDefinition> = {\n audioMetrics: audioMetricsCapability,\n battery: batteryCapability,\n brightness: brightnessCapability,\n cameraStreams: cameraStreamsCapability,\n deviceDiscovery: deviceDiscoveryCapability,\n deviceStatus: deviceStatusCapability,\n doorbell: doorbellCapability,\n featureProbe: featureProbeCapability,\n motion: motionCapability,\n motionTrigger: motionTriggerCapability,\n ptzAutotrack: ptzAutotrackCapability,\n switch: switchCapability,\n zoneAnalytics: zoneAnalyticsCapability,\n zoneRules: zoneRulesCapability,\n zones: zonesCapability,\n}\n\n/**\n * Cap-name keyed runtime-state map (kebab-case keys, e.g. `'battery'`,\n * `'device-discovery'`). Companion to `DeviceLocalState` (which uses\n * camelCase property keys). Consumed by the\n * `IDeviceRuntimeState.getCapState` overload so callers passing a\n * cap-name literal get the typed slice back without an explicit\n * generic argument:\n *\n * const slice = this.runtimeState.getCapState('battery')\n * // ^^^^^ inferred as InferRuntimeState<typeof batteryCapability>\n *\n * Eliminates the `as`-cast at every `getCapState<X>('cap-name')` site.\n */\nexport interface CapNameToRuntimeStateMap {\n 'audio-metrics': InferRuntimeState<typeof audioMetricsCapability>\n 'battery': InferRuntimeState<typeof batteryCapability>\n 'brightness': InferRuntimeState<typeof brightnessCapability>\n 'camera-streams': InferRuntimeState<typeof cameraStreamsCapability>\n 'device-discovery': InferRuntimeState<typeof deviceDiscoveryCapability>\n 'device-status': InferRuntimeState<typeof deviceStatusCapability>\n 'doorbell': InferRuntimeState<typeof doorbellCapability>\n 'feature-probe': InferRuntimeState<typeof featureProbeCapability>\n 'motion': InferRuntimeState<typeof motionCapability>\n 'motion-trigger': InferRuntimeState<typeof motionTriggerCapability>\n 'ptz-autotrack': InferRuntimeState<typeof ptzAutotrackCapability>\n 'switch': InferRuntimeState<typeof switchCapability>\n 'zone-analytics': InferRuntimeState<typeof zoneAnalyticsCapability>\n 'zone-rules': InferRuntimeState<typeof zoneRulesCapability>\n 'zones': InferRuntimeState<typeof zonesCapability>\n}\n","import { z } from 'zod'\nimport { DeviceConfig } from './device-config.js'\nimport { DeviceRuntimeState } from './device-runtime-state.js'\nimport type { IDeviceRuntimeState } from './device-runtime-state.js'\nimport type { DeviceType, DeviceFeature, DeviceRole } from './device-type.js'\nimport type { DeviceContext } from './device-context.js'\nimport type { IDevice } from './device.js'\nimport type { ConfigUISchemaWithValues } from '../interfaces/config-ui.js'\nimport { deviceStatusCapability, type DeviceStatus } from '../capabilities/device-status.cap.js'\nimport { featureProbeCapability, type FeatureProbeStatus } from '../capabilities/feature-probe.cap.js'\nimport type { CapabilityDefinition, InferRuntimeState } from '../capabilities/capability-definition.js'\nimport { DEVICE_LOCAL_STATE_CAPS, type DeviceLocalState } from '../generated/device-local-state.js'\n\n// Zod 4's `ZodRawShape = $ZodShape = Record<string, $ZodType<unknown, unknown>>`\n// is too strict for concrete-shape schemas: a `z.object({ host: z.string(), … })`\n// produces `ZodObject<{ host: ZodString, … }>` whose fields' types\n// (`ZodString`, `ZodDefault<ZodNumber>`, …) don't widen to\n// `$ZodType<unknown, unknown>` once a subclass has 30+ fields, so\n// HikvisionCamera fails TS2344 on the constraint.\n//\n// Zod ships `$ZodLooseShape = Record<string, any>` for exactly this\n// pattern — generic constraints that should accept any concrete schema.\n// Using it on the type parameter keeps the typed inference path\n// (`z.infer<T>`, `T['shape']['host']`) intact while admitting concrete\n// schemas from subclasses.\nexport abstract class BaseDevice<T extends z.ZodObject<z.core.$ZodLooseShape> = z.ZodObject<z.ZodRawShape>> implements IDevice {\n readonly id: number\n readonly stableId: string\n readonly type: DeviceType\n readonly name: string\n readonly parentDeviceId: number | null\n readonly role?: DeviceRole\n /**\n * Cap-keyed runtime-state slice is the single source of truth for\n * `online`. Both getter and setter proxy to the slice — drivers can\n * write `this.online = true` ergonomically, and the cap event fires\n * automatically through the runtime-state writer. `markOnline()` is\n * kept as the explicit method form mandated by `IDevice`.\n */\n get online(): boolean {\n const slice = this.runtimeState.getCapState<DeviceStatus>('device-status')\n return slice?.online ?? false\n }\n set online(value: boolean) {\n this.markOnline(value)\n }\n\n /**\n * Generic per-cap runtime-state namespace. One entry per cap with\n * `runtimeState:` declared, auto-generated by codegen — see\n * `device-local-state.ts`. Drivers access via:\n *\n * `this.state.battery.sleeping = true` // patches the battery slice\n * `const pct = this.state.battery.percentage` // reads the battery slice\n * `this.state.deviceStatus.online = true` // mirrors `markOnline(true)`\n *\n * Adding a new cap with `runtimeState:` automatically extends this\n * namespace — drivers don't have to declare proxies. Reads return\n * `undefined` when the slice hasn't been seeded; writes patch via\n * `runtimeState.patchCapState` and validate against the cap's schema\n * (so partial writes need the slice to be seeded with the required\n * fields first — drivers do this on cap registration).\n *\n * For caps not exposed in `DeviceLocalState`, drivers can build their\n * own typed proxy via `this.sliceProxy(cap)`.\n */\n get state(): DeviceLocalState {\n if (!this._stateProxyCache) {\n const cache: Record<string, unknown> = {}\n const handler: ProxyHandler<Record<string, unknown>> = {\n get: (_target, key) => {\n const k = key as string\n if (k in cache) return cache[k]\n const cap = (DEVICE_LOCAL_STATE_CAPS as Record<string, CapabilityDefinition | undefined>)[k]\n if (!cap) return undefined\n const proxy = this.sliceProxy(cap)\n cache[k] = proxy\n return proxy\n },\n }\n this._stateProxyCache = new Proxy(cache, handler) as unknown as DeviceLocalState\n }\n return this._stateProxyCache\n }\n private _stateProxyCache?: DeviceLocalState\n abstract readonly features: readonly DeviceFeature[]\n readonly config: DeviceConfig<T>\n /**\n * Per-device runtime state, cap-keyed. Always installed — slices\n * for individual caps materialise as those caps register their\n * native providers (`ctx.registerNativeCap`). The cap's own\n * `runtimeState` schema is the source of truth for the slice\n * shape; drivers don't redeclare it, they just write through.\n *\n * Read: `this.runtimeState.getCapState('battery')` →\n * `{percentage, charging, sleeping, lastUpdated}` for any\n * provider that registers `batteryCapability`.\n * Write: `this.runtimeState.setCapState('battery', { … })`.\n *\n * Cross-process consumers reach this state through the\n * `deviceState` cap router (or via cap-specific events the driver\n * emits — e.g. `battery.onStatusChanged`). The local handle is\n * accessed in-process by the driver to avoid roundtrips.\n */\n readonly runtimeState: IDeviceRuntimeState\n readonly ctx: DeviceContext\n\n /**\n * Operator-organisational location label (room / area / zone).\n * Read from `ctx.deviceMeta.location`; mutated via\n * `kernel.devices.setLocation(id, value)`. Free-text — providers\n * don't interpret it; the UI groups devices by this for filters\n * like \"show me all cameras in Kitchen\". `null` when unset.\n */\n readonly location: string | null\n /**\n * Soft-disabled flag. When `true`, the device class is still\n * instantiated and visible in the UI (so the operator can flip\n * back on without re-adding) but lifecycle hooks (publishToBroker,\n * alarm-stream subscribe, …) MUST be gated by the driver to skip\n * work. The `BaseDevice` enforces this by exposing the flag here;\n * it does NOT mutate cap behaviour automatically — drivers consult\n * `this.disabled` at the top of their lifecycle methods. Read from\n * `ctx.deviceMeta.disabled`; mutated via\n * `kernel.devices.setDisabled(id, value)`.\n */\n readonly disabled: boolean\n\n constructor(\n ctx: DeviceContext,\n schema: T,\n options: {\n type: DeviceType\n /** Optional semantic role within parent — see `DeviceRole`. */\n role?: DeviceRole\n },\n ) {\n this.ctx = ctx\n this.id = ctx.id\n this.stableId = ctx.stableId\n this.type = options.type\n // Operator-organisational fields (`name` / `location` / `disabled`)\n // come exclusively from the kernel-managed meta surface. Production\n // contexts always populate `ctx.deviceMeta`; test fixtures must\n // supply it explicitly. No fallback to `options.name` — the only\n // way to set the display name is through the meta API.\n if (!ctx.deviceMeta) {\n throw new Error(\n `BaseDevice constructor: ctx.deviceMeta is required (id=${ctx.id} stableId=${ctx.stableId})`,\n )\n }\n this.name = ctx.deviceMeta.name\n this.location = ctx.deviceMeta.location\n this.disabled = ctx.deviceMeta.disabled\n this.role = options.role\n this.parentDeviceId = ctx.parentDeviceId\n // DeviceContext.persistConfig is typed as (data: unknown) => Promise<void>\n // to break the circular dependency between DeviceContext and every schema type T.\n // DeviceConfig.fromSchema requires (data: z.infer<T>) => Promise<void>, which is a\n // subtype of (data: unknown) => Promise<void> at runtime (TypeScript variance rules\n // prevent direct assignment for function parameters). The wrapper below narrows the\n // type without losing safety — the actual data passed is always z.infer<T> because\n // DeviceConfig itself only calls persistFn with validated T values.\n //\n // Self-hydrate: the kernel pre-loads the per-device persisted\n // config blob from the DB and stuffs it into `ctx.persistedConfig`\n // before this constructor runs. We seed `DeviceConfig` from that\n // blob alone — operator-supplied initial config (Add-Device form\n // input) reaches us via the same DB read because providers\n // pre-persist via `kernel.devices.create(stableId, Class, config)`\n // (or `persistInitialConfig` in the manual flow), which writes\n // the blob to the DB BEFORE constructing the device. The device\n // class therefore never sees an `initialData` constructor arg —\n // every config read goes through `this.config.get(...)` which is\n // a thin in-memory cache over the DB row. Schema defaults fill\n // any missing keys via Zod's parse pass.\n const seedData = ctx.persistedConfig ?? {}\n this.config = DeviceConfig.fromSchema(\n schema,\n (data: z.infer<T>) => ctx.persistConfig(data),\n seedData,\n ({ droppedKeys, issues }) => {\n // Stale persisted values that no longer match the schema —\n // logged once at boot so operators can see what got reset.\n // The DB blob is healed asynchronously inside `fromSchema`\n // (it persists the cleaned data), so this log is the only\n // visible trace of the recovery path firing.\n ctx.logger.warn('Device config recovery: dropping invalid persisted fields', {\n tags: { deviceId: ctx.id, stableId: ctx.stableId },\n meta: {\n droppedKeys: [...droppedKeys],\n firstIssue: issues[0]?.message ?? null,\n },\n })\n },\n )\n\n // Always install runtime state — schemas attach lazily as the\n // device's caps register their native providers (see\n // `ctx.registerNativeCap` wiring in the kernel context factory).\n //\n // Writer routes through `fetchDevice(id).deviceState.setCapSlice`\n // so we share the same per-device facade admin-ui + addons use.\n // The DeviceProxy auto-injects deviceId; the dispatch falls\n // through to the local hub provider (or its Moleculer bridge\n // proxy when device-manager runs cross-process).\n //\n // The proxy is fetched lazily on the first write and cached for\n // the device's lifetime — `getBindings` is one cheap query, and\n // `setCapSlice` is a system-cap call that doesn't read binding\n // entries (so cache staleness is irrelevant for this writer).\n let cachedProxy: Promise<import('../generated/device-proxy.js').DeviceProxy> | null = null\n const writer = async (capName: string, slice: Record<string, unknown>): Promise<void> => {\n if (!cachedProxy) cachedProxy = ctx.fetchDevice(ctx.id)\n const dev = await cachedProxy\n await dev.deviceState.setCapSlice({ capName, slice })\n }\n const initial = ctx.initialRuntimeState ?? {}\n this.runtimeState = DeviceRuntimeState.fromInitial(initial, writer)\n // Hand the reference back to the context so subsequent\n // `ctx.registerNativeCap` calls (fired from this constructor's\n // own `registerNativeCapabilities` chain) can install each\n // cap's `runtimeState` schema. Optional hook — test contexts\n // skip it; caps with runtime state in those contexts go memory-\n // only without schema validation.\n ctx.bindRuntimeState?.(this.runtimeState)\n\n // Auto-register the generic `device-status` cap so every device\n // exposes a uniform cap-keyed slice for the base device-level\n // flags (`online`, `lastChangedAt`). Cross-process consumers read\n // via `device-state.getCapSlice({deviceId, capName: 'device-status'})`\n // instead of having to special-case `online` against the device\n // summary RPC. Driver-specific caps (`battery`, `doorbell`, …)\n // own their own slices.\n ctx.registerNativeCap?.(deviceStatusCapability, {})\n // Seed the slice synchronously with the canonical pre-firmware\n // default (`online: false`) so the `online` getter resolves and\n // the first cross-process read returns a populated record.\n const seed: DeviceStatus = { online: false, lastChangedAt: Date.now() }\n this.runtimeState.setCapState('device-status', seed)\n\n // Auto-register the generic `feature-probe` cap. Drivers populate it\n // from `onProbe()` (kernel calls it once after register, before\n // accessory reconciliation). The slice is the single source of truth\n // for `getAccessoryChildren()` decisions and the public `features`\n // array — it replaces the older driver-local `deviceCache.has*`\n // duplication.\n ctx.registerNativeCap?.(featureProbeCapability, {})\n const probeSeed: FeatureProbeStatus = {\n flags: {},\n deviceType: null,\n model: null,\n channelCount: null,\n lastProbedAt: 0,\n lastFetchedAt: 0,\n }\n this.runtimeState.setCapState('feature-probe', probeSeed)\n }\n\n async removeDevice(): Promise<void> {\n // Override in subclass for cleanup (disconnect, stop streams, etc.)\n }\n\n /**\n * Set the device's online flag. Called by `BaseDeviceProvider` after\n * aggregating per-profile stream-broker health, or directly by drivers\n * that have provider-side liveness signals (e.g. ONVIF heartbeats,\n * Reolink Baichuan firmware push events). Mirrors the new value into\n * the `device-status` runtime-state slice so cross-process consumers\n * pick it up via the standard cap-state channel. Subclasses can\n * override to gate side effects on the transition.\n */\n markOnline(online: boolean): void {\n if (this.online === online) return\n const next: DeviceStatus = { online, lastChangedAt: Date.now() }\n this.runtimeState.setCapState('device-status', next)\n }\n\n /**\n * Re-publish the device's current `features` array to the persisted\n * meta blob. Drivers call this after a probe finishes when the live\n * `features` getter has gained new flags (e.g. `hasIntercom` flips\n * to true → `DeviceFeature.TwoWayAudio` joins the list).\n *\n * Without this, only the construction-time snapshot is written —\n * `deviceManager.registerDevice` is invoked once per boot, so probe-\n * driven additions don't reach the persisted index until the next\n * server restart, and `getDevice` / `listAll` keep returning the\n * stale list for forked-worker devices (whose live IDevice instance\n * is invisible to the hub registry).\n *\n * Idempotent: re-calling with the same features just no-ops on the\n * persisted meta. Best-effort: lookup or write failures are logged\n * at debug and swallowed — the live `device.features` getter is\n * still authoritative within this process, so callers never block\n * device boot on a meta refresh.\n */\n protected async refreshFeatures(): Promise<void> {\n const api = this.ctx.api as unknown as {\n deviceManager?: {\n registerDevice?: { mutate: (input: {\n addonId: string\n stableId: string\n id: number\n type: string\n name: string\n parentDeviceId: number | null\n features?: readonly string[]\n config: Record<string, unknown>\n }) => Promise<void> }\n }\n }\n const action = api?.deviceManager?.registerDevice\n if (!action) return\n try {\n await action.mutate({\n addonId: this.ctx.deviceMeta.addonId,\n stableId: this.stableId,\n id: this.id,\n type: this.type,\n name: this.name,\n parentDeviceId: this.parentDeviceId,\n features: [...this.features],\n // Empty config — the kernel's registerDevice ignores the field\n // when there's no payload (the per-device store is the\n // canonical source after construction).\n config: {},\n })\n } catch (err) {\n // No logger on BaseDevice (would require ctx wiring) — drivers\n // that want visibility wrap the call themselves.\n void err\n }\n }\n\n /**\n * Typed read-through to a cap-keyed runtime-state slice. Drivers\n * call `this.getCapSlice(batteryCapability)` and the return type\n * is inferred from the cap's `runtimeState` Zod schema — no string\n * key, no manual generic. Returns `null` when the slice hasn't\n * been written yet (e.g. driver hasn't seeded battery yet).\n */\n protected getCapSlice<TCap extends CapabilityDefinition>(cap: TCap): InferRuntimeState<TCap> | null {\n const slice = this.runtimeState.getCapState(cap.name)\n return (slice as InferRuntimeState<TCap> | undefined) ?? null\n }\n\n /**\n * Typed writer to a cap-keyed runtime-state slice. Routes through\n * the runtime-state writer (validate → persist → emit cap event).\n * Equivalent to `this.runtimeState.setCapState(cap.name, value)`\n * but with the cap's `runtimeState` schema enforcing the value\n * shape at compile time. Mirrors the symmetry of\n * `getCapSlice` / `setCapSlice` for cross-cap consistency.\n */\n protected setCapSlice<TCap extends CapabilityDefinition>(\n cap: TCap,\n value: InferRuntimeState<TCap> & Record<string, unknown>,\n ): void {\n this.runtimeState.setCapState(cap.name, value)\n }\n\n /**\n * Field-level read/write proxy over a cap's runtime-state slice.\n * Drivers that want ergonomic per-field access declare:\n *\n * ```ts\n * protected battery = this.sliceProxy(batteryCapability)\n * // …\n * this.battery.sleeping = true // patches the slice\n * const charging = this.battery.charging // reads the slice\n * ```\n *\n * Reads return `undefined` when the slice hasn't been seeded yet\n * (cap not registered, or seeded but the field is absent). Writes\n * route through `runtimeState.patchCapState` so the cap's `runtimeState`\n * schema validates the merged result and the cap event fires.\n *\n * Pattern is generic — same shape works for `battery`, `device-status`,\n * `motion`, `doorbell`, anything with a `runtimeState:` schema. Drivers\n * declare one proxy per cap they read/write directly.\n */\n protected sliceProxy<TCap extends CapabilityDefinition>(cap: TCap): InferRuntimeState<TCap> {\n const target: Record<string, unknown> = {}\n const handler: ProxyHandler<Record<string, unknown>> = {\n get: (_, key) => {\n const slice = this.runtimeState.getCapState(cap.name)\n return slice?.[key as string]\n },\n set: (_, key, value: unknown) => {\n this.runtimeState.patchCapState(cap.name, { [key as string]: value })\n return true\n },\n has: (_, key) => {\n const slice = this.runtimeState.getCapState(cap.name)\n return slice ? key in slice : false\n },\n ownKeys: () => {\n const slice = this.runtimeState.getCapState(cap.name)\n return slice ? Object.keys(slice) : []\n },\n getOwnPropertyDescriptor: (_, key) => {\n const slice = this.runtimeState.getCapState(cap.name)\n if (!slice || !(key in slice)) return undefined\n return { configurable: true, enumerable: true, value: slice[key as string] }\n },\n }\n return new Proxy(target, handler) as InferRuntimeState<TCap>\n }\n\n /**\n * Default empty settings UI. Drivers override this to expose an\n * editable form in the device-details page. Returning an empty sections\n * array signals \"nothing to contribute\" — the aggregator drops the\n * contribution entirely rather than rendering a blank panel.\n */\n getSettingsUISchema(): ConfigUISchemaWithValues {\n return { sections: [] }\n }\n\n /**\n * Default write path: forward the flat patch directly to storage.\n * Drivers that project a UI shape different from storage (e.g. `RtspCamera`\n * exposing `mainStreamUrl`/`subStreamUrl` over `streams[]`) override this\n * to reshape before `config.setAll`.\n */\n async applySettingsPatch(patch: Record<string, unknown>): Promise<void> {\n await this.config.setAll(patch)\n }\n\n // ── Lifecycle hooks ────────────────────────────────────────────────\n //\n // The kernel orchestrates the device lifecycle in distinct phases.\n // Drivers override only the hooks they need:\n //\n // 1. Construct — `new DeviceClass(ctx)` (sync)\n // 2. RegisterIdentity — kernel writes meta + id to device-manager\n // 3. Probe — `onProbe()` populates `feature-probe` slice\n // 4. ReconcileAccessories — kernel calls `getAccessoryChildren()`\n // (sees post-probe flags), spawns missing,\n // removes orphans, refreshes meta features\n // 5. Activate — `onActivate()` does \"device is live\" work:\n // broker publish, snapshot tabs, watchdogs\n //\n // Failures in `onProbe` / `onActivate` are logged and swallowed — the\n // device IS already registered; partial init shouldn't unwind the\n // create the caller succeeded at.\n\n /**\n * Phase 3 — populate device-scoped state needed by downstream phases\n * (accessory reconciliation, public `features` array, optional cap\n * registration). Called ONCE per construction, after register but\n * before `getAccessoryChildren()`.\n *\n * Drivers write the `feature-probe` runtime-state slice via\n * `this.runtimeState.setCapState('feature-probe', {...})` — flag bag\n * is open (Reolink writes `hasPtz/hasIntercom`, Hikvision writes\n * `hasSupplementalLight/hasAlarmIo`, etc).\n *\n * Default: no-op (driver had no probe to run).\n */\n async onProbe(): Promise<void> {\n /* override in subclass */\n }\n\n /**\n * Phase 5 — fired after the device + its accessories are registered.\n * Drivers publish streams to the broker, kick off background tasks,\n * or subscribe to lib events that need a fully-registered device id.\n *\n * Default: no-op.\n *\n * RENAMED FROM `onCreated` (which still exists for back-compat in this\n * pass). The new name reflects the post-probe, post-accessory contract.\n */\n async onActivate(): Promise<void> {\n /* override in subclass */\n }\n\n /**\n * Re-run the probe + reconcile accessories + refresh features meta.\n * Drivers call this when device-side state changes (battery cam wakes,\n * firmware update, manual operator trigger).\n *\n * The kernel injects `_kernelReprobe` on registration so this method\n * delegates to the same orchestrator that runs the boot-time phase\n * 3 + 4 sequence. Drivers should NOT override this — they override\n * `onProbe()` instead.\n */\n async reprobe(): Promise<void> {\n if (this._kernelReprobe) await this._kernelReprobe()\n else await this.onProbe()\n }\n\n /**\n * Kernel-injected callback that runs the full post-probe orchestration\n * (onProbe → registerDevice meta refresh → accessory reconciliation).\n * Set by `device-cap-proxy.register()`. Drivers should not touch this\n * directly — call `reprobe()` instead.\n */\n _kernelReprobe?: () => Promise<void>\n\n /**\n * Declare accessory child devices the kernel should auto-spawn\n * after `onProbe()` resolves. Each spec fully describes one child\n * — stableId suffix (deterministic per kind for restore-safety),\n * meta (type / name / location), config (initial blob the child\n * self-hydrates), and a factory that constructs the concrete\n * class with whatever closure-captured refs it needs (typically\n * `this` for the parent reference).\n *\n * The kernel handles the rest: allocateDeviceId, persistInitialConfig\n * (skipped on restore when the row already exists),\n * persistInitialMeta, createContext, factory invocation, register,\n * and recursive lifecycle (probe + accessories + activate).\n *\n * Implementations should derive children from\n * `this.runtimeState.getCapState('feature-probe')` (post-probe truth).\n * Drivers can use the `getProbeFlags()` helper to read the flag bag\n * with a typed cast.\n *\n * Default: no children.\n */\n getAccessoryChildren(): readonly AccessoryChildSpec[] {\n return []\n }\n\n /**\n * Read the current feature-probe flag bag with a typed cast. Helper\n * for `getAccessoryChildren()` and `features` getters that derive\n * outputs from the probe results.\n */\n protected getProbeFlags<F extends Record<string, unknown> = Record<string, unknown>>(): F {\n const slice = this.runtimeState.getCapState<FeatureProbeStatus>('feature-probe')\n return (slice?.flags ?? {}) as F\n }\n\n /**\n * Returns true once `onProbe` has completed at least once\n * (`lastProbedAt > 0`). Drivers gate `getAccessoryChildren()` on this\n * to avoid spawning stale accessories on a fresh device whose probe\n * hasn't landed yet.\n */\n protected hasProbed(): boolean {\n const slice = this.runtimeState.getCapState<FeatureProbeStatus>('feature-probe')\n return (slice?.lastProbedAt ?? 0) > 0\n }\n}\n\n/**\n * Specification for one accessory child a parent device wants the\n * kernel to auto-spawn. Returned from `BaseDevice.getAccessoryChildren()`.\n */\nexport interface AccessoryChildSpec {\n /**\n * Stable suffix appended to the parent's stableId to derive the\n * child's stableId (e.g. `siren` → `${parent.stableId}-siren`).\n * Must be deterministic per (parent, accessory kind) so restore\n * resolves the same numeric id and re-instantiates without\n * orphaning the persisted config.\n */\n readonly stableIdSuffix: string\n /** Operator-organisational meta passed to `kernel.devices.create()`'s\n * `initialMeta` arg. The kernel pre-writes the meta row before\n * the child class constructor runs. */\n readonly meta: import('./device-management.js').InitialDeviceMeta\n /** Initial config blob the child self-hydrates from on first\n * create. Empty `{}` on restore (DB row carries the canonical\n * values) — the kernel detects the existing row and skips the\n * pre-persist step. */\n readonly config: Record<string, unknown>\n /**\n * Constructor closure — invoked with the kernel-built context\n * after meta + config are persisted. Closures over the parent\n * reference for child classes that need `parent` as a constructor\n * arg (e.g. accessories that share the parent's connection). The\n * returned IDevice is registered + `onCreated`-fired by the\n * kernel.\n */\n readonly factory: (ctx: DeviceContext) => IDevice\n}\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\nconst ProviderStatusSchema = z.object({\n connected: z.boolean(),\n deviceCount: z.number(),\n error: z.string().optional(),\n})\n\nconst DiscoveredDeviceSchema = z.object({\n externalId: z.string(),\n name: z.string(),\n type: z.string(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\n/**\n * Candidate handed back from discovery and accepted by\n * `adoptDiscoveredDevice`. Shape mirrors the in-process\n * `DiscoveredDevice` interface used by `DeviceDiscovery`.\n */\nconst DiscoveryCandidateSchema = z.object({\n stableId: z.string(),\n type: z.enum(DeviceType),\n suggestedName: z.string(),\n prefilledConfig: z.record(z.string(), z.unknown()),\n})\n\n/**\n * Flat device summary returned by `createDevice` / `adoptDiscoveredDevice`.\n * Mirrors `toDeviceShape()` output in `device-management.router.ts` so the\n * tRPC layer can pass it through without reshaping.\n */\nconst DeviceSummarySchema = z.object({\n id: z.number(),\n stableId: z.string(),\n addonId: z.string(),\n type: z.string(),\n name: z.string(),\n parentDeviceId: z.number().nullable(),\n online: z.boolean(),\n features: z.array(z.string()),\n config: z.record(z.string(), z.unknown()),\n})\n\n/**\n * Result of a live field test (e.g. probing an RTSP URL during device\n * creation). Matches the UI-side `FieldProbeResult` in\n * `interfaces/config-ui.ts` — the admin `FormBuilder` renders the\n * returned `labels` as chips next to the input.\n */\nconst FieldProbeResultSchema = z.object({\n status: z.enum(['ok', 'error']),\n labels: z.array(z.string()).optional(),\n error: z.string().optional(),\n})\n\n/**\n * The output of `getChildCreationSchema` is a UI schema tree. We store\n * it as `unknown` at the capability layer — the router just passes it\n * through and the admin UI renders it via `FormBuilder`. The actual\n * type is `ConfigUISchema` (see `packages/types/src/interfaces/config-ui.ts`),\n * but we deliberately avoid a Zod mirror because the union is large and\n * not meant for runtime validation at this seam.\n */\nconst CreationSchemaOutputSchema = z.unknown()\n\nexport const deviceProviderCapability = {\n name: 'device-provider',\n scope: 'system',\n mode: 'collection',\n methods: {\n // ── Lifecycle + introspection ─────────────────────────────────────\n start: method(z.void(), z.void(), { kind: 'mutation' }),\n stop: method(z.void(), z.void(), { kind: 'mutation' }),\n getStatus: method(z.void(), ProviderStatusSchema),\n getDevices: method(z.void(), z.array(z.object({\n id: z.string(),\n name: z.string(),\n type: z.string(),\n }))),\n\n // ── Discovery + adoption (optional — see supportsDiscovery) ──────\n supportsDiscovery: method(z.object({}), z.boolean()),\n discoverDevices: method(\n z.object({}),\n z.array(DiscoveryCandidateSchema),\n { kind: 'mutation', auth: 'admin' },\n ),\n adoptDiscoveredDevice: method(\n z.object({ candidate: DiscoveryCandidateSchema }),\n DeviceSummarySchema,\n { kind: 'mutation', auth: 'admin' },\n ),\n\n // ── Manual creation (optional — see supportsManualCreation) ──────\n supportsManualCreation: method(z.object({}), z.boolean()),\n /**\n * Fetch the creation form schema for a given DeviceType. Returns\n * `null` when the provider does not support manually creating\n * devices of that type. The output is a `ConfigUISchema` — the\n * router type-asserts it at the boundary.\n */\n getChildCreationSchema: method(\n z.object({ type: z.enum(DeviceType) }),\n CreationSchemaOutputSchema,\n ),\n createDevice: method(\n z.object({\n type: z.enum(DeviceType),\n config: z.record(z.string(), z.unknown()),\n }),\n DeviceSummarySchema,\n { kind: 'mutation', auth: 'admin' },\n ),\n /**\n * Test a single field in the creation form before the device has\n * been persisted. Typical use: probing an RTSP URL entered by the\n * user. Providers that don't support field probing return\n * `{ success: true, message: 'Field test not supported' }`.\n *\n * `formValues` is the live snapshot of every field in the form at\n * the moment the user clicked Test — useful for probes that depend\n * on multiple fields together (e.g. Reolink autodetect needs host\n * + credentials + UID + transport mode in a single call). Optional\n * for backwards compatibility; providers free to ignore it.\n */\n testCreationField: method(\n z.object({\n type: z.enum(DeviceType),\n key: z.string(),\n value: z.unknown(),\n formValues: z.record(z.string(), z.unknown()).optional(),\n }),\n FieldProbeResultSchema,\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IDeviceProvider = InferProvider<typeof deviceProviderCapability>\n\nexport {\n ProviderStatusSchema,\n DiscoveredDeviceSchema,\n DiscoveryCandidateSchema,\n DeviceSummarySchema,\n FieldProbeResultSchema,\n}\n","import type {\n ProviderRegistration,\n ConfigUISchema,\n SavedDevice,\n IDevice,\n} from '../index.js'\nimport { BaseAddon } from '../addon/base-addon.js'\nimport { deviceProviderCapability } from '../capabilities/device-provider.cap.js'\nimport { DeviceType } from './device-type.js'\nimport type { CreateDeviceSpec } from './device-management.js'\nimport type { DeviceConstructor } from './device-context.js'\n\n// ── Shared interfaces (previously duplicated in each provider) ──────\n\nexport interface DiscoveryCandidate {\n readonly stableId: string\n readonly type: DeviceType\n readonly suggestedName: string\n readonly prefilledConfig: Record<string, unknown>\n}\n\nexport interface DeviceSummary {\n readonly id: number\n readonly stableId: string\n readonly addonId: string\n readonly type: string\n readonly name: string\n readonly parentDeviceId: number | null\n readonly online: boolean\n readonly features: readonly string[]\n readonly config: Record<string, unknown>\n}\n\nexport interface ProviderStatus {\n readonly connected: boolean\n readonly deviceCount: number\n readonly error?: string\n}\n\nexport interface FieldProbeResult {\n readonly status: 'ok' | 'error'\n readonly labels?: readonly string[]\n readonly error?: string\n}\n\n// ── Utility ─────────────────────────────────────────────────────────\n\n/**\n * Convert an IDevice to the flat DeviceSummary shape expected by the\n * device-provider cap router. Shared across all providers.\n */\nexport function toDeviceSummary(device: IDevice, addonId: string): DeviceSummary {\n const config: Record<string, unknown> = {}\n for (const entry of device.config.entries()) {\n config[entry.key] = entry.value\n }\n return {\n id: device.id,\n stableId: device.stableId,\n addonId,\n type: String(device.type),\n name: device.name,\n parentDeviceId: device.parentDeviceId,\n online: device.online,\n features: [...device.features],\n config,\n }\n}\n\n// ── Base class ──────────────────────────────────────────────────────\n\n/**\n * Base class for device-provider addons (rtsp, onvif, frigate).\n *\n * Provides default implementations for the common device-provider cap\n * methods (`start`, `stop`, `getStatus`, `getDevices`, `supportsDiscovery`,\n * `supportsManualCreation`, `toDeviceSummary`). Subclasses override the\n * methods that differ per provider.\n *\n * @example\n * ```ts\n * class RtspProvider extends BaseDeviceProvider {\n * protected readonly addonId = 'provider-rtsp'\n * protected readonly providerName = 'RTSP'\n *\n * protected async onCreateDevice(input) { ... }\n * protected async onGetCreationSchema(type) { ... }\n * protected async onRestoreDevices(saved) { ... }\n * }\n * ```\n */\nexport abstract class BaseDeviceProvider<TConfig extends object = Record<string, unknown>> extends BaseAddon<TConfig> {\n /** Addon ID used in DeviceSummary. Must match package.json id. */\n protected abstract readonly addonId: string\n\n /** Human-readable provider name for log messages. */\n protected abstract readonly providerName: string\n\n // ── Lifecycle (BaseAddon hooks) ─────────────────────────────────────\n\n protected async onInitialize(): Promise<ProviderRegistration[]> {\n this.ctx.logger.info(`${this.providerName} Provider initialized`)\n return [{ capability: deviceProviderCapability, provider: this }]\n }\n\n protected async onShutdown(): Promise<void> {\n // Decommission every device this provider owns BEFORE returning.\n // Mirrors what Moleculer SIGTERM + in-process restart paths\n // expect: each device's `removeDevice()` lifecycle hook fires\n // (closes alarm streams, ISAPI clients, polling timers, intercom\n // sessions, …), native caps unregister cleanly, registry entries\n // drop. The persisted device-meta / config rows stay intact so\n // the next boot's `restoreDevices` rehydrates the same set with\n // freshly-instantiated IDevice classes — that's the whole point\n // of \"decommission, don't delete\".\n //\n // Subclasses that need extra teardown (Moleculer service handle,\n // background workers) should override and call `super.onShutdown()`\n // first so devices are torn down before vendor-specific resources.\n const devices = await this.ctx.kernel.devices?.getAll() ?? []\n for (const device of devices) {\n try {\n await this.ctx.kernel.devices?.decommission(device.id)\n } catch (err) {\n this.ctx.logger.warn(`${this.providerName}: decommission failed`, {\n tags: { deviceId: device.id, stableId: device.stableId },\n meta: { error: err instanceof Error ? err.message : String(err) },\n })\n }\n }\n this.ctx.logger.info(`${this.providerName} Provider shut down`, {\n meta: { decommissionedCount: devices.length },\n })\n }\n\n // ── device-provider cap — lifecycle + introspection ─────────────────\n // Default implementations. Override in subclass if needed.\n\n async start(): Promise<void> {\n /* no-op — providers are passive by default */\n }\n\n async stop(): Promise<void> {\n /* no-op */\n }\n\n async getStatus(): Promise<ProviderStatus> {\n const all = (await this.ctx.kernel.devices?.getAll()) ?? []\n return { connected: true, deviceCount: all.length }\n }\n\n async getDevices(): Promise<ReadonlyArray<{ id: string; name: string; type: string }>> {\n const all = (await this.ctx.kernel.devices?.getAll()) ?? []\n return all.map((d) => ({ id: d.stableId, name: d.name, type: String(d.type) }))\n }\n\n // ── device-provider cap — discovery ─────────────────────────────────\n // Default: no discovery. Override in providers that support it (ONVIF).\n\n async supportsDiscovery(): Promise<boolean> {\n return false\n }\n\n async discoverDevices(): Promise<readonly DiscoveryCandidate[]> {\n return []\n }\n\n async adoptDiscoveredDevice(_input: {\n candidate: DiscoveryCandidate\n }): Promise<DeviceSummary> {\n throw new Error(`${this.providerName} provider does not support discovery-based adoption`)\n }\n\n // ── device-provider cap — manual creation ───────────────────────────\n // Default: supports manual creation. Subclass must implement\n // onGetCreationSchema and onCreateDevice.\n\n async supportsManualCreation(): Promise<boolean> {\n return true\n }\n\n async getChildCreationSchema(input: { type: DeviceType }): Promise<ConfigUISchema | null> {\n return this.onGetCreationSchema(input.type)\n }\n\n /**\n * Default kernel-orchestrated `createDevice` implementation. The\n * subclass's `onCreateDevice` returns a declarative\n * `CreateDeviceSpec` (`{meta, config}`) — this method handles\n * stableId generation, class lookup, kernel.devices.create\n * dispatch, and DeviceSummary mapping. Subclasses should NOT\n * override this method; override `onCreateDevice` and\n * `deviceClasses` instead.\n */\n async createDevice(input: {\n type: DeviceType\n config: Record<string, unknown>\n }): Promise<DeviceSummary> {\n const spec = await this.onCreateDevice(input.type, input.config)\n const Class = this.deviceClasses[spec.meta.type] as DeviceConstructor<IDevice> | undefined\n if (!Class) {\n throw new Error(\n `${this.providerName} provider: no device class registered for type \"${spec.meta.type}\" — add it to the deviceClasses map`,\n )\n }\n const stableId = this.generateStableId(spec.meta.type, spec.config)\n const device = await this.ctx.kernel.devices!.create(\n stableId,\n Class,\n spec.config,\n null,\n spec.meta,\n )\n if (spec.onAfterCreate) {\n try {\n await spec.onAfterCreate(device)\n } catch (err) {\n this.ctx.logger.warn('createDevice: onAfterCreate hook threw — device is already registered', {\n tags: { deviceId: device.id, stableId },\n meta: { error: err instanceof Error ? err.message : String(err) },\n })\n }\n }\n return this.toSummary(device)\n }\n\n /**\n * Generate a stableId for a newly-created device. Default uses the\n * `${addonId}-${Date.now()}` pattern as a unique-but-opaque\n * fallback; any provider that has access to durable hardware\n * identity (UID, MAC, serial) should override and derive from it\n * so re-adding the same physical device reuses its persisted row.\n *\n * `config` is the parsed CreateDeviceSpec.config the subclass\n * returned from `onCreateDevice` — the override has access to\n * every operator-supplied + autodetect-resolved field. Optional\n * for back-compat: existing overrides that take only `type`\n * keep working unchanged.\n */\n protected generateStableId(_type: DeviceType, _config?: Record<string, unknown>): string {\n return `${this.addonId}-${Date.now()}`\n }\n\n async testCreationField(_input: {\n type: DeviceType\n key: string\n value: unknown\n formValues?: Record<string, unknown>\n }): Promise<FieldProbeResult> {\n return { status: 'ok', labels: ['probe not implemented'] }\n }\n\n // ── Boot restore ────────────────────────────────────────────────────\n\n async restoreDevices(savedDevices: readonly SavedDevice[]): Promise<void> {\n await this.onRestoreDevices(savedDevices)\n if (savedDevices.length > 0) {\n this.ctx.logger.info(`Restored ${savedDevices.length} ${this.providerName} device(s)`)\n }\n }\n\n // ── Subclass hooks ──────────────────────────────────────────────────\n\n /**\n * Concrete device classes this provider can spawn, keyed by\n * `DeviceType`. Used by:\n * - `createDevice` to look up the class for the type the operator\n * selected in the Add-Device modal\n * - the default `onRestoreDevices` to instantiate persisted rows\n * based on their `type` field\n *\n * Required for the declarative create + restore flow. Providers\n * that need custom-arg constructors (accessory child devices) wire\n * those up via `BaseDevice.getAccessoryChildren()` instead — the\n * top-level type → class map only handles parent devices.\n */\n protected abstract readonly deviceClasses: Partial<Record<DeviceType, DeviceConstructor<IDevice>>>\n\n /** Return the creation form schema for a given device type, or null if unsupported. */\n protected abstract onGetCreationSchema(type: DeviceType): Promise<ConfigUISchema | null>\n\n /**\n * Build the create spec from operator-supplied form values. Returns\n * `{meta, config}` — kernel handles allocateId, persist, instantiate,\n * register, and accessory auto-spawn. Provider's only job is to:\n * - validate / probe the input\n * - emit the meta (`type`, `name`, optional `location`)\n * - emit the `config` blob the device class will self-hydrate\n */\n protected abstract onCreateDevice(type: DeviceType, config: Record<string, unknown>): Promise<CreateDeviceSpec>\n\n /**\n * Restore devices from persisted state. Two-pass:\n *\n * 1. **Top-level pass** — invokes `kernel.devices.create()` for every\n * `parentDeviceId === null` row using the `deviceClasses` map.\n * The kernel's register flow handles `getAccessoryChildren()` for\n * each parent (siren / floodlight / PIR / etc).\n *\n * 2. **Hub-adopted children pass** — for rows with\n * `parentDeviceId !== null` whose `type` IS in `deviceClasses`\n * (e.g. Reolink hub-adopted cameras under an NVR), spawn them\n * explicitly with the persisted `parentDeviceId`. These are\n * NOT accessory children — they're first-class adopted devices\n * that just happen to have a parent. Without this pass, every\n * server restart would lose hub-adopted cameras (their type is\n * in `deviceClasses` but parent's `getAccessoryChildren` doesn't\n * spawn them — that callback is only for purpose-built\n * accessory roles).\n *\n * Rows whose `type` is NOT in `deviceClasses` are skipped — those\n * are accessory children (siren/light/sensor) that the kernel's\n * accessory-spawn flow handles via the parent's\n * `getAccessoryChildren()`. Override only when the default doesn't\n * fit.\n */\n protected async onRestoreDevices(savedDevices: readonly SavedDevice[]): Promise<void> {\n // Pass 1 — top-level\n const restored = new Set<number>()\n for (const saved of savedDevices) {\n if (saved.parentDeviceId !== null) continue\n const Class = this.deviceClasses[saved.type] as DeviceConstructor<IDevice> | undefined\n if (!Class) {\n this.ctx.logger.warn('No device class registered for restored type — skipping', {\n tags: { stableId: saved.stableId },\n meta: { type: saved.type },\n })\n continue\n }\n try {\n await this.ctx.kernel.devices!.create(saved.stableId, Class, {})\n restored.add(saved.id)\n } catch (err) {\n this.ctx.logger.warn('Failed to restore device', {\n tags: { stableId: saved.stableId },\n meta: { type: saved.type, error: err instanceof Error ? err.message : String(err) },\n })\n }\n }\n // Pass 2 — hub-adopted children (first-class devices with a parent\n // that is itself a registered device class). Iterates in order of\n // declared `parentDeviceId` to handle nested hubs gracefully.\n const childRows = savedDevices.filter(s => s.parentDeviceId !== null)\n for (const saved of childRows) {\n const Class = this.deviceClasses[saved.type] as DeviceConstructor<IDevice> | undefined\n if (!Class) continue // not a first-class type → accessory, skip\n if (saved.parentDeviceId === null) continue\n if (!restored.has(saved.parentDeviceId)) {\n // Parent isn't a known top-level device this provider owns —\n // probably a stale row pointing at a removed parent. Leave it\n // alone; orphan reconciliation runs later.\n continue\n }\n try {\n await this.ctx.kernel.devices!.create(\n saved.stableId,\n Class,\n {},\n saved.parentDeviceId,\n )\n restored.add(saved.id)\n } catch (err) {\n this.ctx.logger.warn('Failed to restore hub-adopted child', {\n tags: { stableId: saved.stableId, parentDeviceId: saved.parentDeviceId },\n meta: { type: saved.type, error: err instanceof Error ? err.message : String(err) },\n })\n }\n }\n }\n\n // ── Utility ─────────────────────────────────────────────────────────\n\n /** Convert an IDevice to the flat DeviceSummary for the cap router. */\n protected toSummary(device: IDevice): DeviceSummary {\n return toDeviceSummary(device, this.addonId)\n }\n}\n","import { z } from 'zod'\nimport type {\n ConfigUISchema,\n ConfigField,\n ConfigTextField,\n ConfigNumberField,\n ConfigBooleanField,\n ConfigSelectField,\n ConfigPasswordField,\n ConfigTextAreaField,\n} from '../interfaces/config-ui.js'\n\n// --- Entry type matching DeviceConfig.entries() output ---\n\nexport interface DeviceConfigEntry {\n key: string\n schema: z.ZodType\n value: unknown\n description?: string\n}\n\n// --- Internal Zod v4 _def shapes (accessed at runtime, not exposed in typings) ---\n\ninterface ZodV4CheckDef {\n check: string\n value?: number\n inclusive?: boolean\n}\n\ninterface ZodV4Check {\n _zod: { def: ZodV4CheckDef }\n}\n\ninterface ZodV4NumberDef {\n type: string\n checks?: ZodV4Check[]\n}\n\ninterface ZodV4DefaultDef {\n type: string\n defaultValue: unknown\n innerType: z.ZodType\n}\n\n/** Access Zod v4 internal .def — not in public typings but stable at runtime */\nfunction zodDef<T>(schema: z.ZodType): T {\n return (schema as unknown as { def: T }).def\n}\n\n/** Access internal properties on a Zod schema instance */\nfunction zodInternals<T>(schema: z.ZodType): T {\n return schema as unknown as T\n}\n\n// --- Public API ---\n\n/**\n * Convert DeviceConfig.entries() output to ConfigUISchema for the admin UI FormBuilder.\n *\n * Each entry's Zod type is inspected to determine the correct ConfigField type:\n * - ZodString → 'text' (or 'password' when key contains \"password\"/\"secret\"/\"token\"/\"apikey\")\n * - ZodNumber → 'number' (extracts min/max/step from Zod v4 checks)\n * - ZodBoolean → 'boolean'\n * - ZodEnum → 'select' (options built from enum values)\n * - Anything else → 'text' fallback\n *\n * Wrapper types ZodDefault, ZodOptional, and ZodNullable are unwrapped transparently.\n * Default values are extracted from ZodDefault wrappers.\n */\nexport function zodEntriesToConfigUI(\n entries: readonly DeviceConfigEntry[],\n sectionTitle = 'Configuration',\n sectionId = 'main',\n): ConfigUISchema {\n const fields: ConfigField[] = entries.map(entry =>\n zodToConfigField(entry.key, entry.schema, entry.description),\n )\n\n return {\n sections: [\n {\n id: sectionId,\n title: sectionTitle,\n fields,\n },\n ],\n }\n}\n\n// --- Internal helpers ---\n\nfunction zodToConfigField(key: string, schema: z.ZodType, description?: string): ConfigField {\n const inner = unwrapZod(schema)\n const defaultValue = getZodDefault(schema)\n const label = description ?? humanizeKey(key)\n\n const base = {\n key,\n label,\n description,\n default: defaultValue,\n } as const\n\n if (inner instanceof z.ZodString) {\n return buildStringField(key, base)\n }\n\n if (inner instanceof z.ZodNumber) {\n return buildNumberField(inner, base)\n }\n\n if (inner instanceof z.ZodBoolean) {\n const field: ConfigBooleanField = { ...base, type: 'boolean' }\n return field\n }\n\n if (inner instanceof z.ZodEnum) {\n return buildEnumField(inner, base)\n }\n\n // Arrays + objects don't fit any primitive field — render as a JSON\n // textarea so the operator at least sees the shape and can copy/edit\n // it, instead of `[object Object],…` produced by the text fallback.\n // `isJson: true` tells the UI + hydrator to round-trip via JSON.\n if (inner instanceof z.ZodArray || inner instanceof z.ZodObject) {\n const field: ConfigTextAreaField = { ...base, type: 'textarea', rows: 6, isJson: true }\n return field\n }\n\n // Fallback — render as plain text\n const fallback: ConfigTextField = { ...base, type: 'text' }\n return fallback\n}\n\nfunction buildStringField(\n key: string,\n base: { key: string; label: string; description?: string; default?: unknown },\n): ConfigTextField | ConfigPasswordField {\n const lowerKey = key.toLowerCase()\n const isSecret =\n lowerKey.includes('password') ||\n lowerKey.includes('secret') ||\n lowerKey.includes('token') ||\n lowerKey.includes('apikey') ||\n lowerKey.includes('api_key')\n\n if (isSecret) {\n const field: ConfigPasswordField = { ...base, type: 'password', showToggle: true }\n return field\n }\n\n const field: ConfigTextField = { ...base, type: 'text' }\n return field\n}\n\nfunction buildNumberField(\n inner: z.ZodNumber,\n base: { key: string; label: string; description?: string; default?: unknown },\n): ConfigNumberField {\n // Zod v4 exposes min/max via public getters minValue/maxValue.\n // When unconstrained, these return -Infinity / Infinity — treat those as absent.\n const anyInner = zodInternals<{ minValue?: number | null; maxValue?: number | null }>(inner)\n const rawMin = anyInner.minValue\n const rawMax = anyInner.maxValue\n const min =\n rawMin != null && isFinite(rawMin) ? rawMin : undefined\n const max =\n rawMax != null && isFinite(rawMax) ? rawMax : undefined\n\n // Step is stored in checks with check name 'multiple_of'\n const step = getMultipleOfStep(inner)\n\n const field: ConfigNumberField = {\n ...base,\n type: 'number',\n ...(min !== undefined ? { min } : {}),\n ...(max !== undefined ? { max } : {}),\n ...(step !== undefined ? { step } : {}),\n }\n return field\n}\n\nfunction getMultipleOfStep(inner: z.ZodNumber): number | undefined {\n const def = zodDef<ZodV4NumberDef>(inner)\n const checks = def.checks ?? []\n for (const check of checks) {\n if (check._zod?.def?.check === 'multiple_of' && check._zod.def.value !== undefined) {\n return check._zod.def.value\n }\n }\n return undefined\n}\n\n// Zod v4: ZodEnum<T> where T extends Readonly<Record<string, string | number>>\n// options returns Array<T[keyof T]> which is (string | number)[]\nfunction buildEnumField(\n inner: z.ZodEnum,\n base: { key: string; label: string; description?: string; default?: unknown },\n): ConfigSelectField {\n const values = (inner.options as (string | number)[]).map(v => String(v))\n\n const field: ConfigSelectField = {\n ...base,\n type: 'select',\n options: values.map(v => ({ label: humanizeKey(v), value: v })),\n }\n return field\n}\n\nfunction unwrapZod(schema: z.ZodType): z.ZodType {\n if (schema instanceof z.ZodDefault) return unwrapZod(zodDef<ZodV4DefaultDef>(schema).innerType)\n if (schema instanceof z.ZodOptional) return unwrapZod(zodDef<{ innerType: z.ZodType }>(schema).innerType)\n if (schema instanceof z.ZodNullable) return unwrapZod(zodDef<{ innerType: z.ZodType }>(schema).innerType)\n return schema\n}\n\nfunction getZodDefault(schema: z.ZodType): unknown {\n if (schema instanceof z.ZodDefault) {\n // Zod v4: def.defaultValue is the literal value (not a function at runtime)\n return zodDef<ZodV4DefaultDef>(schema).defaultValue\n }\n return undefined\n}\n\nfunction humanizeKey(key: string): string {\n return key\n .replace(/([A-Z])/g, ' $1')\n .replace(/[_-]/g, ' ')\n .replace(/^\\w/, c => c.toUpperCase())\n .trim()\n}\n","/**\n * Reactive read handle for one cap-keyed slice of a device's\n * runtime state. Returned by `createDeviceProxy(...).state[capName]`.\n *\n * Three pieces:\n * - `value`: last-known slice. `undefined` until something has\n * populated it (an active subscription, an explicit `refresh()`,\n * or — in the case of the SystemManager mirror source — a\n * warm-boot `getAllSnapshots` payload). Read sync.\n * - `refresh()`: one-shot pull from the underlying source. For\n * the lazy tRPC source this is `deviceState.getCapSlice`; for\n * the SystemManager mirror it's a no-op (the mirror is push-only).\n * - `subscribe(cb)`: hooks into the source's notification channel,\n * filtered by `(deviceId, capName)`. Refcounted — the underlying\n * subscription closes when the last caller unsubscribes.\n *\n * Cross-environment: the same API works in browser (admin-ui via the\n * tRPC client) and on the server (in-process AddonApi). The transport\n * is whatever the supplied source exposes.\n */\nexport interface SliceHandle<T> {\n /** Latest cached slice. Reflects the most recent `refresh()` or\n * push event. `undefined` if neither has happened. */\n readonly value: T | undefined\n /** Force a re-fetch from the hub mirror. Updates `value` + notifies\n * every active subscriber. No-op for the SystemManager mirror\n * source (it's already push-driven). */\n refresh(): Promise<void>\n /** Subscribe to slice changes. Returns the unsubscribe fn.\n * Auto-fires the callback once with the current value (or\n * `undefined`) so the caller sees a snapshot immediately. */\n subscribe(cb: (slice: T | undefined) => void): () => void\n /**\n * Replace the slice on the hub. Routes through\n * `device-state.setCapSlice` — the canonical cross-layer write\n * entrypoint. The local mirror updates via the `onChanged` event\n * (round-trip), so callers should treat the write as eventually\n * consistent and read the new value via `subscribe` rather than\n * synchronously after `await`.\n */\n set(slice: T): Promise<void>\n /**\n * Shallow-merge `partial` into the current slice on the hub.\n * Implemented as read-modify-write client-side: pulls `value`\n * (or refreshes), merges, calls `set()`. Single-writer\n * conventions on each cap make atomic-merge semantics\n * unnecessary — concurrent patches on the same slice from\n * different processes are undefined and should be avoided.\n */\n patch(partial: Partial<T>): Promise<void>\n}\n\n/**\n * Minimal tRPC API surface used by the lazy source. Both `AddonApi`\n * (server) and the tRPC client proxy (browser) satisfy it structurally\n * — we don't import either to avoid pulling them in from a leaf type\n * module.\n */\nexport interface SliceHandleApi {\n readonly deviceState: {\n readonly getCapSlice: {\n query(input: { deviceId: number; capName: string }): Promise<Record<string, unknown> | null>\n }\n readonly setCapSlice: {\n mutate(input: { deviceId: number; capName: string; slice: Record<string, unknown> }): Promise<void>\n }\n }\n readonly live?: {\n readonly onEvent: {\n subscribe(\n input: { category: string },\n opts: { onData: (evt: { data: unknown }) => void; onError?: (err: unknown) => void },\n ): { unsubscribe: () => void }\n }\n }\n}\n\n/**\n * Pluggable state-source contract. `createSliceHandle` is now a thin\n * adapter over this interface — every implementation produces an\n * identical `SliceHandle<T>` shape. Two impls today:\n *\n * - `createLazyTrpcSource(api)`: per-handle local cache, refresh\n * via `deviceState.getCapSlice`, subscribe via `live.onEvent`.\n * Default behavior, used by `createDeviceProxy(api, binding)`\n * when no source is passed.\n * - `createMirrorSource(mirror, listeners)`: reads from a shared\n * `Map<deviceId, Map<capName, slice>>` populated by a\n * `SystemManager` warm-boot. Refresh is a no-op; subscribe\n * registers in a shared listener set that the SystemManager\n * fans out to on every push event.\n *\n * Both produce the same `SliceHandle<T>` API; consumers don't see\n * which source is behind the handle.\n */\nexport interface SliceHandleSource {\n /** Sync read of the last-known slice for `(deviceId, capName)`. */\n read(deviceId: number, capName: string): unknown | undefined\n /** Force a re-fetch (where applicable). No-op when the source is\n * push-only (e.g. the SystemManager mirror). */\n refresh(deviceId: number, capName: string): Promise<void>\n /** Register a listener for slice changes. Returns the unsubscribe\n * fn. Implementations should fan out the latest cached slice to\n * the callback synchronously when seeding is desired (the handle\n * always seeds via a separate `cb(read(...))` call). */\n watch(\n deviceId: number,\n capName: string,\n cb: (slice: unknown | undefined) => void,\n ): () => void\n /** Write the slice for `(deviceId, capName)` to the hub via the\n * canonical `device-state.setCapSlice` entrypoint. Throws if the\n * source has no write transport (e.g. a mirror source built\n * without an api reference). */\n write(deviceId: number, capName: string, slice: Record<string, unknown>): Promise<void>\n}\n\nconst DEVICE_STATE_EVENT_CATEGORY = 'device.state-changed'\n\n/**\n * Lazy tRPC source — the default behavior. Maintains a per-key local\n * cache (`{deviceId}:{capName}` → last slice), one shared\n * `live.onEvent` bridge that fans out into the listener map, and\n * `refresh` round-trips through `deviceState.getCapSlice`.\n *\n * The bridge is opened on first `watch()` and closed when the last\n * watcher unsubscribes — keeps idle handles cheap.\n */\nexport function createLazyTrpcSource(api: SliceHandleApi): SliceHandleSource {\n const cache = new Map<string, unknown>()\n const listeners = new Map<string, Set<(slice: unknown | undefined) => void>>()\n let bridge: { unsubscribe: () => void } | null = null\n\n const keyOf = (deviceId: number, capName: string): string => `${deviceId}:${capName}`\n\n const ensureBridge = (): void => {\n if (bridge) return\n if (!api.live?.onEvent) return\n bridge = api.live.onEvent.subscribe(\n { category: DEVICE_STATE_EVENT_CATEGORY },\n {\n onData: (evt) => {\n const data = evt.data as { deviceId?: number; capName?: string; slice?: unknown } | null\n if (!data || typeof data.deviceId !== 'number' || typeof data.capName !== 'string') return\n const k = keyOf(data.deviceId, data.capName)\n cache.set(k, data.slice)\n const set = listeners.get(k)\n if (!set) return\n for (const cb of set) {\n try { cb(data.slice) } catch { /* listener errors don't break the bridge */ }\n }\n },\n },\n )\n }\n\n const closeBridgeIfIdle = (): void => {\n if (!bridge) return\n if (listeners.size > 0) return\n bridge.unsubscribe()\n bridge = null\n }\n\n return {\n read(deviceId, capName) {\n return cache.get(keyOf(deviceId, capName))\n },\n async refresh(deviceId, capName) {\n const slice = await api.deviceState.getCapSlice.query({ deviceId, capName })\n const k = keyOf(deviceId, capName)\n cache.set(k, slice ?? undefined)\n const set = listeners.get(k)\n if (set) {\n for (const cb of set) {\n try { cb(slice ?? undefined) } catch { /* listener errors don't break refresh */ }\n }\n }\n },\n watch(deviceId, capName, cb) {\n const k = keyOf(deviceId, capName)\n let set = listeners.get(k)\n if (!set) { set = new Set(); listeners.set(k, set) }\n set.add(cb)\n ensureBridge()\n return () => {\n set!.delete(cb)\n if (set!.size === 0) listeners.delete(k)\n closeBridgeIfIdle()\n }\n },\n async write(deviceId, capName, slice) {\n await api.deviceState.setCapSlice.mutate({ deviceId, capName, slice })\n },\n }\n}\n\n/**\n * Mirror source — reads from a shared map populated by a\n * `SystemManager` warm-boot + push event handler. Refresh is a no-op\n * (the SystemManager owns the update loop). `watch()` registers in a\n * shared listener set — the SystemManager calls these from its single\n * `device.state-changed` subscription.\n *\n * The mirror map and listener map are passed in by reference so the\n * SystemManager can mutate both as events arrive.\n */\nexport function createMirrorSource(\n mirror: ReadonlyMap<number, ReadonlyMap<string, unknown>>,\n listeners: Map<string, Set<(slice: unknown | undefined) => void>>,\n api?: SliceHandleApi,\n): SliceHandleSource {\n const keyOf = (deviceId: number, capName: string): string => `${deviceId}:${capName}`\n return {\n read(deviceId, capName) {\n return mirror.get(deviceId)?.get(capName)\n },\n async refresh() {\n // No-op: the mirror is fed by `device.state-changed` events at\n // the SystemManager level. Forcing a re-fetch from a single\n // handle would race with the global update loop and is never\n // what the caller wants.\n },\n watch(deviceId, capName, cb) {\n const k = keyOf(deviceId, capName)\n let set = listeners.get(k)\n if (!set) { set = new Set(); listeners.set(k, set) }\n set.add(cb)\n return () => {\n set!.delete(cb)\n if (set!.size === 0) listeners.delete(k)\n }\n },\n async write(deviceId, capName, slice) {\n if (!api) {\n throw new Error('createMirrorSource: write requires an api reference — pass it as the third argument when constructing the source')\n }\n await api.deviceState.setCapSlice.mutate({ deviceId, capName, slice })\n },\n }\n}\n\n/**\n * Build a `SliceHandle<T>` bound to `(deviceId, capName)`. Caller\n * provides the type parameter — codegen passes\n * `InferRuntimeState<typeof <cap>>` so consumers see the cap's typed\n * shape:\n *\n * const dev = createDeviceProxy(api, binding)\n * dev.state.battery.value // BatteryStatus | undefined\n * dev.state.battery.value?.percentage\n *\n * Two-arg form (deprecated path, kept for spec compatibility):\n * passes the api directly, builds a per-handle lazy source. New\n * code should pre-build a single source and reuse it across handles\n * via the explicit `source` form.\n */\nexport function createSliceHandle<T>(\n source: SliceHandleSource | SliceHandleApi,\n deviceId: number,\n capName: string,\n): SliceHandle<T> {\n // Discriminate between source and api by structure: a source has\n // a `read` method, an api has a `deviceState` namespace. Spec-style\n // tests still pass `api`; production codegen passes a source.\n const src: SliceHandleSource = isSource(source)\n ? source\n : createLazyTrpcSource(source)\n\n return {\n get value() { return src.read(deviceId, capName) as T | undefined },\n refresh() { return src.refresh(deviceId, capName) },\n subscribe(cb) {\n const unwatch = src.watch(deviceId, capName, (slice) => {\n try { cb(slice as T | undefined) } catch { /* listener errors are isolated */ }\n })\n // Seed the listener with the current cached read — sync,\n // deterministic, no transport. Mirror sources serve the\n // canonical value here; lazy sources serve their per-key\n // cache (undefined on cold start).\n try { cb(src.read(deviceId, capName) as T | undefined) } catch { /* ignore */ }\n // Cold-start kick: when the read returned nothing AND the\n // source has a meaningful refresh path (lazy tRPC), pull once\n // in the background. Fan-out via `watch` delivers the result\n // to the same listener — no double-seeding. The mirror\n // source's refresh is a no-op, so this is a cheap miss for\n // SystemManager-backed handles.\n if (src.read(deviceId, capName) === undefined) {\n void src.refresh(deviceId, capName).catch(() => undefined)\n }\n return unwatch\n },\n async set(slice) {\n await src.write(deviceId, capName, slice as Record<string, unknown>)\n },\n async patch(partial) {\n const current = src.read(deviceId, capName) as Record<string, unknown> | undefined\n const next = { ...(current ?? {}), ...partial as Record<string, unknown> }\n await src.write(deviceId, capName, next)\n },\n }\n}\n\nfunction isSource(x: SliceHandleSource | SliceHandleApi): x is SliceHandleSource {\n return typeof (x as SliceHandleSource).read === 'function'\n && typeof (x as SliceHandleSource).watch === 'function'\n}\n","// AUTO-GENERATED — do not edit manually.\n// Regenerate with: npx tsx scripts/generate-device-proxy.ts\n/* eslint-disable */\n\nimport type { InferDeviceProxyCap, InferRuntimeState } from '../capabilities/capability-definition.js'\nimport type { DeviceBinding } from '../device/device-binding.js'\nimport { createSliceHandle, createLazyTrpcSource, type SliceHandle, type SliceHandleApi, type SliceHandleSource } from '../device/device-state-handle.js'\nimport type { AddonApi } from './addon-api.js'\nimport type { accessoriesCapability } from '../capabilities/accessories.cap.js'\nimport type { audioAnalysisCapability } from '../capabilities/audio-analysis.cap.js'\nimport type { audioMetricsCapability } from '../capabilities/audio-metrics.cap.js'\nimport type { batteryCapability } from '../capabilities/battery.cap.js'\nimport type { brightnessCapability } from '../capabilities/brightness.cap.js'\nimport type { cameraCredentialsCapability } from '../capabilities/camera-credentials.cap.js'\nimport type { cameraStreamsCapability } from '../capabilities/camera-streams.cap.js'\nimport type { detectionPipelineCapability } from '../capabilities/detection-pipeline.cap.js'\nimport type { deviceDiscoveryCapability } from '../capabilities/device-discovery.cap.js'\nimport type { deviceOpsCapability } from '../capabilities/device-ops.cap.js'\nimport type { deviceStatusCapability } from '../capabilities/device-status.cap.js'\nimport type { doorbellCapability } from '../capabilities/doorbell.cap.js'\nimport type { eventsCapability } from '../capabilities/events.cap.js'\nimport type { featureProbeCapability } from '../capabilities/feature-probe.cap.js'\nimport type { intercomCapability } from '../capabilities/intercom.cap.js'\nimport type { motionCapability } from '../capabilities/motion.cap.js'\nimport type { motionDetectionCapability } from '../capabilities/motion-detection.cap.js'\nimport type { motionTriggerCapability } from '../capabilities/motion-trigger.cap.js'\nimport type { nativeObjectDetectionCapability } from '../capabilities/native-object-detection.cap.js'\nimport type { osdCapability } from '../capabilities/osd.cap.js'\nimport type { pipelineAnalyticsCapability } from '../capabilities/pipeline-analytics.cap.js'\nimport type { ptzCapability } from '../capabilities/ptz.cap.js'\nimport type { ptzAutotrackCapability } from '../capabilities/ptz-autotrack.cap.js'\nimport type { rebootCapability } from '../capabilities/reboot.cap.js'\nimport type { recordingCapability } from '../capabilities/recording.cap.js'\nimport type { snapshotCapability } from '../capabilities/snapshot.cap.js'\nimport type { switchCapability } from '../capabilities/switch.cap.js'\nimport type { webrtcSessionCapability } from '../capabilities/webrtc-session.cap.js'\nimport type { zoneAnalyticsCapability } from '../capabilities/zone-analytics.cap.js'\nimport type { zoneRulesCapability } from '../capabilities/zone-rules.cap.js'\nimport type { zonesCapability } from '../capabilities/zones.cap.js'\nimport type { addonSettingsCapability } from '../capabilities/addon-settings.cap.js'\nimport type { deviceManagerCapability } from '../capabilities/device-manager.cap.js'\nimport type { deviceStateCapability } from '../capabilities/device-state.cap.js'\nimport type { networkQualityCapability } from '../capabilities/network-quality.cap.js'\nimport type { pipelineExecutorCapability } from '../capabilities/pipeline-executor.cap.js'\nimport type { pipelineOrchestratorCapability } from '../capabilities/pipeline-orchestrator.cap.js'\nimport type { pipelineRunnerCapability } from '../capabilities/pipeline-runner.cap.js'\nimport type { recordingEngineCapability } from '../capabilities/recording-engine.cap.js'\nimport type { snapshotProviderCapability } from '../capabilities/snapshot-provider.cap.js'\nimport type { streamBrokerCapability } from '../capabilities/stream-broker.cap.js'\n\n/**\n * Reactive read handle bag for device runtime state. Each entry mirrors the\n * cap's `runtimeState` schema and stays live via the `device-state` cap's\n * `onChanged` event. See `device-state-handle.ts` for the contract.\n */\nexport interface DeviceProxyState {\n readonly audioMetrics: SliceHandle<InferRuntimeState<typeof audioMetricsCapability>>\n readonly battery: SliceHandle<InferRuntimeState<typeof batteryCapability>>\n readonly brightness: SliceHandle<InferRuntimeState<typeof brightnessCapability>>\n readonly cameraStreams: SliceHandle<InferRuntimeState<typeof cameraStreamsCapability>>\n readonly deviceDiscovery: SliceHandle<InferRuntimeState<typeof deviceDiscoveryCapability>>\n readonly deviceStatus: SliceHandle<InferRuntimeState<typeof deviceStatusCapability>>\n readonly doorbell: SliceHandle<InferRuntimeState<typeof doorbellCapability>>\n readonly featureProbe: SliceHandle<InferRuntimeState<typeof featureProbeCapability>>\n readonly motion: SliceHandle<InferRuntimeState<typeof motionCapability>>\n readonly motionTrigger: SliceHandle<InferRuntimeState<typeof motionTriggerCapability>>\n readonly ptzAutotrack: SliceHandle<InferRuntimeState<typeof ptzAutotrackCapability>>\n readonly switch: SliceHandle<InferRuntimeState<typeof switchCapability>>\n readonly zoneAnalytics: SliceHandle<InferRuntimeState<typeof zoneAnalyticsCapability>>\n readonly zoneRules: SliceHandle<InferRuntimeState<typeof zoneRulesCapability>>\n readonly zones: SliceHandle<InferRuntimeState<typeof zonesCapability>>\n}\n\n/**\n * Unified per-device proxy interface. Each optional property is present at\n * runtime only when the device's binding includes that capability.\n *\n * The optional `binding` field is populated post-construction by callers\n * that own a binding cache (e.g. the SDK's `System` mirror). Consumers\n * that need the full per-device binding map can read it from there\n * without paying for a second `getBindings` round-trip — see Phase 5\n * dedup notes in `scripts/generate-device-proxy.ts`.\n */\nexport interface DeviceProxy {\n readonly deviceId: number\n /** Reactive runtime state, one slot per cap that declares `runtimeState`. */\n readonly state: DeviceProxyState\n /** Resolved binding entry list (or null if the proxy was constructed\n * without a cache-aware caller — defaults to null since\n * `createDeviceProxy` itself does not own the binding). */\n readonly binding: DeviceBinding | null\n readonly accessories?: InferDeviceProxyCap<typeof accessoriesCapability>\n readonly audioAnalysis?: InferDeviceProxyCap<typeof audioAnalysisCapability>\n readonly audioMetrics?: InferDeviceProxyCap<typeof audioMetricsCapability>\n readonly battery?: InferDeviceProxyCap<typeof batteryCapability>\n readonly brightness?: InferDeviceProxyCap<typeof brightnessCapability>\n readonly cameraCredentials?: InferDeviceProxyCap<typeof cameraCredentialsCapability>\n readonly cameraStreams?: InferDeviceProxyCap<typeof cameraStreamsCapability>\n readonly detectionPipeline?: InferDeviceProxyCap<typeof detectionPipelineCapability>\n readonly deviceDiscovery?: InferDeviceProxyCap<typeof deviceDiscoveryCapability>\n readonly deviceOps?: InferDeviceProxyCap<typeof deviceOpsCapability>\n readonly deviceStatus?: InferDeviceProxyCap<typeof deviceStatusCapability>\n readonly doorbell?: InferDeviceProxyCap<typeof doorbellCapability>\n readonly events?: InferDeviceProxyCap<typeof eventsCapability>\n readonly featureProbe?: InferDeviceProxyCap<typeof featureProbeCapability>\n readonly intercom?: InferDeviceProxyCap<typeof intercomCapability>\n readonly motion?: InferDeviceProxyCap<typeof motionCapability>\n readonly motionDetection?: InferDeviceProxyCap<typeof motionDetectionCapability>\n readonly motionTrigger?: InferDeviceProxyCap<typeof motionTriggerCapability>\n readonly nativeObjectDetection?: InferDeviceProxyCap<typeof nativeObjectDetectionCapability>\n readonly osd?: InferDeviceProxyCap<typeof osdCapability>\n readonly pipelineAnalytics?: InferDeviceProxyCap<typeof pipelineAnalyticsCapability>\n readonly ptz?: InferDeviceProxyCap<typeof ptzCapability>\n readonly ptzAutotrack?: InferDeviceProxyCap<typeof ptzAutotrackCapability>\n readonly reboot?: InferDeviceProxyCap<typeof rebootCapability>\n readonly recording?: InferDeviceProxyCap<typeof recordingCapability>\n readonly snapshot?: InferDeviceProxyCap<typeof snapshotCapability>\n readonly switch?: InferDeviceProxyCap<typeof switchCapability>\n readonly webrtcSession?: InferDeviceProxyCap<typeof webrtcSessionCapability>\n readonly zoneAnalytics?: InferDeviceProxyCap<typeof zoneAnalyticsCapability>\n readonly zoneRules?: InferDeviceProxyCap<typeof zoneRulesCapability>\n readonly zones?: InferDeviceProxyCap<typeof zonesCapability>\n readonly addonSettings: Pick<InferDeviceProxyCap<typeof addonSettingsCapability>, 'getDeviceSettings' | 'updateDeviceSettings'>\n readonly deviceManager: Pick<InferDeviceProxyCap<typeof deviceManagerCapability>, 'loadConfig' | 'loadRuntimeState' | 'loadMeta' | 'setName' | 'setLocation' | 'setMetadata' | 'setDisabled' | 'getDevice' | 'getStreamSources' | 'getConfigSchema' | 'getSettingsSchema' | 'updateConfig' | 'enable' | 'disable' | 'remove' | 'getStreamProfileMap' | 'setStreamProfileMap' | 'probeStreams' | 'getBindings' | 'getAllBindings' | 'setWrapperActive' | 'getDeviceSettingsAggregate' | 'getDeviceLiveInfoAggregate' | 'getDeviceAggregate' | 'updateDeviceField' | 'updateDeviceFieldsBatch' | 'testField' | 'getDeviceStatusAggregate'>\n readonly deviceState: Pick<InferDeviceProxyCap<typeof deviceStateCapability>, 'getSnapshot' | 'getCapSlice' | 'setCapSlice'>\n readonly networkQuality: Pick<InferDeviceProxyCap<typeof networkQualityCapability>, 'getDeviceStats' | 'reportClientStats'>\n readonly pipelineExecutor: Pick<InferDeviceProxyCap<typeof pipelineExecutorCapability>, 'runPipeline' | 'runPipelineBatch'>\n readonly pipelineOrchestrator: Pick<InferDeviceProxyCap<typeof pipelineOrchestratorCapability>, 'assignPipeline' | 'unassignPipeline' | 'getPipelineAssignment' | 'getCameraMetrics' | 'assignDecoder' | 'unassignDecoder' | 'assignAudio' | 'unassignAudio' | 'getAudioAssignment' | 'getAudioAssignments' | 'getDecoderAssignment' | 'getCameraSettings' | 'setCameraStepToggle' | 'getCameraStepOverrides' | 'setCameraStepOverride' | 'setCameraPipelineForAgent' | 'resolvePipeline' | 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>\n readonly pipelineRunner: Pick<InferDeviceProxyCap<typeof pipelineRunnerCapability>, 'detachCamera' | 'getCameraMetrics'>\n readonly recordingEngine: Pick<InferDeviceProxyCap<typeof recordingEngineCapability>, 'getPolicyStatus'>\n readonly snapshotProvider: Pick<InferDeviceProxyCap<typeof snapshotProviderCapability>, 'supportsDevice' | 'getSnapshot'>\n readonly streamBroker: Pick<InferDeviceProxyCap<typeof streamBrokerCapability>, 'publishCameraStream' | 'retractCameraStream' | 'assignProfile' | 'unassignProfile' | 'restartProfile' | 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>\n}\n\n/**\n * Build a DeviceProxy that pre-binds deviceId + nodeId on every method call\n * and dispatches through the existing cap-router tRPC procedures.\n *\n * Optional `opts.stateSource` lets a SystemManager pass a shared mirror\n * source so every device proxy reads from the same in-memory map and\n * shares the warm-boot/push-event update loop. When omitted, a per-proxy\n * lazy tRPC source is created — the path used by `ctx.fetchDevice` and\n * `BackendClient.fetchDevice` for one-off reads.\n *\n * The returned proxy's `binding` field is set to the input `binding`\n * by default — callers that want to expose a different value (e.g. the\n * SDK's `System` patches it from a shared cache) can overwrite the\n * field on the returned object.\n */\nexport function createDeviceProxy(\n api: AddonApi,\n binding: DeviceBinding,\n opts?: { stateSource?: SliceHandleSource },\n): DeviceProxy {\n const typedApi = api as unknown as Record<string, Record<string, Record<string, (input?: unknown) => unknown>>>\n // Default lazy source: builds its own cache + bridge on first watch().\n // The SystemManager passes a shared mirror source instead.\n const stateSource: SliceHandleSource = opts?.stateSource\n ?? createLazyTrpcSource(api as unknown as SliceHandleApi)\n\n // ── Dispatch helpers ────────────────────────────────────────────────\n //\n // Every per-cap method below collapses to a single `dispatch(...)` /\n // `dispatchSystem(...)` call. The helpers handle three concerns\n // uniformly so the per-method code reads as a one-line declaration of\n // intent (cap + method + kind) rather than 25 lines of plumbing.\n type Kind = 'query' | 'mutation' | 'subscription'\n\n /** Merge `{deviceId, nodeId?}` into the caller-supplied input. */\n function mergeInput(input: unknown, nodeId: string | undefined): Record<string, unknown> {\n const base = typeof input === 'object' && input !== null ? input as Record<string, unknown> : {}\n return nodeId !== undefined\n ? { ...base, deviceId: binding.deviceId, nodeId }\n : { ...base, deviceId: binding.deviceId }\n }\n\n /**\n * Invoke `api.<capProp>.<method>.{query|mutate|subscribe}(merged)`.\n * Returns `any` so the caller-side per-method declaration assigns\n * cleanly into the strongly-typed `InferDeviceProxyCap<...>` shape on\n * the `DeviceProxy` interface — the proxy's contract is enforced by\n * the interface, not the dispatch helper.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function callLeaf(capProp: string, method: string, kind: Kind, merged: unknown, push: unknown): any {\n const leaf = typedApi[capProp]?.[method]\n if (!leaf) throw new Error(`DeviceProxy: api has no '${capProp}.${method}'`)\n const fn = leaf as unknown as {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n query: (i: unknown) => any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n mutate: (i: unknown) => any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n subscribe: (i: unknown, push: unknown) => any\n }\n if (kind === 'mutation') return fn.mutate(merged)\n if (kind === 'subscription') return fn.subscribe(merged, push)\n return fn.query(merged)\n }\n\n /**\n * Device-scoped cap dispatch. Looks up the binding entry for `capName`\n * to pin the call to the worker that owns the per-device provider; when\n * no entry exists (cluster-wide singletons like `zones` /\n * `zone-rules` / `audio-metrics` that don't register per-device\n * natives), nodeId is omitted and the cap-router's `resolveProvider`\n * falls through to the local provider — a Moleculer bridge proxy when\n * the actual singleton lives in a worker.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function dispatch(capName: string, capProp: string, method: string, kind: Kind, input?: unknown, push?: unknown): any {\n const entry = binding.entries.find((e) => e.capName === capName)\n return callLeaf(capProp, method, kind, mergeInput(input, entry?.providerNodeId), push)\n }\n\n /**\n * System-cap dispatch. No binding gate — system caps are cluster-wide\n * singletons; the nodeId is left absent so caps that load-balance (e.g.\n * `pipeline-runner`) can resolve their own target node.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function dispatchSystem(capProp: string, method: string, kind: Kind, input?: unknown, push?: unknown): any {\n return callLeaf(capProp, method, kind, mergeInput(input, undefined), push)\n }\n\n const accessoriesInterface = {\n getStatus: (input?: unknown) => dispatch('accessories', 'accessories', 'getStatus', 'query', input),\n }\n\n const audioAnalysisInterface = {\n resolveDeviceSettings: (input?: unknown) => dispatch('audio-analysis', 'audioAnalysis', 'resolveDeviceSettings', 'query', input),\n getDeviceSettingsContribution: (input?: unknown) => dispatch('audio-analysis', 'audioAnalysis', 'getDeviceSettingsContribution', 'query', input),\n getDeviceLiveContribution: (input?: unknown) => dispatch('audio-analysis', 'audioAnalysis', 'getDeviceLiveContribution', 'query', input),\n applyDeviceSettingsPatch: (input?: unknown) => dispatch('audio-analysis', 'audioAnalysis', 'applyDeviceSettingsPatch', 'mutation', input),\n }\n\n const audioMetricsInterface = {\n getCurrentSnapshot: (input?: unknown) => dispatch('audio-metrics', 'audioMetrics', 'getCurrentSnapshot', 'query', input),\n getHistory: (input?: unknown) => dispatch('audio-metrics', 'audioMetrics', 'getHistory', 'query', input),\n }\n\n const batteryInterface = {\n getStatus: (input?: unknown) => dispatch('battery', 'battery', 'getStatus', 'query', input),\n }\n\n const brightnessInterface = {\n setBrightness: (input?: unknown) => dispatch('brightness', 'brightness', 'setBrightness', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('brightness', 'brightness', 'getStatus', 'query', input),\n }\n\n const cameraCredentialsInterface = {\n getCredentials: (input?: unknown) => dispatch('camera-credentials', 'cameraCredentials', 'getCredentials', 'query', input),\n getStatus: (input?: unknown) => dispatch('camera-credentials', 'cameraCredentials', 'getStatus', 'query', input),\n }\n\n const cameraStreamsInterface = {\n getCameraStreams: (input?: unknown) => dispatch('camera-streams', 'cameraStreams', 'getCameraStreams', 'query', input),\n getBrokerStreams: (input?: unknown) => dispatch('camera-streams', 'cameraStreams', 'getBrokerStreams', 'query', input),\n getRtspEntries: (input?: unknown) => dispatch('camera-streams', 'cameraStreams', 'getRtspEntries', 'query', input),\n }\n\n const detectionPipelineInterface = {\n getDeviceSettingsContribution: (input?: unknown) => dispatch('detection-pipeline', 'detectionPipeline', 'getDeviceSettingsContribution', 'query', input),\n getDeviceLiveContribution: (input?: unknown) => dispatch('detection-pipeline', 'detectionPipeline', 'getDeviceLiveContribution', 'query', input),\n applyDeviceSettingsPatch: (input?: unknown) => dispatch('detection-pipeline', 'detectionPipeline', 'applyDeviceSettingsPatch', 'mutation', input),\n }\n\n const deviceDiscoveryInterface = {\n listDiscovered: (input?: unknown) => dispatch('device-discovery', 'deviceDiscovery', 'listDiscovered', 'query', input),\n refreshDiscovery: (input?: unknown) => dispatch('device-discovery', 'deviceDiscovery', 'refreshDiscovery', 'mutation', input),\n adoptDevice: (input?: unknown) => dispatch('device-discovery', 'deviceDiscovery', 'adoptDevice', 'mutation', input),\n releaseDevice: (input?: unknown) => dispatch('device-discovery', 'deviceDiscovery', 'releaseDevice', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('device-discovery', 'deviceDiscovery', 'getStatus', 'query', input),\n }\n\n const deviceOpsInterface = {\n getStreamSources: (input?: unknown) => dispatch('device-ops', 'deviceOps', 'getStreamSources', 'query', input),\n getConfigEntries: (input?: unknown) => dispatch('device-ops', 'deviceOps', 'getConfigEntries', 'query', input),\n setConfig: (input?: unknown) => dispatch('device-ops', 'deviceOps', 'setConfig', 'mutation', input),\n removeDevice: (input?: unknown) => dispatch('device-ops', 'deviceOps', 'removeDevice', 'mutation', input),\n getSettingsSchema: (input?: unknown) => dispatch('device-ops', 'deviceOps', 'getSettingsSchema', 'query', input),\n }\n\n const deviceStatusInterface = {\n getStatus: (input?: unknown) => dispatch('device-status', 'deviceStatus', 'getStatus', 'query', input),\n }\n\n const doorbellInterface = {\n getStatus: (input?: unknown) => dispatch('doorbell', 'doorbell', 'getStatus', 'query', input),\n }\n\n const eventsInterface = {\n getEvents: (input?: unknown) => dispatch('events', 'events', 'getEvents', 'query', input),\n getEventThumbnail: (input?: unknown) => dispatch('events', 'events', 'getEventThumbnail', 'query', input),\n getEventClipUrl: (input?: unknown) => dispatch('events', 'events', 'getEventClipUrl', 'query', input),\n }\n\n const featureProbeInterface = {\n getStatus: (input?: unknown) => dispatch('feature-probe', 'featureProbe', 'getStatus', 'query', input),\n }\n\n const intercomInterface = {\n startSession: (input?: unknown) => dispatch('intercom', 'intercom', 'startSession', 'mutation', input),\n handleAnswer: (input?: unknown) => dispatch('intercom', 'intercom', 'handleAnswer', 'mutation', input),\n stopSession: (input?: unknown) => dispatch('intercom', 'intercom', 'stopSession', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('intercom', 'intercom', 'getStatus', 'query', input),\n }\n\n const motionInterface = {\n isDetected: (input?: unknown) => dispatch('motion', 'motion', 'isDetected', 'query', input),\n getStatus: (input?: unknown) => dispatch('motion', 'motion', 'getStatus', 'query', input),\n }\n\n const motionDetectionInterface = {\n analyze: (input?: unknown) => dispatch('motion-detection', 'motionDetection', 'analyze', 'mutation', input),\n removeCamera: (input?: unknown) => dispatch('motion-detection', 'motionDetection', 'removeCamera', 'mutation', input),\n reset: (input?: unknown) => dispatch('motion-detection', 'motionDetection', 'reset', 'mutation', input),\n getDeviceSettingsContribution: (input?: unknown) => dispatch('motion-detection', 'motionDetection', 'getDeviceSettingsContribution', 'query', input),\n getDeviceLiveContribution: (input?: unknown) => dispatch('motion-detection', 'motionDetection', 'getDeviceLiveContribution', 'query', input),\n applyDeviceSettingsPatch: (input?: unknown) => dispatch('motion-detection', 'motionDetection', 'applyDeviceSettingsPatch', 'mutation', input),\n }\n\n const motionTriggerInterface = {\n setMotionTrigger: (input?: unknown) => dispatch('motion-trigger', 'motionTrigger', 'setMotionTrigger', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('motion-trigger', 'motionTrigger', 'getStatus', 'query', input),\n }\n\n const nativeObjectDetectionInterface = {\n getStatus: (input?: unknown) => dispatch('native-object-detection', 'nativeObjectDetection', 'getStatus', 'query', input),\n }\n\n const osdInterface = {\n setOverlay: (input?: unknown) => dispatch('osd', 'osd', 'setOverlay', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('osd', 'osd', 'getStatus', 'query', input),\n }\n\n const pipelineAnalyticsInterface = {\n getActiveTracks: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getActiveTracks', 'query', input),\n getTrack: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getTrack', 'query', input),\n listTracks: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'listTracks', 'query', input),\n clearTracks: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'clearTracks', 'mutation', input),\n getMotionEvents: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getMotionEvents', 'query', input),\n getObjectEvents: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getObjectEvents', 'query', input),\n getAudioEvents: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getAudioEvents', 'query', input),\n getEventMedia: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getEventMedia', 'query', input),\n getTrackMedia: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getTrackMedia', 'query', input),\n getDeviceSettingsContribution: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getDeviceSettingsContribution', 'query', input),\n getDeviceLiveContribution: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getDeviceLiveContribution', 'query', input),\n applyDeviceSettingsPatch: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'applyDeviceSettingsPatch', 'mutation', input),\n }\n\n const ptzInterface = {\n move: (input?: unknown) => dispatch('ptz', 'ptz', 'move', 'mutation', input),\n continuousMove: (input?: unknown) => dispatch('ptz', 'ptz', 'continuousMove', 'mutation', input),\n stop: (input?: unknown) => dispatch('ptz', 'ptz', 'stop', 'mutation', input),\n getPresets: (input?: unknown) => dispatch('ptz', 'ptz', 'getPresets', 'query', input),\n goToPreset: (input?: unknown) => dispatch('ptz', 'ptz', 'goToPreset', 'mutation', input),\n goHome: (input?: unknown) => dispatch('ptz', 'ptz', 'goHome', 'mutation', input),\n getPosition: (input?: unknown) => dispatch('ptz', 'ptz', 'getPosition', 'query', input),\n getStatus: (input?: unknown) => dispatch('ptz', 'ptz', 'getStatus', 'query', input),\n }\n\n const ptzAutotrackInterface = {\n getStatus: (input?: unknown) => dispatch('ptz-autotrack', 'ptzAutotrack', 'getStatus', 'query', input),\n setEnabled: (input?: unknown) => dispatch('ptz-autotrack', 'ptzAutotrack', 'setEnabled', 'mutation', input),\n getSettings: (input?: unknown) => dispatch('ptz-autotrack', 'ptzAutotrack', 'getSettings', 'query', input),\n setSettings: (input?: unknown) => dispatch('ptz-autotrack', 'ptzAutotrack', 'setSettings', 'mutation', input),\n }\n\n const rebootInterface = {\n reboot: (input?: unknown) => dispatch('reboot', 'reboot', 'reboot', 'mutation', input),\n }\n\n const recordingInterface = {\n getSegments: (input?: unknown) => dispatch('recording', 'recording', 'getSegments', 'query', input),\n getPlaybackUrl: (input?: unknown) => dispatch('recording', 'recording', 'getPlaybackUrl', 'query', input),\n getThumbnailAt: (input?: unknown) => dispatch('recording', 'recording', 'getThumbnailAt', 'query', input),\n }\n\n const snapshotInterface = {\n getSnapshot: (input?: unknown) => dispatch('snapshot', 'snapshot', 'getSnapshot', 'query', input),\n invalidateCache: (input?: unknown) => dispatch('snapshot', 'snapshot', 'invalidateCache', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('snapshot', 'snapshot', 'getStatus', 'query', input),\n getDeviceSettingsContribution: (input?: unknown) => dispatch('snapshot', 'snapshot', 'getDeviceSettingsContribution', 'query', input),\n getDeviceLiveContribution: (input?: unknown) => dispatch('snapshot', 'snapshot', 'getDeviceLiveContribution', 'query', input),\n applyDeviceSettingsPatch: (input?: unknown) => dispatch('snapshot', 'snapshot', 'applyDeviceSettingsPatch', 'mutation', input),\n }\n\n const switchInterface = {\n setState: (input?: unknown) => dispatch('switch', 'switch', 'setState', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('switch', 'switch', 'getStatus', 'query', input),\n }\n\n const webrtcSessionInterface = {\n listStreams: (input?: unknown) => dispatch('webrtc-session', 'webrtcSession', 'listStreams', 'query', input),\n createSession: (input?: unknown) => dispatch('webrtc-session', 'webrtcSession', 'createSession', 'mutation', input),\n handleAnswer: (input?: unknown) => dispatch('webrtc-session', 'webrtcSession', 'handleAnswer', 'mutation', input),\n closeSession: (input?: unknown) => dispatch('webrtc-session', 'webrtcSession', 'closeSession', 'mutation', input),\n hasAdaptiveBitrate: (input?: unknown) => dispatch('webrtc-session', 'webrtcSession', 'hasAdaptiveBitrate', 'query', input),\n }\n\n const zoneAnalyticsInterface = {\n getCurrentSnapshot: (input?: unknown) => dispatch('zone-analytics', 'zoneAnalytics', 'getCurrentSnapshot', 'query', input),\n getZoneHistory: (input?: unknown) => dispatch('zone-analytics', 'zoneAnalytics', 'getZoneHistory', 'query', input),\n getCameraHistory: (input?: unknown) => dispatch('zone-analytics', 'zoneAnalytics', 'getCameraHistory', 'query', input),\n getUnzonedHistory: (input?: unknown) => dispatch('zone-analytics', 'zoneAnalytics', 'getUnzonedHistory', 'query', input),\n }\n\n const zoneRulesInterface = {\n listRules: (input?: unknown) => dispatch('zone-rules', 'zoneRules', 'listRules', 'query', input),\n setRules: (input?: unknown) => dispatch('zone-rules', 'zoneRules', 'setRules', 'mutation', input),\n }\n\n const zonesInterface = {\n listZones: (input?: unknown) => dispatch('zones', 'zones', 'listZones', 'query', input),\n addZone: (input?: unknown) => dispatch('zones', 'zones', 'addZone', 'mutation', input),\n removeZone: (input?: unknown) => dispatch('zones', 'zones', 'removeZone', 'mutation', input),\n updateZone: (input?: unknown) => dispatch('zones', 'zones', 'updateZone', 'mutation', input),\n }\n\n const addonSettingsInterface = {\n getDeviceSettings: (input?: unknown) => dispatchSystem('addonSettings', 'getDeviceSettings', 'query', input),\n updateDeviceSettings: (input?: unknown) => dispatchSystem('addonSettings', 'updateDeviceSettings', 'mutation', input),\n }\n\n const deviceManagerInterface = {\n loadConfig: (input?: unknown) => dispatchSystem('deviceManager', 'loadConfig', 'query', input),\n loadRuntimeState: (input?: unknown) => dispatchSystem('deviceManager', 'loadRuntimeState', 'query', input),\n loadMeta: (input?: unknown) => dispatchSystem('deviceManager', 'loadMeta', 'query', input),\n setName: (input?: unknown) => dispatchSystem('deviceManager', 'setName', 'mutation', input),\n setLocation: (input?: unknown) => dispatchSystem('deviceManager', 'setLocation', 'mutation', input),\n setMetadata: (input?: unknown) => dispatchSystem('deviceManager', 'setMetadata', 'mutation', input),\n setDisabled: (input?: unknown) => dispatchSystem('deviceManager', 'setDisabled', 'mutation', input),\n getDevice: (input?: unknown) => dispatchSystem('deviceManager', 'getDevice', 'query', input),\n getStreamSources: (input?: unknown) => dispatchSystem('deviceManager', 'getStreamSources', 'query', input),\n getConfigSchema: (input?: unknown) => dispatchSystem('deviceManager', 'getConfigSchema', 'query', input),\n getSettingsSchema: (input?: unknown) => dispatchSystem('deviceManager', 'getSettingsSchema', 'query', input),\n updateConfig: (input?: unknown) => dispatchSystem('deviceManager', 'updateConfig', 'mutation', input),\n enable: (input?: unknown) => dispatchSystem('deviceManager', 'enable', 'mutation', input),\n disable: (input?: unknown) => dispatchSystem('deviceManager', 'disable', 'mutation', input),\n remove: (input?: unknown) => dispatchSystem('deviceManager', 'remove', 'mutation', input),\n getStreamProfileMap: (input?: unknown) => dispatchSystem('deviceManager', 'getStreamProfileMap', 'query', input),\n setStreamProfileMap: (input?: unknown) => dispatchSystem('deviceManager', 'setStreamProfileMap', 'mutation', input),\n probeStreams: (input?: unknown) => dispatchSystem('deviceManager', 'probeStreams', 'mutation', input),\n getBindings: (input?: unknown) => dispatchSystem('deviceManager', 'getBindings', 'query', input),\n getAllBindings: (input?: unknown) => dispatchSystem('deviceManager', 'getAllBindings', 'query', input),\n setWrapperActive: (input?: unknown) => dispatchSystem('deviceManager', 'setWrapperActive', 'mutation', input),\n getDeviceSettingsAggregate: (input?: unknown) => dispatchSystem('deviceManager', 'getDeviceSettingsAggregate', 'query', input),\n getDeviceLiveInfoAggregate: (input?: unknown) => dispatchSystem('deviceManager', 'getDeviceLiveInfoAggregate', 'query', input),\n getDeviceAggregate: (input?: unknown) => dispatchSystem('deviceManager', 'getDeviceAggregate', 'query', input),\n updateDeviceField: (input?: unknown) => dispatchSystem('deviceManager', 'updateDeviceField', 'mutation', input),\n updateDeviceFieldsBatch: (input?: unknown) => dispatchSystem('deviceManager', 'updateDeviceFieldsBatch', 'mutation', input),\n testField: (input?: unknown) => dispatchSystem('deviceManager', 'testField', 'mutation', input),\n getDeviceStatusAggregate: (input?: unknown) => dispatchSystem('deviceManager', 'getDeviceStatusAggregate', 'query', input),\n }\n\n const deviceStateInterface = {\n getSnapshot: (input?: unknown) => dispatchSystem('deviceState', 'getSnapshot', 'query', input),\n getCapSlice: (input?: unknown) => dispatchSystem('deviceState', 'getCapSlice', 'query', input),\n setCapSlice: (input?: unknown) => dispatchSystem('deviceState', 'setCapSlice', 'mutation', input),\n }\n\n const networkQualityInterface = {\n getDeviceStats: (input?: unknown) => dispatchSystem('networkQuality', 'getDeviceStats', 'query', input),\n reportClientStats: (input?: unknown) => dispatchSystem('networkQuality', 'reportClientStats', 'mutation', input),\n }\n\n const pipelineExecutorInterface = {\n runPipeline: (input?: unknown) => dispatchSystem('pipelineExecutor', 'runPipeline', 'mutation', input),\n runPipelineBatch: (input?: unknown) => dispatchSystem('pipelineExecutor', 'runPipelineBatch', 'mutation', input),\n }\n\n const pipelineOrchestratorInterface = {\n assignPipeline: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'assignPipeline', 'mutation', input),\n unassignPipeline: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'unassignPipeline', 'mutation', input),\n getPipelineAssignment: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getPipelineAssignment', 'query', input),\n getCameraMetrics: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getCameraMetrics', 'query', input),\n assignDecoder: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'assignDecoder', 'mutation', input),\n unassignDecoder: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'unassignDecoder', 'mutation', input),\n assignAudio: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'assignAudio', 'mutation', input),\n unassignAudio: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'unassignAudio', 'mutation', input),\n getAudioAssignment: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getAudioAssignment', 'query', input),\n getAudioAssignments: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getAudioAssignments', 'query', input),\n getDecoderAssignment: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getDecoderAssignment', 'query', input),\n getCameraSettings: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getCameraSettings', 'query', input),\n setCameraStepToggle: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'setCameraStepToggle', 'mutation', input),\n getCameraStepOverrides: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getCameraStepOverrides', 'query', input),\n setCameraStepOverride: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'setCameraStepOverride', 'mutation', input),\n setCameraPipelineForAgent: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'setCameraPipelineForAgent', 'mutation', input),\n resolvePipeline: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'resolvePipeline', 'query', input),\n getDeviceSettingsContribution: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getDeviceSettingsContribution', 'query', input),\n getDeviceLiveContribution: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getDeviceLiveContribution', 'query', input),\n applyDeviceSettingsPatch: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'applyDeviceSettingsPatch', 'mutation', input),\n }\n\n const pipelineRunnerInterface = {\n detachCamera: (input?: unknown) => dispatchSystem('pipelineRunner', 'detachCamera', 'mutation', input),\n getCameraMetrics: (input?: unknown) => dispatchSystem('pipelineRunner', 'getCameraMetrics', 'query', input),\n }\n\n const recordingEngineInterface = {\n getPolicyStatus: (input?: unknown) => dispatchSystem('recordingEngine', 'getPolicyStatus', 'query', input),\n }\n\n const snapshotProviderInterface = {\n supportsDevice: (input?: unknown) => dispatchSystem('snapshotProvider', 'supportsDevice', 'query', input),\n getSnapshot: (input?: unknown) => dispatchSystem('snapshotProvider', 'getSnapshot', 'query', input),\n }\n\n const streamBrokerInterface = {\n publishCameraStream: (input?: unknown) => dispatchSystem('streamBroker', 'publishCameraStream', 'mutation', input),\n retractCameraStream: (input?: unknown) => dispatchSystem('streamBroker', 'retractCameraStream', 'mutation', input),\n assignProfile: (input?: unknown) => dispatchSystem('streamBroker', 'assignProfile', 'mutation', input),\n unassignProfile: (input?: unknown) => dispatchSystem('streamBroker', 'unassignProfile', 'mutation', input),\n restartProfile: (input?: unknown) => dispatchSystem('streamBroker', 'restartProfile', 'mutation', input),\n getDeviceSettingsContribution: (input?: unknown) => dispatchSystem('streamBroker', 'getDeviceSettingsContribution', 'query', input),\n getDeviceLiveContribution: (input?: unknown) => dispatchSystem('streamBroker', 'getDeviceLiveContribution', 'query', input),\n applyDeviceSettingsPatch: (input?: unknown) => dispatchSystem('streamBroker', 'applyDeviceSettingsPatch', 'mutation', input),\n }\n\n return {\n deviceId: binding.deviceId,\n binding,\n state: {\n audioMetrics: createSliceHandle<InferRuntimeState<typeof audioMetricsCapability>>(stateSource, binding.deviceId, 'audio-metrics'),\n battery: createSliceHandle<InferRuntimeState<typeof batteryCapability>>(stateSource, binding.deviceId, 'battery'),\n brightness: createSliceHandle<InferRuntimeState<typeof brightnessCapability>>(stateSource, binding.deviceId, 'brightness'),\n cameraStreams: createSliceHandle<InferRuntimeState<typeof cameraStreamsCapability>>(stateSource, binding.deviceId, 'camera-streams'),\n deviceDiscovery: createSliceHandle<InferRuntimeState<typeof deviceDiscoveryCapability>>(stateSource, binding.deviceId, 'device-discovery'),\n deviceStatus: createSliceHandle<InferRuntimeState<typeof deviceStatusCapability>>(stateSource, binding.deviceId, 'device-status'),\n doorbell: createSliceHandle<InferRuntimeState<typeof doorbellCapability>>(stateSource, binding.deviceId, 'doorbell'),\n featureProbe: createSliceHandle<InferRuntimeState<typeof featureProbeCapability>>(stateSource, binding.deviceId, 'feature-probe'),\n motion: createSliceHandle<InferRuntimeState<typeof motionCapability>>(stateSource, binding.deviceId, 'motion'),\n motionTrigger: createSliceHandle<InferRuntimeState<typeof motionTriggerCapability>>(stateSource, binding.deviceId, 'motion-trigger'),\n ptzAutotrack: createSliceHandle<InferRuntimeState<typeof ptzAutotrackCapability>>(stateSource, binding.deviceId, 'ptz-autotrack'),\n switch: createSliceHandle<InferRuntimeState<typeof switchCapability>>(stateSource, binding.deviceId, 'switch'),\n zoneAnalytics: createSliceHandle<InferRuntimeState<typeof zoneAnalyticsCapability>>(stateSource, binding.deviceId, 'zone-analytics'),\n zoneRules: createSliceHandle<InferRuntimeState<typeof zoneRulesCapability>>(stateSource, binding.deviceId, 'zone-rules'),\n zones: createSliceHandle<InferRuntimeState<typeof zonesCapability>>(stateSource, binding.deviceId, 'zones'),\n },\n accessories: accessoriesInterface,\n audioAnalysis: audioAnalysisInterface,\n audioMetrics: audioMetricsInterface,\n battery: batteryInterface,\n brightness: brightnessInterface,\n cameraCredentials: cameraCredentialsInterface,\n cameraStreams: cameraStreamsInterface,\n detectionPipeline: detectionPipelineInterface,\n deviceDiscovery: deviceDiscoveryInterface,\n deviceOps: deviceOpsInterface,\n deviceStatus: deviceStatusInterface,\n doorbell: doorbellInterface,\n events: eventsInterface,\n featureProbe: featureProbeInterface,\n intercom: intercomInterface,\n motion: motionInterface,\n motionDetection: motionDetectionInterface,\n motionTrigger: motionTriggerInterface,\n nativeObjectDetection: nativeObjectDetectionInterface,\n osd: osdInterface,\n pipelineAnalytics: pipelineAnalyticsInterface,\n ptz: ptzInterface,\n ptzAutotrack: ptzAutotrackInterface,\n reboot: rebootInterface,\n recording: recordingInterface,\n snapshot: snapshotInterface,\n switch: switchInterface,\n webrtcSession: webrtcSessionInterface,\n zoneAnalytics: zoneAnalyticsInterface,\n zoneRules: zoneRulesInterface,\n zones: zonesInterface,\n addonSettings: addonSettingsInterface,\n deviceManager: deviceManagerInterface,\n deviceState: deviceStateInterface,\n networkQuality: networkQualityInterface,\n pipelineExecutor: pipelineExecutorInterface,\n pipelineOrchestrator: pipelineOrchestratorInterface,\n pipelineRunner: pipelineRunnerInterface,\n recordingEngine: recordingEngineInterface,\n snapshotProvider: snapshotProviderInterface,\n streamBroker: streamBrokerInterface,\n }\n}\n","/**\n * Pure rules-driven zone evaluator. Shared between every consumer\n * that gates items (motion regions, detections, future audio events,\n * …) by `(zones, rules)` pairs. Lives in `@camstack/types/utils` so\n * addon-motion-wasm + addon-detection-pipeline share one canonical\n * implementation.\n *\n * Semantics — match the analytics zone-engine introduced in Phase 2a:\n * - any active include rule fires ⇒ whitelist mode (only items\n * satisfying at least one include rule pass)\n * - otherwise ⇒ blacklist mode (items in any exclude rule are\n * dropped, the rest pass)\n * - inactive rules (`enabled: false`) are skipped before the gate\n * - a rule's `classFilter` narrows it to the listed classes; an\n * item whose class isn't in the filter is invisible to that rule\n *\n * Test point: each item provides a normalised (0–1) center via the\n * `getCenter` accessor; rules fire when the center lies inside any\n * of the rule's referenced zone polygons (ray-cast point-in-polygon).\n * Bbox-area overlap would be marginally more intuitive on tiny\n * items but doubles the per-frame cost; the center test keeps the\n * hot path cheap and matches the operator's intuition for\n * \"where is the activity centered\".\n */\nimport type { Zone } from '../capabilities/zones.cap.js'\nimport type { ZoneRule } from '../capabilities/schemas/zone-rule.js'\n\nexport interface ZoneRuleEvalResult<T> {\n readonly passed: readonly T[]\n readonly excluded: readonly T[]\n}\n\n/**\n * Evaluate `rules` against `items`. Returns the items partitioned\n * into `passed` (kept by the gate) and `excluded` (dropped). When\n * `rules` is empty or `zones` is empty everything passes — the gate\n * is \"off\" without explicit configuration.\n *\n * `getCenter` returns the item's normalised (0–1) center point.\n * `getClassName` is optional — when omitted, every rule's\n * `classFilter` is treated as matching all classes (motion-stage\n * semantics). Provide it for object detections so per-class rules\n * narrow correctly.\n */\nexport function evaluateZoneRules<T>(\n items: readonly T[],\n zones: readonly Zone[],\n rules: readonly ZoneRule[],\n getCenter: (item: T) => { readonly x: number; readonly y: number },\n getClassName?: (item: T) => string | undefined,\n): ZoneRuleEvalResult<T> {\n if (rules.length === 0 || zones.length === 0) {\n return { passed: items, excluded: [] }\n }\n const activeRules = rules.filter(r => r.enabled !== false)\n const includeRules = activeRules.filter(r => r.mode === 'include')\n const excludeRules = activeRules.filter(r => r.mode === 'exclude')\n const whitelistMode = includeRules.length > 0\n const zonesById = new Map(zones.map(z => [z.id, z]))\n\n const passed: T[] = []\n const excluded: T[] = []\n\n for (const item of items) {\n const center = getCenter(item)\n const className = getClassName?.(item)\n const inInclude = includeRules.some(r => ruleApplies(r, center, className, zonesById))\n const inExclude = excludeRules.some(r => ruleApplies(r, center, className, zonesById))\n if (whitelistMode) {\n if (inInclude && !inExclude) passed.push(item)\n else excluded.push(item)\n } else {\n if (inExclude) excluded.push(item)\n else passed.push(item)\n }\n }\n return { passed, excluded }\n}\n\nfunction ruleApplies(\n rule: ZoneRule,\n center: { readonly x: number; readonly y: number },\n className: string | undefined,\n zonesById: ReadonlyMap<string, Zone>,\n): boolean {\n // Class narrowing — when className is undefined (motion stage),\n // we treat the filter as matching everything. When the item has a\n // class, missing it from the filter excludes the rule.\n if (rule.classFilter && rule.classFilter.length > 0) {\n if (className !== undefined && !rule.classFilter.includes(className)) return false\n }\n for (const zoneId of rule.zoneIds) {\n const zone = zonesById.get(zoneId)\n if (!zone) continue\n if (pointInPolygon(center, zone.polygon)) return true\n }\n return false\n}\n\n/**\n * Standard ray-casting point-in-polygon. Polygon vertices are\n * normalised (0–1); the test point is too — frame-resolution-\n * agnostic. Boundary points count as inside (treats `<` as `<=` on\n * the y-edge crossing).\n */\nfunction pointInPolygon(\n point: { readonly x: number; readonly y: number },\n polygon: ReadonlyArray<{ readonly x: number; readonly y: number }>,\n): boolean {\n if (polygon.length < 3) return false\n let inside = false\n const { x, y } = point\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const a = polygon[i]!\n const b = polygon[j]!\n const intersect =\n ((a.y > y) !== (b.y > y)) &&\n (x < ((b.x - a.x) * (y - a.y)) / (b.y - a.y || Number.EPSILON) + a.x)\n if (intersect) inside = !inside\n }\n return inside\n}\n","// AUTO-GENERATED — do not edit manually.\n// Regenerate with: npx tsx scripts/generate-system-proxy.ts\n/* eslint-disable */\n\nimport type { InferProvider } from '../capabilities/capability-definition.js'\nimport type { AddonApi } from './addon-api.js'\nimport type { addonPagesCapability } from '../capabilities/addon-pages.cap.js'\nimport type { addonsCapability } from '../capabilities/addons.cap.js'\nimport type { addonSettingsCapability } from '../capabilities/addon-settings.cap.js'\nimport type { addonWidgetsCapability } from '../capabilities/addon-widgets.cap.js'\nimport type { alertsCapability } from '../capabilities/alerts.cap.js'\nimport type { audioAnalyzerCapability } from '../capabilities/audio-analyzer.cap.js'\nimport type { audioCodecCapability } from '../capabilities/audio-codec.cap.js'\nimport type { backupCapability } from '../capabilities/backup.cap.js'\nimport type { decoderCapability } from '../capabilities/decoder.cap.js'\nimport type { deviceManagerCapability } from '../capabilities/device-manager.cap.js'\nimport type { deviceProviderCapability } from '../capabilities/device-provider.cap.js'\nimport type { deviceStateCapability } from '../capabilities/device-state.cap.js'\nimport type { integrationsCapability } from '../capabilities/integrations.cap.js'\nimport type { metricsProviderCapability } from '../capabilities/metrics-provider.cap.js'\nimport type { networkQualityCapability } from '../capabilities/network-quality.cap.js'\nimport type { nodesCapability } from '../capabilities/nodes.cap.js'\nimport type { notificationOutputCapability } from '../capabilities/notification-output.cap.js'\nimport type { pipelineExecutorCapability } from '../capabilities/pipeline-executor.cap.js'\nimport type { pipelineOrchestratorCapability } from '../capabilities/pipeline-orchestrator.cap.js'\nimport type { pipelineRunnerCapability } from '../capabilities/pipeline-runner.cap.js'\nimport type { platformProbeCapability } from '../capabilities/platform-probe.cap.js'\nimport type { recordingEngineCapability } from '../capabilities/recording-engine.cap.js'\nimport type { settingsStoreCapability } from '../capabilities/settings-store.cap.js'\nimport type { storageCapability } from '../capabilities/storage.cap.js'\nimport type { streamBrokerCapability } from '../capabilities/stream-broker.cap.js'\nimport type { systemCapability } from '../capabilities/system.cap.js'\nimport type { toastCapability } from '../capabilities/toast.cap.js'\nimport type { turnProviderCapability } from '../capabilities/turn-provider.cap.js'\nimport type { userManagementCapability } from '../capabilities/user-management.cap.js'\n\n/**\n * Cluster-wide facade over every `scope: 'system'` capability. Each entry\n * is a typed namespace exposing only the cap's non-device-bound methods —\n * device-scoped slices already surface on `DeviceProxy`.\n *\n * Consumed by the SDK's `System` class as the source of truth for\n * `system.<cap>.<method>(input)` calls.\n */\nexport interface SystemProxy {\n readonly addonPages: Pick<InferProvider<typeof addonPagesCapability>, 'listPages'>\n readonly addons: Pick<InferProvider<typeof addonsCapability>, 'list' | 'getLogs' | 'listPackages' | 'installPackage' | 'installFromWorkspace' | 'isWorkspaceAvailable' | 'listWorkspacePackages' | 'uninstallPackage' | 'reloadPackages' | 'searchAvailable' | 'listUpdates' | 'updatePackage' | 'forceRefresh' | 'restartServer' | 'getVersions' | 'restartAddon' | 'getAutoUpdateSettings' | 'setAutoUpdateSettings' | 'getAddonAutoUpdate' | 'setAddonAutoUpdate' | 'applyAutoUpdateToAll' | 'custom' | 'onAddonLogs'>\n readonly addonSettings: Pick<InferProvider<typeof addonSettingsCapability>, 'getGlobalSettings' | 'updateGlobalSettings'>\n readonly addonWidgets: Pick<InferProvider<typeof addonWidgetsCapability>, 'listWidgets'>\n readonly alerts: Pick<InferProvider<typeof alertsCapability>, 'emit' | 'update' | 'list' | 'getUnreadCount' | 'markRead' | 'markAllRead' | 'dismiss'>\n readonly audioAnalyzer: Pick<InferProvider<typeof audioAnalyzerCapability>, 'analyseChunk' | 'classify' | 'isReady' | 'dispose' | 'reprobeAudioEngine'>\n readonly audioCodec: Pick<InferProvider<typeof audioCodecCapability>, 'listSupportedCodecs' | 'canHandle' | 'createDecodeSession' | 'createEncodeSession' | 'closeSession' | 'pushEncodedFrame' | 'pullPcm' | 'pushPcm' | 'pullEncoded' | 'flushEncode' | 'listActiveSessions'>\n readonly backup: Pick<InferProvider<typeof backupCapability>, 'trigger' | 'list' | 'restore' | 'delete'>\n readonly decoder: Pick<InferProvider<typeof decoderCapability>, 'supportsCodec' | 'getInfo' | 'createSession' | 'destroySession' | 'pushPacket' | 'openStream' | 'pullFrames' | 'updateConfig' | 'getStats' | 'listActiveSessions' | 'reprobeHwaccel'>\n readonly deviceManager: Pick<InferProvider<typeof deviceManagerCapability>, 'allocateDeviceId' | 'registerDevice' | 'removeDevice' | 'persistConfig' | 'listLocations' | 'addLocation' | 'removeLocation' | 'listPersistedByAddon' | 'listAll' | 'getChildren' | 'listWrappersForCap' | 'listBindableCapsForDeviceType' | 'discoverDevices' | 'adoptDevice' | 'getCreationSchema' | 'createDevice' | 'testCreationField'>\n readonly deviceProvider: Pick<InferProvider<typeof deviceProviderCapability>, 'start' | 'stop' | 'getStatus' | 'getDevices' | 'supportsDiscovery' | 'discoverDevices' | 'adoptDiscoveredDevice' | 'supportsManualCreation' | 'getChildCreationSchema' | 'createDevice' | 'testCreationField'>\n readonly deviceState: Pick<InferProvider<typeof deviceStateCapability>, 'getAllSnapshots'>\n readonly integrations: Pick<InferProvider<typeof integrationsCapability>, 'list' | 'get' | 'getByAddonId' | 'create' | 'update' | 'delete' | 'getSettings' | 'setSettings' | 'getAvailableTypes' | 'testConnection'>\n readonly metricsProvider: Pick<InferProvider<typeof metricsProviderCapability>, 'collectSnapshot' | 'getCached' | 'getCurrent' | 'getDiskSpace' | 'getGpuInfo' | 'getCpuTemperature' | 'getProcessStats' | 'listAddonInstances' | 'getAddonStats' | 'listNodeProcesses' | 'killProcess'>\n readonly networkQuality: Pick<InferProvider<typeof networkQualityCapability>, 'getAllStats'>\n readonly nodes: Pick<InferProvider<typeof nodesCapability>, 'topology' | 'deployAddon' | 'undeployAddon' | 'restartAddon' | 'restartProcess' | 'restartNode' | 'shutdownNode' | 'renameNode' | 'clusterAddonStatus' | 'setProcessLogLevel' | 'executeQuery'>\n readonly notificationOutput: Pick<InferProvider<typeof notificationOutputCapability>, 'send' | 'sendTest'>\n readonly pipelineExecutor: Pick<InferProvider<typeof pipelineExecutorCapability>, 'getAvailableEngines' | 'getSelectedEngine' | 'getDefaultSteps' | 'reprobeEngine' | 'getVideoPipelineSteps' | 'setVideoPipelineSteps' | 'getSchema' | 'getGlobalSteps' | 'getGlobalPipelineConfig' | 'getOrchestratorConfigSchema' | 'listTemplates' | 'saveTemplate' | 'updateTemplate' | 'deleteTemplate' | 'getCapabilities' | 'getAddonModels' | 'downloadModel' | 'deleteModel' | 'detect' | 'cacheFrameInPool' | 'inferCached' | 'uncacheFrame' | 'getEffectiveTuning' | 'listLoadedEngines' | 'spinEngine' | 'killEngine' | 'listReferenceImages' | 'getReferenceImage' | 'getReferenceAudioFiles' | 'getReferenceAudio' | 'getAudioCapabilities' | 'runAudioTest' | 'getDetectionConfigSchema'>\n readonly pipelineOrchestrator: Pick<InferProvider<typeof pipelineOrchestratorCapability>, 'rebalance' | 'getPipelineAssignments' | 'getAgentLoad' | 'getGlobalMetrics' | 'getCapabilityBindings' | 'setCapabilityBinding' | 'getDecoderAssignments' | 'getAudioNodeLoad' | 'getAgentSettings' | 'listAgentSettings' | 'setAgentAddonDefaults' | 'removeAgentSettings' | 'listTemplates' | 'saveTemplate' | 'updateTemplate' | 'deleteTemplate'>\n readonly pipelineRunner: Pick<InferProvider<typeof pipelineRunnerCapability>, 'attachCamera' | 'reportMotion' | 'getLocalLoad' | 'getLocalMetrics' | 'getAllCameraMetrics' | 'getLocalCameras'>\n readonly platformProbe: Pick<InferProvider<typeof platformProbeCapability>, 'getCapabilities' | 'getHardware' | 'resolveInferenceConfig' | 'resolveHwAccel'>\n readonly recordingEngine: Pick<InferProvider<typeof recordingEngineCapability>, 'getStatus' | 'enable' | 'disable' | 'getConfig' | 'updateConfig' | 'getPlaylist' | 'getThumbnail' | 'getSegments' | 'getAvailability' | 'estimateStorage' | 'estimateGlobalStorage' | 'getStorageUsage' | 'setPolicy' | 'getPolicy' | 'getRetentionConfig' | 'updateRetentionConfig' | 'getMotionStats'>\n readonly settingsStore: Pick<InferProvider<typeof settingsStoreCapability>, 'get' | 'set' | 'query' | 'insert' | 'update' | 'delete' | 'count' | 'isEmpty' | 'declareCollection'>\n readonly storage: Pick<InferProvider<typeof storageCapability>, 'resolve' | 'write' | 'read' | 'exists' | 'list' | 'delete' | 'getAvailableSpace'>\n readonly streamBroker: Pick<InferProvider<typeof streamBrokerCapability>, 'listAllCameraStreams' | 'listAllProfileSlots' | 'getBrokerStats' | 'listClients' | 'killClient' | 'getStreamUrl' | 'getBroker' | 'setPreBufferDuration' | 'getPreBufferInfo' | 'getRtspPort' | 'getAllRtspEntries' | 'getRtspEntry' | 'regenerateRtspToken' | 'setRtspEnabled' | 'isRtspEnabled'>\n readonly system: Pick<InferProvider<typeof systemCapability>, 'info' | 'health' | 'featureFlags' | 'networkAddresses' | 'getRetentionConfig' | 'setRetentionConfig' | 'forceRetentionCleanup'>\n readonly toast: Pick<InferProvider<typeof toastCapability>, 'onToast'>\n readonly turnProvider: Pick<InferProvider<typeof turnProviderCapability>, 'getTurnServers'>\n readonly userManagement: Pick<InferProvider<typeof userManagementCapability>, 'listUsers' | 'createUser' | 'updateUser' | 'deleteUser' | 'resetPassword' | 'validateCredentials' | 'listApiKeys' | 'createApiKey' | 'revokeApiKey' | 'validateApiKey' | 'createScopedToken' | 'revokeScopedToken' | 'validateScopedToken' | 'listScopedTokens'>\n}\n\n/**\n * Build a `SystemProxy` that dispatches every namespace method through\n * the existing system-cap tRPC procedures (`api.<capProp>.<method>.{query,mutate,subscribe}`).\n *\n * Pure function — no caching, no live state. The caller (typically\n * `System`) owns the `AddonApi` instance and disposes the proxy by\n * dropping the reference.\n */\nexport function createSystemProxy(api: AddonApi): SystemProxy {\n const typedApi = api as unknown as Record<string, Record<string, Record<string, (input?: unknown) => unknown>>>\n\n type Kind = 'query' | 'mutation' | 'subscription'\n\n /**\n * Invoke `api.<capProp>.<method>.{query|mutate|subscribe}(input)`.\n * Returns `any` so the caller-side per-method declaration assigns\n * cleanly into the strongly-typed `Pick<InferProvider<...>, ...>`\n * shape on the `SystemProxy` interface — the proxy's contract is\n * enforced by the interface, not the dispatch helper.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function dispatch(capProp: string, method: string, kind: Kind, input?: unknown, push?: unknown): any {\n const leaf = typedApi[capProp]?.[method]\n if (!leaf) throw new Error(`SystemProxy: api has no '${capProp}.${method}'`)\n const fn = leaf as unknown as {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n query: (i: unknown) => any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n mutate: (i: unknown) => any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n subscribe: (i: unknown, push: unknown) => any\n }\n if (kind === 'mutation') return fn.mutate(input)\n if (kind === 'subscription') return fn.subscribe(input, push)\n return fn.query(input)\n }\n\n const addonPagesInterface = {\n listPages: (input?: unknown) => dispatch('addonPages', 'listPages', 'query', input),\n }\n\n const addonsInterface = {\n list: (input?: unknown) => dispatch('addons', 'list', 'query', input),\n getLogs: (input?: unknown) => dispatch('addons', 'getLogs', 'query', input),\n listPackages: (input?: unknown) => dispatch('addons', 'listPackages', 'query', input),\n installPackage: (input?: unknown) => dispatch('addons', 'installPackage', 'mutation', input),\n installFromWorkspace: (input?: unknown) => dispatch('addons', 'installFromWorkspace', 'mutation', input),\n isWorkspaceAvailable: (input?: unknown) => dispatch('addons', 'isWorkspaceAvailable', 'query', input),\n listWorkspacePackages: (input?: unknown) => dispatch('addons', 'listWorkspacePackages', 'query', input),\n uninstallPackage: (input?: unknown) => dispatch('addons', 'uninstallPackage', 'mutation', input),\n reloadPackages: (input?: unknown) => dispatch('addons', 'reloadPackages', 'mutation', input),\n searchAvailable: (input?: unknown) => dispatch('addons', 'searchAvailable', 'query', input),\n listUpdates: (input?: unknown) => dispatch('addons', 'listUpdates', 'query', input),\n updatePackage: (input?: unknown) => dispatch('addons', 'updatePackage', 'mutation', input),\n forceRefresh: (input?: unknown) => dispatch('addons', 'forceRefresh', 'mutation', input),\n restartServer: (input?: unknown) => dispatch('addons', 'restartServer', 'mutation', input),\n getVersions: (input?: unknown) => dispatch('addons', 'getVersions', 'query', input),\n restartAddon: (input?: unknown) => dispatch('addons', 'restartAddon', 'mutation', input),\n getAutoUpdateSettings: (input?: unknown) => dispatch('addons', 'getAutoUpdateSettings', 'query', input),\n setAutoUpdateSettings: (input?: unknown) => dispatch('addons', 'setAutoUpdateSettings', 'mutation', input),\n getAddonAutoUpdate: (input?: unknown) => dispatch('addons', 'getAddonAutoUpdate', 'query', input),\n setAddonAutoUpdate: (input?: unknown) => dispatch('addons', 'setAddonAutoUpdate', 'mutation', input),\n applyAutoUpdateToAll: (input?: unknown) => dispatch('addons', 'applyAutoUpdateToAll', 'mutation', input),\n custom: (input?: unknown) => dispatch('addons', 'custom', 'mutation', input),\n onAddonLogs: (input?: unknown, push?: unknown) => dispatch('addons', 'onAddonLogs', 'subscription', input, push),\n }\n\n const addonSettingsInterface = {\n getGlobalSettings: (input?: unknown) => dispatch('addonSettings', 'getGlobalSettings', 'query', input),\n updateGlobalSettings: (input?: unknown) => dispatch('addonSettings', 'updateGlobalSettings', 'mutation', input),\n }\n\n const addonWidgetsInterface = {\n listWidgets: (input?: unknown) => dispatch('addonWidgets', 'listWidgets', 'query', input),\n }\n\n const alertsInterface = {\n emit: (input?: unknown) => dispatch('alerts', 'emit', 'mutation', input),\n update: (input?: unknown) => dispatch('alerts', 'update', 'mutation', input),\n list: (input?: unknown) => dispatch('alerts', 'list', 'query', input),\n getUnreadCount: (input?: unknown) => dispatch('alerts', 'getUnreadCount', 'query', input),\n markRead: (input?: unknown) => dispatch('alerts', 'markRead', 'mutation', input),\n markAllRead: (input?: unknown) => dispatch('alerts', 'markAllRead', 'mutation', input),\n dismiss: (input?: unknown) => dispatch('alerts', 'dismiss', 'mutation', input),\n }\n\n const audioAnalyzerInterface = {\n analyseChunk: (input?: unknown) => dispatch('audioAnalyzer', 'analyseChunk', 'mutation', input),\n classify: (input?: unknown) => dispatch('audioAnalyzer', 'classify', 'query', input),\n isReady: (input?: unknown) => dispatch('audioAnalyzer', 'isReady', 'query', input),\n dispose: (input?: unknown) => dispatch('audioAnalyzer', 'dispose', 'mutation', input),\n reprobeAudioEngine: (input?: unknown) => dispatch('audioAnalyzer', 'reprobeAudioEngine', 'mutation', input),\n }\n\n const audioCodecInterface = {\n listSupportedCodecs: (input?: unknown) => dispatch('audioCodec', 'listSupportedCodecs', 'query', input),\n canHandle: (input?: unknown) => dispatch('audioCodec', 'canHandle', 'query', input),\n createDecodeSession: (input?: unknown) => dispatch('audioCodec', 'createDecodeSession', 'mutation', input),\n createEncodeSession: (input?: unknown) => dispatch('audioCodec', 'createEncodeSession', 'mutation', input),\n closeSession: (input?: unknown) => dispatch('audioCodec', 'closeSession', 'mutation', input),\n pushEncodedFrame: (input?: unknown) => dispatch('audioCodec', 'pushEncodedFrame', 'mutation', input),\n pullPcm: (input?: unknown) => dispatch('audioCodec', 'pullPcm', 'query', input),\n pushPcm: (input?: unknown) => dispatch('audioCodec', 'pushPcm', 'mutation', input),\n pullEncoded: (input?: unknown) => dispatch('audioCodec', 'pullEncoded', 'query', input),\n flushEncode: (input?: unknown) => dispatch('audioCodec', 'flushEncode', 'mutation', input),\n listActiveSessions: (input?: unknown) => dispatch('audioCodec', 'listActiveSessions', 'query', input),\n }\n\n const backupInterface = {\n trigger: (input?: unknown) => dispatch('backup', 'trigger', 'mutation', input),\n list: (input?: unknown) => dispatch('backup', 'list', 'query', input),\n restore: (input?: unknown) => dispatch('backup', 'restore', 'mutation', input),\n delete: (input?: unknown) => dispatch('backup', 'delete', 'mutation', input),\n }\n\n const decoderInterface = {\n supportsCodec: (input?: unknown) => dispatch('decoder', 'supportsCodec', 'query', input),\n getInfo: (input?: unknown) => dispatch('decoder', 'getInfo', 'query', input),\n createSession: (input?: unknown) => dispatch('decoder', 'createSession', 'query', input),\n destroySession: (input?: unknown) => dispatch('decoder', 'destroySession', 'query', input),\n pushPacket: (input?: unknown) => dispatch('decoder', 'pushPacket', 'query', input),\n openStream: (input?: unknown) => dispatch('decoder', 'openStream', 'query', input),\n pullFrames: (input?: unknown) => dispatch('decoder', 'pullFrames', 'query', input),\n updateConfig: (input?: unknown) => dispatch('decoder', 'updateConfig', 'query', input),\n getStats: (input?: unknown) => dispatch('decoder', 'getStats', 'query', input),\n listActiveSessions: (input?: unknown) => dispatch('decoder', 'listActiveSessions', 'query', input),\n reprobeHwaccel: (input?: unknown) => dispatch('decoder', 'reprobeHwaccel', 'mutation', input),\n }\n\n const deviceManagerInterface = {\n allocateDeviceId: (input?: unknown) => dispatch('deviceManager', 'allocateDeviceId', 'mutation', input),\n registerDevice: (input?: unknown) => dispatch('deviceManager', 'registerDevice', 'mutation', input),\n removeDevice: (input?: unknown) => dispatch('deviceManager', 'removeDevice', 'mutation', input),\n persistConfig: (input?: unknown) => dispatch('deviceManager', 'persistConfig', 'mutation', input),\n listLocations: (input?: unknown) => dispatch('deviceManager', 'listLocations', 'query', input),\n addLocation: (input?: unknown) => dispatch('deviceManager', 'addLocation', 'mutation', input),\n removeLocation: (input?: unknown) => dispatch('deviceManager', 'removeLocation', 'mutation', input),\n listPersistedByAddon: (input?: unknown) => dispatch('deviceManager', 'listPersistedByAddon', 'query', input),\n listAll: (input?: unknown) => dispatch('deviceManager', 'listAll', 'query', input),\n getChildren: (input?: unknown) => dispatch('deviceManager', 'getChildren', 'query', input),\n listWrappersForCap: (input?: unknown) => dispatch('deviceManager', 'listWrappersForCap', 'query', input),\n listBindableCapsForDeviceType: (input?: unknown) => dispatch('deviceManager', 'listBindableCapsForDeviceType', 'query', input),\n discoverDevices: (input?: unknown) => dispatch('deviceManager', 'discoverDevices', 'mutation', input),\n adoptDevice: (input?: unknown) => dispatch('deviceManager', 'adoptDevice', 'mutation', input),\n getCreationSchema: (input?: unknown) => dispatch('deviceManager', 'getCreationSchema', 'query', input),\n createDevice: (input?: unknown) => dispatch('deviceManager', 'createDevice', 'mutation', input),\n testCreationField: (input?: unknown) => dispatch('deviceManager', 'testCreationField', 'mutation', input),\n }\n\n const deviceProviderInterface = {\n start: (input?: unknown) => dispatch('deviceProvider', 'start', 'mutation', input),\n stop: (input?: unknown) => dispatch('deviceProvider', 'stop', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('deviceProvider', 'getStatus', 'query', input),\n getDevices: (input?: unknown) => dispatch('deviceProvider', 'getDevices', 'query', input),\n supportsDiscovery: (input?: unknown) => dispatch('deviceProvider', 'supportsDiscovery', 'query', input),\n discoverDevices: (input?: unknown) => dispatch('deviceProvider', 'discoverDevices', 'mutation', input),\n adoptDiscoveredDevice: (input?: unknown) => dispatch('deviceProvider', 'adoptDiscoveredDevice', 'mutation', input),\n supportsManualCreation: (input?: unknown) => dispatch('deviceProvider', 'supportsManualCreation', 'query', input),\n getChildCreationSchema: (input?: unknown) => dispatch('deviceProvider', 'getChildCreationSchema', 'query', input),\n createDevice: (input?: unknown) => dispatch('deviceProvider', 'createDevice', 'mutation', input),\n testCreationField: (input?: unknown) => dispatch('deviceProvider', 'testCreationField', 'mutation', input),\n }\n\n const deviceStateInterface = {\n getAllSnapshots: (input?: unknown) => dispatch('deviceState', 'getAllSnapshots', 'query', input),\n }\n\n const integrationsInterface = {\n list: (input?: unknown) => dispatch('integrations', 'list', 'query', input),\n get: (input?: unknown) => dispatch('integrations', 'get', 'query', input),\n getByAddonId: (input?: unknown) => dispatch('integrations', 'getByAddonId', 'query', input),\n create: (input?: unknown) => dispatch('integrations', 'create', 'mutation', input),\n update: (input?: unknown) => dispatch('integrations', 'update', 'mutation', input),\n delete: (input?: unknown) => dispatch('integrations', 'delete', 'mutation', input),\n getSettings: (input?: unknown) => dispatch('integrations', 'getSettings', 'query', input),\n setSettings: (input?: unknown) => dispatch('integrations', 'setSettings', 'mutation', input),\n getAvailableTypes: (input?: unknown) => dispatch('integrations', 'getAvailableTypes', 'query', input),\n testConnection: (input?: unknown) => dispatch('integrations', 'testConnection', 'mutation', input),\n }\n\n const metricsProviderInterface = {\n collectSnapshot: (input?: unknown) => dispatch('metricsProvider', 'collectSnapshot', 'query', input),\n getCached: (input?: unknown) => dispatch('metricsProvider', 'getCached', 'query', input),\n getCurrent: (input?: unknown) => dispatch('metricsProvider', 'getCurrent', 'query', input),\n getDiskSpace: (input?: unknown) => dispatch('metricsProvider', 'getDiskSpace', 'query', input),\n getGpuInfo: (input?: unknown) => dispatch('metricsProvider', 'getGpuInfo', 'query', input),\n getCpuTemperature: (input?: unknown) => dispatch('metricsProvider', 'getCpuTemperature', 'query', input),\n getProcessStats: (input?: unknown) => dispatch('metricsProvider', 'getProcessStats', 'query', input),\n listAddonInstances: (input?: unknown) => dispatch('metricsProvider', 'listAddonInstances', 'query', input),\n getAddonStats: (input?: unknown) => dispatch('metricsProvider', 'getAddonStats', 'query', input),\n listNodeProcesses: (input?: unknown) => dispatch('metricsProvider', 'listNodeProcesses', 'query', input),\n killProcess: (input?: unknown) => dispatch('metricsProvider', 'killProcess', 'mutation', input),\n }\n\n const networkQualityInterface = {\n getAllStats: (input?: unknown) => dispatch('networkQuality', 'getAllStats', 'query', input),\n }\n\n const nodesInterface = {\n topology: (input?: unknown) => dispatch('nodes', 'topology', 'query', input),\n deployAddon: (input?: unknown) => dispatch('nodes', 'deployAddon', 'mutation', input),\n undeployAddon: (input?: unknown) => dispatch('nodes', 'undeployAddon', 'mutation', input),\n restartAddon: (input?: unknown) => dispatch('nodes', 'restartAddon', 'mutation', input),\n restartProcess: (input?: unknown) => dispatch('nodes', 'restartProcess', 'mutation', input),\n restartNode: (input?: unknown) => dispatch('nodes', 'restartNode', 'mutation', input),\n shutdownNode: (input?: unknown) => dispatch('nodes', 'shutdownNode', 'mutation', input),\n renameNode: (input?: unknown) => dispatch('nodes', 'renameNode', 'mutation', input),\n clusterAddonStatus: (input?: unknown) => dispatch('nodes', 'clusterAddonStatus', 'query', input),\n setProcessLogLevel: (input?: unknown) => dispatch('nodes', 'setProcessLogLevel', 'mutation', input),\n executeQuery: (input?: unknown) => dispatch('nodes', 'executeQuery', 'mutation', input),\n }\n\n const notificationOutputInterface = {\n send: (input?: unknown) => dispatch('notificationOutput', 'send', 'mutation', input),\n sendTest: (input?: unknown) => dispatch('notificationOutput', 'sendTest', 'mutation', input),\n }\n\n const pipelineExecutorInterface = {\n getAvailableEngines: (input?: unknown) => dispatch('pipelineExecutor', 'getAvailableEngines', 'query', input),\n getSelectedEngine: (input?: unknown) => dispatch('pipelineExecutor', 'getSelectedEngine', 'query', input),\n getDefaultSteps: (input?: unknown) => dispatch('pipelineExecutor', 'getDefaultSteps', 'query', input),\n reprobeEngine: (input?: unknown) => dispatch('pipelineExecutor', 'reprobeEngine', 'mutation', input),\n getVideoPipelineSteps: (input?: unknown) => dispatch('pipelineExecutor', 'getVideoPipelineSteps', 'query', input),\n setVideoPipelineSteps: (input?: unknown) => dispatch('pipelineExecutor', 'setVideoPipelineSteps', 'mutation', input),\n getSchema: (input?: unknown) => dispatch('pipelineExecutor', 'getSchema', 'query', input),\n getGlobalSteps: (input?: unknown) => dispatch('pipelineExecutor', 'getGlobalSteps', 'query', input),\n getGlobalPipelineConfig: (input?: unknown) => dispatch('pipelineExecutor', 'getGlobalPipelineConfig', 'query', input),\n getOrchestratorConfigSchema: (input?: unknown) => dispatch('pipelineExecutor', 'getOrchestratorConfigSchema', 'query', input),\n listTemplates: (input?: unknown) => dispatch('pipelineExecutor', 'listTemplates', 'query', input),\n saveTemplate: (input?: unknown) => dispatch('pipelineExecutor', 'saveTemplate', 'mutation', input),\n updateTemplate: (input?: unknown) => dispatch('pipelineExecutor', 'updateTemplate', 'mutation', input),\n deleteTemplate: (input?: unknown) => dispatch('pipelineExecutor', 'deleteTemplate', 'mutation', input),\n getCapabilities: (input?: unknown) => dispatch('pipelineExecutor', 'getCapabilities', 'query', input),\n getAddonModels: (input?: unknown) => dispatch('pipelineExecutor', 'getAddonModels', 'query', input),\n downloadModel: (input?: unknown) => dispatch('pipelineExecutor', 'downloadModel', 'mutation', input),\n deleteModel: (input?: unknown) => dispatch('pipelineExecutor', 'deleteModel', 'mutation', input),\n detect: (input?: unknown) => dispatch('pipelineExecutor', 'detect', 'query', input),\n cacheFrameInPool: (input?: unknown) => dispatch('pipelineExecutor', 'cacheFrameInPool', 'mutation', input),\n inferCached: (input?: unknown) => dispatch('pipelineExecutor', 'inferCached', 'mutation', input),\n uncacheFrame: (input?: unknown) => dispatch('pipelineExecutor', 'uncacheFrame', 'mutation', input),\n getEffectiveTuning: (input?: unknown) => dispatch('pipelineExecutor', 'getEffectiveTuning', 'query', input),\n listLoadedEngines: (input?: unknown) => dispatch('pipelineExecutor', 'listLoadedEngines', 'query', input),\n spinEngine: (input?: unknown) => dispatch('pipelineExecutor', 'spinEngine', 'mutation', input),\n killEngine: (input?: unknown) => dispatch('pipelineExecutor', 'killEngine', 'mutation', input),\n listReferenceImages: (input?: unknown) => dispatch('pipelineExecutor', 'listReferenceImages', 'query', input),\n getReferenceImage: (input?: unknown) => dispatch('pipelineExecutor', 'getReferenceImage', 'query', input),\n getReferenceAudioFiles: (input?: unknown) => dispatch('pipelineExecutor', 'getReferenceAudioFiles', 'query', input),\n getReferenceAudio: (input?: unknown) => dispatch('pipelineExecutor', 'getReferenceAudio', 'query', input),\n getAudioCapabilities: (input?: unknown) => dispatch('pipelineExecutor', 'getAudioCapabilities', 'query', input),\n runAudioTest: (input?: unknown) => dispatch('pipelineExecutor', 'runAudioTest', 'mutation', input),\n getDetectionConfigSchema: (input?: unknown) => dispatch('pipelineExecutor', 'getDetectionConfigSchema', 'query', input),\n }\n\n const pipelineOrchestratorInterface = {\n rebalance: (input?: unknown) => dispatch('pipelineOrchestrator', 'rebalance', 'mutation', input),\n getPipelineAssignments: (input?: unknown) => dispatch('pipelineOrchestrator', 'getPipelineAssignments', 'query', input),\n getAgentLoad: (input?: unknown) => dispatch('pipelineOrchestrator', 'getAgentLoad', 'query', input),\n getGlobalMetrics: (input?: unknown) => dispatch('pipelineOrchestrator', 'getGlobalMetrics', 'query', input),\n getCapabilityBindings: (input?: unknown) => dispatch('pipelineOrchestrator', 'getCapabilityBindings', 'query', input),\n setCapabilityBinding: (input?: unknown) => dispatch('pipelineOrchestrator', 'setCapabilityBinding', 'mutation', input),\n getDecoderAssignments: (input?: unknown) => dispatch('pipelineOrchestrator', 'getDecoderAssignments', 'query', input),\n getAudioNodeLoad: (input?: unknown) => dispatch('pipelineOrchestrator', 'getAudioNodeLoad', 'query', input),\n getAgentSettings: (input?: unknown) => dispatch('pipelineOrchestrator', 'getAgentSettings', 'query', input),\n listAgentSettings: (input?: unknown) => dispatch('pipelineOrchestrator', 'listAgentSettings', 'query', input),\n setAgentAddonDefaults: (input?: unknown) => dispatch('pipelineOrchestrator', 'setAgentAddonDefaults', 'mutation', input),\n removeAgentSettings: (input?: unknown) => dispatch('pipelineOrchestrator', 'removeAgentSettings', 'mutation', input),\n listTemplates: (input?: unknown) => dispatch('pipelineOrchestrator', 'listTemplates', 'query', input),\n saveTemplate: (input?: unknown) => dispatch('pipelineOrchestrator', 'saveTemplate', 'mutation', input),\n updateTemplate: (input?: unknown) => dispatch('pipelineOrchestrator', 'updateTemplate', 'mutation', input),\n deleteTemplate: (input?: unknown) => dispatch('pipelineOrchestrator', 'deleteTemplate', 'mutation', input),\n }\n\n const pipelineRunnerInterface = {\n attachCamera: (input?: unknown) => dispatch('pipelineRunner', 'attachCamera', 'mutation', input),\n reportMotion: (input?: unknown) => dispatch('pipelineRunner', 'reportMotion', 'mutation', input),\n getLocalLoad: (input?: unknown) => dispatch('pipelineRunner', 'getLocalLoad', 'query', input),\n getLocalMetrics: (input?: unknown) => dispatch('pipelineRunner', 'getLocalMetrics', 'query', input),\n getAllCameraMetrics: (input?: unknown) => dispatch('pipelineRunner', 'getAllCameraMetrics', 'query', input),\n getLocalCameras: (input?: unknown) => dispatch('pipelineRunner', 'getLocalCameras', 'query', input),\n }\n\n const platformProbeInterface = {\n getCapabilities: (input?: unknown) => dispatch('platformProbe', 'getCapabilities', 'query', input),\n getHardware: (input?: unknown) => dispatch('platformProbe', 'getHardware', 'query', input),\n resolveInferenceConfig: (input?: unknown) => dispatch('platformProbe', 'resolveInferenceConfig', 'query', input),\n resolveHwAccel: (input?: unknown) => dispatch('platformProbe', 'resolveHwAccel', 'query', input),\n }\n\n const recordingEngineInterface = {\n getStatus: (input?: unknown) => dispatch('recordingEngine', 'getStatus', 'query', input),\n enable: (input?: unknown) => dispatch('recordingEngine', 'enable', 'mutation', input),\n disable: (input?: unknown) => dispatch('recordingEngine', 'disable', 'mutation', input),\n getConfig: (input?: unknown) => dispatch('recordingEngine', 'getConfig', 'query', input),\n updateConfig: (input?: unknown) => dispatch('recordingEngine', 'updateConfig', 'mutation', input),\n getPlaylist: (input?: unknown) => dispatch('recordingEngine', 'getPlaylist', 'query', input),\n getThumbnail: (input?: unknown) => dispatch('recordingEngine', 'getThumbnail', 'query', input),\n getSegments: (input?: unknown) => dispatch('recordingEngine', 'getSegments', 'query', input),\n getAvailability: (input?: unknown) => dispatch('recordingEngine', 'getAvailability', 'query', input),\n estimateStorage: (input?: unknown) => dispatch('recordingEngine', 'estimateStorage', 'query', input),\n estimateGlobalStorage: (input?: unknown) => dispatch('recordingEngine', 'estimateGlobalStorage', 'query', input),\n getStorageUsage: (input?: unknown) => dispatch('recordingEngine', 'getStorageUsage', 'query', input),\n setPolicy: (input?: unknown) => dispatch('recordingEngine', 'setPolicy', 'mutation', input),\n getPolicy: (input?: unknown) => dispatch('recordingEngine', 'getPolicy', 'query', input),\n getRetentionConfig: (input?: unknown) => dispatch('recordingEngine', 'getRetentionConfig', 'query', input),\n updateRetentionConfig: (input?: unknown) => dispatch('recordingEngine', 'updateRetentionConfig', 'mutation', input),\n getMotionStats: (input?: unknown) => dispatch('recordingEngine', 'getMotionStats', 'query', input),\n }\n\n const settingsStoreInterface = {\n get: (input?: unknown) => dispatch('settingsStore', 'get', 'query', input),\n set: (input?: unknown) => dispatch('settingsStore', 'set', 'mutation', input),\n query: (input?: unknown) => dispatch('settingsStore', 'query', 'query', input),\n insert: (input?: unknown) => dispatch('settingsStore', 'insert', 'mutation', input),\n update: (input?: unknown) => dispatch('settingsStore', 'update', 'mutation', input),\n delete: (input?: unknown) => dispatch('settingsStore', 'delete', 'mutation', input),\n count: (input?: unknown) => dispatch('settingsStore', 'count', 'query', input),\n isEmpty: (input?: unknown) => dispatch('settingsStore', 'isEmpty', 'query', input),\n declareCollection: (input?: unknown) => dispatch('settingsStore', 'declareCollection', 'mutation', input),\n }\n\n const storageInterface = {\n resolve: (input?: unknown) => dispatch('storage', 'resolve', 'query', input),\n write: (input?: unknown) => dispatch('storage', 'write', 'mutation', input),\n read: (input?: unknown) => dispatch('storage', 'read', 'query', input),\n exists: (input?: unknown) => dispatch('storage', 'exists', 'query', input),\n list: (input?: unknown) => dispatch('storage', 'list', 'query', input),\n delete: (input?: unknown) => dispatch('storage', 'delete', 'mutation', input),\n getAvailableSpace: (input?: unknown) => dispatch('storage', 'getAvailableSpace', 'query', input),\n }\n\n const streamBrokerInterface = {\n listAllCameraStreams: (input?: unknown) => dispatch('streamBroker', 'listAllCameraStreams', 'query', input),\n listAllProfileSlots: (input?: unknown) => dispatch('streamBroker', 'listAllProfileSlots', 'query', input),\n getBrokerStats: (input?: unknown) => dispatch('streamBroker', 'getBrokerStats', 'query', input),\n listClients: (input?: unknown) => dispatch('streamBroker', 'listClients', 'query', input),\n killClient: (input?: unknown) => dispatch('streamBroker', 'killClient', 'mutation', input),\n getStreamUrl: (input?: unknown) => dispatch('streamBroker', 'getStreamUrl', 'query', input),\n getBroker: (input?: unknown) => dispatch('streamBroker', 'getBroker', 'query', input),\n setPreBufferDuration: (input?: unknown) => dispatch('streamBroker', 'setPreBufferDuration', 'mutation', input),\n getPreBufferInfo: (input?: unknown) => dispatch('streamBroker', 'getPreBufferInfo', 'query', input),\n getRtspPort: (input?: unknown) => dispatch('streamBroker', 'getRtspPort', 'query', input),\n getAllRtspEntries: (input?: unknown) => dispatch('streamBroker', 'getAllRtspEntries', 'query', input),\n getRtspEntry: (input?: unknown) => dispatch('streamBroker', 'getRtspEntry', 'query', input),\n regenerateRtspToken: (input?: unknown) => dispatch('streamBroker', 'regenerateRtspToken', 'mutation', input),\n setRtspEnabled: (input?: unknown) => dispatch('streamBroker', 'setRtspEnabled', 'mutation', input),\n isRtspEnabled: (input?: unknown) => dispatch('streamBroker', 'isRtspEnabled', 'query', input),\n }\n\n const systemInterface = {\n info: (input?: unknown) => dispatch('system', 'info', 'query', input),\n health: (input?: unknown) => dispatch('system', 'health', 'query', input),\n featureFlags: (input?: unknown) => dispatch('system', 'featureFlags', 'query', input),\n networkAddresses: (input?: unknown) => dispatch('system', 'networkAddresses', 'query', input),\n getRetentionConfig: (input?: unknown) => dispatch('system', 'getRetentionConfig', 'query', input),\n setRetentionConfig: (input?: unknown) => dispatch('system', 'setRetentionConfig', 'mutation', input),\n forceRetentionCleanup: (input?: unknown) => dispatch('system', 'forceRetentionCleanup', 'mutation', input),\n }\n\n const toastInterface = {\n onToast: (input?: unknown, push?: unknown) => dispatch('toast', 'onToast', 'subscription', input, push),\n }\n\n const turnProviderInterface = {\n getTurnServers: (input?: unknown) => dispatch('turnProvider', 'getTurnServers', 'query', input),\n }\n\n const userManagementInterface = {\n listUsers: (input?: unknown) => dispatch('userManagement', 'listUsers', 'query', input),\n createUser: (input?: unknown) => dispatch('userManagement', 'createUser', 'mutation', input),\n updateUser: (input?: unknown) => dispatch('userManagement', 'updateUser', 'mutation', input),\n deleteUser: (input?: unknown) => dispatch('userManagement', 'deleteUser', 'mutation', input),\n resetPassword: (input?: unknown) => dispatch('userManagement', 'resetPassword', 'mutation', input),\n validateCredentials: (input?: unknown) => dispatch('userManagement', 'validateCredentials', 'mutation', input),\n listApiKeys: (input?: unknown) => dispatch('userManagement', 'listApiKeys', 'query', input),\n createApiKey: (input?: unknown) => dispatch('userManagement', 'createApiKey', 'mutation', input),\n revokeApiKey: (input?: unknown) => dispatch('userManagement', 'revokeApiKey', 'mutation', input),\n validateApiKey: (input?: unknown) => dispatch('userManagement', 'validateApiKey', 'mutation', input),\n createScopedToken: (input?: unknown) => dispatch('userManagement', 'createScopedToken', 'mutation', input),\n revokeScopedToken: (input?: unknown) => dispatch('userManagement', 'revokeScopedToken', 'mutation', input),\n validateScopedToken: (input?: unknown) => dispatch('userManagement', 'validateScopedToken', 'query', input),\n listScopedTokens: (input?: unknown) => dispatch('userManagement', 'listScopedTokens', 'query', input),\n }\n\n return {\n addonPages: addonPagesInterface,\n addons: addonsInterface,\n addonSettings: addonSettingsInterface,\n addonWidgets: addonWidgetsInterface,\n alerts: alertsInterface,\n audioAnalyzer: audioAnalyzerInterface,\n audioCodec: audioCodecInterface,\n backup: backupInterface,\n decoder: decoderInterface,\n deviceManager: deviceManagerInterface,\n deviceProvider: deviceProviderInterface,\n deviceState: deviceStateInterface,\n integrations: integrationsInterface,\n metricsProvider: metricsProviderInterface,\n networkQuality: networkQualityInterface,\n nodes: nodesInterface,\n notificationOutput: notificationOutputInterface,\n pipelineExecutor: pipelineExecutorInterface,\n pipelineOrchestrator: pipelineOrchestratorInterface,\n pipelineRunner: pipelineRunnerInterface,\n platformProbe: platformProbeInterface,\n recordingEngine: recordingEngineInterface,\n settingsStore: settingsStoreInterface,\n storage: storageInterface,\n streamBroker: streamBrokerInterface,\n system: systemInterface,\n toast: toastInterface,\n turnProvider: turnProviderInterface,\n userManagement: userManagementInterface,\n }\n}\n","/**\n * SystemMirror — system-wide reactive view of every device, like\n * Scrypted's `systemManager.getDeviceById`. One warm-boot fetches the\n * full bindings + runtime-state snapshot + device metadata; live\n * `device.state-changed`, `capability.binding-changed`,\n * `device.registered`, `device.unregistered`, and `device.updated`\n * events keep the in-memory mirrors fresh. Subsequent\n * `getDeviceById(id)` calls are sync.\n *\n * Renamed from `SystemManager` (and its file `system-manager.ts`) when\n * the SDK introduced a top-level `System` facade. The cluster-wide\n * mirror is one of `System`'s collaborators — calling it a \"mirror\"\n * disambiguates from the new public class. The old export name is\n * still available as a deprecated alias from this file.\n *\n * Cap-agnostic by construction: the state mirror is `Map<deviceId,\n * Map<capName, slice>>` and the proxies are produced by the\n * codegen'd `createDeviceProxy` we already use everywhere — so a\n * brand-new cap with `runtimeState:` lights up here without a single\n * line of additional code.\n *\n * Two transports today, same shape:\n * - tRPC client (browser, Electron, SDK consumers).\n * - In-process AddonApi (server REPL, addons that want a global view).\n *\n * Boot:\n *\n * const sm = new SystemMirror(api)\n * await sm.init()\n *\n * const dev = sm.getDeviceById(8) // sync\n * dev?.state.battery.value?.sleeping // sync read from mirror\n * await dev?.snapshot?.getSnapshot({...}) // method dispatch via cap-router\n *\n * sm.query({ addonId: 'reolink', online: true })\n * sm.whereState('battery', s => s.percentage < 20)\n * sm.listenCap('motion', (id, slice) => …)\n * await sm.waitForState(8, 'battery', s => !s.sleeping, 30_000)\n *\n * Lifecycle: caller is responsible for `dispose()` when done — closes\n * the live event subscriptions.\n */\n\nimport type { DeviceBinding } from './device-binding.js'\nimport { createDeviceProxy, type DeviceProxy } from '../generated/device-proxy.js'\nimport type { AddonApi } from '../generated/addon-api.js'\nimport type { DeviceInfo } from '../capabilities/device-manager.cap.js'\nimport { DeviceType } from './device-type.js'\nimport { createMirrorSource, type SliceHandleApi, type SliceHandleSource } from './device-state-handle.js'\n\nconst STATE_CHANGED_CATEGORY = 'device.state-changed'\nconst BINDING_CHANGED_CATEGORY = 'capability.binding-changed'\nconst DEVICE_REGISTERED_CATEGORY = 'device.registered'\nconst DEVICE_UNREGISTERED_CATEGORY = 'device.unregistered'\nconst DEVICE_UPDATED_CATEGORY = 'device.updated'\n\n/**\n * Minimal subset of `AddonApi` the SystemMirror needs.\n */\nexport interface SystemMirrorApi extends SliceHandleApi {\n readonly deviceManager: {\n readonly getAllBindings: {\n query(input: Record<string, never>): Promise<ReadonlyArray<DeviceBinding>>\n }\n readonly listAll: {\n query(input: { addonId?: string }): Promise<ReadonlyArray<DeviceInfo>>\n }\n }\n readonly deviceState: SliceHandleApi['deviceState'] & {\n readonly getAllSnapshots: {\n query(input: Record<string, never>): Promise<Record<string, Record<string, Record<string, unknown>>>>\n }\n }\n}\n\nexport type SystemMirrorListener = (\n deviceId: number,\n capName: string,\n slice: Record<string, unknown> | undefined,\n) => void\n\nexport type DeviceCapListener = (\n deviceId: number,\n slice: Record<string, unknown> | undefined,\n) => void\n\nexport type DeviceLifecycleListener = (\n deviceId: number,\n info: DeviceInfo | null,\n) => void\n\n/**\n * Match shape — `string` is exact match, `RegExp` is regex match,\n * `{ contains }` is case-insensitive substring, `{ exact }` is the\n * verbose form of plain string. Useful for `query({ name: ... })`\n * where the same field accepts multiple match modes.\n */\nexport type StringMatch =\n | string\n | RegExp\n | { readonly exact: string }\n | { readonly contains: string }\n\n/**\n * Filter set for `query()`. All fields are optional and ANDed\n * together. Array values are ORed within a single field\n * (`addonId: ['a', 'b']` matches devices owned by either). The\n * `where` escape hatch runs LAST so the structured filters do the\n * cheap rejection first.\n */\nexport interface DeviceQueryFilters {\n /** Match by exact deviceId. Single value or array (OR'd). */\n readonly id?: number | readonly number[]\n /** Match by exact stableId. Single value or array. */\n readonly stableId?: string | readonly string[]\n /** Match by owning addonId. Single value or array. */\n readonly addonId?: string | readonly string[]\n /** Match by `DeviceType` enum value. Single value or array. */\n readonly type?: DeviceType | readonly DeviceType[]\n /** Match devices that bind ALL listed caps. Single capName or array. */\n readonly caps?: string | readonly string[]\n /** Match devices that bind ANY of the listed caps. Mutually exclusive\n * with `caps`. */\n readonly anyCap?: string | readonly string[]\n /** Match by device name. */\n readonly name?: StringMatch\n /** Match the `online` flag. */\n readonly online?: boolean\n /** Match by parent device id. Pass `null` for top-level devices. */\n readonly parentDeviceId?: number | null\n /** Match devices that expose a feature (e.g. `'BatteryOperated'`). */\n readonly feature?: string | readonly string[]\n /** Match `isCamera` flag. */\n readonly isCamera?: boolean\n /** Custom predicate. Runs last; receives both metadata and proxy. */\n readonly where?: (info: DeviceInfo, proxy: DeviceProxy) => boolean\n}\n\nexport class SystemMirror {\n /** deviceId → capName → slice (push-driven mirror). */\n private readonly stateMirror: Map<number, Map<string, Record<string, unknown>>> = new Map()\n /** deviceId → binding (warm-boot + binding-changed events). */\n private readonly bindings: Map<number, DeviceBinding> = new Map()\n /** deviceId → metadata (warm-boot + lifecycle events). */\n private readonly devices: Map<number, DeviceInfo> = new Map()\n /** Listener map for individual `(deviceId, capName)` watches —\n * shared with every `MirrorSource` we hand out. */\n private readonly handleListeners = new Map<string, Set<(slice: unknown | undefined) => void>>()\n /** Global state-change listeners registered via `listen()`. */\n private readonly globalStateListeners = new Set<SystemMirrorListener>()\n /** Per-cap state listeners registered via `listenCap(capName, …)`. */\n private readonly capListeners = new Map<string, Set<DeviceCapListener>>()\n /** Per-device state listeners registered via `listenDevice(id, …)`. */\n private readonly deviceListeners = new Map<number, Set<SystemMirrorListener>>()\n /** Lifecycle listeners. */\n private readonly addedListeners = new Set<DeviceLifecycleListener>()\n private readonly removedListeners = new Set<DeviceLifecycleListener>()\n /** waitForState pending requests — keyed by an internal counter. */\n private readonly pendingWaits = new Set<{ check: () => boolean; resolve: () => void }>()\n /** Memoised state source — every proxy shares it. */\n private readonly stateSource: SliceHandleSource\n /** Live event bridges — closed in `dispose()`. */\n private bridges: Array<{ unsubscribe: () => void }> = []\n private initialized = false\n private initPromise: Promise<void> | null = null\n\n constructor(private readonly api: SystemMirrorApi) {\n this.stateSource = createMirrorSource(this.stateMirror, this.handleListeners, this.api)\n }\n\n // ── Lifecycle ──────────────────────────────────────────────────────\n\n /**\n * Warm-boot: three round-trips (bindings + snapshots + listAll) and\n * then the live event subscriptions. Idempotent — concurrent callers\n * await the same in-flight Promise.\n *\n * Each warm-boot query is wrapped in a 15s timeout so a missing\n * endpoint or stuck broker poll surfaces as a clear error instead\n * of silently hanging the caller forever. The default is generous\n * enough for cluster-wide setups but short enough for ops to\n * notice and fix the underlying transport issue.\n */\n async init(timeoutMs: number = 15_000): Promise<void> {\n if (this.initialized) return\n if (this.initPromise) return this.initPromise\n\n this.initPromise = (async () => {\n const withTimeout = <T>(p: Promise<T>, label: string): Promise<T> => {\n if (!Number.isFinite(timeoutMs)) return p\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(\n () => reject(new Error(`SystemMirror.init: '${label}' timed out after ${timeoutMs}ms`)),\n timeoutMs,\n )\n p.then(\n (v) => { clearTimeout(timer); resolve(v) },\n (err) => { clearTimeout(timer); reject(err as Error) },\n )\n })\n }\n\n const [allBindings, allSnapshots, allDevices] = await Promise.all([\n withTimeout(this.api.deviceManager.getAllBindings.query({}), 'deviceManager.getAllBindings'),\n withTimeout(this.api.deviceState.getAllSnapshots.query({}), 'deviceState.getAllSnapshots'),\n withTimeout(this.api.deviceManager.listAll.query({}), 'deviceManager.listAll'),\n ])\n\n for (const b of allBindings) this.bindings.set(b.deviceId, b)\n\n for (const [deviceIdStr, perCap] of Object.entries(allSnapshots)) {\n const deviceId = Number(deviceIdStr)\n if (!Number.isFinite(deviceId)) continue\n const capMap = new Map<string, Record<string, unknown>>()\n for (const [capName, slice] of Object.entries(perCap)) capMap.set(capName, slice)\n this.stateMirror.set(deviceId, capMap)\n }\n\n for (const info of allDevices) this.devices.set(info.id, info)\n\n // Subscriptions are best-effort — `live.onEvent` may not be\n // wired in some environments (e.g. when the api is a partial\n // adapter). Catch errors so init still completes; the mirror\n // just stops getting live updates instead of hanging the\n // entire REPL/SDK boot.\n try {\n this.subscribeBus()\n } catch (err) {\n // Swallow — `subscribeBus` itself is safe (it checks\n // `api.live?.onEvent`), but defend against transport\n // wrappers that throw on subscribe.\n void err\n }\n this.initialized = true\n })()\n\n try {\n await this.initPromise\n } finally {\n this.initPromise = null\n }\n }\n\n /** True after `init()` resolves. */\n isReady(): boolean {\n return this.initialized\n }\n\n /** Promise that resolves once `init()` has completed. */\n async awaitReady(): Promise<void> {\n if (this.initialized) return\n if (this.initPromise) return this.initPromise\n return this.init()\n }\n\n /**\n * Tear down the event bridges + clear listener registries. Existing\n * proxy references become inert (slice reads keep working off the\n * stale mirror, but no further updates arrive).\n */\n dispose(): void {\n for (const b of this.bridges) {\n try { b.unsubscribe() } catch { /* ignore */ }\n }\n this.bridges = []\n this.handleListeners.clear()\n this.globalStateListeners.clear()\n this.capListeners.clear()\n this.deviceListeners.clear()\n this.addedListeners.clear()\n this.removedListeners.clear()\n this.pendingWaits.clear()\n this.initialized = false\n }\n\n // ── Lookup ─────────────────────────────────────────────────────────\n\n /** Sync lookup by numeric id. `null` if unknown. */\n getDeviceById(deviceId: number): DeviceProxy | null {\n const binding = this.bindings.get(deviceId)\n if (!binding) return null\n return createDeviceProxy(this.api as AddonApi, binding, { stateSource: this.stateSource })\n }\n\n /** Sync lookup by display name (exact match). `null` if unknown. */\n getDeviceByName(name: string): DeviceProxy | null {\n for (const info of this.devices.values()) {\n if (info.name === name) return this.getDeviceById(info.id)\n }\n return null\n }\n\n /** Sync lookup by stableId (the addon-scoped external id). */\n getDeviceByStableId(stableId: string): DeviceProxy | null {\n for (const info of this.devices.values()) {\n if (info.stableId === stableId) return this.getDeviceById(info.id)\n }\n return null\n }\n\n /** All devices owned by an addon. */\n getDevicesByAddon(addonId: string): readonly DeviceProxy[] {\n return this.query({ addonId })\n }\n\n /** All devices of a given `DeviceType`. */\n getDevicesByType(type: DeviceType): readonly DeviceProxy[] {\n return this.query({ type })\n }\n\n /**\n * Live metadata snapshot for a device. Same shape as\n * `deviceManager.getDevice(id)`; sync from the mirror.\n */\n getDeviceInfo(deviceId: number): DeviceInfo | null {\n return this.devices.get(deviceId) ?? null\n }\n\n /** Snapshot of every known device as a typed proxy. */\n getAllDevices(): readonly DeviceProxy[] {\n const out: DeviceProxy[] = []\n for (const id of this.bindings.keys()) {\n const proxy = this.getDeviceById(id)\n if (proxy) out.push(proxy)\n }\n return out\n }\n\n /** Filter devices by cap presence — shorthand for `query({caps: capName})`. */\n filterByCap(capName: string): readonly DeviceProxy[] {\n return this.query({ caps: capName })\n }\n\n // ── Unified query ──────────────────────────────────────────────────\n\n /**\n * Filter the fleet against a structured filter set. All fields ANDed,\n * arrays ORed within a single field. Returns proxies — chain with\n * cap-method calls or state reads as needed.\n *\n * Examples:\n *\n * sm.query({ addonId: 'reolink', online: true })\n * sm.query({ type: DeviceType.Camera, caps: ['snapshot', 'motion'] })\n * sm.query({ id: [1, 2, 3] })\n * sm.query({ name: { contains: 'sala' } })\n * sm.query({ name: /^cam-\\d+$/ })\n * sm.query({ parentDeviceId: 8 }) // accessories of cam 8\n * sm.query({ where: (info, dev) => dev.state.battery.value?.sleeping })\n */\n query(filters: DeviceQueryFilters = {}): readonly DeviceProxy[] {\n const out: DeviceProxy[] = []\n for (const [deviceId, binding] of this.bindings) {\n const info = this.devices.get(deviceId)\n // Most filters need DeviceInfo. If we don't have it, only `id` /\n // `caps` / `anyCap` filters can resolve — for everything else\n // skip the device. (This window is brief: warm-boot races\n // bindings vs metadata for a few ms.)\n if (filters.id !== undefined && !inSet(deviceId, filters.id)) continue\n if (filters.stableId !== undefined) {\n if (!info) continue\n if (!inSet(info.stableId, filters.stableId)) continue\n }\n if (filters.addonId !== undefined) {\n if (!info) continue\n if (!inSet(info.addonId, filters.addonId)) continue\n }\n if (filters.type !== undefined) {\n if (!info) continue\n if (!inSet(info.type, filters.type)) continue\n }\n if (filters.caps !== undefined) {\n const required = toArray(filters.caps)\n const bound = new Set(binding.entries.map((e) => e.capName))\n if (!required.every((c) => bound.has(c))) continue\n }\n if (filters.anyCap !== undefined) {\n const wanted = toArray(filters.anyCap)\n const bound = new Set(binding.entries.map((e) => e.capName))\n if (!wanted.some((c) => bound.has(c))) continue\n }\n if (filters.name !== undefined) {\n if (!info) continue\n if (!matchesString(info.name, filters.name)) continue\n }\n if (filters.online !== undefined) {\n if (!info) continue\n if (info.online !== filters.online) continue\n }\n if (filters.parentDeviceId !== undefined) {\n if (!info) continue\n const want = filters.parentDeviceId\n const got = info.parentDeviceId ?? null\n if (got !== want) continue\n }\n if (filters.feature !== undefined) {\n if (!info) continue\n const want = toArray(filters.feature)\n if (!want.every((f) => info.features.includes(f))) continue\n }\n if (filters.isCamera !== undefined) {\n if (!info) continue\n if (info.isCamera !== filters.isCamera) continue\n }\n const proxy = this.getDeviceById(deviceId)\n if (!proxy) continue\n if (filters.where && info) {\n if (!filters.where(info, proxy)) continue\n } else if (filters.where && !info) {\n continue\n }\n out.push(proxy)\n }\n return out\n }\n\n // ── State-driven queries ───────────────────────────────────────────\n\n /**\n * Return every proxy whose runtime-state slice for `capName` matches\n * `predicate`. Devices without the cap or without a slice are\n * skipped. The predicate receives a typed slice reference — pass\n * the typed cap (e.g. `'battery'`) and TypeScript widens to\n * `Record<string, unknown>`; cast inside the predicate body if the\n * caller knows the cap shape.\n */\n whereState<T extends Record<string, unknown> = Record<string, unknown>>(\n capName: string,\n predicate: (slice: T, deviceId: number) => boolean,\n ): readonly DeviceProxy[] {\n const out: DeviceProxy[] = []\n for (const [deviceId, perCap] of this.stateMirror) {\n const slice = perCap.get(capName) as T | undefined\n if (!slice) continue\n if (!predicate(slice, deviceId)) continue\n const proxy = this.getDeviceById(deviceId)\n if (proxy) out.push(proxy)\n }\n return out\n }\n\n /** Map every device's slice for `capName` to a derived value. Devices\n * without the cap or without a slice are skipped. */\n mapState<T extends Record<string, unknown> = Record<string, unknown>, R = unknown>(\n capName: string,\n mapper: (slice: T, deviceId: number) => R,\n ): readonly R[] {\n const out: R[] = []\n for (const [deviceId, perCap] of this.stateMirror) {\n const slice = perCap.get(capName) as T | undefined\n if (!slice) continue\n out.push(mapper(slice, deviceId))\n }\n return out\n }\n\n /** First device whose slice matches `predicate`, or null. */\n findState<T extends Record<string, unknown> = Record<string, unknown>>(\n capName: string,\n predicate: (slice: T, deviceId: number) => boolean,\n ): DeviceProxy | null {\n for (const [deviceId, perCap] of this.stateMirror) {\n const slice = perCap.get(capName) as T | undefined\n if (!slice) continue\n if (!predicate(slice, deviceId)) continue\n return this.getDeviceById(deviceId)\n }\n return null\n }\n\n /** Count devices that bind a cap. Faster than `filterByCap(...).length`. */\n countByCap(capName: string): number {\n let n = 0\n for (const binding of this.bindings.values()) {\n if (binding.entries.some((e) => e.capName === capName)) n++\n }\n return n\n }\n\n /** Count devices whose slice for `capName` matches `predicate`. */\n countByState<T extends Record<string, unknown> = Record<string, unknown>>(\n capName: string,\n predicate: (slice: T, deviceId: number) => boolean,\n ): number {\n let n = 0\n for (const [deviceId, perCap] of this.stateMirror) {\n const slice = perCap.get(capName) as T | undefined\n if (!slice) continue\n if (predicate(slice, deviceId)) n++\n }\n return n\n }\n\n // ── Listeners ──────────────────────────────────────────────────────\n\n /**\n * Global listener — fires for every `device.state-changed` event the\n * mirror absorbs.\n */\n listen(cb: SystemMirrorListener): () => void {\n this.globalStateListeners.add(cb)\n return () => { this.globalStateListeners.delete(cb) }\n }\n\n /**\n * Per-cap listener — fires only for state changes on `capName`,\n * across every device. The callback receives the deviceId so the\n * caller can route.\n */\n listenCap(capName: string, cb: DeviceCapListener): () => void {\n let set = this.capListeners.get(capName)\n if (!set) { set = new Set(); this.capListeners.set(capName, set) }\n set.add(cb)\n return () => {\n set!.delete(cb)\n if (set!.size === 0) this.capListeners.delete(capName)\n }\n }\n\n /**\n * Per-device listener — fires for every cap change on `deviceId`.\n */\n listenDevice(deviceId: number, cb: SystemMirrorListener): () => void {\n let set = this.deviceListeners.get(deviceId)\n if (!set) { set = new Set(); this.deviceListeners.set(deviceId, set) }\n set.add(cb)\n return () => {\n set!.delete(cb)\n if (set!.size === 0) this.deviceListeners.delete(deviceId)\n }\n }\n\n /** Fires when `device.registered` lands. Receives the new metadata. */\n onDeviceAdded(cb: DeviceLifecycleListener): () => void {\n this.addedListeners.add(cb)\n return () => { this.addedListeners.delete(cb) }\n }\n\n /** Fires when `device.unregistered` lands. `info` is the LAST-known\n * metadata (or null if the device was never seen). */\n onDeviceRemoved(cb: DeviceLifecycleListener): () => void {\n this.removedListeners.add(cb)\n return () => { this.removedListeners.delete(cb) }\n }\n\n // ── Wait primitives ────────────────────────────────────────────────\n\n /**\n * Resolve when `predicate` over the runtime-state slice for\n * `(deviceId, capName)` becomes true. Resolves immediately if the\n * current slice already matches. Rejects with `Error('timeout')`\n * after `timeoutMs` (default 30s; pass `Infinity` to wait forever).\n *\n * Returns the matching slice — caller can read it directly without\n * a second mirror lookup.\n */\n waitForState<T extends Record<string, unknown> = Record<string, unknown>>(\n deviceId: number,\n capName: string,\n predicate: (slice: T) => boolean,\n timeoutMs: number = 30_000,\n ): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const check = (): T | null => {\n const slice = this.stateMirror.get(deviceId)?.get(capName) as T | undefined\n if (slice && predicate(slice)) return slice\n return null\n }\n const initial = check()\n if (initial) {\n resolve(initial)\n return\n }\n\n let timer: ReturnType<typeof setTimeout> | null = null\n const off = this.listenDevice(deviceId, (_id, cap, slice) => {\n if (cap !== capName) return\n if (!slice) return\n if (predicate(slice as T)) {\n if (timer) clearTimeout(timer)\n off()\n resolve(slice as T)\n }\n })\n if (Number.isFinite(timeoutMs)) {\n timer = setTimeout(() => {\n off()\n reject(new Error(`waitForState timed out after ${timeoutMs}ms (deviceId=${deviceId}, capName=${capName})`))\n }, timeoutMs)\n }\n })\n }\n\n /**\n * Resolve when a device with `deviceId` becomes available (a\n * binding exists). Resolves immediately if already known. Rejects\n * with timeout.\n */\n waitForDevice(deviceId: number, timeoutMs: number = 30_000): Promise<DeviceProxy> {\n return new Promise<DeviceProxy>((resolve, reject) => {\n const existing = this.getDeviceById(deviceId)\n if (existing) {\n resolve(existing)\n return\n }\n let timer: ReturnType<typeof setTimeout> | null = null\n const off = this.onDeviceAdded((id) => {\n if (id !== deviceId) return\n const proxy = this.getDeviceById(id)\n if (!proxy) return\n if (timer) clearTimeout(timer)\n off()\n resolve(proxy)\n })\n if (Number.isFinite(timeoutMs)) {\n timer = setTimeout(() => {\n off()\n reject(new Error(`waitForDevice timed out after ${timeoutMs}ms (deviceId=${deviceId})`))\n }, timeoutMs)\n }\n })\n }\n\n // ── Batch actions ──────────────────────────────────────────────────\n\n /**\n * Iterate every device that binds `capName`. Awaits each callback\n * sequentially — for parallel use `invokeCap` with explicit\n * parallelism.\n */\n async forEachCap(\n capName: string,\n cb: (proxy: DeviceProxy) => void | Promise<void>,\n ): Promise<void> {\n for (const proxy of this.filterByCap(capName)) {\n await cb(proxy)\n }\n }\n\n /**\n * Invoke a cap method on every device that binds the cap. Returns\n * one result per device, success or failure isolated. Optional\n * parallelism cap — useful for \"snapshot all cameras but only 4\n * at a time so battery cams don't all wake at once\".\n *\n * Example:\n *\n * const results = await sm.invokeCap('snapshot', 'getSnapshot', {}, { parallelism: 4 })\n * const failed = results.filter(r => !r.ok)\n */\n async invokeCap<R = unknown>(\n capName: string,\n methodName: string,\n args: Record<string, unknown>,\n opts: { parallelism?: number } = {},\n ): Promise<ReadonlyArray<{ deviceId: number; ok: boolean; result?: R; error?: unknown }>> {\n const targets = this.filterByCap(capName)\n const parallelism = Math.max(1, opts.parallelism ?? targets.length)\n const out: Array<{ deviceId: number; ok: boolean; result?: R; error?: unknown }> = []\n\n for (let i = 0; i < targets.length; i += parallelism) {\n const chunk = targets.slice(i, i + parallelism)\n const settled = await Promise.allSettled(\n chunk.map(async (proxy) => {\n const cap = (proxy as unknown as Record<string, Record<string, (input: unknown) => unknown>>)[capName]\n if (!cap || typeof cap[methodName] !== 'function') {\n throw new Error(`device '${proxy.deviceId}' does not expose '${capName}.${methodName}'`)\n }\n return await cap[methodName]!(args) as R\n }),\n )\n for (let j = 0; j < settled.length; j++) {\n const proxy = chunk[j]!\n const r = settled[j]!\n if (r.status === 'fulfilled') {\n out.push({ deviceId: proxy.deviceId, ok: true, result: r.value })\n } else {\n out.push({ deviceId: proxy.deviceId, ok: false, error: r.reason })\n }\n }\n }\n\n return out\n }\n\n // ── Diagnostics ────────────────────────────────────────────────────\n\n /**\n * One-shot summary — fleet size, breakdown by cap / addon / type.\n * Designed for REPL inspection (`sm.summary()`).\n */\n summary(): {\n totalDevices: number\n online: number\n offline: number\n byCap: Record<string, number>\n byAddon: Record<string, number>\n byType: Record<string, number>\n statedDevices: number\n } {\n const byCap: Record<string, number> = {}\n const byAddon: Record<string, number> = {}\n const byType: Record<string, number> = {}\n let online = 0\n let offline = 0\n\n for (const binding of this.bindings.values()) {\n for (const entry of binding.entries) {\n byCap[entry.capName] = (byCap[entry.capName] ?? 0) + 1\n }\n }\n\n for (const info of this.devices.values()) {\n byAddon[info.addonId] = (byAddon[info.addonId] ?? 0) + 1\n byType[info.type] = (byType[info.type] ?? 0) + 1\n if (info.online) online++; else offline++\n }\n\n return {\n totalDevices: this.bindings.size,\n online,\n offline,\n byCap,\n byAddon,\n byType,\n statedDevices: this.stateMirror.size,\n }\n }\n\n /**\n * Debug-friendly dump — full state + binding + metadata for one\n * device or all devices. Cheap deep clone so caller mutations don't\n * leak into the mirror.\n */\n dump(deviceId?: number): unknown {\n const dumpOne = (id: number): unknown => {\n const info = this.devices.get(id) ?? null\n const binding = this.bindings.get(id) ?? null\n const state: Record<string, Record<string, unknown>> = {}\n const perCap = this.stateMirror.get(id)\n if (perCap) {\n for (const [cap, slice] of perCap) state[cap] = { ...slice }\n }\n return {\n deviceId: id,\n info,\n binding: binding ? { ...binding, entries: binding.entries.map((e) => ({ ...e })) } : null,\n state,\n }\n }\n\n if (deviceId !== undefined) return dumpOne(deviceId)\n\n const out: unknown[] = []\n for (const id of this.bindings.keys()) out.push(dumpOne(id))\n return out\n }\n\n /**\n * Direct read-only access to the underlying state mirror. Use\n * sparingly — `getSystemState` returns a deep copy that's safer for\n * exploratory work; this avoids the clone cost when iterating\n * thousands of slices.\n */\n getRawMirror(): ReadonlyMap<number, ReadonlyMap<string, Record<string, unknown>>> {\n return this.stateMirror\n }\n\n /**\n * Snapshot of the full state mirror — same shape as the warm-boot\n * payload. Deep-cloned; safe to mutate.\n */\n getSystemState(): Map<number, Map<string, Record<string, unknown>>> {\n const copy = new Map<number, Map<string, Record<string, unknown>>>()\n for (const [id, perCap] of this.stateMirror) {\n const dup = new Map<string, Record<string, unknown>>()\n for (const [k, v] of perCap) dup.set(k, { ...v })\n copy.set(id, dup)\n }\n return copy\n }\n\n // ── Internals ──────────────────────────────────────────────────────\n\n private subscribeBus(): void {\n if (!this.api.live?.onEvent) return\n const sub = this.api.live.onEvent\n\n this.bridges.push(\n sub.subscribe(\n { category: STATE_CHANGED_CATEGORY },\n {\n onData: (evt) => {\n const data = evt.data as { deviceId?: number; capName?: string; slice?: Record<string, unknown> } | null\n if (!data || typeof data.deviceId !== 'number' || typeof data.capName !== 'string') return\n this.applyStateUpdate(data.deviceId, data.capName, data.slice)\n },\n },\n ),\n )\n\n this.bridges.push(\n sub.subscribe(\n { category: BINDING_CHANGED_CATEGORY },\n {\n onData: (evt) => {\n const data = evt.data as { deviceId?: number; source?: { type?: string; id?: number | string } } | null\n const deviceId =\n typeof data?.deviceId === 'number'\n ? data.deviceId\n : data?.source?.type === 'device' && typeof data.source.id === 'number'\n ? data.source.id\n : null\n if (deviceId === null) return\n void this.refreshBinding(deviceId)\n },\n },\n ),\n )\n\n this.bridges.push(\n sub.subscribe(\n { category: DEVICE_REGISTERED_CATEGORY },\n {\n onData: (evt) => {\n const data = evt.data as { deviceId?: number } | null\n if (typeof data?.deviceId !== 'number') return\n void this.refreshDeviceMetadata(data.deviceId, 'added')\n },\n },\n ),\n )\n\n this.bridges.push(\n sub.subscribe(\n { category: DEVICE_UNREGISTERED_CATEGORY },\n {\n onData: (evt) => {\n const data = evt.data as { deviceId?: number } | null\n if (typeof data?.deviceId !== 'number') return\n this.applyDeviceRemoval(data.deviceId)\n },\n },\n ),\n )\n\n this.bridges.push(\n sub.subscribe(\n { category: DEVICE_UPDATED_CATEGORY },\n {\n onData: (evt) => {\n const data = evt.data as { deviceId?: number } | null\n if (typeof data?.deviceId !== 'number') return\n void this.refreshDeviceMetadata(data.deviceId, 'updated')\n },\n },\n ),\n )\n }\n\n private applyStateUpdate(\n deviceId: number,\n capName: string,\n slice: Record<string, unknown> | undefined,\n ): void {\n let perCap = this.stateMirror.get(deviceId)\n if (!perCap) {\n perCap = new Map()\n this.stateMirror.set(deviceId, perCap)\n }\n if (slice === undefined) {\n perCap.delete(capName)\n } else {\n perCap.set(capName, slice)\n }\n\n const handleKey = `${deviceId}:${capName}`\n const handleSet = this.handleListeners.get(handleKey)\n if (handleSet) {\n for (const cb of handleSet) {\n try { cb(slice) } catch { /* isolated */ }\n }\n }\n\n for (const cb of this.globalStateListeners) {\n try { cb(deviceId, capName, slice) } catch { /* isolated */ }\n }\n\n const capSet = this.capListeners.get(capName)\n if (capSet) {\n for (const cb of capSet) {\n try { cb(deviceId, slice) } catch { /* isolated */ }\n }\n }\n\n const devSet = this.deviceListeners.get(deviceId)\n if (devSet) {\n for (const cb of devSet) {\n try { cb(deviceId, capName, slice) } catch { /* isolated */ }\n }\n }\n }\n\n private applyDeviceRemoval(deviceId: number): void {\n const lastInfo = this.devices.get(deviceId) ?? null\n this.bindings.delete(deviceId)\n this.devices.delete(deviceId)\n this.stateMirror.delete(deviceId)\n for (const cb of this.removedListeners) {\n try { cb(deviceId, lastInfo) } catch { /* isolated */ }\n }\n }\n\n private async refreshBinding(deviceId: number): Promise<void> {\n try {\n const all = await this.api.deviceManager.getAllBindings.query({})\n const fresh = all.find((b) => b.deviceId === deviceId)\n if (fresh) {\n this.bindings.set(deviceId, fresh)\n } else {\n // Device was removed — emit lifecycle hook so consumers can\n // clean up. Use the same path as `device.unregistered` events.\n this.applyDeviceRemoval(deviceId)\n }\n } catch {\n // Transient failure — leave stale binding; next event retries.\n }\n }\n\n private async refreshDeviceMetadata(deviceId: number, kind: 'added' | 'updated'): Promise<void> {\n try {\n // listAll is cheap and idempotent. Single-device fetch\n // (`getDevice(id)`) would be lighter but means another method\n // on the api surface for tests; sticking with listAll keeps the\n // contract small.\n const all = await this.api.deviceManager.listAll.query({})\n const info = all.find((d) => d.id === deviceId)\n if (!info) return\n\n const wasNew = !this.devices.has(deviceId)\n this.devices.set(deviceId, info)\n\n if (kind === 'added' && wasNew) {\n // `device.registered` event ran but the bindings/state for\n // the new device may still be in flight from the worker.\n // Refresh bindings so consumers can immediately use the\n // device proxy. Lifecycle listener fires after binding lands.\n await this.refreshBinding(deviceId)\n for (const cb of this.addedListeners) {\n try { cb(deviceId, info) } catch { /* isolated */ }\n }\n }\n } catch {\n /* transient — next event retries */\n }\n }\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────\n\nfunction inSet<T>(value: T, set: T | readonly T[]): boolean {\n if (Array.isArray(set)) return (set as readonly T[]).includes(value)\n return value === set\n}\n\nfunction toArray<T>(value: T | readonly T[]): readonly T[] {\n return Array.isArray(value) ? (value as readonly T[]) : [value as T]\n}\n\nfunction matchesString(haystack: string, match: StringMatch): boolean {\n if (typeof match === 'string') return haystack === match\n if (match instanceof RegExp) return match.test(haystack)\n if ('exact' in match) return haystack === match.exact\n if ('contains' in match) return haystack.toLowerCase().includes(match.contains.toLowerCase())\n return false\n}\n\n","/**\n * Custom-action contracts — a mechanism for addons to expose system-level\n * extensibility endpoints (e.g. benchmark addon API) through a single\n * generic `api.addons.custom` tRPC endpoint.\n *\n * The contract shape mirrors `method()` from capability-definition.ts —\n * input/output Zod schemas, kind, auth — plus a `scope` discriminated union\n * (today only 'system' is runtime-supported; 'device' is typed for forward\n * compat).\n */\n\nimport type { z } from 'zod'\nimport type { DeviceType } from '../device/device-type.js'\nimport type { CapabilityMethodAuth } from './capability-definition.js'\n\n/** Scope of a custom action. Today only `system` is supported by the runtime. */\nexport type CustomActionScope =\n | { readonly kind: 'system' }\n | { readonly kind: 'device'; readonly deviceTypes?: readonly DeviceType[] }\n\nexport interface CustomActionSpec<\n TIn extends z.ZodType = z.ZodType,\n TOut extends z.ZodType = z.ZodType,\n TKind extends 'query' | 'mutation' | 'subscription' = 'query' | 'mutation' | 'subscription',\n TAuth extends CapabilityMethodAuth = CapabilityMethodAuth,\n TScope extends CustomActionScope = CustomActionScope,\n> {\n readonly input: TIn\n readonly output: TOut\n readonly kind: TKind\n readonly auth: TAuth\n readonly scope: TScope\n}\n\nexport type CustomActionsSpec = Record<string, CustomActionSpec>\n\n/**\n * Identity — preserves literal types for downstream inference.\n *\n * The constraint is `Record<string, unknown>` (not `CustomActionsSpec`) so\n * TypeScript does not widen each entry's literal `kind`/`auth` fields to\n * the broader unions declared on `CustomActionSpec`'s default generics.\n * Shape validity is enforced separately by the `customAction(...)` helper\n * whose return type is already a `CustomActionSpec<...>`.\n */\nexport function defineCustomActions<T extends Record<string, unknown>>(spec: T): T {\n return spec\n}\n\nexport interface CustomActionOptions<\n TKind extends 'query' | 'mutation' | 'subscription' = 'query',\n TAuth extends CapabilityMethodAuth = 'protected',\n> {\n readonly kind?: TKind\n readonly auth?: TAuth\n readonly scope?: CustomActionScope\n}\n\nexport function customAction<\n TIn extends z.ZodType,\n TOut extends z.ZodType,\n TKind extends 'query' | 'mutation' | 'subscription' = 'query',\n TAuth extends CapabilityMethodAuth = 'protected',\n>(\n input: TIn,\n output: TOut,\n options?: CustomActionOptions<TKind, TAuth>,\n): CustomActionSpec<TIn, TOut, TKind, TAuth, { readonly kind: 'system' }> {\n return {\n input,\n output,\n kind: (options?.kind ?? 'query') as TKind,\n auth: (options?.auth ?? 'protected') as TAuth,\n scope: (options?.scope ?? { kind: 'system' as const }) as { readonly kind: 'system' },\n }\n}\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n// ── Zod schemas for ConfigUISchemaWithValues ─────────────────────────\n//\n// Same loose field typing as the addons.router.ts schemas — the\n// polymorphic discriminated-union schema would explode to ~14 variants\n// with nested group recursion. `z.any()` keeps runtime validation on\n// the outer structure while preserving assignability to the domain type.\n\nconst ConfigTabDeclarationSchema = z.object({\n id: z.string(),\n label: z.string(),\n icon: z.string(),\n order: z.number().optional(),\n})\n\nconst ConfigSectionWithValuesSchema = z.object({\n id: z.string(),\n title: z.string(),\n description: z.string().optional(),\n style: z.enum(['card', 'accordion']).optional(),\n defaultCollapsed: z.boolean().optional(),\n columns: z.union([z.literal(1), z.literal(2), z.literal(3), z.literal(4)]).optional(),\n tab: z.string().optional(),\n // Hoist the section into a top-level device tab. DeviceDetail\n // discovers these from the aggregate and renders one tab per unique\n // `tab` id; the default `'settings'` keeps the section under Config.\n location: z.enum(['settings', 'top-tab']).optional(),\n order: z.number().optional(),\n fields: z.array(z.any()),\n})\n\nconst SettingsSchemaWithValuesSchema = z.object({\n tabs: z.array(ConfigTabDeclarationSchema).optional(),\n sections: z.array(ConfigSectionWithValuesSchema),\n})\n\n/** Patch object — keys are field names, values are the new field values. */\nconst SettingsPatchSchema = z.record(z.string(), z.unknown())\n\n/** Standard success response for update operations. */\nconst SettingsUpdateResultSchema = z.object({\n success: z.literal(true),\n})\n\n/**\n * addon-settings — singleton gateway for three-level addon settings.\n *\n * Works like `device-manager`: a single hub-side provider that resolves\n * `addonId` to the target addon and delegates the call. For hub-local\n * addons the call is direct; for remote agents it proxies via the\n * per-addon Moleculer service.\n *\n * Replaces the `$addonHost` Moleculer service. Transport transparency\n * is handled by the provider implementation — callers (admin UI, other\n * addons via `ctx.api`) never know which node hosts the target addon.\n *\n * Three levels:\n * - **addon**: addon-scoped settings (installation config, API keys, …)\n * - **global**: settings applied to all devices by default\n * - **device**: per-device overrides\n *\n * Optional `nodeId` allows explicit node targeting. When absent the\n * provider resolves the addon's host node automatically.\n */\n/**\n * `addon-settings` is a **hub-centric** cap: the hub hosts the single\n * provider, and `nodeId` in the input is data for the hub provider's\n * internal dispatcher, not a routing hint for the cap-router. See\n * `CapabilityDefinition.nodeIdMode` for the contract.\n */\nexport const addonSettingsCapability = {\n name: 'addon-settings',\n scope: 'system',\n mode: 'singleton',\n nodeIdMode: 'data',\n methods: {\n // ── Global-level settings ─────────────────────────────────────────\n //\n // `overlay` — optional preview overlay. When present, the provider\n // hydrates the schema as if the overlay were merged on top of the\n // persisted store (without writing anything). Used by override-mode\n // UIs (benchmark tabs) to get cascade-aware option lists when the\n // operator tweaks an upstream field — e.g. changing engineRuntime\n // from 'python' to 'node' refetches with `overlay: {engineRuntime:\n // 'node'}` so the backend/device dropdowns re-derive.\n getGlobalSettings: method(\n z.object({\n addonId: z.string(),\n nodeId: z.string().optional(),\n overlay: z.record(z.string(), z.unknown()).optional(),\n }),\n SettingsSchemaWithValuesSchema.nullable(),\n ),\n updateGlobalSettings: method(\n z.object({ addonId: z.string(), nodeId: z.string().optional(), patch: SettingsPatchSchema }),\n SettingsUpdateResultSchema,\n { kind: 'mutation', auth: 'admin' },\n ),\n\n // ── Device-level settings ─────────────────────────────────────────\n getDeviceSettings: method(\n z.object({ addonId: z.string(), deviceId: z.number(), nodeId: z.string().optional() }),\n SettingsSchemaWithValuesSchema.nullable(),\n ),\n updateDeviceSettings: method(\n z.object({ addonId: z.string(), deviceId: z.number(), nodeId: z.string().optional(), patch: SettingsPatchSchema }),\n SettingsUpdateResultSchema,\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IAddonSettingsProvider = InferProvider<typeof addonSettingsCapability>\n\nexport {\n SettingsSchemaWithValuesSchema,\n ConfigSectionWithValuesSchema,\n ConfigTabDeclarationSchema,\n SettingsPatchSchema,\n SettingsUpdateResultSchema,\n}\n","/**\n * Alerts capability — collection-based internal alert system.\n *\n * Multiple providers can register. Each provider filters by EventBus category\n * and creates/updates alerts. The built-in Alert Center addon persists alerts\n * in the DB and serves them to the admin UI.\n */\n\nimport { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n// ── Alert schemas ───────────────────────────────────────────────────\n\nexport const AlertSeveritySchema = z.enum(['info', 'success', 'warning', 'error'])\n\nexport const AlertStatusSchema = z.enum(['active', 'in-progress', 'completed', 'failed', 'dismissed'])\n\nexport const AlertSourceSchema = z.object({\n type: z.string(),\n id: z.string(),\n})\n\nexport const AlertSchema = z.object({\n id: z.string(),\n category: z.string(),\n severity: AlertSeveritySchema,\n title: z.string(),\n message: z.string(),\n status: AlertStatusSchema,\n progress: z.number().optional(),\n read: z.boolean(),\n createdAt: z.number(),\n updatedAt: z.number(),\n source: AlertSourceSchema.optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\n// ── Inferred types ─────────────────────────────────────────────────\n\nexport type AlertSeverity = z.infer<typeof AlertSeveritySchema>\nexport type AlertStatus = z.infer<typeof AlertStatusSchema>\nexport type Alert = z.infer<typeof AlertSchema>\n\n// ── Capability definition ──────────────────────────────────────────\n\nexport const alertsCapability = {\n name: 'alerts',\n scope: 'system',\n mode: 'singleton',\n methods: {\n emit: method(AlertSchema, z.void(), { kind: 'mutation' }),\n update: method(\n z.object({ alertId: z.string(), patch: AlertSchema.partial() }),\n z.void(),\n { kind: 'mutation' },\n ),\n list: method(\n z.object({ unreadOnly: z.boolean().optional(), limit: z.number().optional() }).optional(),\n z.array(AlertSchema).readonly(),\n ),\n getUnreadCount: method(z.void(), z.number()),\n markRead: method(z.object({ alertId: z.string() }), z.void(), { kind: 'mutation' }),\n markAllRead: method(z.void(), z.void(), { kind: 'mutation' }),\n dismiss: method(z.object({ alertId: z.string() }), z.void(), { kind: 'mutation' }),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IAlertsProvider = InferProvider<typeof alertsCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\nconst StorageLocationTypeSchema = z.enum(['data', 'media', 'recordings', 'models', 'cache', 'logs', 'addons-data'])\n\nexport const storageCapability = {\n name: 'storage',\n scope: 'system',\n mode: 'collection',\n methods: {\n resolve: method(\n z.object({ location: StorageLocationTypeSchema, relativePath: z.string() }),\n z.string(),\n ),\n write: method(\n z.object({ location: StorageLocationTypeSchema, relativePath: z.string() }),\n z.void(),\n { kind: 'mutation' },\n ),\n read: method(\n z.object({ location: StorageLocationTypeSchema, relativePath: z.string() }),\n z.instanceof(Uint8Array),\n ),\n exists: method(\n z.object({ location: StorageLocationTypeSchema, relativePath: z.string() }),\n z.boolean(),\n ),\n list: method(\n z.object({ location: StorageLocationTypeSchema, prefix: z.string().optional() }),\n z.array(z.string()).readonly(),\n ),\n delete: method(\n z.object({ location: StorageLocationTypeSchema, relativePath: z.string() }),\n z.void(),\n { kind: 'mutation' },\n ),\n getAvailableSpace: method(\n z.object({ location: StorageLocationTypeSchema }),\n z.number().nullable(),\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IStorageCapProvider = InferProvider<typeof storageCapability>\n\nexport { StorageLocationTypeSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\nconst BackupEntrySchema = z.object({\n id: z.string(),\n label: z.string().optional(),\n createdAt: z.number(),\n sizeBytes: z.number(),\n locations: z.array(z.string()).optional(),\n})\n\n/**\n * backup — singleton capability for backup management.\n *\n * Implemented by `local-backup` addon. Future providers (S3, rsync)\n * can replace it by registering the same capability.\n */\nexport const backupCapability = {\n name: 'backup',\n scope: 'system',\n mode: 'singleton',\n methods: {\n trigger: method(\n z.object({ locations: z.array(z.string()).optional(), label: z.string().optional() }).optional(),\n BackupEntrySchema,\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n list: method(z.void(), z.array(BackupEntrySchema).readonly(), { auth: 'superAdmin' }),\n restore: method(z.object({ backupId: z.string() }), z.void(), { kind: 'mutation', auth: 'superAdmin' }),\n delete: method(z.object({ backupId: z.string() }), z.void(), { kind: 'mutation', auth: 'superAdmin' }),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IBackupProvider = InferProvider<typeof backupCapability>\n\nexport { BackupEntrySchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n/**\n * Query filter for settings-store collections.\n */\nconst QueryFilterSchema = z.object({\n where: z.record(z.string(), z.unknown()).optional(),\n whereIn: z.record(z.string(), z.array(z.unknown())).optional(),\n whereBetween: z.record(z.string(), z.tuple([z.unknown(), z.unknown()])).optional(),\n orderBy: z.object({\n field: z.string(),\n direction: z.enum(['asc', 'desc']),\n }).optional(),\n limit: z.number().optional(),\n offset: z.number().optional(),\n})\n\n/** A single stored record: `{ id, data }`. */\nconst SettingsRecordSchema = z.object({\n id: z.string(),\n data: z.record(z.string(), z.unknown()),\n})\n\n/**\n * Column declaration for a structured (SQL-backed) collection.\n * SQLite types: TEXT, INTEGER, REAL, JSON (JSON is a compatibility type —\n * SQLite stores it as TEXT, backend handles serialization).\n */\nconst CollectionColumnSchema = z.object({\n name: z.string(),\n type: z.enum(['TEXT', 'INTEGER', 'REAL', 'JSON']),\n primaryKey: z.boolean().optional(),\n notNull: z.boolean().optional(),\n unique: z.boolean().optional(),\n})\n\nconst CollectionIndexSchema = z.object({\n name: z.string(),\n columns: z.array(z.string()).readonly(),\n unique: z.boolean().optional(),\n})\n\n/**\n * settings-store — singleton capability for addon-scoped persistence.\n *\n * Every method operates within a `collection`. An optional `namespace`\n * field provides access to additional data spaces beyond the default\n * addon settings — useful for business data (events, tracks, faces, etc.).\n *\n * Scoping: the implementation prefixes every collection with the calling\n * addon's ID automatically. Addons never see each other's data.\n *\n * - No namespace (default): `\"addon-settings\"` → `\"<addonId>:addon-settings\"`\n * - With namespace: `{ namespace: 'events', collection: 'detections' }` →\n * `\"<addonId>:events:detections\"`\n *\n * Implemented by `@camstack/core/builtins/sqlite-settings` (SQLite WAL backend).\n * Addons access it via `ctx.api.settingsStore.*`.\n */\nexport const settingsStoreCapability = {\n name: 'settings-store',\n scope: 'system',\n mode: 'singleton',\n methods: {\n /** Get a single value by key from a collection. */\n get: method(\n z.object({ namespace: z.string().optional(), collection: z.string(), key: z.string() }),\n z.unknown(),\n ),\n\n /** Set a value by key in a collection (upsert). */\n set: method(\n z.object({ namespace: z.string().optional(), collection: z.string(), key: z.string(), value: z.unknown() }),\n z.void(),\n { kind: 'mutation' },\n ),\n\n /** Get all entries matching an optional filter. */\n query: method(\n z.object({ namespace: z.string().optional(), collection: z.string(), filter: QueryFilterSchema.optional() }),\n z.array(SettingsRecordSchema).readonly(),\n ),\n\n /** Insert a new record. */\n insert: method(\n z.object({ namespace: z.string().optional(), collection: z.string(), record: SettingsRecordSchema }),\n z.void(),\n { kind: 'mutation' },\n ),\n\n /** Update an existing record by ID. */\n update: method(\n z.object({ namespace: z.string().optional(), collection: z.string(), id: z.string(), data: z.record(z.string(), z.unknown()) }),\n z.void(),\n { kind: 'mutation' },\n ),\n\n /** Delete a record by key/ID. */\n delete: method(\n z.object({ namespace: z.string().optional(), collection: z.string(), key: z.string() }),\n z.void(),\n { kind: 'mutation' },\n ),\n\n /** Count entries in a collection, optionally filtered. */\n count: method(\n z.object({ namespace: z.string().optional(), collection: z.string(), filter: QueryFilterSchema.optional() }),\n z.number(),\n ),\n\n /** Check if a collection is empty. */\n isEmpty: method(\n z.object({ namespace: z.string().optional(), collection: z.string() }),\n z.boolean(),\n ),\n\n /**\n * Declare a typed (SQL-backed) collection with explicit columns +\n * indexes. Idempotent: re-declaring an existing collection with the\n * same shape is a no-op; shape changes (new columns, new indexes)\n * are applied additively. Subsequent `insert` / `update` / `delete`\n * / `query` calls on this collection use typed columns instead of\n * JSON-blob storage — `record.data` fields are spread across\n * columns, `query.filter.where` matches real columns (no\n * `json_extract` overhead), `orderBy` uses column indexes.\n *\n * Addons call this in `onInitialize` before their first read/write.\n * Collection names should be namespaced by addon (e.g.\n * `pipeline-analytics:object-events`) to avoid cross-addon\n * clashes — no automatic prefix is added.\n */\n declareCollection: method(\n z.object({\n namespace: z.string().optional(),\n collection: z.string(),\n columns: z.array(CollectionColumnSchema).readonly(),\n indexes: z.array(CollectionIndexSchema).readonly().optional(),\n }),\n z.void(),\n { kind: 'mutation' },\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type ISettingsStoreProvider = InferProvider<typeof settingsStoreCapability>\n\n/**\n * tRPC client namespace type for the settings-store capability.\n * Used as the dependency type for services that need settings persistence.\n * Methods are accessed as `client.get.query(input)`, `client.set.mutate(input)`, etc.\n */\nexport type SettingsStoreClient = import('../generated/addon-api.js').AddonApi['settingsStore']\n\nexport { QueryFilterSchema, SettingsRecordSchema, CollectionColumnSchema, CollectionIndexSchema }\n\nexport type CollectionColumn = z.infer<typeof CollectionColumnSchema>\nexport type CollectionIndex = z.infer<typeof CollectionIndexSchema>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\nconst LogLevelSchema = z.enum(['debug', 'info', 'warn', 'error'])\n\nconst LogEntrySchema = z.object({\n timestamp: z.date(),\n level: LogLevelSchema,\n scope: z.array(z.string()),\n message: z.string(),\n meta: z.record(z.string(), z.unknown()).optional(),\n tags: z.record(z.string(), z.string()).optional(),\n})\n\nexport const logDestinationCapability = {\n name: 'log-destination',\n scope: 'system',\n mode: 'collection',\n internal: true,\n methods: {\n write: method(LogEntrySchema, z.void(), { kind: 'mutation' }),\n query: method(\n z.object({\n scope: z.array(z.string()).optional(),\n level: LogLevelSchema.optional(),\n since: z.date().optional(),\n until: z.date().optional(),\n limit: z.number().optional(),\n tags: z.record(z.string(), z.string()).optional(),\n }),\n z.array(LogEntrySchema).readonly(),\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type ILogDestinationProvider = InferProvider<typeof logDestinationCapability>\n\nexport { LogEntrySchema, LogLevelSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\nexport const adminUiCapability = {\n name: 'admin-ui',\n scope: 'system',\n mode: 'singleton',\n internal: true,\n methods: {\n getStaticDir: method(z.void(), z.string()),\n getVersion: method(z.void(), z.string()),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IAdminUiProvider = InferProvider<typeof adminUiCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n/**\n * `addon-pages` — system-scoped singleton aggregator cap. Public-facing\n * surface that admin-ui consumes through `useAddonPagesListPages()`.\n *\n * The provider iterates every `addon-pages-source` (collection) provider\n * and emits `AddonPageInfo[]` enriched with versioned `bundleUrl` strings\n * pointing at `/api/addon-pages/<addonId>/<bundle>?v=<mtime>`. The\n * filesystem `mtime` cache-buster lets the browser pick up addon\n * rebuilds without manual reload.\n *\n * The hub-local builtin `addon-pages-aggregator` (see\n * `@camstack/core/builtins/addon-pages-aggregator`) registers the\n * provider. Splitting the public aggregator from the raw collection\n * keeps both ends in codegen — there's no hand-written\n * `addon-pages.router.ts` wrapper anymore.\n */\n\nconst AddonPageDeclarationSchema = z.object({\n id: z.string(),\n label: z.string(),\n icon: z.string(),\n path: z.string(),\n remoteName: z.string(),\n bundle: z.string(),\n})\n\nconst AddonPageInfoSchema = z.object({\n addonId: z.string(),\n page: AddonPageDeclarationSchema,\n bundleUrl: z.string(),\n})\n\nexport const addonPagesCapability = {\n name: 'addon-pages',\n scope: 'system',\n mode: 'singleton',\n methods: {\n listPages: method(z.void(), z.array(AddonPageInfoSchema).readonly()),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IAddonPagesAggregatorProvider = InferProvider<typeof addonPagesCapability>\n\nexport { AddonPageInfoSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n/**\n * `addon-pages-source` — collection cap exposing per-provider raw page\n * declarations. Every addon that contributes a UI page registers a\n * provider here. The hub-side singleton aggregator (`addon-pages` cap,\n * see `addon-pages.cap.ts`) walks this collection, stamps versioned\n * `bundleUrl` values, and returns the enriched `AddonPageInfo[]` list\n * that admin-ui consumes.\n *\n * The split exists because the public listing has a different output\n * shape than the per-provider raw declarations, and we want both ends\n * to flow through codegen instead of relying on a hand-written wrapper.\n */\nconst AddonPageDeclarationSchema = z.object({\n id: z.string(),\n label: z.string(),\n icon: z.string(),\n path: z.string(),\n /**\n * Module Federation remote name — must match the `name` field on the\n * page addon's `federation()` plugin config. Used by admin-ui's\n * `<AddonPageLoader>` to call `loadRemote('<remoteName>/page')`.\n * Conventionally `addon_<id>_page` (snake_case; MF names cannot\n * contain hyphens).\n */\n remoteName: z.string(),\n /**\n * Bundle filename inside the addon's `dist/` dir served at\n * `/api/addon-pages/<addonId>/<bundle>`. With Module Federation this\n * is always `'remoteEntry.js'`; the value is kept on the metadata so\n * the static-file route can compute an mtime-based cache-buster URL\n * without a separate filesystem stat.\n */\n bundle: z.string(),\n})\n\nexport const addonPagesSourceCapability = {\n name: 'addon-pages-source',\n scope: 'system',\n mode: 'collection',\n internal: true,\n methods: {\n listPages: method(z.void(), z.array(AddonPageDeclarationSchema).readonly()),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IAddonPagesSourceProvider = InferProvider<typeof addonPagesSourceCapability>\n\nexport { AddonPageDeclarationSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { WidgetMetadataSchema } from './addon-widgets-source.cap.js'\n\n/**\n * `addon-widgets` — system-scoped singleton aggregator cap. Public-facing\n * surface that admin-ui consumes through `useAddonWidgetsListWidgets()`.\n *\n * The provider iterates every `addon-widgets-source` (collection)\n * provider and emits `EnrichedWidgetMetadata[]` enriched with versioned\n * `bundleUrl` strings pointing at\n * `/api/addon-widgets/<addonId>/<bundle>?v=<mtime>`. The filesystem\n * `mtime` cache-buster lets the browser pick up addon rebuilds without\n * manual reload — same scheme used by `addon-pages`.\n *\n * The hub-local builtin `addon-widgets-aggregator` (see\n * `@camstack/core/builtins/addon-widgets-aggregator`) registers the\n * provider. Splitting the public aggregator from the raw collection\n * keeps both ends in codegen — there's no hand-written wrapper.\n */\n\nconst EnrichedWidgetMetadataSchema = WidgetMetadataSchema.extend({\n addonId: z.string(),\n bundleUrl: z.string(),\n})\n\nexport const addonWidgetsCapability = {\n name: 'addon-widgets',\n scope: 'system',\n mode: 'singleton',\n methods: {\n listWidgets: method(z.void(), z.array(EnrichedWidgetMetadataSchema).readonly()),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IAddonWidgetsAggregatorProvider = InferProvider<typeof addonWidgetsCapability>\n\nexport { EnrichedWidgetMetadataSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n/**\n * `addon-widgets-source` — collection cap exposing per-addon raw widget\n * declarations. Mirrors the addon-pages split: every addon shipping\n * widgets registers a provider on this collection cap; the hub-local\n * aggregator (`addon-widgets`, see `addon-widgets.cap.ts`) walks the\n * collection, stamps versioned `bundleUrl`s onto each declaration, and\n * exposes the public listing surface that admin-ui consumes.\n *\n * The split exists because the public listing has a different output\n * shape (flat enriched metadata with `addonId` + `bundleUrl`) than the\n * per-provider raw declarations. Both ends flow through codegen.\n */\nconst WidgetHostEnum = z.enum(['device-tab', 'dashboard', 'integration-detail'])\nconst WidgetSizeEnum = z.enum(['xs', 'sm', 'md', 'lg', 'xl'])\n\nconst WidgetMetadataSchema = z.object({\n /** Stable id within the addon — kebab-case. */\n stableId: z.string(),\n /** Operator-facing label. */\n label: z.string(),\n description: z.string().optional(),\n icon: z.string().optional(),\n /**\n * Module Federation remote name — must match the `name` field on the\n * widget addon's `federation()` plugin config. Used by the host's\n * `<WidgetRegistryProvider>` to call `loadRemote('<remoteName>/widgets')`.\n * Conventionally `addon_<addonid>_widgets` (snake_case; MF names\n * cannot contain hyphens).\n */\n remoteName: z.string(),\n /**\n * Bundle filename inside the addon's `dist/` dir served at\n * `/api/addon-widgets/<addonId>/<bundle>`. With Module Federation\n * this is always `'remoteEntry.js'` — the value is kept on the\n * metadata so the static-file route can compute an mtime-based\n * cache-buster URL without a separate filesystem stat.\n */\n bundle: z.string(),\n /** Where the widget makes sense to render. */\n hosts: z.array(WidgetHostEnum).readonly(),\n /** Required props the host must supply. Validated at <WidgetSlot> mount. */\n requires: z.object({\n deviceContext: z.boolean().default(false),\n integrationContext: z.boolean().default(false),\n }),\n /** Dashboard placement HINTS (operator can override per instance). */\n defaultSize: WidgetSizeEnum.default('md'),\n allowedSizes: z.array(WidgetSizeEnum).readonly().default(['sm', 'md', 'lg']),\n defaultColumns: z.number().int().min(1).max(12).default(6),\n defaultRows: z.number().int().min(1).max(12).default(1),\n})\n\nexport const addonWidgetsSourceCapability = {\n name: 'addon-widgets-source',\n scope: 'system',\n mode: 'collection',\n internal: true,\n methods: {\n listWidgets: method(z.void(), z.array(WidgetMetadataSchema).readonly()),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IAddonWidgetsSourceProvider = InferProvider<typeof addonWidgetsSourceCapability>\n\nexport { WidgetMetadataSchema, WidgetHostEnum, WidgetSizeEnum }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\nconst AddonHttpRouteSchema = z.object({\n method: z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH']),\n path: z.string(),\n})\n\nexport const addonRoutesCapability = {\n name: 'addon-routes',\n scope: 'system',\n mode: 'collection',\n internal: true,\n methods: {\n getRoutes: method(z.void(), z.array(AddonHttpRouteSchema)),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IAddonRoutesProvider = InferProvider<typeof addonRoutesCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport type { HwAccelBackend } from '../interfaces/addon.js'\nimport {\n DecoderSessionConfigSchema,\n DecoderStatsSchema,\n} from '../interfaces/stream-broker.js'\nimport {\n EncodedPacketSchema,\n DecodedFrameSchema,\n} from './schemas/streaming-shared.js'\n\n/**\n * Operator-facing hwaccel selection — wins over `probedBestHwaccel`\n * when concrete; `'auto'` defers to the session's local resolver\n * (`ctx.kernel.hwaccel`) which probes the host. Shared across every\n * decoder addon (node-av, ffmpeg, …) so UI + settings + sessions all\n * speak the same vocabulary.\n */\nexport type HwAccelChoice = 'auto' | 'none' | HwAccelBackend\n\n/**\n * Stable UI option list for the `hwaccel` setting. Decoder addons\n * reuse this for `globalSettingsSchema()` so the dropdown is\n * identical everywhere. Order: auto → off → common backends by\n * platform affinity (macOS, NVIDIA, Intel/AMD, Windows, Linux).\n */\nexport const HWACCEL_OPTIONS: ReadonlyArray<{ value: HwAccelChoice; label: string }> = [\n { value: 'auto', label: 'Auto (defer to probed best)' },\n { value: 'none', label: 'Off (software)' },\n { value: 'videotoolbox', label: 'VideoToolbox (macOS)' },\n { value: 'cuda', label: 'CUDA (NVIDIA)' },\n { value: 'nvdec', label: 'NVDEC (NVIDIA legacy)' },\n { value: 'vaapi', label: 'VAAPI (Linux Intel/AMD)' },\n { value: 'qsv', label: 'QuickSync (Intel)' },\n { value: 'd3d11va', label: 'D3D11VA (Windows)' },\n { value: 'dxva2', label: 'DXVA2 (Windows legacy)' },\n { value: 'amf', label: 'AMF (AMD)' },\n { value: 'vdpau', label: 'VDPAU (Linux NVIDIA legacy)' },\n { value: 'drm', label: 'DRM (Linux generic)' },\n]\n\n/**\n * Shared shape of a decoder addon's global settings. Every decoder\n * owns its own instance (node-av, ffmpeg, future backends) — they\n * don't share a store, but they share this config shape.\n */\nexport interface DecoderHwAccelConfig {\n readonly hwaccel: HwAccelChoice\n readonly probedBestHwaccel: string\n}\n\nexport const DEFAULT_DECODER_HWACCEL_CONFIG: DecoderHwAccelConfig = {\n hwaccel: 'auto',\n probedBestHwaccel: '',\n}\n\nexport const decoderCapability = {\n name: 'decoder',\n scope: 'system',\n // Singleton — one decoder per node. `decoder-nodeav` is the default\n // install; operators can swap to a different provider via the\n // binding system's active-addon selection. The old collection shape\n // existed to let node-av + ffmpeg coexist and priority-sort at\n // stream-start; that fallback was dropped once node-av covered the\n // full codec matrix.\n mode: 'singleton',\n methods: {\n // ── Discovery ─────────────────────────────────────────────────\n supportsCodec: method(z.object({ codec: z.string() }), z.boolean()),\n getInfo: method(z.void(), z.object({\n id: z.string(),\n name: z.string(),\n isPullMode: z.boolean().optional(),\n priority: z.number().optional(),\n })),\n\n // ── Session lifecycle ─────────────────────────────────────────\n // `nodeId` carries the Moleculer nodeID of the decoder provider that\n // owns the session. Brokers store it so they can react to per-agent\n // events (e.g. `pipeline.agent-hwaccel-changed`) and rotate only the\n // sessions that actually live on the affected node.\n createSession: method(DecoderSessionConfigSchema, z.object({ sessionId: z.string(), nodeId: z.string() })),\n destroySession: method(z.object({ sessionId: z.string() }), z.void()),\n\n // ── Data plane ────────────────────────────────────────────────\n pushPacket: method(z.object({\n sessionId: z.string(),\n packet: EncodedPacketSchema,\n }), z.void()),\n openStream: method(z.object({\n sessionId: z.string(),\n url: z.string(),\n }), z.void()),\n\n // ── Output — polling-based frame retrieval ────────────────────\n pullFrames: method(z.object({\n sessionId: z.string(),\n maxCount: z.number().default(1),\n }), z.array(DecodedFrameSchema)),\n\n // ── Control ───────────────────────────────────────────────────\n updateConfig: method(z.object({\n sessionId: z.string(),\n config: DecoderSessionConfigSchema.partial(),\n }), z.void()),\n getStats: method(z.object({ sessionId: z.string() }), DecoderStatsSchema),\n\n // ── Inventory — session-level state ONLY ─────────────────────\n // Sessions are a decoder concept, so `listActiveSessions` lives\n // here. Process-level measurements (memory/cpu) go through the\n // generic `metrics-provider` cap — decoder stays free of\n // observability concerns that aren't specific to decoding.\n listActiveSessions: method(z.void(), z.array(z.object({\n sessionId: z.string(),\n codec: z.string(),\n outputFormat: z.string(),\n createdAtMs: z.number(),\n })).readonly()),\n\n /**\n * Re-run the host platform-probe for the decoder's hwaccel backend\n * and write the detected value into the addon's own global\n * settings (`probedBestHwaccel`). Replaces the legacy per-agent\n * `pipeline-orchestrator.reprobeAgentHwAccel` — each decoder addon\n * now owns its own probe.\n *\n * Returns the backend the probe picked (`'none'` = software-only\n * host, otherwise one of `HwAccelBackend`). The operator's\n * `hwaccel` setting (auto / none / backend) is not touched; only\n * the `probedBestHwaccel` hint.\n */\n reprobeHwaccel: method(\n z.void(),\n z.object({ backend: z.string() }),\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IDecoderCapProvider = InferProvider<typeof decoderCapability>\n\n/**\n * Pure cap-only view of the decoder provider.\n *\n * For the in-process interface with live `createSession()`, `id`, `name`,\n * `priority`, `isPullMode` fields, consumers should import\n * `IDecoderProvider` from `@camstack/types/interfaces/decoder` — that\n * remains the canonical in-process contract the broker + tests depend\n * on. The live `createSession()` + session object cannot cross process\n * boundaries and will need a session-id based cap API (Phase 4, decoder\n * forkable work) — tracked separately, not in scope for session 5\n * Sprint A.\n *\n * Prior to session 5 this alias used to extend the inferred cap type\n * with the live fields, creating a hybrid interface. No consumer ever\n * referenced `IDecoderProviderV2` — the broker, tests, and addon\n * implementations all imported `IDecoderProvider` directly. The\n * extension was therefore dead code and is removed here.\n */\n\nexport { DecoderSessionConfigSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\nconst RegisteredStreamSchema = z.object({\n streamId: z.string(),\n label: z.string().optional(),\n codec: z.string(),\n type: z.enum(['video', 'audio']),\n sourceUrl: z.string(),\n})\n\nconst ExposedResourceSchema = z.object({\n streamId: z.string(),\n format: z.string(),\n value: z.string(),\n})\n\nexport const restreamerCapability = {\n name: 'restreamer',\n scope: 'system',\n mode: 'collection',\n internal: true,\n methods: {\n registerDevice: method(\n z.object({ deviceId: z.number(), streams: z.array(RegisteredStreamSchema).readonly() }),\n z.void(),\n { kind: 'mutation' },\n ),\n unregisterDevice: method(z.object({ deviceId: z.number() }), z.void(), { kind: 'mutation' }),\n getExposedResources: method(\n z.object({ deviceId: z.number() }),\n z.array(ExposedResourceSchema).readonly(),\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IRestreamerProvider = InferProvider<typeof restreamerCapability>\n\nexport { RegisteredStreamSchema, ExposedResourceSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n/**\n * Optional client-side hints sent at session creation to help the\n * provider pick the best native source. All fields are optional —\n * a viewer that knows nothing still gets a sane default.\n */\nexport const webrtcClientHintsSchema = z.object({\n viewportWidth: z.number().int().positive().optional(),\n viewportHeight: z.number().int().positive().optional(),\n devicePixelRatio: z.number().positive().optional(),\n /** navigator.connection.downlink — Mbps the browser estimates. */\n downlinkMbps: z.number().nonnegative().optional(),\n /** Hard tier override; takes precedence over scoring when registered. */\n prefersTier: z.string().optional(),\n}).partial()\n\nexport type WebrtcClientHints = z.infer<typeof webrtcClientHintsSchema>\n\nexport const webrtcCapability = {\n name: 'webrtc',\n scope: 'system',\n mode: 'collection',\n internal: true,\n methods: {\n handleOffer: method(\n z.object({ streamId: z.string(), sdpOffer: z.string() }),\n z.string(),\n { kind: 'mutation' },\n ),\n supportsStream: method(z.object({ streamId: z.string() }), z.boolean()),\n registerStream: method(\n z.object({ streamId: z.string(), codec: z.string() }),\n z.void(),\n { kind: 'mutation' },\n ),\n unregisterStream: method(z.object({ streamId: z.string() }), z.void(), { kind: 'mutation' }),\n /**\n * Two-step server-offer signaling. `hints` is optional — providers\n * that don't care about adaptive source selection ignore it.\n */\n createSession: method(\n z.object({\n streamId: z.string(),\n hints: webrtcClientHintsSchema.optional(),\n }),\n z.object({ sessionId: z.string(), sdpOffer: z.string() }),\n { kind: 'mutation' },\n ),\n handleAnswer: method(\n z.object({ sessionId: z.string(), sdpAnswer: z.string() }),\n z.void(),\n { kind: 'mutation' },\n ),\n closeSession: method(z.object({ sessionId: z.string() }), z.void(), { kind: 'mutation' }),\n /**\n * Whether this provider supports adaptive bitrate for the given stream.\n * Currently always false — adaptive selection is one-shot at session\n * start, not in-session encoder switching. Phase 5 plans to layer\n * encoder-driven adaptation on top.\n */\n hasAdaptiveBitrate: method(\n z.object({ streamId: z.string() }),\n z.boolean(),\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IWebrtcProvider = InferProvider<typeof webrtcCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\nimport { CamProfileSchema } from './schemas/streaming-shared.js'\nimport { webrtcClientHintsSchema } from './webrtc.cap.js'\n\n/**\n * Discriminated target for a WebRTC session. The client sends this\n * structured object instead of building / parsing brokerId strings;\n * the server resolves it to a brokerId via the assignments map.\n *\n * - `adaptive`: server picks the best broker for the device based on\n * client hints (viewport, downlink).\n * - `profile`: pin the session to a profile slot (`high`/`mid`/`low`).\n * The actual source can change as the operator reassigns the slot.\n * - `cam-stream`: pin the session to a specific source by camStreamId\n * (e.g. `native:main`, `rtsp:sub`). Useful when the operator wants\n * a stable view of a specific source regardless of profile bindings,\n * or to consume a manually-activated stream that isn't profile-bound.\n */\nexport const WebrtcStreamTargetSchema = z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('adaptive') }),\n z.object({ kind: z.literal('profile'), profile: CamProfileSchema }),\n z.object({ kind: z.literal('cam-stream'), camStreamId: z.string().min(1) }),\n])\nexport type WebrtcStreamTarget = z.infer<typeof WebrtcStreamTargetSchema>\n\n/** A stream choice the UI can offer for a device. */\nexport const WebrtcStreamChoiceSchema = z.object({\n /** Stable id for React keys / dropdowns (e.g. `'adaptive'`, `'profile:high'`, `'stream:native:main'`). */\n id: z.string(),\n /** Display label. */\n label: z.string(),\n /** Discriminated target — pass straight to `createSession`. */\n target: WebrtcStreamTargetSchema,\n /** Codec of the underlying broker stream (null for adaptive). */\n codec: z.string().nullable(),\n /** Resolution of the underlying stream (null for adaptive). */\n resolution: z.object({ width: z.number(), height: z.number() }).nullable(),\n /** Broker status (null for adaptive). */\n status: z.enum(['idle', 'connecting', 'streaming', 'error', 'stopped']).nullable(),\n /** Input FPS from the camera (null for adaptive). */\n inputFps: z.number().nullable(),\n /** Decoded FPS (null for adaptive). */\n decodeFps: z.number().nullable(),\n /** Bitrate in kbps (null for adaptive). */\n bitrateKbps: z.number().nullable(),\n})\nexport type WebrtcStreamChoice = z.infer<typeof WebrtcStreamChoiceSchema>\n\n/**\n * WebRTC session — device-scoped facade over the system `webrtc` cap.\n *\n * Exposes per-device signaling (`createSession`, `handleAnswer`,\n * `closeSession`) on the device proxy so UI / integrations can\n * negotiate a session by (deviceId, profile) instead of constructing\n * an opaque `${deviceId}/${profile}` streamId string. The provider is\n * registered by the stream-broker addon for every camera device with\n * at least one active profile slot; internally it resolves\n * `${deviceId}/${profile}` and forwards to the system webrtc provider.\n *\n * The system `webrtc` cap remains available for cross-device / raw\n * streamId callers (debugging, admin tools). Production UI should\n * prefer this device-scoped cap.\n */\nexport const webrtcSessionCapability = {\n name: 'webrtc-session',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n methods: {\n /**\n * List available WebRTC streams for a device.\n * Returns adaptive (if any profile is assigned) + each assigned profile\n * with codec/resolution info. UI renders this directly — no hardcoded\n * profile names needed.\n */\n listStreams: method(\n z.object({ deviceId: z.number().int().nonnegative() }),\n z.array(WebrtcStreamChoiceSchema),\n ),\n /**\n * Open a WebRTC session against a specific target on the device.\n * `target.kind` discriminates between adaptive selection, a profile\n * slot, or a specific cam stream source — see `WebrtcStreamTarget`.\n * The server resolves the target to a live broker; clients never\n * build or parse brokerId strings.\n */\n createSession: method(\n z.object({\n deviceId: z.number().int().nonnegative(),\n target: WebrtcStreamTargetSchema,\n hints: webrtcClientHintsSchema.optional(),\n }),\n z.object({ sessionId: z.string(), sdpOffer: z.string() }),\n { kind: 'mutation' },\n ),\n handleAnswer: method(\n z.object({\n deviceId: z.number().int().nonnegative(),\n sessionId: z.string(),\n sdpAnswer: z.string(),\n }),\n z.void(),\n { kind: 'mutation' },\n ),\n closeSession: method(\n z.object({\n deviceId: z.number().int().nonnegative(),\n sessionId: z.string(),\n }),\n z.void(),\n { kind: 'mutation' },\n ),\n /** Whether the underlying provider supports adaptive bitrate for this profile. */\n hasAdaptiveBitrate: method(\n z.object({\n deviceId: z.number().int().nonnegative(),\n profile: CamProfileSchema,\n }),\n z.boolean(),\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IWebrtcSessionProvider = InferProvider<typeof webrtcSessionCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { RunnerLocalLoadSchema } from './pipeline-runner.cap.js'\nimport { CameraMetricsSchema } from './schemas/orchestrator-metrics.js'\nimport { PipelineEngineChoiceSchema, PipelineStepInputSchema } from './pipeline-executor.cap.js'\n\n// ── Per-camera pipeline config & templates ─────────────────────────\n//\n// Stateless-pipeline model (spec: 2026-04-18-stateless-pipeline-per-camera):\n// the orchestrator owns per-camera pipelines and the global template\n// library. Runners never persist; they receive content via attachCamera.\n\nconst CameraPipelineConfigSchema = z.object({\n engine: PipelineEngineChoiceSchema,\n steps: z.array(PipelineStepInputSchema).readonly(),\n audio: z.object({\n engine: PipelineEngineChoiceSchema,\n modelId: z.string(),\n enabled: z.boolean(),\n settings: z.record(z.string(), z.unknown()).readonly().optional(),\n }).nullable().optional(),\n})\n\nconst PipelineTemplateSchema = z.object({\n id: z.string(),\n name: z.string(),\n description: z.string().optional(),\n config: CameraPipelineConfigSchema,\n createdAt: z.string(),\n updatedAt: z.string(),\n})\n\n// ── 3-level pipeline settings schemas ─────────────────────────────────\n// Agent-level addon config: one entry per addonId in the catalog. The\n// resolver expands this flat map into a tree at dispatch time using\n// catalog compat (inputClasses ↔ outputClasses).\nconst AgentAddonConfigSchema = z.object({\n enabled: z.boolean(),\n modelId: z.string(),\n settings: z.record(z.string(), z.unknown()).readonly(),\n})\n\n// Agent settings (phase 2f): only `addonDefaults` remain on the\n// orchestrator. `userChoice`, `hwaccel`, `audio`, and the authoritative\n// engine triple all moved to per-addon global settings\n// (detection-pipeline / decoder-nodeav / decoder-ffmpeg / audio-analyzer).\nconst AgentPipelineSettingsSchema = z.object({\n addonDefaults: z.record(z.string(), AgentAddonConfigSchema).readonly(),\n})\n\n// Per-agent wholesale pipeline override — a camera can pin a full\n// pipeline for a specific agent, bypassing addonDefaults + stepToggles.\n// The **engine** is NOT carried here: per the 3-level design, the\n// device+agent override still runs under the engine selected on that\n// agent (detection-pipeline global settings there). The operator\n// picks which steps + what audio run — not which engine — so that\n// moving a camera between agents with different engines doesn't\n// require rewriting the override. Same applies to `audio.engine` —\n// inferred from the agent, not stored per-override.\nconst CameraPipelineForAgentSchema = z.object({\n steps: z.array(PipelineStepInputSchema).readonly(),\n audio: z.object({\n modelId: z.string(),\n enabled: z.boolean(),\n }).nullable(),\n})\n\n// Per-(device, agent, addon) shallow patch over agent.addonDefaults[addonId].\n// All fields optional — unset means \"inherit from agent default\".\nconst CameraStepOverridePatchSchema = z.object({\n enabled: z.boolean().optional(),\n modelId: z.string().optional(),\n settings: z.record(z.string(), z.unknown()).readonly().optional(),\n})\n\n// Camera settings — sparse overlay on agent defaults.\nconst CameraPipelineSettingsSchema = z.object({\n pinnedAgentNodeId: z.string().optional(),\n stepToggles: z.record(z.string(), z.boolean()).optional(),\n stepOverridesByAgent: z.record(\n z.string(),\n z.record(z.string(), CameraStepOverridePatchSchema),\n ).optional(),\n pipelineByAgent: z.record(z.string(), CameraPipelineForAgentSchema).optional(),\n})\n\n/**\n * Pipeline placement record persisted by `addon-pipeline-orchestrator` via\n * the multi-level settings store. The orchestrator looks up these records\n * on every `DeviceStreamsRegistered` event to decide whether the camera\n * has a manual pipeline node pin (L1 affinity) or whether the load\n * balancer (L2 capacity / L3 hardware-aware) needs to pick one.\n *\n * Naming convention: `{Pipeline,Decoder}AssignmentSchema` — one schema per\n * placement domain managed by the orchestrator.\n */\nconst PipelineAssignmentSchema = z.object({\n deviceId: z.number(),\n /** Moleculer node id of the runner currently responsible for this camera. */\n agentNodeId: z.string(),\n /** True when the assignment was set manually, false when chosen by the balancer. */\n pinned: z.boolean(),\n /** Why this assignment was made — useful for debugging the load balancer. */\n reason: z.enum(['manual', 'capacity', 'hardware-affinity', 'failover', 'rebalance']),\n /** Unix timestamp (ms) when the assignment was last updated. */\n assignedAt: z.number(),\n})\n\n/**\n * Decoder placement record. Symmetric to `PipelineAssignmentSchema` but for\n * the decoder-node placement domain (`balanceDecoder` decision: manual pin\n * → co-located with pipeline → capacity).\n */\nconst DecoderAssignmentSchema = z.object({\n deviceId: z.number(),\n /** Moleculer node id of the decoder provider currently responsible for this camera. */\n decoderNodeId: z.string(),\n /** True when the assignment was set manually via `assignDecoder`, false when chosen by the balancer. */\n pinned: z.boolean(),\n /** Why this assignment was made — useful for debugging the decoder balancer. */\n reason: z.enum(['manual', 'co-located', 'capacity', 'hardware-affinity']),\n})\n\n/**\n * Per-agent load summary surfaced to the load balancer + dashboards.\n * Aggregated from each runner's `getLocalLoad` cap call.\n */\nconst AgentLoadSummarySchema = z.object({\n nodeId: z.string(),\n online: z.boolean(),\n load: RunnerLocalLoadSchema,\n /** Computed score used by the L2 capacity balancer (lower = less loaded). */\n score: z.number(),\n})\n\n/**\n * Aggregate metrics across the whole detection cluster. Replaces the legacy\n * `IPipelineExecutorProvider.orchestratorStatus()` cap method as the\n * canonical source of truth for global pipeline health.\n */\nconst GlobalMetricsSchema = z.object({\n totalAgents: z.number(),\n onlineAgents: z.number(),\n totalCameras: z.number(),\n attachedCameras: z.number(),\n activeCameras: z.number(),\n /** Average inference time across all agents weighted by their camera count. */\n avgInferenceTimeMs: z.number(),\n /** Total queue depth across all agents. */\n queueDepth: z.number(),\n})\n\n/**\n * Per-node capability binding map: which addon implements each well-known\n * cap on the named node. Persisted hub-side under\n * `addon:pipeline-orchestrator` settings keyed by `nodeBindings.<nodeId>`.\n *\n * The kernel of each process consults its local copy of this map (via the\n * `capability.binding-changed` event subscription) when resolving\n * capability providers.\n */\nconst CapabilityBindingsSchema = z.record(z.string(), z.string())\n\n// NOTE — Phase 6 cleanup (orchestrator settings rework):\n//\n// The `OrchestrationDeviceSettings` and `ResolvedOrchestrationSettings`\n// types used to live here, along with the cap methods\n// `getDeviceOrchestrationSettings` / `getDeviceOrchestrationOverrides`\n// / `getGlobalOrchestrationSettings`. They were a central bottleneck\n// that duplicated the standard addon settings store.\n//\n// Consumers now read per-device settings directly via the kernel\n// helper `resolveAddonSettings(schema, global, device)` from\n// `@camstack/types`, using the standard\n// `AddonRegistryService.getAddonConfigSchema` +\n// `ConfigService.getAddonConfig` / `getAddonDevice` pair. There is no\n// alias cap method on the orchestrator — the 3-level resolver is the\n// one and only read path for every addon, including this one.\n//\n// If a caller needs a typed view of the merged result, it's their\n// responsibility to narrow the returned `Record<string, unknown>`\n// locally (see `DetectionWiringService.resolveDeviceSettings` for the\n// canonical example).\n\n/**\n * Pipeline Orchestrator capability — global load balancer + camera dispatcher.\n *\n * Lives on the hub. Tracks the camera-to-agent assignment map, listens to\n * device lifecycle events, queries each runner's capacity + hardware\n * profile, and dispatches `attachCamera` / `detachCamera` cap calls to the\n * appropriate runner instances. Persists assignments via the multi-level\n * settings store so they survive hub restarts.\n *\n * Strictly the control plane: never sees a frame, never calls inference,\n * never drains queues. The runner does that work locally on each agent.\n */\nexport const pipelineOrchestratorCapability = {\n name: 'pipeline-orchestrator',\n scope: 'system',\n mode: 'singleton',\n exposesDeviceSettings: true,\n methods: {\n // ── Pipeline placement overrides ────────────────────────────────────\n /**\n * Pin a camera's pipeline to a specific agent (L1 affinity).\n * The orchestrator re-evaluates the assignment immediately.\n */\n assignPipeline: method(\n z.object({ deviceId: z.number(), agentNodeId: z.string() }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n /**\n * Clear a camera's pipeline pin and let the auto-balancer re-pick\n * the optimal agent. The orchestrator persists `preferredAgent=null`\n * (and `pipelineNodeId='auto'`), then re-runs the balancer with the\n * cached `RunnerCameraConfig` and migrates only when the chosen\n * node differs. The camera stays in `getPipelineAssignments()` —\n * just with `pinned=false`. If no runner is currently available\n * (cluster-wide), the camera is left unassigned but the cached\n * config is kept so the next dispatch event re-attaches it.\n */\n unassignPipeline: method(\n z.object({ deviceId: z.number() }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n /**\n * Trigger a full rebalance pass. Iterates over all assigned cameras,\n * recomputes the optimal agent for each one based on current load +\n * hardware affinity, and migrates cameras whose current agent is no\n * longer optimal. Pinned cameras are never migrated.\n */\n rebalance: method(z.void(), z.object({ migrated: z.number() }), { kind: 'mutation', auth: 'admin' }),\n\n // ── Observability ────────────────────────────────────────────────\n /** Get the full camera-to-agent assignment map. */\n getPipelineAssignments: method(z.void(), z.array(PipelineAssignmentSchema).readonly()),\n /** Get one camera's assignment, or null if unassigned. */\n getPipelineAssignment: method(z.object({ deviceId: z.number() }), PipelineAssignmentSchema.nullable()),\n /** Get per-agent load summaries used by the load balancer + dashboards. */\n getAgentLoad: method(z.void(), z.array(AgentLoadSummarySchema).readonly()),\n /** Aggregate global metrics across the whole detection cluster. */\n getGlobalMetrics: method(z.void(), GlobalMetricsSchema),\n /**\n * Per-camera live metrics (phase, fps, inference, queue, drops).\n * The orchestrator owns the device→agent assignment map and is the\n * canonical place to ask \"give me the metrics for this camera\". It\n * resolves the agent that holds the camera and delegates to that\n * runner's `getCameraMetrics`. Returns null if the device is not\n * assigned or the runner has no record for it (e.g. the camera was\n * just dispatched and the runner hasn't received the first frame).\n */\n getCameraMetrics: method(z.object({ deviceId: z.number() }), CameraMetricsSchema.nullable()),\n\n // ── Capability bindings (which addon implements each cap on each node) ──\n /** Read the capability binding map for one node. Empty record = no overrides (first-registered wins). */\n getCapabilityBindings: method(z.object({ nodeId: z.string() }), CapabilityBindingsSchema),\n /** Set the addon that implements `capName` on `nodeId`. Emits `capability.binding-changed`. */\n setCapabilityBinding: method(\n z.object({ nodeId: z.string(), capName: z.string(), addonId: z.string() }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n // ── Decoder scheduling ─────────────────────────────────────────────\n /** Pin a device's decoder to a specific node. */\n assignDecoder: method(\n z.object({ deviceId: z.number(), nodeId: z.string() }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n /** Clear a device's decoder pin (revert to auto). */\n unassignDecoder: method(\n z.object({ deviceId: z.number() }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n /** Get every camera's decoder placement. */\n getDecoderAssignments: method(z.void(), z.array(DecoderAssignmentSchema).readonly()),\n\n // ── Audio scheduling ───────────────────────────────────────────────\n /** Pin a device's audio analysis to a specific cluster node. */\n assignAudio: method(\n z.object({ deviceId: z.number(), nodeId: z.string() }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n /** Clear a device's audio node pin (revert to auto load-balanced). */\n unassignAudio: method(\n z.object({ deviceId: z.number() }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n /** Get the current audio assignment for one device, or null if not yet assigned. */\n getAudioAssignment: method(\n z.object({ deviceId: z.number() }),\n z.object({\n nodeId: z.string(),\n pinned: z.boolean(),\n assignedAt: z.number(),\n }).nullable(),\n ),\n /** Get per-node audio load (device counts) for all known audio-analyzer nodes. */\n getAudioNodeLoad: method(\n z.void(),\n z.array(z.object({ nodeId: z.string(), deviceCount: z.number() })),\n ),\n /** Get all current audio assignments across all devices. */\n getAudioAssignments: method(\n z.void(),\n z.array(z.object({\n deviceId: z.number(),\n nodeId: z.string(),\n pinned: z.boolean(),\n assignedAt: z.number(),\n })),\n ),\n\n /**\n * Get one camera's decoder placement (computed if not yet pinned).\n * Consumed by `stream-broker.createBroker` so decoder provider\n * selection is deterministic — fixes the 2026-04-18 race where\n * `capProviders[0]` silently picked ffmpeg-on-agent-0 for a\n * hub-assigned camera.\n *\n * `pipelineNodeId` is the node already chosen to run inference for\n * this camera. When provided, the balancer prefers co-location with\n * it; omitted → falls back to the last known assignment in the\n * `assignments` map and finally to 'hub'.\n */\n getDecoderAssignment: method(\n z.object({\n deviceId: z.number(),\n pipelineNodeId: z.string().optional(),\n }),\n DecoderAssignmentSchema,\n ),\n\n // NOTE: the `getDeviceOrchestrationSettings`,\n // `getDeviceOrchestrationOverrides` and `getGlobalOrchestrationSettings`\n // methods were removed in Phase 6. Consumers now read settings via\n // the standard 3-level resolver (`resolveAddonSettings`) over the\n // addon config store — see the top of this file for details.\n\n // ── 3-level pipeline settings (new model) ──────────────────────────\n //\n // Replaces the per-camera full-config + cluster-default model with:\n // `agent.addonDefaults` (flat per-addon config; auto-seeded from catalog),\n // `camera.stepToggles` (bool overlay; absent = inherit agent),\n // `camera.pipelineByAgent` (wholesale override escape hatch).\n //\n // The orchestrator's `resolvePipeline` collapses these into the\n // `CameraPipelineConfig` the runner consumes at dispatch.\n\n // `agentNodeId` (not `nodeId`) is intentional: the generated cap router\n // auto-routes any input field literally named `nodeId` to that node's\n // provider. `pipeline-orchestrator` is a HUB-SINGLETON cap — the\n // agent-node identifier here is DATA (\"which agent to read/write\"),\n // not routing. Using `agentNodeId` keeps the call on the hub as\n // intended.\n\n /** Read one agent's settings. Null when not yet seeded. */\n getAgentSettings: method(\n z.object({ agentNodeId: z.string() }),\n AgentPipelineSettingsSchema.nullable(),\n ),\n /** Enumerate every agent's settings (hub + remote runners). */\n listAgentSettings: method(\n z.void(),\n z.array(z.object({\n nodeId: z.string(),\n settings: AgentPipelineSettingsSchema,\n })).readonly(),\n ),\n /** Bulk-replace ALL addon configs on one agent. Used by the agent-level PipelineEditor which emits the full map per edit. Merges on top of existing entries — omitted addonIds are left alone. */\n setAgentAddonDefaults: method(\n z.object({\n agentNodeId: z.string(),\n defaults: z.record(z.string(), AgentAddonConfigSchema),\n }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n /**\n * Drop a single agent's persisted settings. Used by the cluster\n * \"Offline agents\" panel to evict stale entries left behind when an\n * agent's data dir was rebuilt (new random nodeId) or older code wrote\n * the env name as the nodeId. The orchestrator otherwise never deletes\n * agentSettings — entries accumulate until a hub reset.\n *\n * `success: false` indicates the nodeId wasn't in the store (no-op).\n * Refuses to remove `hub` (the orchestrator always co-resides with it).\n */\n removeAgentSettings: method(\n z.object({ agentNodeId: z.string() }),\n z.object({ success: z.boolean(), removed: z.boolean() }),\n { kind: 'mutation', auth: 'admin' },\n ),\n // Phase 2f: `setAgentEngineChoice`, `setAgentHwAccel`,\n // `reprobeAgentHwAccel` removed. Engine ownership moved to the\n // `detection-pipeline` addon (`engineRuntime/engineBackend/engineDevice`\n // + `pipelineExecutor.reprobeEngine`). Hwaccel ownership moved to\n // each decoder addon (`decoder-nodeav`/`decoder-ffmpeg` global\n // settings + `decoder.reprobeHwaccel`). UI + decoder sessions read\n // via `api.addonSettings.getGlobalSettings({addonId, nodeId})`.\n\n /** Read one camera's settings. Null when never touched (inherits agent defaults fully). */\n getCameraSettings: method(\n z.object({ deviceId: z.number() }),\n CameraPipelineSettingsSchema.nullable(),\n ),\n /** Set or clear the 3-state toggle for one (camera, addonId). Pass `enabled: null` to clear and revert to agent default. */\n setCameraStepToggle: method(\n z.object({\n deviceId: z.number(),\n addonId: z.string(),\n enabled: z.boolean().nullable(),\n }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n /** Read every L2.5 override map for a device. Null when device has no overrides. */\n getCameraStepOverrides: method(\n z.object({ deviceId: z.number() }),\n z.record(\n z.string(), // agentNodeId\n z.record(z.string(), CameraStepOverridePatchSchema),\n ).nullable(),\n ),\n /**\n * Write or clear the L2.5 per-agent override for one addonId on a device.\n * `patch: null` clears the entry entirely for that (agent, addon) pair.\n */\n setCameraStepOverride: method(\n z.object({\n deviceId: z.number(),\n agentNodeId: z.string(),\n addonId: z.string(),\n patch: CameraStepOverridePatchSchema.nullable(),\n }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n /** Write or clear the wholesale per-agent pipeline override. Pass `pipeline: null` to drop the override. */\n setCameraPipelineForAgent: method(\n z.object({\n deviceId: z.number(),\n agentNodeId: z.string(),\n pipeline: CameraPipelineForAgentSchema.nullable(),\n }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n /** Resolve the effective pipeline for `(deviceId, agentNodeId?)` — walks the full precedence chain. Read-only preview used by the UI to show what will run. */\n resolvePipeline: method(\n z.object({ deviceId: z.number(), agentNodeId: z.string().optional() }),\n CameraPipelineConfigSchema,\n ),\n\n // ── Template library (hub-only, read by any device-details UI) ─────\n /** List every template the operator has saved. */\n listTemplates: method(z.void(), z.array(PipelineTemplateSchema).readonly()),\n /** Create a new named preset from a given CameraPipelineConfig. */\n saveTemplate: method(\n z.object({\n name: z.string(),\n description: z.string().optional(),\n config: CameraPipelineConfigSchema,\n }),\n PipelineTemplateSchema,\n { kind: 'mutation', auth: 'admin' },\n ),\n /** Partial update of a template. Any omitted field is preserved. */\n updateTemplate: method(\n z.object({\n id: z.string(),\n name: z.string().optional(),\n description: z.string().optional(),\n config: CameraPipelineConfigSchema.optional(),\n }),\n PipelineTemplateSchema,\n { kind: 'mutation', auth: 'admin' },\n ),\n /** Remove a template. Camera configs that were seeded from it keep a copy. */\n deleteTemplate: method(\n z.object({ id: z.string() }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IPipelineOrchestratorProvider = InferProvider<typeof pipelineOrchestratorCapability>\n\nexport {\n PipelineAssignmentSchema,\n DecoderAssignmentSchema,\n AgentLoadSummarySchema,\n GlobalMetricsSchema,\n CapabilityBindingsSchema,\n CameraPipelineConfigSchema,\n CameraStepOverridePatchSchema,\n PipelineTemplateSchema as OrchestratorPipelineTemplateSchema,\n}\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { AudioChunkInputSchema, AudioLevelSchema, AudioClassificationLabelSchema } from './schemas/detection-shared.js'\n\nconst AudioAnalysisResultSchema = z.object({\n level: AudioLevelSchema,\n classification: z.object({\n labels: z.array(AudioClassificationLabelSchema).readonly(),\n inferenceMs: z.number(),\n }).optional(),\n timestamp: z.number(),\n})\n\nconst AudioAnalysisSettingsSchema = z.object({\n minConfidence: z.number().min(0).max(1).default(0.3),\n allowedClasses: z.array(z.string()).default([]),\n})\n\n// Merged from audio-classifier.cap.ts — AudioAnalyzerAddon now owns the\n// pipeline directly (no tRPC roundtrip to a separate classifier addon).\nconst AudioClassificationResultSchema = z.object({\n // Macro-aggregated labels (25-class taxonomy from `AUDIO_MACRO_LABELS`).\n // Primary surface — used by the live audio analyzer and notifications.\n labels: z.array(AudioClassificationLabelSchema).readonly(),\n // Raw backend-native labels (e.g. YAMNet's 521 classes or Apple\n // SoundAnalysis's 303 classes), unaggregated. Optional so existing\n // consumers continue to work; populated by the analyzer provider\n // for callers that want fine-grained output — the benchmark UI uses\n // this in `micro` mode.\n rawLabels: z.array(AudioClassificationLabelSchema).readonly().optional(),\n inferenceMs: z.number(),\n})\n\n/**\n * audio-analyzer — system-scoped compute cap.\n *\n * Owns the engine lifecycle (isReady / dispose), the stateless\n * `analyseChunk` call and the `classify` method. Per-device settings,\n * device-settings contribution and the `onAudioLevel` event live on the\n * paired `audio-analysis` cap (device-scoped, singleton, wrapper\n * defaultActive) so every camera gets its own bindings row and per-device\n * toggle. Pairing mirrors `stream-broker` (system) + `camera-streams`\n * (device) + `webrtc-session` (device) — single addon registers both.\n */\n/**\n * Operator-facing audio-backend choice. 'auto' defers to the addon's\n * platform heuristic (Apple SoundAnalysis on macOS, YAMNet elsewhere).\n */\nexport const AUDIO_BACKEND_CHOICES = [\n { value: 'auto', label: 'Auto (platform default)' },\n { value: 'apple-soundanalysis', label: 'Apple SoundAnalysis (macOS 12+)' },\n { value: 'yamnet-onnx', label: 'YAMNet ONNX (cross-platform)' },\n] as const\n\nexport type AudioBackendChoice = typeof AUDIO_BACKEND_CHOICES[number]['value']\n\n/**\n * Shared shape of the audio-analyzer addon's global settings.\n * `audioBackend` = operator choice (wins); `probedBestAudioBackend`\n * = hint refreshed by `reprobeAudioEngine`. `selectedAudioModel`\n * replaces the orchestrator's legacy\n * `AgentPipelineSettings.audio.modelId`.\n *\n * NOTE — enable/disable is NOT stored here:\n * - per-device: `audio-analysis` wrapper cap + `setWrapperActive`\n * (binding system — the canonical gate).\n * - cluster-wide: `addonDefaults['audio-classifier'].enabled` on\n * the pipeline-orchestrator; drives whether the audio step\n * appears in the resolved tree at all.\n */\nexport interface AudioAnalyzerGlobalConfig {\n readonly audioBackend: AudioBackendChoice\n readonly probedBestAudioBackend: string\n readonly selectedAudioModel: string\n}\n\nexport const DEFAULT_AUDIO_ANALYZER_CONFIG: AudioAnalyzerGlobalConfig = {\n audioBackend: 'auto',\n probedBestAudioBackend: '',\n selectedAudioModel: '',\n}\n\nexport const audioAnalyzerCapability = {\n name: 'audio-analyzer',\n scope: 'system',\n mode: 'singleton',\n methods: {\n analyseChunk: method(\n z.object({ chunk: AudioChunkInputSchema, settings: AudioAnalysisSettingsSchema }),\n AudioAnalysisResultSchema.nullable(),\n { kind: 'mutation' },\n ),\n // ONNX / Apple SoundAnalysis inference can exceed the broker's default\n // 5s requestTimeout on first load or under CPU pressure. 30s covers\n // even the worst-case cold-start without hanging indefinitely.\n classify: method(AudioChunkInputSchema, AudioClassificationResultSchema, { timeoutMs: 30_000 }),\n isReady: method(z.void(), z.boolean()),\n dispose: method(z.void(), z.void(), { kind: 'mutation' }),\n\n /**\n * Re-run the host platform-probe for the audio backend and persist\n * the detected value into `probedBestAudioBackend`. Replaces the\n * orchestrator's legacy `AgentPipelineSettings.audio.engine` —\n * audio-analyzer now owns the choice. Operator `audioBackend` is\n * not touched; only the probed-best hint.\n */\n reprobeAudioEngine: method(\n z.void(),\n z.object({ backend: z.string() }),\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IAudioAnalyzerProvider = InferProvider<typeof audioAnalyzerCapability>\n\nexport { AudioAnalysisResultSchema, AudioAnalysisSettingsSchema, AudioClassificationResultSchema }\n","import { z } from 'zod'\nimport { method, event, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\nimport type { AudioAnalysisSettings } from '../types/io.js'\n\n/**\n * audio-analysis — device-scoped facade over the system `audio-analyzer`.\n *\n * Pairs with `audio-analyzer` (system, singleton) the way `camera-streams`\n * pairs with `stream-broker`: the system cap owns the compute path\n * (`processChunk`, engine lifecycle) while `audio-analysis` exposes the\n * per-device surface — settings resolution, device-settings contribution,\n * audio-level events — and is the binding row every camera sees in the\n * device-manager bindings UI.\n *\n * Registered as a wrapper with `defaultActive: true` by `addon-audio-analysis`\n * so every camera picks up audio analysis automatically; operators can\n * disable per-device via `device-manager.setWrapperActive` when they don't\n * want a given camera to be analysed (e.g. muted / motion-only cams).\n */\nexport const audioAnalysisCapability = {\n name: 'audio-analysis',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n exposesDeviceSettings: true,\n methods: {\n /**\n * Resolve per-device audio analysis settings (minConfidence,\n * allowedClasses) from the addon settings store for a given camera.\n * Orchestrator callers use this before handing chunks to\n * `audio-analyzer.processChunk`.\n */\n resolveDeviceSettings: method(\n z.object({ deviceId: z.number() }),\n z.custom<AudioAnalysisSettings | null>(),\n ),\n },\n events: {\n onAudioLevel: event(z.object({\n deviceId: z.number(),\n rms: z.number(),\n dbfs: z.number(),\n })),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IAudioAnalysisProvider = InferProvider<typeof audioAnalysisCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n// ── Schema fragments ─────────────────────────────────────────────────────────\n\nconst PcmSampleFormatSchema = z.enum(['f32le', 's16le'])\n\nconst AudioCodecInfoSchema = z.object({\n codec: z.string(),\n canDecode: z.boolean(),\n canEncode: z.boolean(),\n label: z.string().optional(),\n})\n\nconst AudioDecodeSessionConfigSchema = z.object({\n codec: z.string(),\n sourceSampleRate: z.number().int().positive(),\n sourceChannels: z.number().int().positive(),\n extraData: z.instanceof(Uint8Array).optional(),\n targetSampleRate: z.number().int().positive(),\n targetChannels: z.number().int().positive(),\n targetFormat: PcmSampleFormatSchema.optional(),\n idleMs: z.number().int().positive().optional(),\n tag: z.string().optional(),\n})\n\nconst AudioEncodeSessionConfigSchema = z.object({\n codec: z.string(),\n sourceSampleRate: z.number().int().positive(),\n sourceChannels: z.number().int().positive(),\n sourceFormat: PcmSampleFormatSchema.optional(),\n targetSampleRate: z.number().int().positive(),\n targetChannels: z.number().int().positive(),\n bitrateKbps: z.number().int().positive().optional(),\n idleMs: z.number().int().positive().optional(),\n tag: z.string().optional(),\n})\n\nconst AudioPcmChunkSchema = z.object({\n data: z.instanceof(Uint8Array),\n sampleRate: z.number().int().positive(),\n channels: z.number().int().positive(),\n format: PcmSampleFormatSchema,\n pts: z.number(),\n})\n\nconst AudioEncodedChunkSchema = z.object({\n data: z.instanceof(Uint8Array),\n codec: z.string(),\n pts: z.number(),\n frameComplete: z.boolean(),\n})\n\nconst SessionInventoryEntrySchema = z.object({\n sessionId: z.string(),\n kind: z.enum(['decode', 'encode']),\n codec: z.string(),\n sourceSampleRate: z.number(),\n sourceChannels: z.number(),\n targetSampleRate: z.number(),\n targetChannels: z.number(),\n format: PcmSampleFormatSchema,\n tag: z.string().optional(),\n createdAtMs: z.number(),\n lastActivityMs: z.number(),\n framesIn: z.number(),\n framesOut: z.number(),\n})\n\n// ── Capability definition ────────────────────────────────────────────────────\n\n/**\n * audio-codec — bidirectional PCM ↔ encoded audio I/O box.\n *\n * Independent per-consumer sessions. The provider runs decode + resample\n * (or resample + encode) inside the session so a 16kHz mono ASA\n * subscriber and a 48kHz stereo WebRTC subscriber on the same source\n * stream don't share resamplers.\n *\n * Singleton on each node. Decoder and encoder live in the same provider\n * because they share the underlying libav contexts (node-av today,\n * pluggable later) — operators always install one or the other together.\n */\nexport const audioCodecCapability = {\n name: 'audio-codec',\n scope: 'system',\n mode: 'singleton',\n methods: {\n // ── Discovery ─────────────────────────────────────────────────────────\n /** Probe the local runtime and return the supported codec matrix. */\n listSupportedCodecs: method(z.void(), z.array(AudioCodecInfoSchema).readonly()),\n\n /** Cheap predicate — does the runtime support `(codec, kind)`? */\n canHandle: method(\n z.object({ codec: z.string(), kind: z.enum(['decode', 'encode']) }),\n z.boolean(),\n ),\n\n // ── Session lifecycle ─────────────────────────────────────────────────\n createDecodeSession: method(\n AudioDecodeSessionConfigSchema,\n z.object({ sessionId: z.string(), nodeId: z.string() }),\n { kind: 'mutation' },\n ),\n\n createEncodeSession: method(\n AudioEncodeSessionConfigSchema,\n z.object({ sessionId: z.string(), nodeId: z.string() }),\n { kind: 'mutation' },\n ),\n\n closeSession: method(\n z.object({ sessionId: z.string(), nodeId: z.string().optional() }),\n z.void(),\n { kind: 'mutation' },\n ),\n\n // ── Decode data plane ─────────────────────────────────────────────────\n // Session-bound methods include an optional `nodeId` field so the\n // generated cap router auto-routes calls to the same node that owns\n // the session. Audio-codec sessions are process-local — without sticky\n // routing the round-robin across nodes serves \"session not found\" on\n // every other call.\n\n /** Push one encoded audio frame into a decode session. */\n pushEncodedFrame: method(\n z.object({\n sessionId: z.string(),\n nodeId: z.string().optional(),\n data: z.instanceof(Uint8Array),\n /** Source PTS in milliseconds. Synthesised when omitted. */\n pts: z.number().optional(),\n }),\n z.void(),\n { kind: 'mutation' },\n ),\n\n /** Pull up to `maxCount` PCM chunks from a decode session. */\n pullPcm: method(\n z.object({\n sessionId: z.string(),\n nodeId: z.string().optional(),\n maxCount: z.number().int().positive().default(8),\n }),\n z.array(AudioPcmChunkSchema),\n ),\n\n // ── Encode data plane ─────────────────────────────────────────────────\n /** Push one PCM chunk into an encode session. */\n pushPcm: method(\n z.object({\n sessionId: z.string(),\n nodeId: z.string().optional(),\n data: z.instanceof(Uint8Array),\n /** Source PTS in milliseconds. */\n pts: z.number().optional(),\n }),\n z.void(),\n { kind: 'mutation' },\n ),\n\n /** Pull up to `maxCount` encoded chunks from an encode session. */\n pullEncoded: method(\n z.object({\n sessionId: z.string(),\n nodeId: z.string().optional(),\n maxCount: z.number().int().positive().default(8),\n }),\n z.array(AudioEncodedChunkSchema),\n ),\n\n /** Flush any pending encoded output (call before close on graceful tear). */\n flushEncode: method(\n z.object({ sessionId: z.string(), nodeId: z.string().optional() }),\n z.array(AudioEncodedChunkSchema),\n { kind: 'mutation' },\n ),\n\n // ── Inventory ─────────────────────────────────────────────────────────\n listActiveSessions: method(\n z.void(),\n z.array(SessionInventoryEntrySchema).readonly(),\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IAudioCodecCapProvider = InferProvider<typeof audioCodecCapability>\n\nexport {\n AudioCodecInfoSchema,\n AudioDecodeSessionConfigSchema,\n AudioEncodeSessionConfigSchema,\n AudioPcmChunkSchema,\n AudioEncodedChunkSchema,\n PcmSampleFormatSchema,\n}\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\nconst EmbeddingResultSchema = z.object({\n embedding: z.array(z.number()),\n dimensions: z.number(),\n})\n\nconst EmbeddingInfoSchema = z.object({\n modelId: z.string(),\n dimensions: z.number(),\n inputSize: z.number(),\n})\n\nexport const embeddingEncoderCapability = {\n name: 'embedding-encoder',\n scope: 'system',\n mode: 'collection',\n internal: true,\n methods: {\n encode: method(\n z.object({ crop: z.instanceof(Uint8Array), width: z.number(), height: z.number() }),\n EmbeddingResultSchema,\n ),\n encodeText: method(z.object({ text: z.string() }), EmbeddingResultSchema),\n getInfo: method(z.void(), EmbeddingInfoSchema),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IEmbeddingEncoderProvider = InferProvider<typeof embeddingEncoderCapability>\n\nexport { EmbeddingResultSchema, EmbeddingInfoSchema }\n","/**\n * Device Manager capability — hub-side singleton that unifies device persistence,\n * live registry access, and all management operations into a single tRPC surface.\n *\n * Replaces:\n * - `device-persistence` capability (persistence methods absorbed here)\n * - `device-management.router.ts` (deleted in Phase 2)\n * - `device-ops.router.ts` (compat layer — deleted; device-provider ops absorbed here)\n *\n * All device provider addons (rtsp, onvif, frigate, …) are hub-local: they may\n * fork into separate processes but never run on remote cluster agents. Therefore:\n * - No nodeId routing needed — this is a pure hub singleton.\n * - The hub's DeviceRegistry is the single source of truth for all live devices.\n * - No shadow registry or cross-node aggregation required.\n *\n * Forked workers register devices back to the hub via `ctx.devices`\n * (DeviceManagerApi → ctx.api.deviceManager.registerDevice), same as today.\n */\nimport { z } from 'zod'\nimport { method, type CapabilityDefinition } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\nimport { StreamSourceEntrySchema } from './schemas/streaming-shared.js'\nimport { SettingsSchemaWithValuesSchema } from './addon-settings.cap.js'\nimport {\n DiscoveryCandidateSchema,\n DeviceSummarySchema,\n FieldProbeResultSchema,\n} from './device-provider.cap.js'\n\n// ── Output schemas ────────────────────────────────────────────────────────────\n\n/**\n * Serializable projection of a live IDevice.\n * Returned by listAll, getDevice, getChildren.\n * Live methods (getStreamSources, getConfigSchema) are separate calls.\n */\nexport const DeviceInfoSchema = z.object({\n /** Progressive, system-wide unique number. Allocated synchronously by\n * `device-manager.allocateDeviceId` BEFORE the owning `IDevice` is\n * constructed, so every live device exposes an `id` — no transient\n * null window. Distinct from `stableId`, which is unique per\n * integration. Ids are monotonic and never reissued on removal. */\n id: z.number(),\n stableId: z.string(),\n addonId: z.string(),\n type: z.enum(DeviceType),\n name: z.string(),\n /** Operator-organisational location label. `null` when unset. */\n location: z.string().nullable(),\n /** Soft-disabled flag. */\n disabled: z.boolean(),\n parentDeviceId: z.number().nullable(),\n /** Optional semantic role — `DeviceRole` string. null for top-level devices. */\n role: z.string().nullable().optional(),\n online: z.boolean(),\n features: z.array(z.string()),\n /** true when the device has a getStreamSources() method (ICameraDevice) */\n isCamera: z.boolean(),\n /** Current config values — serializable snapshot */\n config: z.record(z.string(), z.unknown()),\n /** Hardware + identity blob (manufacturer / model / firmware / sn /\n * uid / mac / …). Populated by drivers; editable via setMetadata. */\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n})\n\nexport const ConfigEntrySchema = z.object({\n key: z.string(),\n value: z.unknown(),\n description: z.string().optional(),\n})\n\nexport { StreamSourceEntrySchema }\n\nexport const SavedDeviceRowSchema = z.object({\n /** Numeric id reserved at allocateDeviceId time. */\n id: z.number(),\n /** External-system identifier — required for the worker's `kernel.devices.create()` call. */\n stableId: z.string(),\n type: z.string(),\n name: z.string(),\n /** Operator-organisational location label. `null` when unset. */\n location: z.string().nullable(),\n /** Soft-disabled flag. */\n disabled: z.boolean(),\n parentDeviceId: z.number().nullable(),\n /** Optional semantic role — stringified `DeviceRole` enum value. null for top-level devices. */\n role: z.string().nullable().optional(),\n})\n\n/** Operator-organisational meta surface — populated by the kernel\n * on `DeviceContext.deviceMeta` so `BaseDevice` can resolve\n * `name` / `location` / `disabled` without subclass schema duplication.\n * Mirrors `DeviceMeta` in `device-management.ts` for the cap wire shape. */\nexport const DeviceMetaSchema = z.object({\n id: z.number(),\n stableId: z.string(),\n addonId: z.string(),\n type: z.string(),\n name: z.string(),\n location: z.string().nullable(),\n disabled: z.boolean(),\n parentDeviceId: z.number().nullable(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n})\n\n/** ConfigUISchema passed through as unknown — mirrors device-provider's CreationSchemaOutputSchema */\nconst ConfigUISchemaOutput = z.unknown().nullable()\n\nconst StreamProbeResultSchema = z.object({\n streamId: z.string(),\n width: z.number().optional(),\n height: z.number().optional(),\n codec: z.string().optional(),\n fps: z.number().optional(),\n bitrateKbps: z.number().optional(),\n})\n\n// ── Re-export persistence schemas (for DeviceManagerApi / DevicePersistenceAddon consumers) ──\n\nexport const DeviceRegisterPayloadSchema = z.object({\n addonId: z.string(),\n stableId: z.string(),\n /** Pre-allocated numeric id from `allocateDeviceId`. The hub persists\n * it alongside the meta record; callers never invent this value. */\n id: z.number(),\n type: z.string(),\n name: z.string(),\n /** Operator-organisational location label. Optional on register —\n * the hub seeds `null` when omitted. */\n location: z.string().nullable().optional(),\n /** Soft-disabled flag. Optional on register — the hub seeds `false`. */\n disabled: z.boolean().optional(),\n parentDeviceId: z.number().nullable(),\n /** Optional semantic role — see `DeviceRole`. Driver authors pass this\n * at register time when the device is an accessory with a known role. */\n role: z.string().nullable().optional(),\n /** Snapshot of `device.features` at registration time. Persisted in\n * `DeviceMeta` so the hub can answer `getDevice` for forked-worker\n * devices with the right `DeviceFeature[]` even when the live\n * instance lives on a remote node. Re-published on every register\n * call (workers re-register on init), so probe-driven updates\n * (e.g. PTZ flag flipping after the abilities probe) propagate. */\n features: z.array(z.string()).optional(),\n config: z.record(z.string(), z.unknown()),\n})\n\nexport const DeviceRemovePayloadSchema = z.object({\n deviceId: z.number(),\n})\n\nexport const DevicePersistConfigPayloadSchema = z.object({\n deviceId: z.number(),\n data: z.record(z.string(), z.unknown()),\n})\n\n// ── Capability definition ─────────────────────────────────────────────────────\n\nexport const deviceManagerCapability = {\n name: 'device-manager',\n scope: 'system',\n mode: 'singleton',\n methods: {\n // ── Persistence (migrated from device-persistence) ────────────────────────\n\n /** Reserve (or re-resolve) a progressive numeric id for `(addonId, stableId)`.\n * Idempotent: returns the existing id if one is already persisted for the\n * pair. Callers invoke this before `registerDevice` so the live IDevice\n * can bind `id` at construction time through `DeviceContext.id`. */\n allocateDeviceId: method(\n z.object({ addonId: z.string(), stableId: z.string() }),\n z.object({ id: z.number() }),\n { kind: 'mutation' },\n ),\n\n /** Register a device in the DB + in-memory registry. Called by DeviceManagerApi.register(). */\n registerDevice: method(DeviceRegisterPayloadSchema, z.void(), { kind: 'mutation' }),\n\n /** Remove a device from the DB + in-memory registry. Called by DeviceManagerApi.remove(). */\n removeDevice: method(DeviceRemovePayloadSchema, z.void(), { kind: 'mutation' }),\n\n /** Persist device config blob. Called by DeviceConfig.set/setAll(). */\n persistConfig: method(DevicePersistConfigPayloadSchema, z.void(), { kind: 'mutation' }),\n\n /** Load persisted config for a device. Called at restore time. */\n loadConfig: method(\n z.object({ deviceId: z.number() }),\n z.record(z.string(), z.unknown()),\n ),\n\n /** Load persisted runtime state. Called at device adopt time. */\n loadRuntimeState: method(\n z.object({ deviceId: z.number() }),\n z.record(z.string(), z.unknown()),\n ),\n\n /** Load operator-organisational meta surface for a device. Called by\n * the kernel proxy to populate `DeviceContext.deviceMeta` before\n * the device class constructor runs. Returns `null` when the id\n * doesn't resolve to a persisted row. */\n loadMeta: method(\n z.object({ deviceId: z.number() }),\n DeviceMetaSchema.nullable(),\n ),\n\n /** Update the operator-edited display name. Persists to the meta\n * row + emits `EventCategory.DeviceMetaChanged`. */\n setName: method(\n z.object({ deviceId: z.number(), name: z.string() }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /** Update the operator-organisational location label. `null`\n * clears it. */\n setLocation: method(\n z.object({ deviceId: z.number(), location: z.string().nullable() }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /** Patch the device's hardware-identity metadata blob. Merges\n * `patch` over the current blob (shallow). Value `null` for a\n * given key removes that key. Drivers populate factual fields\n * on first probe (model / firmware / mac / sn / uid); operators\n * can override or augment via the Device Info tab. */\n setMetadata: method(\n z.object({\n deviceId: z.number(),\n patch: z.record(z.string(), z.unknown()),\n }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /** Operator-curated location registry. Returns the union of:\n * (1) labels persisted in the registry via `addLocation`, and\n * (2) labels currently in use on at least one device's\n * `meta.location` field.\n * Sorted case-insensitively + deduped + trimmed of empty strings.\n * Drives the autocomplete in the Device Info location editor. */\n listLocations: method(\n z.void(),\n z.array(z.string()),\n ),\n\n /** Add a label to the curated location registry. No-op when the\n * label (case-insensitive, trimmed) is already present. Empty\n * / whitespace-only inputs throw. */\n addLocation: method(\n z.object({ name: z.string() }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /** Remove a label from the curated registry. Devices that still\n * reference this label keep their `meta.location` value — the\n * registry is purely a suggestion list. To purge from devices,\n * iterate them and call `setLocation(deviceId, null)`\n * separately (or pass `cascade: true` to do it in one shot). */\n removeLocation: method(\n z.object({ name: z.string(), cascade: z.boolean().optional() }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /** Soft-disable / re-enable the device. Drivers consult\n * `BaseDevice.disabled` to gate lifecycle hooks. */\n setDisabled: method(\n z.object({ deviceId: z.number(), disabled: z.boolean() }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /** List persisted devices for an addon (DB, for restore). */\n listPersistedByAddon: method(\n z.object({ addonId: z.string() }),\n z.array(SavedDeviceRowSchema),\n ),\n\n // ── Query — live registry ─────────────────────────────────────────────────\n\n /** List all devices (live registry), optionally filtered by addonId. */\n listAll: method(\n z.object({ addonId: z.string().optional() }),\n z.array(DeviceInfoSchema),\n ),\n\n /** Get a single device by numeric deviceId. */\n getDevice: method(\n z.object({ deviceId: z.number() }),\n DeviceInfoSchema.nullable(),\n ),\n\n /** List children of a parent device (by parent numeric id). */\n getChildren: method(\n z.object({ parentDeviceId: z.number() }),\n z.array(DeviceInfoSchema),\n ),\n\n // ── Runtime — live device operations ─────────────────────────────────────\n\n /** Get stream sources for a camera device. */\n getStreamSources: method(\n z.object({ deviceId: z.number() }),\n z.array(StreamSourceEntrySchema),\n ),\n\n /** Get config entries (key + value + description) for a device. */\n getConfigSchema: method(\n z.object({ deviceId: z.number() }),\n z.array(ConfigEntrySchema),\n ),\n\n /** Get the ConfigUISchema for a device's settings (for admin UI rendering). */\n getSettingsSchema: method(\n z.object({ deviceId: z.number() }),\n ConfigUISchemaOutput,\n ),\n\n // ── Mutations — config changes, enable/disable, remove ────────────────────\n\n /** Update device config values (partial merge). */\n updateConfig: method(\n z.object({\n deviceId: z.number(),\n values: z.record(z.string(), z.unknown()),\n }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /** Enable a device (writes enabled=true to device config). */\n enable: method(\n z.object({ deviceId: z.number() }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /** Disable a device (writes enabled=false to device config). */\n disable: method(\n z.object({ deviceId: z.number() }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /** Remove a device and all children: calls device.removeDevice() then removes from registry + DB. */\n remove: method(\n z.object({ deviceId: z.number() }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n // ── Stream profile map ────────────────────────────────────────────────────\n\n /** Get quality→streamId mapping for a camera. Derived from profileHint if not explicitly set. */\n getStreamProfileMap: method(\n z.object({ deviceId: z.number() }),\n z.record(z.string(), z.string().nullable()),\n ),\n\n /** Persist quality→streamId mapping in device config under reserved key _profileMap. */\n setStreamProfileMap: method(\n z.object({\n deviceId: z.number(),\n profileMap: z.record(z.string(), z.string().nullable()),\n }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /** Run ffprobe on each stream source URL and return metadata. No-op if stream probe unavailable. */\n probeStreams: method(\n z.object({ deviceId: z.number() }),\n z.array(StreamProbeResultSchema),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n // ── Bindings — per-device capability provider map ────────────────────────\n\n /**\n * Return the per-capability binding map for a device. Each entry lists the\n * currently-active provider (native or wrapper) + the underlying native\n * addon id, so consumers can decide routing without re-running discovery.\n */\n getBindings: method(\n z.object({ deviceId: z.number() }),\n z.object({\n deviceId: z.number(),\n entries: z.array(z.object({\n capName: z.string(),\n kind: z.enum(['native', 'wrapped']),\n providerAddonId: z.string(),\n providerNodeId: z.string(),\n nativeAddonId: z.string(),\n })),\n }),\n ),\n\n /**\n * Return the binding map for every device known to the hub. Used by\n * `SystemManager` warm-boot: a single round-trip resolves the\n * routing for the entire fleet so subsequent `sm.getDeviceById(id)`\n * calls are sync. Bindings change rarely (only on wrapper toggle or\n * device add/remove) — clients invalidate via the\n * `capability.binding-changed` event.\n */\n getAllBindings: method(\n z.object({}),\n z.array(z.object({\n deviceId: z.number(),\n entries: z.array(z.object({\n capName: z.string(),\n kind: z.enum(['native', 'wrapped']),\n providerAddonId: z.string(),\n providerNodeId: z.string(),\n nativeAddonId: z.string(),\n })),\n })),\n ),\n\n /**\n * Activate (or deactivate) a wrapper addon for a (device, cap) pair.\n * Persists the binding via ctx.settings. active=false clears the wrapper\n * (falls back to native if registered).\n */\n setWrapperActive: method(\n z.object({\n deviceId: z.number(),\n capName: z.string(),\n wrapperAddonId: z.string(),\n active: z.boolean(),\n }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /**\n * Return the addon ids that declared a wrapper provider for `capName`.\n * Backs the device-bindings UI's wrapper-picker dropdown. Entries are\n * sourced from `CapabilityRegistry.wrapperProviders`, populated at\n * `ProviderRegistration.kind === 'wrapper'` time.\n */\n listWrappersForCap: method(\n z.object({ capName: z.string() }),\n z.array(z.string()),\n ),\n\n /**\n * Return every device-scoped capability name that applies to a\n * deviceType (scope:'device' + deviceTypes includes the given type),\n * paired with the wrappers that can provide it. Backs the device\n * bindings UI so it can show rows for bindable caps even when no\n * native is registered yet — the user can still activate a wrapper\n * to light the cap up (e.g. snapshot via ffmpeg fallback for a camera\n * without `snapshotUrl`).\n */\n listBindableCapsForDeviceType: method(\n z.object({ deviceType: z.string() }),\n z.array(z.object({\n capName: z.string(),\n wrappers: z.array(z.string()),\n })),\n ),\n\n // ── Device-details aggregators ───────────────────────────────────────────\n //\n // Single entry point the admin UI calls to render the device-details page.\n // The hub enumerates every provider of `device-settings-contributor` (a\n // `collection` cap) plus its own base section and returns a single\n // `ConfigUISchemaWithValues` with merged tabs/sections.\n //\n // Two endpoints, two cadences:\n // - `getDeviceSettingsAggregate` — editable fields + static readonly.\n // Cached on the UI side, invalidated on successful `updateDeviceField`.\n // - `getDeviceLiveInfoAggregate` — readonly, dynamic. UI polls at a\n // short interval (~2-3 s). Fields carry `source: 'live'` so the\n // renderer knows which query owns the value.\n //\n // Save flow goes through `updateDeviceField` — the aggregator routes the\n // write to `addon-settings.updateDeviceSettings` for the declared\n // `writerAddonId` (or to its own device config store when `writerAddonId`\n // equals the device-manager addon id).\n\n getDeviceSettingsAggregate: method(\n z.object({ deviceId: z.number() }),\n SettingsSchemaWithValuesSchema.nullable(),\n ),\n getDeviceLiveInfoAggregate: method(\n z.object({ deviceId: z.number() }),\n SettingsSchemaWithValuesSchema.nullable(),\n ),\n /**\n * Unified entry point — returns both settings + live in a single call\n * so the admin UI pulls the whole device-details panel with one round-\n * trip instead of firing two parallel queries. The `live` field is the\n * polled portion; the UI re-fetches the whole aggregate at the live\n * cadence and uses the `settings` slice verbatim until the user\n * writes through `updateDeviceFieldsBatch`.\n */\n getDeviceAggregate: method(\n z.object({ deviceId: z.number() }),\n z.object({\n settings: SettingsSchemaWithValuesSchema.nullable(),\n live: SettingsSchemaWithValuesSchema.nullable(),\n }),\n ),\n updateDeviceField: method(\n z.object({\n deviceId: z.number(),\n writerCapName: z.string(),\n writerAddonId: z.string(),\n key: z.string(),\n value: z.unknown(),\n }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n /**\n * Batched counterpart of `updateDeviceField` — the admin UI groups\n * per-provider changes so a single round-trip triggers at most one\n * `applyDeviceSettingsPatch` per `(capName, addonId)` tuple. Per-patch\n * failures are reported in `failures[]` without aborting the others;\n * consumers inspect the list and surface targeted errors.\n */\n updateDeviceFieldsBatch: method(\n z.object({\n deviceId: z.number(),\n changes: z.array(z.object({\n writerCapName: z.string(),\n writerAddonId: z.string(),\n key: z.string(),\n value: z.unknown(),\n })),\n }),\n z.object({\n success: z.literal(true),\n failures: z.array(z.object({\n writerCapName: z.string(),\n writerAddonId: z.string(),\n error: z.string(),\n })),\n }),\n { kind: 'mutation', auth: 'admin' },\n ),\n // ── Device-provider operations (routed via CapabilityRegistry) ────────────\n //\n // These methods proxy to the `device-provider` capability collection,\n // routing by addonId. Moving them here from the compat router\n // (`device-ops.router.ts`) allows addon ctx.api callers to reach them\n // through the standard Moleculer-registered cap surface.\n\n /** Trigger device discovery on a device-provider addon. */\n discoverDevices: method(\n z.object({ addonId: z.string() }),\n z.array(DiscoveryCandidateSchema),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /** Adopt a discovered device via the device-provider capability. */\n adoptDevice: method(\n z.object({\n addonId: z.string(),\n candidate: DiscoveryCandidateSchema,\n }),\n DeviceSummarySchema,\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /**\n * Get the creation form schema (ConfigUISchema) for a device type from a provider.\n * Returns null when the provider does not support manual creation.\n */\n getCreationSchema: method(\n z.object({\n addonId: z.string(),\n type: z.enum(DeviceType),\n }),\n z.unknown().nullable(),\n ),\n\n /** Create a new device via the device-provider capability. */\n createDevice: method(\n z.object({\n addonId: z.string(),\n type: z.enum(DeviceType),\n config: z.record(z.string(), z.unknown()),\n }),\n DeviceSummarySchema,\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /**\n * Test a single form field value during device creation (no device\n * exists yet). `formValues` carries the live snapshot of every\n * field in the form so probes that depend on multiple fields (e.g.\n * Reolink autodetect needs host + credentials + UID together) can\n * run without a separate round-trip per field. Optional for\n * backwards compatibility.\n */\n testCreationField: method(\n z.object({\n addonId: z.string(),\n type: z.enum(DeviceType),\n key: z.string(),\n value: z.unknown(),\n formValues: z.record(z.string(), z.unknown()).optional(),\n }),\n FieldProbeResultSchema,\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /**\n * Test a field value on an existing device (e.g. probe an RTSP URL).\n * Routes through the device-provider for the owning addon.\n */\n testField: method(\n z.object({\n deviceId: z.number(),\n key: z.string(),\n value: z.unknown(),\n }),\n FieldProbeResultSchema,\n { kind: 'mutation', auth: 'admin' },\n ),\n\n /**\n * Aggregate status snapshot across every cap registered for a\n * device. Returns a flat map `{ capName: status | null }` where\n * `status` is whatever `capDef.status.schema` validates to — or\n * `null` when no provider for that cap is registered on the\n * device, or the provider returned null, or the returned value\n * failed validation.\n *\n * `caps` is a positional tuple of cap names. The runtime only\n * returns entries for caps that are KNOWN to the system (validated\n * against `CAP_NAMES_WITH_STATUS` at call time); unknown names are\n * silently skipped. The client-side hook narrows the return type\n * using `CapStatusTypeMap` so the TS-inferred shape matches the\n * runtime shape.\n *\n * When `caps` is omitted, the server returns status for EVERY\n * registered cap on the device. Use this only for debug / overview\n * pages — it's O(N caps) per call.\n */\n getDeviceStatusAggregate: method(\n z.object({\n deviceId: z.number(),\n caps: z.array(z.string()).readonly().optional(),\n }),\n z.record(z.string(), z.unknown().nullable()),\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IDeviceManagerProvider = import('./capability-definition.js').InferProvider<typeof deviceManagerCapability>\nexport type DeviceInfo = z.infer<typeof DeviceInfoSchema>\n","import { z } from 'zod'\nimport { type CapabilityDefinition, method, event } from './capability-definition.js'\n\n/**\n * `deviceState` — generic, cap-agnostic surface for cross-process\n * access to per-device runtime state. Read pendant for every cap's\n * runtime-state slice + the canonical write entrypoint. Mirrors the\n * in-process `BaseDevice.runtimeState` API:\n *\n * - `getSnapshot({deviceId})` → full `Record<capName, slice>`.\n * - `getCapSlice({deviceId, capName})` → one slice.\n * - `setCapSlice({deviceId, capName, slice})` → unified single-slice\n * write. Hub validates (when a cap schema is registered),\n * persists to disk (debounced), updates the mirror, and emits\n * `onChanged` for that cap.\n * - `onChanged` event → fires on every slice change.\n *\n * Drivers don't implement this cap directly — the kernel auto-mounts\n * a singleton provider against `device-manager`'s in-hub mirror.\n * Every `setCapState` call on a `BaseDevice.runtimeState` ultimately\n * routes through `setCapSlice` (single cross-layer entrypoint) so\n * UIs / addons subscribe to a single event channel for every\n * cap-state change; per-cap events (`battery.onStatusChanged`, …)\n * remain available for typed consumers but no longer have to be\n * defined on every new cap with runtime state.\n */\nexport const deviceStateCapability = {\n name: 'device-state',\n scope: 'system',\n mode: 'singleton',\n methods: {\n /** Full state snapshot for one device. Empty object if no\n * cap-keyed slice has been written yet. */\n getSnapshot: method(\n z.object({ deviceId: z.number() }),\n z.record(z.string(), z.record(z.string(), z.unknown())),\n ),\n /** Single cap slice. Returns null when the slice hasn't been\n * written or the device isn't registered. */\n getCapSlice: method(\n z.object({ deviceId: z.number(), capName: z.string() }),\n z.record(z.string(), z.unknown()).nullable(),\n ),\n /**\n * Whole-system snapshot — every device's full state in one\n * payload. Used by `SystemManager` for warm-boot: a single\n * round-trip populates the client mirror so every subsequent\n * `sm.getDeviceById(id).state.<cap>.value` is sync. Empty inner\n * record for devices that haven't emitted any slice yet.\n */\n getAllSnapshots: method(\n z.object({}),\n z.record(z.string(), z.record(z.string(), z.record(z.string(), z.unknown()))),\n ),\n\n /**\n * Canonical cross-layer WRITE for one cap-keyed slice. Used by\n * everyone who needs to publish runtime state for a device:\n * device providers (via `BaseDevice.runtimeState.setCapState`\n * which delegates here), system-scope addons (e.g. the pipeline\n * runner writing the `motion` slice on phase transitions), and\n * direct cap-router callers in tests.\n *\n * Behavior on the hub:\n * 1. Resolve the device — throws if unknown.\n * 2. Diff the slice against the current mirror (no-op on\n * identical writes — saves disk and event churn).\n * 3. Update the mirror in place.\n * 4. Persist the full per-device blob to disk (debounced).\n * 5. Emit `onChanged` for this cap so subscribers (UI mirror,\n * SystemManager, per-cap typed listeners) refresh.\n *\n * Schema validation is the caller's responsibility — callers\n * going through `BaseDevice.runtimeState.setCapState` get the\n * cap's `runtimeState` schema enforced in-process before the\n * write reaches here. Direct callers should validate against\n * the cap's schema themselves.\n *\n * No `patch` variant — for shallow merges read the slice via\n * `getCapSlice` first, merge, and write. The single-writer\n * conventions on each cap make atomic-merge semantics\n * unnecessary in practice.\n */\n setCapSlice: method(\n z.object({\n deviceId: z.number(),\n capName: z.string(),\n slice: z.record(z.string(), z.unknown()),\n }),\n z.void(),\n { kind: 'mutation' },\n ),\n },\n events: {\n /**\n * Fires whenever a cap-keyed slice changes. Per-event payload\n * carries the slice that changed — subscribers can render off\n * the payload alone without re-querying. Filterable by `deviceId`\n * via the standard `EventFilter` helpers.\n */\n onChanged: event(z.object({\n deviceId: z.number(),\n capName: z.string(),\n slice: z.record(z.string(), z.unknown()),\n })),\n },\n} as const satisfies CapabilityDefinition\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\nconst AuthResultSchema = z.object({\n userId: z.string(),\n username: z.string(),\n email: z.string().optional(),\n displayName: z.string().optional(),\n roles: z.array(z.string()).optional(),\n})\n\nexport const authProviderCapability = {\n name: 'auth-provider',\n scope: 'system',\n mode: 'collection',\n internal: true,\n methods: {\n validateCredentials: method(\n z.object({ username: z.string(), password: z.string() }),\n AuthResultSchema.nullable(),\n { kind: 'mutation' },\n ),\n getLoginUrl: method(z.object({ state: z.string() }), z.string()),\n handleCallback: method(z.record(z.string(), z.string()), AuthResultSchema, { kind: 'mutation' }),\n validateToken: method(z.object({ token: z.string() }), AuthResultSchema.nullable()),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IAuthProvider = InferProvider<typeof authProviderCapability>\n\nexport { AuthResultSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\nconst NetworkEndpointSchema = z.object({\n url: z.string(),\n hostname: z.string(),\n port: z.number(),\n protocol: z.enum(['http', 'https']),\n})\n\nconst NetworkAccessStatusSchema = z.object({\n connected: z.boolean(),\n endpoint: NetworkEndpointSchema.nullable(),\n error: z.string().optional(),\n})\n\nexport const networkAccessCapability = {\n name: 'network-access',\n scope: 'system',\n mode: 'collection',\n internal: true,\n methods: {\n start: method(z.void(), NetworkEndpointSchema, { kind: 'mutation' }),\n stop: method(z.void(), z.void(), { kind: 'mutation' }),\n getEndpoint: method(z.void(), NetworkEndpointSchema.nullable()),\n getStatus: method(z.void(), NetworkAccessStatusSchema),\n },\n} as const satisfies CapabilityDefinition\n\nexport type INetworkAccessProvider = InferProvider<typeof networkAccessCapability>\n\nexport { NetworkEndpointSchema, NetworkAccessStatusSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n/**\n * A single ICE TURN/STUN server entry, shape compatible with\n * `RTCIceServer` in the WebRTC spec.\n */\nconst TurnServerSchema = z.object({\n /** Single URL or list of URLs (e.g. \"turn:turn.example.com:3478?transport=udp\"). */\n urls: z.union([z.string(), z.array(z.string())]),\n username: z.string().optional(),\n credential: z.string().optional(),\n})\n\n/**\n * turn-provider — system collection of TURN/STUN server providers.\n *\n * Consumed by `webrtc` providers (e.g. addon-go2rtc) when building the\n * ICE server list for an offer. Multiple providers can coexist\n * (Cloudflare, self-hosted coturn, Twilio, etc.) — the webrtc layer\n * concatenates servers from all registered implementations.\n *\n * Exposed over tRPC so that out-of-process addons (forked workers or\n * remote agents) can also enumerate available TURN servers without\n * requiring in-process access to the capability registry.\n */\nexport const turnProviderCapability = {\n name: 'turn-provider',\n scope: 'system',\n mode: 'collection',\n methods: {\n /**\n * Return the current list of TURN/STUN servers with credentials.\n * Implementations may fetch fresh short-lived credentials on each call\n * (e.g. Cloudflare API) — consumers SHOULD call this per-session.\n */\n getTurnServers: method(\n z.void(),\n z.array(TurnServerSchema).readonly(),\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type ITurnProvider = InferProvider<typeof turnProviderCapability>\n\nexport { TurnServerSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * A single device snapshot returned as base64 JPEG/PNG.\n *\n * Shared with the `snapshot-provider` collection cap — the orchestrator\n * receives the same shape from each native provider and from the\n * broker-based fallback.\n */\nconst SnapshotImageSchema = z.object({\n base64: z.string(),\n contentType: z.string(),\n})\n\n/**\n * snapshot — device-scoped capability for camera image capture.\n *\n * Two kinds of providers coexist behind this cap name:\n *\n * - **Native** providers (kind:'native'): registered per-device by\n * device-driver addons (RtspCamera, OnvifCamera, …) via\n * `DeviceContext.registerNativeCap`. Each knows how to fetch a frame\n * straight from the camera (HTTP snapshot URL, ONVIF action, etc.).\n *\n * - **Wrapper** providers (kind:'wrapper'): register as a system\n * provider (SnapshotAddon in `@camstack/core/builtins/snapshot`). The\n * wrapper owns the cache and invokes the native via\n * `ctx.getNativeProvider(snapshotCapability, deviceId)` on miss.\n *\n * Device-scoped routing: callers use `ctx.fetchDevice(id).snapshot.*`;\n * the DeviceProxy auto-injects `deviceId` + `nodeId` and dispatches to\n * the provider currently active for that device (wrapper wins when\n * activated via `setWrapperActive`, otherwise the native).\n */\n/**\n * Live readable snapshot state — diagnostic info that a consumer can\n * pull to know when the last image was captured, how stale the cache\n * is, and which stream was used. Distinct from `getSnapshot` which\n * returns the JPEG itself.\n */\nconst SnapshotStatusSchema = z.object({\n /** Ms epoch of the last successful capture. Null if none yet. */\n lastCapturedAt: z.number().nullable(),\n /** Age of the cached image in ms. Null if no cache. */\n cacheAgeMs: z.number().nullable(),\n /** Size in bytes of the last captured image. Null if no capture. */\n lastBytes: z.number().nullable(),\n /** Stream id used for the last capture ('high'|'mid'|'low' or custom). Null if via HTTP endpoint. */\n lastStreamId: z.string().nullable(),\n})\n\nexport const snapshotCapability = {\n name: 'snapshot',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n // Owns per-device snapshot settings (preferred stream, debug logging).\n // The three DeviceSettingsContribution methods are auto-added to the\n // provider interface via `InferProvider` — `SnapshotAddon` implements\n // them and persists per-device state through `ctx.settings.writeDeviceStore`.\n exposesDeviceSettings: true,\n methods: {\n getSnapshot: method(\n z.object({\n deviceId: z.number(),\n streamId: z.string().optional(),\n /**\n * Bypass the cache freshness check and fetch directly from the\n * native (or stream-broker fallback). Triggered by the UI's\n * \"refresh\" button so an operator can force a fresh frame\n * even when the cache is well within `snapshotMaxAgeMs`.\n * On battery cams this WILL wake the camera — accept the\n * cost only when the user explicitly asks for it.\n */\n force: z.boolean().optional(),\n }),\n SnapshotImageSchema.nullable(),\n ),\n invalidateCache: method(\n z.object({ deviceId: z.number() }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n status: {\n schema: SnapshotStatusSchema,\n kind: 'poll',\n },\n} as const satisfies CapabilityDefinition\n\nexport type ISnapshotOrchestrator = InferProvider<typeof snapshotCapability>\n\nexport { SnapshotImageSchema, SnapshotStatusSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { SnapshotImageSchema } from './snapshot.cap.js'\n\n/**\n * snapshot-provider — collection of native snapshot implementations.\n *\n * Device provider addons (ONVIF, Frigate, Scrypted, etc.) register here\n * when they can capture frames through a protocol-native path (e.g.\n * ONVIF GetSnapshotUri, Frigate /api/<cam>/latest.jpg). The `snapshot`\n * singleton orchestrator iterates over the collection, asking each\n * provider whether it supports the requested device, and calls the\n * first matching one.\n *\n * If no provider in the collection supports a device, the orchestrator\n * falls back to `stream-broker.grabFrame` (universal fallback).\n *\n * Public tRPC router (auto-mounted) so out-of-process addons, agents,\n * and advanced clients can bypass the orchestrator when needed.\n */\nexport const snapshotProviderCapability = {\n name: 'snapshot-provider',\n scope: 'system',\n mode: 'collection',\n methods: {\n supportsDevice: method(\n z.object({ deviceId: z.number() }),\n z.boolean(),\n ),\n getSnapshot: method(\n z.object({\n deviceId: z.number(),\n streamId: z.string().optional(),\n }),\n SnapshotImageSchema.nullable(),\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type ISnapshotProvider = InferProvider<typeof snapshotProviderCapability> & {\n readonly id: string\n readonly name: string\n}\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\nconst NotificationSchema = z.object({\n title: z.string(),\n body: z.string(),\n imageUrl: z.string().optional(),\n deviceId: z.number().optional(),\n eventId: z.string().optional(),\n priority: z.enum(['low', 'normal', 'high', 'critical']).default('normal'),\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const notificationOutputCapability = {\n name: 'notification-output',\n scope: 'system',\n mode: 'collection',\n methods: {\n send: method(NotificationSchema, z.void(), { kind: 'mutation' }),\n sendTest: method(\n z.void(),\n z.object({ success: z.boolean(), error: z.string().optional() }),\n { kind: 'mutation' },\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type INotificationOutputProvider = InferProvider<typeof notificationOutputCapability>\n\nexport { NotificationSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\nconst NotificationRuleSchema = z.object({\n id: z.string(),\n name: z.string(),\n enabled: z.boolean(),\n conditions: z.record(z.string(), z.unknown()),\n actions: z.array(z.record(z.string(), z.unknown())),\n})\n\nconst NotificationHistoryEntrySchema = z.object({\n id: z.string(),\n ruleId: z.string(),\n timestamp: z.number(),\n deviceId: z.number().optional(),\n success: z.boolean(),\n error: z.string().optional(),\n})\n\nexport const advancedNotifierCapability = {\n name: 'advanced-notifier',\n scope: 'system',\n mode: 'singleton',\n internal: true,\n methods: {\n getRules: method(z.void(), z.array(NotificationRuleSchema).readonly()),\n upsertRule: method(NotificationRuleSchema, z.void(), { kind: 'mutation' }),\n deleteRule: method(z.object({ ruleId: z.string() }), z.void(), { kind: 'mutation' }),\n testRule: method(\n z.object({ ruleId: z.string(), lookbackMinutes: z.number() }),\n z.array(z.record(z.string(), z.unknown())),\n { kind: 'mutation' },\n ),\n getHistory: method(\n z.object({ ruleId: z.string().optional(), limit: z.number().optional() }),\n z.array(NotificationHistoryEntrySchema),\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IAdvancedNotifierProvider = InferProvider<typeof advancedNotifierCapability>\n\nexport { NotificationRuleSchema, NotificationHistoryEntrySchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n// ── Shared sub-schemas ─────────────────────────────────────────────\n\nconst RecordingModeSchema = z.enum(['continuous', 'motion', 'scheduled', 'composite'])\n\nconst StreamPolicySchema = z.object({\n streamId: z.string(),\n mode: z.enum(['always', 'inherit']),\n})\n\nconst ScheduleRuleSchema = z.object({\n days: z.array(z.number()).readonly(),\n startTime: z.string(),\n endTime: z.string(),\n mode: z.enum(['continuous', 'motion']),\n})\n\nconst RecordingPolicySchema = z.object({\n deviceId: z.number(),\n mode: RecordingModeSchema,\n streams: z.array(StreamPolicySchema).readonly(),\n enabled: z.boolean(),\n preBufferSec: z.number(),\n postBufferSec: z.number(),\n scheduleRules: z.array(ScheduleRuleSchema).readonly().optional(),\n})\n\nconst DataCategorySchema = z.enum([\n 'recording:main', 'recording:mid', 'recording:sub',\n 'thumbnail:scrub', 'thumbnail:event',\n])\n\nconst RecordingStorageConfigSchema = z.object({\n deviceId: z.number(),\n dataCategory: DataCategorySchema,\n storageName: z.string(),\n subDirectory: z.string(),\n retentionDays: z.number().nullable(),\n retentionGb: z.number().nullable(),\n})\n\nconst RecordingSegmentSchema = z.object({\n id: z.string(),\n deviceId: z.number(),\n streamId: z.string(),\n startTime: z.number(),\n endTime: z.number(),\n duration: z.number(),\n path: z.string(),\n storageName: z.string(),\n subDirectory: z.string(),\n sizeBytes: z.number(),\n codec: z.enum(['h264', 'h265']),\n hasAudio: z.boolean(),\n})\n\nconst RecordingThumbnailSchema = z.object({\n deviceId: z.number(),\n timestamp: z.number(),\n path: z.string(),\n storageName: z.string(),\n subDirectory: z.string(),\n sizeBytes: z.number(),\n category: z.enum(['scrub', 'event']),\n})\n\nconst AvailabilityRangeSchema = z.object({\n startTime: z.number(),\n endTime: z.number(),\n streams: z.array(z.string()).readonly(),\n})\n\nconst StorageUsageSchema = z.object({\n totalBytes: z.number(),\n segmentCount: z.number(),\n})\n\nconst StreamEstimateSchema = z.object({\n bitrateKbps: z.number(),\n retentionDays: z.number().nullable(),\n retentionGb: z.number().nullable(),\n estimatedGb: z.number(),\n estimatedDaysAtCapacity: z.number().nullable(),\n})\n\nconst StorageEstimateSchema = z.object({\n perStream: z.record(z.string(), StreamEstimateSchema),\n thumbnails: z.object({ estimatedGb: z.number() }),\n totalEstimatedGb: z.number(),\n motionEstimate: z.object({\n avgEventsPerDay: z.number(),\n avgDurationSec: z.number(),\n dutyCyclePercent: z.number(),\n }).optional(),\n})\n\nconst MotionStatsSchema = z.object({\n totalEvents: z.number(),\n avgDurationSec: z.number(),\n avgEventsPerDay: z.number(),\n dutyCyclePercent: z.number(),\n})\n\n// ── Inputs ─────────────────────────────────────────────────────────\n\nconst DeviceIdInput = z.object({ deviceId: z.number() })\n\nconst EnableInput = z.object({\n deviceId: z.number(),\n policy: RecordingPolicySchema.omit({ deviceId: true }),\n storageOverrides: z.array(RecordingStorageConfigSchema.omit({ deviceId: true })).readonly().optional(),\n ffmpegOverrides: z.record(z.string(), z.unknown()).optional(),\n})\n\nconst TimeRangeInput = z.object({\n deviceId: z.number(),\n startTime: z.number(),\n endTime: z.number(),\n})\n\nconst StreamTimeRangeInput = z.object({\n deviceId: z.number(),\n streamId: z.string(),\n startTime: z.number(),\n endTime: z.number(),\n})\n\nconst PlaylistInput = z.object({\n deviceId: z.number(),\n streamId: z.string(),\n startTime: z.number(),\n endTime: z.number(),\n live: z.boolean().optional(),\n})\n\nconst ThumbnailInput = z.object({\n deviceId: z.number(),\n timestamp: z.number(),\n category: z.string().optional(),\n})\n\nconst DeviceStreamInput = z.object({\n deviceId: z.number(),\n streamId: z.string(),\n})\n\nconst StorageEstimateInput = z.object({\n deviceId: z.number(),\n motionInput: z.object({\n avgEventsPerDay: z.number(),\n avgDurationSec: z.number(),\n }).optional(),\n})\n\nconst RetentionConfigInput = z.object({\n deviceId: z.number(),\n dataCategory: DataCategorySchema,\n})\n\nconst SetPolicyInput = z.object({\n deviceId: z.number(),\n policy: RecordingPolicySchema.omit({ deviceId: true }),\n})\n\nconst UpdateConfigInput = z.object({\n deviceId: z.number(),\n policy: RecordingPolicySchema.omit({ deviceId: true }),\n ffmpegOverrides: z.record(z.string(), z.unknown()).optional(),\n})\n\n// ── Capability definition ──────────────────────────────────────────\n\n/**\n * Recording engine — manages per-device recording lifecycle, policies,\n * playlists, segments, thumbnails, and storage estimation.\n *\n * Implemented by the `recording` sub-addon inside `addon-analytics-suite`.\n * Session 5 Sprint D expanded the cap from 1 method (`getStatus`) to the\n * full 17-method contract, replacing the broken hand-written\n * `recording.router.ts` that invoked non-existent methods on the addon.\n *\n * The provider implementation is a facade wrapping RecordingCoordinator,\n * RecordingDb, PlaylistGenerator, StorageEstimator, and RetentionManager.\n */\nexport const recordingEngineCapability = {\n name: 'recording-engine',\n scope: 'system',\n mode: 'singleton',\n methods: {\n // ── Status ────────────────────────────────────────────────────────\n getStatus: method(z.void(), z.object({\n activeRecordings: z.number(),\n totalSegments: z.number(),\n totalSizeMB: z.number(),\n })),\n\n // ── Lifecycle ─────────────────────────────────────────────────────\n enable: method(EnableInput, z.void(), { kind: 'mutation', auth: 'admin' }),\n disable: method(DeviceIdInput, z.void(), { kind: 'mutation', auth: 'admin' }),\n\n // ── Config ────────────────────────────────────────────────────────\n getConfig: method(DeviceIdInput, RecordingPolicySchema.nullable()),\n updateConfig: method(UpdateConfigInput, z.void(), { kind: 'mutation', auth: 'admin' }),\n\n // ── Playback ──────────────────────────────────────────────────────\n getPlaylist: method(PlaylistInput, z.string()),\n getThumbnail: method(ThumbnailInput, RecordingThumbnailSchema.nullable()),\n getSegments: method(StreamTimeRangeInput, z.array(RecordingSegmentSchema).readonly()),\n getAvailability: method(TimeRangeInput, z.array(AvailabilityRangeSchema).readonly()),\n\n // ── Storage ───────────────────────────────────────────────────────\n estimateStorage: method(StorageEstimateInput, StorageEstimateSchema),\n estimateGlobalStorage: method(z.void(), StorageEstimateSchema),\n getStorageUsage: method(DeviceStreamInput, StorageUsageSchema),\n\n // ── Policy ────────────────────────────────────────────────────────\n setPolicy: method(SetPolicyInput, z.void(), { kind: 'mutation', auth: 'admin' }),\n getPolicy: method(DeviceIdInput, RecordingPolicySchema.nullable()),\n getPolicyStatus: method(DeviceIdInput, z.object({\n deviceId: z.number(),\n enabled: z.boolean(),\n mode: RecordingModeSchema,\n activeStreams: z.number(),\n }).nullable()),\n\n // ── Retention ─────────────────────────────────────────────────────\n getRetentionConfig: method(RetentionConfigInput, RecordingStorageConfigSchema.nullable()),\n updateRetentionConfig: method(RecordingStorageConfigSchema, z.void(), { kind: 'mutation', auth: 'admin' }),\n\n // ── Motion ────────────────────────────────────────────────────────\n getMotionStats: method(TimeRangeInput, MotionStatsSchema),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IRecordingEngineProvider = InferProvider<typeof recordingEngineCapability>\n\nexport {\n RecordingPolicySchema,\n RecordingSegmentSchema,\n RecordingThumbnailSchema,\n RecordingStorageConfigSchema,\n AvailabilityRangeSchema,\n StorageUsageSchema,\n StorageEstimateSchema,\n MotionStatsSchema,\n RecordingModeSchema,\n DataCategorySchema,\n}\n","import { type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * detection-pipeline — device-scoped facade over the system\n * `pipeline-executor`.\n *\n * Pairs with `pipeline-executor` (system, singleton) the way\n * `audio-analysis` pairs with `audio-analyzer`: the system cap owns the\n * engine lifecycle (engines, templates, models, runPipeline) while\n * `detection-pipeline` is the per-camera binding row in the\n * device-manager UI.\n *\n * Registered as a wrapper with `defaultActive: true` by\n * `addon-detection-pipeline` so every camera opts into detection\n * automatically. Operators disable per-device via\n * `device-manager.setWrapperActive` — replaces the legacy\n * `pipelineEnabled` / `disableInference` flags previously stored in the\n * orchestrator's device-settings.\n *\n * `exposesDeviceSettings: true` is intentional — the three\n * DeviceSettingsContribution methods auto-added to the provider\n * interface serve the per-device detection settings panel in the admin\n * UI (model selection, class filters, confidence thresholds).\n */\nexport const detectionPipelineCapability = {\n name: 'detection-pipeline',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n exposesDeviceSettings: true,\n methods: {},\n} as const satisfies CapabilityDefinition\n\nexport type IDetectionPipelineProvider = InferProvider<typeof detectionPipelineCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\nimport { BoundingBoxSchema } from './schemas/detection-shared.js'\n\n/**\n * pipeline-analytics — device-scoped wrapper cap. Refines raw\n * per-frame detections emitted by the pipeline runner into tracked\n * objects, per-kind event collections (motion / object / audio), and\n * persisted media. Owns the post-detection domain end-to-end:\n *\n * runner emits PipelineInferenceResult\n * ↓ (event bus)\n * pipeline-analytics subscriber\n * ↓ SORT tracker + zone engine + state analyzer + event emitter\n * → three DB collections (one per kind), one FS media tree, one\n * unified event emitter (FrameTracked + TrackStarted/Ended +\n * DetectionEvent on bus)\n *\n * Pure subscriber model. No `processFrame` cap method — the runner\n * already publishes the raw frame on the bus. The cap surface is\n * only QUERIES + per-device settings, bound on/off via\n * `device-manager.setWrapperActive`. `defaultActive: true` because\n * every camera with a detection pipeline wants its raw detections\n * refined; operators opt out per-device via BindingsTab when needed.\n *\n * Replaces the legacy `analysis-pipeline`, `analysis-data-persistence`\n * (per-device surface) and `track-trail` caps — see P11 cleanup.\n */\n\n// ── Shared sub-schemas ──────────────────────────────────────────────\n\nconst TrackStateSchema = z.enum(['new', 'entered', 'left', 'moving', 'idle'])\nexport type TrackState = z.infer<typeof TrackStateSchema>\n\nconst EventKindSchema = z.enum(['motion', 'object', 'audio'])\nexport type EventKind = z.infer<typeof EventKindSchema>\n\n// ── Track (unified: identity + positions + snapshots) ───────────────\n\nconst TrackPositionSchema = z.object({\n x: z.number(),\n y: z.number(),\n timestamp: z.number(),\n bbox: BoundingBoxSchema,\n})\n\nconst TrackSnapshotSchema = z.object({\n timestamp: z.number(),\n position: TrackPositionSchema,\n /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */\n mediaKey: z.string(),\n})\n\nconst TrackSchema = z.object({\n trackId: z.string(),\n deviceId: z.number(),\n className: z.string(),\n label: z.string().optional(),\n firstSeen: z.number(),\n lastSeen: z.number(),\n /** Frame-rate position history (subject to maxPositionHistory cap). */\n positions: z.array(TrackPositionSchema).readonly(),\n /** Periodic snapshots at snapshotIntervalMs cadence (subject to\n * saveThumbnails policy). */\n snapshots: z.array(TrackSnapshotSchema).readonly(),\n /** Deduplicated zones the track has entered at least once. */\n zonesVisited: z.array(z.string()).readonly(),\n /** Cumulative normalized distance travelled (0..1 units = full frame width). */\n totalDistance: z.number(),\n state: TrackStateSchema,\n active: z.boolean(),\n})\nexport type Track = z.infer<typeof TrackSchema>\n// TrackPosition / TrackSnapshot types stay internal — consumers access\n// them through `track.positions[i]` / `track.snapshots[i]`. Top-level\n// names are reserved for the legacy interfaces/analysis-persistence.ts\n// until P11 cleanup.\n\n// ── Events (per-kind, three separate backing collections) ───────────\n\nconst BaseEventFields = {\n id: z.string(),\n deviceId: z.number(),\n timestamp: z.number(),\n}\n\nconst MotionEventSchema = z.object({\n ...BaseEventFields,\n kind: z.literal('motion'),\n regionCount: z.number(),\n regions: z.array(z.object({\n bbox: BoundingBoxSchema,\n pixelCount: z.number(),\n intensity: z.number(),\n })).readonly(),\n frameWidth: z.number(),\n frameHeight: z.number(),\n})\nexport type MotionEvent = z.infer<typeof MotionEventSchema>\n\nconst ObjectEventSchema = z.object({\n ...BaseEventFields,\n kind: z.literal('object'),\n trackId: z.string(),\n className: z.string(),\n label: z.string().optional(),\n confidence: z.number(),\n bbox: BoundingBoxSchema,\n zones: z.array(z.string()).readonly(),\n state: TrackStateSchema,\n /** MediaStore key for the crop attached to this event (if any). */\n mediaKey: z.string().optional(),\n})\nexport type ObjectEvent = z.infer<typeof ObjectEventSchema>\n\nconst AudioEventSchema = z.object({\n ...BaseEventFields,\n kind: z.literal('audio'),\n rms: z.number(),\n dbfs: z.number(),\n classification: z.object({\n className: z.string(),\n originalClass: z.string().optional(),\n score: z.number(),\n }).optional(),\n})\nexport type AudioEvent = z.infer<typeof AudioEventSchema>\n\n// ── Media files (crops / thumbs / snapshots) ────────────────────────\n\nconst MediaFileSchema = z.object({\n key: z.string(),\n kind: z.enum(['crop', 'thumbnail', 'snapshot']),\n base64: z.string(),\n sizeBytes: z.number(),\n timestamp: z.number(),\n})\nexport type MediaFile = z.infer<typeof MediaFileSchema>\n\n// ── Query input schemas ─────────────────────────────────────────────\n\n// Hard cap on event-list responses. Without it, queries against the\n// 1M+ row analytics tables (audio classifier inserts ~1500 rows/min\n// per active camera) return every row + classification blob, blow\n// past the tRPC 5s default, and OOM the JSON serializer. Callers\n// needing more than MAX in one batch should paginate via since/until.\nconst DEFAULT_EVENT_QUERY_LIMIT = 1000\nconst MAX_EVENT_QUERY_LIMIT = 5000\n\nconst DeviceEventQueryInput = z.object({\n deviceId: z.number(),\n since: z.number().optional(),\n until: z.number().optional(),\n limit: z.number().int().min(1).max(MAX_EVENT_QUERY_LIMIT).default(DEFAULT_EVENT_QUERY_LIMIT),\n})\n\nconst ObjectEventQueryInput = DeviceEventQueryInput.extend({\n classFilter: z.string().optional(),\n})\n\n// ── Enriched frame emitted on bus after refinement ──────────────────\n//\n// Lightweight: carries only the tracked-detection metadata consumers\n// need to overlay track IDs / zones on a live stream. Full Track state\n// is queryable via getActiveTracks / getTrack.\n\nconst TrackedDetectionSchema = z.object({\n trackId: z.string(),\n className: z.string(),\n confidence: z.number(),\n bbox: BoundingBoxSchema,\n zones: z.array(z.string()).readonly(),\n state: TrackStateSchema,\n})\n\n// ── Capability definition ───────────────────────────────────────────\n\nexport const pipelineAnalyticsCapability = {\n name: 'pipeline-analytics',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n exposesDeviceSettings: true,\n methods: {\n // ── Tracks ────────────────────────────────────────────────\n getActiveTracks: method(\n z.object({ deviceId: z.number() }),\n z.array(TrackSchema).readonly(),\n ),\n getTrack: method(\n z.object({ deviceId: z.number(), trackId: z.string() }),\n TrackSchema.nullable(),\n ),\n /** Historical completed tracks for a device. Queried from the\n * persisted `pipeline-analytics:tracks` collection; active tracks\n * still in RAM are not included. */\n listTracks: method(\n z.object({\n deviceId: z.number(),\n since: z.number().optional(),\n until: z.number().optional(),\n limit: z.number().optional(),\n }),\n z.array(TrackSchema).readonly(),\n ),\n clearTracks: method(\n z.object({ deviceId: z.number() }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n\n // ── Events (per-kind, parallel-queryable) ─────────────────\n getMotionEvents: method(\n DeviceEventQueryInput,\n z.array(MotionEventSchema).readonly(),\n ),\n getObjectEvents: method(\n ObjectEventQueryInput,\n z.array(ObjectEventSchema).readonly(),\n ),\n getAudioEvents: method(\n DeviceEventQueryInput,\n z.array(AudioEventSchema).readonly(),\n ),\n\n // ── Media ─────────────────────────────────────────────────\n getEventMedia: method(\n z.object({ eventId: z.string() }),\n z.array(MediaFileSchema).readonly(),\n ),\n getTrackMedia: method(\n z.object({ trackId: z.string() }),\n z.array(MediaFileSchema).readonly(),\n ),\n },\n events: {\n /**\n * Enriched frame emitted after refinement. Carries lightweight\n * tracked-detection metadata (track id, class, zones, state) so\n * downstream consumers (stream overlays, notifications) can\n * annotate without querying full Track state.\n */\n onFrameTracked: {\n data: z.object({\n deviceId: z.number(),\n timestamp: z.number(),\n frameWidth: z.number(),\n frameHeight: z.number(),\n detections: z.array(TrackedDetectionSchema).readonly(),\n }),\n },\n /** Track entered active state (first-seen). */\n onTrackStarted: {\n data: z.object({\n deviceId: z.number(),\n trackId: z.string(),\n className: z.string(),\n }),\n },\n /** Track expired (TTL reached after last detection). */\n onTrackEnded: {\n data: z.object({\n deviceId: z.number(),\n trackId: z.string(),\n className: z.string(),\n durationMs: z.number(),\n }),\n },\n /** Canonical \"something happened at device X\" event, per-kind. */\n onDetectionEvent: {\n data: z.object({\n deviceId: z.number(),\n kind: EventKindSchema,\n eventId: z.string(),\n timestamp: z.number(),\n }),\n },\n },\n} as const satisfies CapabilityDefinition\n\nexport type IPipelineAnalyticsProvider = InferProvider<typeof pipelineAnalyticsCapability>\n\nexport {\n TrackStateSchema,\n EventKindSchema,\n TrackSchema,\n MotionEventSchema,\n ObjectEventSchema,\n AudioEventSchema,\n MediaFileSchema,\n TrackedDetectionSchema,\n}\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n// ── Snapshot schemas ────────────────────────────────────────────────\n\nconst CpuBreakdownSchema = z.object({\n total: z.number(),\n user: z.number(),\n system: z.number(),\n irq: z.number(),\n nice: z.number(),\n loadAvg: z.tuple([z.number(), z.number(), z.number()]),\n cores: z.number(),\n})\n\nconst MemoryInfoSchema = z.object({\n percent: z.number(),\n totalBytes: z.number(),\n usedBytes: z.number(),\n availableBytes: z.number(),\n swapUsedBytes: z.number(),\n swapTotalBytes: z.number(),\n})\n\nconst DiskIoSnapshotSchema = z.object({\n readBytes: z.number(),\n writeBytes: z.number(),\n readOps: z.number(),\n writeOps: z.number(),\n timestampMs: z.number(),\n})\n\nconst NetworkIoSnapshotSchema = z.object({\n rxBytes: z.number(),\n txBytes: z.number(),\n rxPackets: z.number(),\n txPackets: z.number(),\n rxErrors: z.number(),\n txErrors: z.number(),\n timestampMs: z.number(),\n})\n\nconst MetricsGpuInfoSchema = z.object({\n utilization: z.number(),\n model: z.string(),\n memoryUsedBytes: z.number(),\n memoryTotalBytes: z.number(),\n temperature: z.number().nullable(),\n})\n\nconst ProcessResourceInfoSchema = z.object({\n openFds: z.number(),\n threadCount: z.number(),\n activeHandles: z.number(),\n activeRequests: z.number(),\n})\n\nconst PressureAvgsSchema = z.object({\n avg10: z.number(),\n avg60: z.number(),\n avg300: z.number(),\n})\n\nconst PressureInfoSchema = z.object({\n some: PressureAvgsSchema,\n full: PressureAvgsSchema.nullable(),\n})\n\nconst SystemResourceSnapshotSchema = z.object({\n cpu: CpuBreakdownSchema,\n memory: MemoryInfoSchema,\n gpu: MetricsGpuInfoSchema.nullable(),\n network: NetworkIoSnapshotSchema,\n disk: DiskIoSnapshotSchema,\n pressure: z.object({\n cpu: PressureInfoSchema.nullable(),\n memory: PressureInfoSchema.nullable(),\n io: PressureInfoSchema.nullable(),\n }),\n process: ProcessResourceInfoSchema,\n cpuTemperature: z.number().nullable(),\n timestampMs: z.number(),\n})\n\nconst DiskSpaceInfoSchema = z.object({\n path: z.string(),\n totalBytes: z.number(),\n usedBytes: z.number(),\n availableBytes: z.number(),\n percent: z.number(),\n})\n\nconst PidResourceStatsSchema = z.object({\n pid: z.number(),\n cpu: z.number(),\n memory: z.number(),\n})\n\nconst AddonInstanceSchema = z.object({\n addonId: z.string(),\n nodeId: z.string(),\n role: z.enum(['hub', 'worker']),\n pid: z.number(),\n state: z.enum(['starting', 'running', 'stopping', 'stopped', 'crashed']),\n uptimeSec: z.number(),\n})\n\n// ── Process tree snapshot (ghost / zombie surfacing) ────────────────\n//\n// Each entry describes one OS process on the node that looks camstack-\n// related. Classification is ancestry-driven: walk pid→ppid until we\n// hit a known supervisor boundary OR ppid=1.\n//\n// root — the current node's own pid (process.pid)\n// managed — forked addon worker registered in `$process.list`\n// system — ancestry walk crosses a known supervisor boundary\n// (tsx watch launcher, agent CLI, concurrently, vite,\n// npm wrapper). Belongs to the intentional dev tree even\n// when not in $process.list. NEVER killable.\n// ghost — ancestry reaches ppid=1 (or parent invisible in `ps`)\n// without crossing a supervisor boundary. The ONLY\n// classification eligible for kill from the UI.\nconst NodeProcessSchema = z.object({\n pid: z.number(),\n ppid: z.number(),\n pgid: z.number(),\n classification: z.enum(['root', 'managed', 'system', 'ghost']),\n /** `$process` addon binding when `managed`, else null. */\n addonId: z.string().nullable(),\n /** Kernel-reported nodeId when the process is a known agent/worker. */\n nodeId: z.string().nullable(),\n /** Truncated command line. */\n command: z.string(),\n cpuPercent: z.number(),\n memoryRssBytes: z.number(),\n /** Wall-clock uptime (seconds). Parsed from `ps etime`. */\n uptimeSec: z.number(),\n /** True when ancestor walk reaches `ppid=1` (reparented to init/launchd). */\n orphaned: z.boolean(),\n})\n\nconst KillProcessInputSchema = z.object({\n pid: z.number(),\n /** Force = SIGKILL. Default is SIGTERM. */\n force: z.boolean().optional(),\n})\n\nconst KillProcessResultSchema = z.object({\n success: z.boolean(),\n reason: z.string().optional(),\n signal: z.enum(['SIGTERM', 'SIGKILL']).optional(),\n})\n\n// Public SystemMetrics summary — light-weight cached view used by UI widgets.\nconst SystemMetricsSchema = z.object({\n cpuPercent: z.number(),\n memoryPercent: z.number(),\n memoryUsedMB: z.number(),\n memoryTotalMB: z.number(),\n diskPercent: z.number().optional(),\n temperature: z.number().optional(),\n gpuPercent: z.number().optional(),\n gpuMemoryPercent: z.number().optional(),\n})\n\n// ── Capability definition ───────────────────────────────────────────\n\nexport const metricsProviderCapability = {\n name: 'metrics-provider',\n scope: 'system',\n mode: 'singleton',\n methods: {\n /** Fresh, full system snapshot (triggers OS-level collection). */\n collectSnapshot: method(z.void(), SystemResourceSnapshotSchema),\n /** Most recent cached snapshot from the background sampler, or null pre-first-sample. */\n getCached: method(z.void(), SystemResourceSnapshotSchema.nullable()),\n /** Light-weight cached summary for heartbeats and list views. */\n getCurrent: method(z.void(), SystemMetricsSchema),\n /** Disk space for the given mount/path. */\n getDiskSpace: method(z.object({ dirPath: z.string() }), DiskSpaceInfoSchema),\n /** GPU info (null if unavailable). */\n getGpuInfo: method(z.void(), MetricsGpuInfoSchema.nullable()),\n /** CPU temperature in °C (null if unavailable). */\n getCpuTemperature: method(z.void(), z.number().nullable()),\n /** Per-PID resource stats. Missing/dead PIDs are omitted from the result. */\n getProcessStats: method(\n z.object({ pids: z.array(z.number()) }),\n z.array(PidResourceStatsSchema),\n ),\n /**\n * List addon instances known to this node — one entry per forked worker\n * plus a synthetic 'hub' entry representing the local hub process.\n * Used by benchmarks/observability to detect whether a given addon runs\n * in its own process (measurable independently) or inline with the hub.\n */\n listAddonInstances: method(z.void(), z.array(AddonInstanceSchema).readonly()),\n /**\n * Resource stats for the process hosting the given addon.\n * Returns null when the addon runs in-process on the hub (can't measure\n * independently — caller should detect via listAddonInstances). Returns\n * hub process stats for addonId '$hub'.\n */\n getAddonStats: method(z.object({ addonId: z.string() }), PidResourceStatsSchema.nullable()),\n /**\n * Snapshot of every camstack-related process on this node with a\n * ghost/managed/root classification. Powers the Cluster → Agent →\n * Processes tab: cross-references `$process.list` against a `ps` scan\n * so orphaned trees (PPID=1) or unknown children show up as `ghost`\n * and can be killed from the UI.\n */\n listNodeProcesses: method(z.void(), z.array(NodeProcessSchema).readonly()),\n /**\n * Send SIGTERM (or SIGKILL when `force`) to a pid inside this node's\n * process tree. The provider refuses pids that aren't in the live\n * `listNodeProcesses()` snapshot — callers can't use this endpoint\n * to kill arbitrary system processes.\n */\n killProcess: method(\n KillProcessInputSchema,\n KillProcessResultSchema,\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IMetricsProvider = InferProvider<typeof metricsProviderCapability>\n\nexport {\n SystemMetricsSchema,\n SystemResourceSnapshotSchema,\n DiskSpaceInfoSchema,\n MetricsGpuInfoSchema,\n PidResourceStatsSchema,\n AddonInstanceSchema,\n NodeProcessSchema,\n KillProcessInputSchema,\n KillProcessResultSchema,\n CpuBreakdownSchema,\n MemoryInfoSchema,\n DiskIoSnapshotSchema,\n NetworkIoSnapshotSchema,\n ProcessResourceInfoSchema,\n PressureInfoSchema,\n}\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\nconst PtzPresetSchema = z.object({ id: z.string(), name: z.string() })\nconst PtzPositionSchema = z.object({ pan: z.number(), tilt: z.number(), zoom: z.number() })\nconst PtzMoveCommandSchema = z.object({\n pan: z.number().optional(),\n tilt: z.number().optional(),\n zoom: z.number().optional(),\n speed: z.number().optional(),\n})\n\nexport const ptzCapability = {\n name: 'ptz',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n methods: {\n move: method(\n PtzMoveCommandSchema.extend({ deviceId: z.number() }),\n z.void(),\n { kind: 'mutation' },\n ),\n continuousMove: method(\n PtzMoveCommandSchema.extend({ deviceId: z.number() }),\n z.void(),\n { kind: 'mutation' },\n ),\n stop: method(\n z.object({ deviceId: z.number() }),\n z.void(),\n { kind: 'mutation' },\n ),\n getPresets: method(\n z.object({ deviceId: z.number() }),\n z.array(PtzPresetSchema),\n ),\n goToPreset: method(\n z.object({ deviceId: z.number(), presetId: z.string() }),\n z.void(),\n { kind: 'mutation' },\n ),\n goHome: method(\n z.object({ deviceId: z.number() }),\n z.void(),\n { kind: 'mutation' },\n ),\n /**\n * Pull the current PTZ position. Redundant with the auto-injected\n * `getStatus` method (see `status` below); kept for callers that\n * haven't migrated. Will be folded into `getStatus` in a future\n * cleanup pass once all consumers use the typed status surface.\n */\n getPosition: method(\n z.object({ deviceId: z.number() }),\n PtzPositionSchema,\n ),\n },\n status: {\n schema: PtzPositionSchema,\n kind: 'command-driven',\n },\n} as const satisfies CapabilityDefinition\n\nexport type IPtzProvider = InferProvider<typeof ptzCapability>\nexport { PtzPresetSchema, PtzPositionSchema, PtzMoveCommandSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\nconst EventItemSchema = z.object({\n id: z.string(),\n type: z.string(),\n timestamp: z.number(), // unix ms\n label: z.string().optional(),\n thumbnailUrl: z.string().optional(),\n clipUrl: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const eventsCapability = {\n name: 'events',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n methods: {\n getEvents: method(\n z.object({\n deviceId: z.number(),\n from: z.number().optional(),\n to: z.number().optional(),\n limit: z.number().optional(),\n }),\n z.array(EventItemSchema),\n ),\n getEventThumbnail: method(\n z.object({ deviceId: z.number(), eventId: z.string() }),\n z.object({ base64: z.string(), contentType: z.string() }).nullable(),\n ),\n getEventClipUrl: method(\n z.object({ deviceId: z.number(), eventId: z.string() }),\n z.string().nullable(),\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IEventsProvider = InferProvider<typeof eventsCapability>\nexport { EventItemSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\nconst SegmentSchema = z.object({\n id: z.string(),\n startTs: z.number(), // unix ms\n endTs: z.number(),\n durationSec: z.number(),\n sizeBytes: z.number().optional(),\n})\n\nexport const recordingCapability = {\n name: 'recording',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n methods: {\n getSegments: method(\n z.object({\n deviceId: z.number(),\n from: z.number().optional(),\n to: z.number().optional(),\n }),\n z.array(SegmentSchema),\n ),\n getPlaybackUrl: method(\n z.object({ deviceId: z.number(), segmentId: z.string() }),\n z.string().nullable(),\n ),\n getThumbnailAt: method(\n z.object({ deviceId: z.number(), timestamp: z.number() }),\n z.object({ base64: z.string(), contentType: z.string() }).nullable(),\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IRecordingProvider = InferProvider<typeof recordingCapability>\nexport { SegmentSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n/**\n * device-ops — device-scoped cap that unifies the per-IDevice operations\n * previously routed through the `.device-ops` Moleculer bridge service.\n *\n * Each worker that hosts live `IDevice` instances auto-registers a native\n * provider for this cap (per device) backed by its local\n * `DeviceRegistry`. Hub-side callers reach it transparently through\n * `ctx.fetchDevice(id).deviceOps.*` — the DeviceProxy injects\n * `deviceId` + `nodeId` and dispatches through the standard cap-router,\n * so there's no parallel bridge path anymore.\n *\n * The surface is intentionally small — every method corresponds to a\n * single action on the live `IDevice` (or `ICameraDevice` for\n * `getStreamSources`). Richer orchestration (enable/disable with\n * integration plumbing, bulk updates) stays in the `device-manager` cap;\n * `device-ops` is the per-device primitive the device-manager routes to.\n */\nconst StreamSourceEntrySchema = z.object({\n id: z.string(),\n label: z.string(),\n protocol: z.enum(['rtsp', 'rtmp', 'annexb', 'http-mjpeg', 'webrtc', 'custom']),\n url: z.string().optional(),\n resolution: z.object({ width: z.number(), height: z.number() }).optional(),\n fps: z.number().optional(),\n bitrate: z.number().optional(),\n codec: z.string().optional(),\n profileHint: z.enum(['high', 'mid', 'low']).optional(),\n sdp: z.string().optional(),\n})\n\nconst ConfigEntrySchema = z.object({\n key: z.string(),\n value: z.unknown(),\n})\n\nexport const deviceOpsCapability = {\n name: 'device-ops',\n scope: 'device',\n mode: 'singleton',\n methods: {\n /**\n * Return stream sources for camera-like devices. Non-camera devices\n * return an empty array (the bridge did the same; preserved for compat).\n */\n getStreamSources: method(\n z.object({ deviceId: z.number() }),\n z.array(StreamSourceEntrySchema),\n ),\n\n /**\n * Return the device's config entries (key + current value). Used by\n * the device-manager aggregator when reading the driver's schema+values.\n */\n getConfigEntries: method(\n z.object({ deviceId: z.number() }),\n z.array(ConfigEntrySchema),\n ),\n\n /**\n * Bulk-apply a config patch via `IDevice.config.setAll`. Covers the\n * updateConfig / setStreamProfileMap / enable-as-config paths from\n * the old bridge.\n */\n setConfig: method(\n z.object({\n deviceId: z.number(),\n values: z.record(z.string(), z.unknown()),\n }),\n z.void(),\n { kind: 'mutation' },\n ),\n\n /**\n * Invoke `IDevice.removeDevice()` so the driver can release resources\n * (close sockets, stop background tasks, …). The device-manager still\n * performs its own persistence cleanup before/after this call.\n */\n removeDevice: method(\n z.object({ deviceId: z.number() }),\n z.void(),\n { kind: 'mutation' },\n ),\n\n /**\n * Build the ConfigUISchema (FormBuilder input shape) from the device's\n * Zod config schema. Runs on the worker that owns the IDevice so the\n * Zod types stay local (they're function references, not\n * serializable). Returns a fully JSON-serializable schema with\n * sections/fields the admin UI renders directly.\n *\n * Needed because the hub-side `device-manager.getSettingsSchema`\n * couldn't reach forked-worker devices — it had no registry entry\n * and no cross-process lookup, so the UI silently rendered an empty\n * settings panel for every worker-owned device.\n *\n * Returns `null` when the device isn't found on this worker.\n */\n getSettingsSchema: method(\n z.object({ deviceId: z.number() }),\n z.unknown().nullable(),\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IDeviceOpsProvider = InferProvider<typeof deviceOpsCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * camera-credentials — device-scoped cap exposing the camera's network\n * + auth surface in a vendor-neutral shape.\n *\n * Why it exists: cross-vendor wrappers (the planned ONVIF generic addon\n * for PTZ / intercom / events; future homekit / mqtt bridges) need the\n * camera's IP + port + creds without each wrapper re-implementing\n * vendor-specific config-blob extraction. With this cap, every camera\n * provider returns a uniform CameraCredentials and consumers stay\n * vendor-agnostic.\n *\n * Implementations:\n * - Each camera-providing addon registers this cap natively per\n * device (Reolink, Hikvision, RTSP, Frigate, ONVIF self).\n * - Returns a snapshot from the persisted device config blob — no\n * extra round-trip to the camera, no probing.\n * - The cap is admin-only (`auth: 'admin'`) — credentials must not\n * leak through user-scoped paths.\n *\n * Sensitive data handling:\n * - getCredentials returns the full snapshot to admin callers only.\n * - Wrappers are expected to use the value to construct a per-call\n * client and NOT to log / event-bus-emit the password field.\n * - The cap status payload (mirrored to runtime-state) carries\n * non-sensitive metadata only — host + ports + protocol hints. The\n * password / username live on `getCredentials` exclusively.\n *\n * See `docs/onvif-generic-addon-plan.md` for the consuming wrapper\n * design.\n */\n\nexport const CameraCredentialsSchema = z.object({\n /** Camera IP or hostname (no scheme). */\n host: z.string(),\n /** Primary protocol port (varies per vendor: Baichuan 9000, ISAPI 80/443, RTSP 554). */\n port: z.number().int().positive().optional(),\n /** ONVIF service port if known by the provider. */\n onvifPort: z.number().int().positive().optional(),\n /** RTSP service port if known. */\n rtspPort: z.number().int().positive().optional(),\n /** HTTP(S) flag for the primary protocol port. */\n https: z.boolean().optional(),\n /** Login username. */\n username: z.string().optional(),\n /** Login password. CONSUMERS MUST NOT log or event-bus this value. */\n password: z.string().optional(),\n /** ONVIF profile hint advertised by the camera (`T`, `Q`, `G`, `S`). */\n onvifProfile: z.string().optional(),\n})\n\nexport type CameraCredentials = z.infer<typeof CameraCredentialsSchema>\n\n/**\n * Non-sensitive camera-credentials status — host + ports + protocol\n * hints only. Mirrors what shows up in the bindings UI / device\n * aggregate. The full credentials (with password) are exposed only via\n * `getCredentials` to admin callers.\n */\nexport const CameraCredentialsStatusSchema = z.object({\n host: z.string(),\n port: z.number().int().positive().nullable(),\n onvifPort: z.number().int().positive().nullable(),\n rtspPort: z.number().int().positive().nullable(),\n https: z.boolean().nullable(),\n hasUsername: z.boolean(),\n hasPassword: z.boolean(),\n onvifProfile: z.string().nullable(),\n})\n\nexport type CameraCredentialsStatus = z.infer<typeof CameraCredentialsStatusSchema>\n\nexport const cameraCredentialsCapability = {\n name: 'camera-credentials',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n methods: {\n /**\n * Return the camera's full credential bundle for admin consumers.\n * Each provider implementation returns a snapshot of its persisted\n * config — no I/O to the camera. Returns null when the device is\n * not owned by this addon (deviceId mismatch).\n */\n getCredentials: method(\n z.object({ deviceId: z.number() }),\n CameraCredentialsSchema.nullable(),\n { kind: 'query', auth: 'admin' },\n ),\n },\n status: {\n schema: CameraCredentialsStatusSchema,\n kind: 'command-driven',\n },\n} as const satisfies CapabilityDefinition\n\nexport type ICameraCredentialsProvider = InferProvider<typeof cameraCredentialsCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * reboot — device-scoped capability for \"soft\" device reboots (firmware\n * reboot via vendor protocol; cameras, NVRs, doorbells). Surfaces a\n * single mutation so the UI can offer a confirm-and-reboot button for\n * any device whose driver advertises `DeviceFeature.Rebootable`.\n *\n * Implementation contract: the driver SHOULD return only after the\n * remote acknowledges the request (camera will go offline shortly\n * after). Wrappers in the addon should NOT block on the device coming\n * back online — operators read the device-online indicator for that.\n *\n * Errors propagate verbatim: a 401 from the camera surfaces as a tRPC\n * error to the UI, which renders it next to the button.\n */\nexport const rebootCapability = {\n name: 'reboot',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch],\n methods: {\n reboot: method(\n z.object({ deviceId: z.number().int().nonnegative() }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IRebootProvider = InferProvider<typeof rebootCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * Generic on-screen-display (video overlay) cap. Each camera exposes\n * a firmware-defined list of overlays (channel name, timestamp,\n * watermark, logo, …); the cap models them as a homogeneous array of\n * descriptors so the admin UI can render them with zero per-firmware\n * code.\n */\n\nexport const OsdOverlayKindEnum = z.enum(['text', 'timestamp', 'watermark'])\nexport type OsdOverlayKind = z.infer<typeof OsdOverlayKindEnum>\n\nexport const OsdPositionEnum = z.enum([\n 'top-left', 'top-center', 'top-right',\n 'bottom-left', 'bottom-center', 'bottom-right',\n 'custom',\n])\nexport type OsdPosition = z.infer<typeof OsdPositionEnum>\n\nexport const OsdOverlaySchema = z.object({\n /** Stable driver-assigned id. Reolink uses `'channel'`, `'time'`, `'watermark'`. */\n id: z.string(),\n kind: OsdOverlayKindEnum,\n enabled: z.boolean(),\n /** Active text (text/watermark). Undefined for 'timestamp' (firmware-generated). */\n text: z.string().optional(),\n position: OsdPositionEnum.optional(),\n /**\n * Positions the firmware accepts for this specific overlay. Populated\n * by the driver at register time. Empty array → positioning not\n * configurable; the UI hides the position field.\n */\n availablePositions: z.array(OsdPositionEnum).readonly(),\n /** Firmware does not allow editing the `text` field (e.g. timestamp). */\n readOnly: z.boolean().optional(),\n})\n\nexport type OsdOverlay = z.infer<typeof OsdOverlaySchema>\n\nexport const OsdStatusSchema = z.object({\n overlays: z.array(OsdOverlaySchema).readonly(),\n})\n\nexport type OsdStatus = z.infer<typeof OsdStatusSchema>\n\nconst OsdOverlayPatchSchema = z.object({\n enabled: z.boolean().optional(),\n text: z.string().optional(),\n position: OsdPositionEnum.optional(),\n}).partial()\n\nexport const osdCapability = {\n name: 'osd',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n methods: {\n /**\n * Patch a single overlay by id. Provider handles read-modify-write\n * against firmware APIs that require the full object (Reolink\n * `SetOsd`). Omitted patch keys are preserved. Successful\n * completion triggers `onStatusChanged`.\n */\n setOverlay: method(\n z.object({\n deviceId: z.number(),\n overlayId: z.string(),\n patch: OsdOverlayPatchSchema,\n }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n events: {\n onStatusChanged: { data: z.object({\n deviceId: z.number(),\n status: OsdStatusSchema,\n })},\n },\n status: {\n schema: OsdStatusSchema,\n kind: 'command-driven',\n },\n settings: {\n bindings: [{\n kind: 'array',\n statusPath: 'overlays',\n idField: 'id',\n method: 'setOverlay',\n idArg: 'overlayId',\n patchArg: 'patch',\n sectionId: 'osd',\n sectionTitle: 'Video overlays',\n itemFields: {\n enabled: {\n label: (o) => `${String(o.id)} enabled`,\n kind: 'boolean',\n },\n text: {\n label: (o) => `${String(o.id)} text`,\n kind: 'text',\n when: (o) => o.kind !== 'timestamp' && !o.readOnly,\n },\n position: {\n label: (o) => `${String(o.id)} position`,\n kind: 'select',\n options: (o) => (o.availablePositions as readonly string[] | undefined) ?? [],\n when: (o) => Array.isArray(o.availablePositions) && o.availablePositions.length > 0,\n },\n },\n }],\n },\n} as const satisfies CapabilityDefinition\n\nexport type IOsdProvider = InferProvider<typeof osdCapability>\nexport { OsdOverlayPatchSchema }\n","import { z } from 'zod'\nimport { type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * List of accessory children linked to a parent device (camera, hub).\n * Returns only numeric device ids — the rest (role, deviceType, name,\n * caps) is derived by fetching each child via `device-manager.getDevice`.\n *\n * The single-source-of-truth for what an accessory IS remains the child\n * device itself; this cap only surfaces the grouping.\n */\nexport const AccessoriesStatusSchema = z.object({\n childDeviceIds: z.array(z.number()).readonly(),\n})\n\nexport type AccessoriesStatus = z.infer<typeof AccessoriesStatusSchema>\n\nexport const accessoriesCapability = {\n name: 'accessories',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera, DeviceType.Hub],\n methods: {},\n events: {\n /**\n * Emitted when a child device is created, removed, or its parent\n * assignment changes. Payload carries the fresh list.\n */\n onAccessoriesChanged: { data: z.object({\n deviceId: z.number(),\n childDeviceIds: z.array(z.number()).readonly(),\n })},\n },\n status: {\n schema: AccessoriesStatusSchema,\n kind: 'command-driven',\n },\n} as const satisfies CapabilityDefinition\n\nexport type IAccessoriesProvider = InferProvider<typeof accessoriesCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * Two-way audio / talk-back cap. Clients open a WebRTC audio-only\n * session (server-initiated offer pattern, identical to the main\n * video WebRTC flow) and the browser captures the mic; the server\n * receives Opus RTP via werift, decodes through ffmpeg, re-encodes\n * to the firmware's expected codec (Reolink: IMA ADPCM), and pipes\n * it onto the camera's dedicated talk channel.\n *\n * All audio transcoding happens server-side — clients don't need to\n * know the camera's wire format. The `ability` cached in `status`\n * exposes the firmware's codec/sampleRate only for display/debug;\n * the client never has to act on those values.\n */\nexport const IntercomAbilitySchema = z.object({\n /** Codecs accepted by firmware, in preference order. Driver-authored strings. */\n codecs: z.array(z.string()),\n /** Sample rate (Hz) the firmware expects. Reolink typical: 16000. */\n sampleRate: z.number(),\n duplex: z.enum(['half', 'full']),\n /** Max in-flight audio backlog before drop (ms). Server uses this to bound latency. */\n maxBacklogMs: z.number(),\n})\n\nexport type IntercomAbility = z.infer<typeof IntercomAbilitySchema>\n\nexport const IntercomStatusSchema = z.object({\n /** True while a talk session is open. */\n talking: z.boolean(),\n /** Ms epoch of the most recent session start. Null if never opened. */\n lastSessionAt: z.number().nullable(),\n /** Firmware ability cached at first session creation. Null until probed. */\n ability: IntercomAbilitySchema.nullable(),\n})\n\nexport type IntercomStatus = z.infer<typeof IntercomStatusSchema>\n\nexport const intercomCapability = {\n name: 'intercom',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n methods: {\n /**\n * Open a server-side WebRTC audio-only session. Returns an SDP\n * offer with a single sendonly audio m-line the client answers\n * (client → server direction). The server wakes battery cams\n * transparently before opening the upstream talk channel.\n */\n startSession: method(\n z.object({ deviceId: z.number() }),\n z.object({ sessionId: z.string(), sdpOffer: z.string() }),\n { kind: 'mutation', auth: 'admin' },\n ),\n handleAnswer: method(\n z.object({\n deviceId: z.number(),\n sessionId: z.string(),\n sdpAnswer: z.string(),\n }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n /** Close explicitly. Server also auto-closes on 30s idle. */\n stopSession: method(\n z.object({ deviceId: z.number(), sessionId: z.string() }),\n z.void(),\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n events: {\n onStatusChanged: { data: z.object({\n deviceId: z.number(),\n status: IntercomStatusSchema,\n })},\n },\n status: {\n schema: IntercomStatusSchema,\n kind: 'command-driven',\n },\n} as const satisfies CapabilityDefinition\n\nexport type IIntercomProvider = InferProvider<typeof intercomCapability>\n","import { z } from 'zod'\nimport { type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { DeviceType } from '../device/device-type.js'\n\n/**\n * On-camera AI object detection cap. Surfaces per-device the classes\n * the firmware can detect and the last-seen instance of each. The\n * provider also fan-outs these to the global `detection.camera-native`\n * event bus with `source: 'onboard'` so cross-cutting system services\n * (alert-center, advanced-notifier, recording-engine) can subscribe\n * once and receive events from every camera.\n *\n * Distinct from `motion-detection` (ML pipeline) and `motion` (hardware\n * PIR or firmware motion pulse): this cap is specifically the AI\n * classifier output coming FROM the camera, not the local pipeline.\n */\nexport const NativeObjectClassEnum = z.enum([\n 'person', 'vehicle', 'animal', 'face', 'package', 'other',\n])\n\nexport type NativeObjectClass = z.infer<typeof NativeObjectClassEnum>\n\nexport const NativeDetectionSchema = z.object({\n class: NativeObjectClassEnum,\n timestamp: z.number(),\n /** Firmware-provided confidence [0..1]. Reolink pushes don't carry it → undefined. */\n confidence: z.number().min(0).max(1).optional(),\n})\n\nexport type NativeDetection = z.infer<typeof NativeDetectionSchema>\n\nexport const NativeObjectDetectionStatusSchema = z.object({\n /**\n * Last observed instance per class. Undefined entries mean the class\n * is supported but nothing has been seen since the provider started.\n */\n lastByClass: z.record(NativeObjectClassEnum, NativeDetectionSchema.nullable()),\n /** Classes the firmware is capable of detecting — enumerated at device register. */\n supportedClasses: z.array(NativeObjectClassEnum).readonly(),\n})\n\nexport type NativeObjectDetectionStatus = z.infer<typeof NativeObjectDetectionStatusSchema>\n\nexport const nativeObjectDetectionCapability = {\n name: 'native-object-detection',\n scope: 'device',\n mode: 'singleton',\n deviceTypes: [DeviceType.Camera],\n methods: {},\n events: {\n onDetected: { data: z.object({\n deviceId: z.number(),\n detection: NativeDetectionSchema,\n })},\n },\n status: {\n schema: NativeObjectDetectionStatusSchema,\n kind: 'push',\n },\n} as const satisfies CapabilityDefinition\n\nexport type INativeObjectDetectionProvider = InferProvider<typeof nativeObjectDetectionCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\nimport { MODEL_FORMATS } from '../types/models.js'\n\nconst ModelFormatSchema = z.enum(MODEL_FORMATS)\n\nconst HwAccelBackendInputSchema = z.enum([\n 'videotoolbox', 'cuda', 'nvdec', 'vaapi', 'qsv',\n 'd3d11va', 'dxva2', 'amf', 'vdpau', 'drm',\n 'coreml', 'tensorrt', 'openvino', 'directml', 'webgpu',\n 'none',\n]).nullable().optional()\n\nconst HwAccelResolutionSchema = z.object({\n preferred: z.array(z.string()).readonly(),\n})\n\n/**\n * platform-probe — per-node singleton capability.\n *\n * Scope: each node (hub, agent, future workers) runs its own probe and\n * registers its own provider via this cap. Inference addons consume the\n * provider local to their node via `ctx.api.platformProbe.*`; the\n * localProviderLink routes the call to the co-located implementation.\n *\n * Implementation: `@camstack/addon-platform-probe-native` ships as a base\n * infra addon installed on every node (see `AddonInstaller.REQUIRED_PACKAGES`\n * and `AGENT_PACKAGES`). Replaces the former `PlatformScorer` that lived\n * in `@camstack/core` and was driven by the backend's AddonRegistry.\n */\n\nconst HardwarePlatformSchema = z.enum(['darwin', 'linux', 'win32'])\nconst HardwareArchSchema = z.enum(['arm64', 'x64'])\n\nconst GpuInfoSchema = z.object({\n type: z.enum(['nvidia', 'amd', 'intel', 'apple']),\n name: z.string(),\n memoryMB: z.number().optional(),\n})\n\nconst NpuInfoSchema = z.object({\n type: z.enum(['apple-ane', 'intel-npu']),\n})\n\nconst HardwareInfoSchema = z.object({\n platform: HardwarePlatformSchema,\n arch: HardwareArchSchema,\n cpuModel: z.string(),\n cpuCores: z.number(),\n totalRAM_MB: z.number(),\n availableRAM_MB: z.number(),\n gpu: GpuInfoSchema.nullable(),\n npu: NpuInfoSchema.nullable(),\n})\n\nconst PlatformScoreSchema = z.object({\n runtime: z.enum(['node', 'python']),\n backend: z.string(),\n format: z.enum(['onnx', 'coreml', 'openvino']),\n score: z.number(),\n reason: z.string(),\n available: z.boolean(),\n})\n\nconst PlatformCapabilitiesSchema = z.object({\n hardware: HardwareInfoSchema,\n scores: z.array(PlatformScoreSchema).readonly(),\n bestScore: PlatformScoreSchema,\n pythonPath: z.string().nullable(),\n})\n\nconst ModelRequirementSchema = z.object({\n modelId: z.string(),\n name: z.string(),\n minRAM_MB: z.number(),\n accuracyScore: z.number(),\n formats: z.array(z.string()).readonly(),\n})\n\nconst ResolvedInferenceConfigSchema = z.object({\n modelId: z.string(),\n runtime: z.enum(['node', 'python']),\n backend: z.string(),\n format: ModelFormatSchema,\n reason: z.string(),\n})\n\nexport const platformProbeCapability = {\n name: 'platform-probe',\n scope: 'system',\n mode: 'singleton',\n methods: {\n /** Return cached hardware + scored backends for this node. */\n getCapabilities: method(\n z.void(),\n PlatformCapabilitiesSchema,\n ),\n /** Convenience getter — hardware only. */\n getHardware: method(\n z.void(),\n HardwareInfoSchema,\n ),\n /**\n * Resolve the best (model, runtime, backend, format) for a given list\n * of requirements, using this node's scored backends as the candidate\n * pool. Always returns a config — falls back to CPU when no preferred\n * backend matches.\n */\n resolveInferenceConfig: method(\n z.object({\n requirements: z.array(ModelRequirementSchema).readonly(),\n }),\n ResolvedInferenceConfigSchema,\n ),\n /**\n * Resolve the ordered HW acceleration backend list for this node.\n * Pass `prefer` to hint a specific backend; pass `null` or omit\n * for auto-detection. Replaces the legacy `$hwaccel.resolve`\n * Moleculer action — cap routing handles per-node dispatch via\n * `nodeId`.\n */\n resolveHwAccel: method(\n z.object({\n prefer: HwAccelBackendInputSchema,\n nodeId: z.string().optional(),\n }),\n HwAccelResolutionSchema,\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IPlatformProbeProvider = InferProvider<typeof platformProbeCapability>\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\nconst UserRoleSchema = z.enum(['super_admin', 'admin', 'viewer', 'agent'])\n\nconst UserSummarySchema = z.object({\n id: z.string(),\n username: z.string(),\n role: UserRoleSchema,\n allowedProviders: z.union([z.array(z.string()), z.literal('*')]),\n allowedDevices: z.record(z.string(), z.union([z.array(z.string()), z.literal('*')])),\n createdAt: z.number(),\n updatedAt: z.number(),\n})\n\nconst CreateUserInputSchema = z.object({\n username: z.string(),\n password: z.string().min(6),\n role: UserRoleSchema,\n allowedProviders: z.union([z.array(z.string()), z.literal('*')]).optional(),\n allowedDevices: z.record(z.string(), z.union([z.array(z.string()), z.literal('*')])).optional(),\n})\n\nconst UpdateUserInputSchema = z.object({\n id: z.string(),\n role: UserRoleSchema.optional(),\n allowedProviders: z.union([z.array(z.string()), z.literal('*')]).optional(),\n allowedDevices: z.record(z.string(), z.union([z.array(z.string()), z.literal('*')])).optional(),\n})\n\nconst ApiKeySummarySchema = z.object({\n id: z.string(),\n label: z.string(),\n role: UserRoleSchema,\n allowedProviders: z.union([z.array(z.string()), z.literal('*')]).optional(),\n allowedDevices: z.record(z.string(), z.union([z.array(z.string()), z.literal('*')])).optional(),\n tokenPrefix: z.string(),\n createdAt: z.number(),\n lastUsedAt: z.number().optional(),\n})\n\nconst CreateApiKeyInputSchema = z.object({\n label: z.string(),\n role: UserRoleSchema,\n allowedProviders: z.union([z.array(z.string()), z.literal('*')]).optional(),\n allowedDevices: z.record(z.string(), z.union([z.array(z.string()), z.literal('*')])).optional(),\n})\n\nconst CreateApiKeyResultSchema = z.object({\n token: z.string(),\n record: ApiKeySummarySchema,\n})\n\nconst TokenScopeSchema = z.object({\n type: z.enum(['addon', 'route-prefix', 'capability']),\n target: z.string(),\n})\n\nconst ScopedTokenSummarySchema = z.object({\n id: z.string(),\n userId: z.string(),\n name: z.string(),\n tokenPrefix: z.string(),\n scopes: z.array(TokenScopeSchema),\n expiresAt: z.number().optional(),\n lastUsedAt: z.number().optional(),\n createdAt: z.number(),\n})\n\nconst CreateScopedTokenInputSchema = z.object({\n name: z.string(),\n scopes: z.array(TokenScopeSchema),\n expiresAt: z.number().optional(),\n})\n\nconst CreateScopedTokenResultSchema = z.object({\n token: z.string(),\n record: ScopedTokenSummarySchema,\n})\n\n/**\n * user-management — singleton capability for user accounts, API keys,\n * and scoped tokens.\n *\n * Implemented by the `local-auth` addon. Covers all CRUD operations\n * that were previously hand-written in `users.router.ts` and\n * `scoped-tokens.router.ts`.\n *\n * Login/logout/me stay in the server's core auth router because they\n * depend on JWT signing (a server-level concern, not an addon concern).\n *\n * Extension: the `auth-provider` capability (collection) provides\n * pluggable authentication mechanisms (local password, OIDC, etc.).\n * The server's login flow delegates to `auth-provider.validateCredentials()`\n * and then signs the JWT.\n */\nexport const userManagementCapability = {\n name: 'user-management',\n scope: 'system',\n mode: 'singleton',\n methods: {\n // ── Users ──────────────────────────────────────────────────────\n listUsers: method(z.void(), z.array(UserSummarySchema), { auth: 'admin' }),\n createUser: method(CreateUserInputSchema, UserSummarySchema, { kind: 'mutation', auth: 'superAdmin' }),\n updateUser: method(UpdateUserInputSchema, z.object({ success: z.literal(true) }), { kind: 'mutation', auth: 'superAdmin' }),\n deleteUser: method(z.object({ id: z.string() }), z.object({ success: z.literal(true) }), { kind: 'mutation', auth: 'superAdmin' }),\n resetPassword: method(\n z.object({ id: z.string(), newPassword: z.string().min(6) }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n validateCredentials: method(\n z.object({ username: z.string(), password: z.string() }),\n UserSummarySchema.extend({ passwordHash: z.string() }).nullable(),\n { kind: 'mutation' },\n ),\n\n // ── API Keys ──────────────────────────────────────────────────\n listApiKeys: method(z.void(), z.array(ApiKeySummarySchema), { auth: 'admin' }),\n createApiKey: method(CreateApiKeyInputSchema, CreateApiKeyResultSchema, { kind: 'mutation', auth: 'admin' }),\n revokeApiKey: method(z.object({ id: z.string() }), z.object({ success: z.literal(true) }), { kind: 'mutation', auth: 'admin' }),\n validateApiKey: method(z.object({ token: z.string() }), ApiKeySummarySchema.nullable(), { kind: 'mutation' }),\n\n // ── Scoped Tokens ─────────────────────────────────────────────\n createScopedToken: method(CreateScopedTokenInputSchema, CreateScopedTokenResultSchema, { kind: 'mutation', auth: 'admin' }),\n revokeScopedToken: method(z.object({ id: z.string() }), z.object({ success: z.literal(true) }), { kind: 'mutation', auth: 'admin' }),\n validateScopedToken: method(z.object({ token: z.string() }), ScopedTokenSummarySchema.nullable()),\n listScopedTokens: method(z.object({ userId: z.string() }), z.array(ScopedTokenSummarySchema), { auth: 'admin' }),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IUserManagementProvider = InferProvider<typeof userManagementCapability>\n\nexport {\n UserSummarySchema, CreateUserInputSchema, UpdateUserInputSchema,\n ApiKeySummarySchema, CreateApiKeyInputSchema, CreateApiKeyResultSchema,\n ScopedTokenSummarySchema, CreateScopedTokenInputSchema, CreateScopedTokenResultSchema,\n}\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n/**\n * system — system-scoped singleton capability exposing hub-level\n * health, feature flags, network interface enumeration, and the\n * analytics-suite retention controls.\n *\n * Implementation lives in the server's `FeatureService` plus the\n * `analysis-data-persistence` singleton (provided by\n * `addon-analytics-suite`). The provider is registered from\n * `trpc.router.ts` against the existing services — no addon owns\n * this surface end-to-end.\n *\n * Phase E of the API consolidation: previously a hand-written core\n * router. Cap conversion lets the canonical hooks\n * (`useSystemInfo`, `useSystemHealth`, `useSystemNetworkAddresses`,\n * `useSystemGetRetentionConfig`, `useSystemSetRetentionConfig`,\n * `useSystemForceRetentionCleanup`) flow through the same codegen\n * as every other cap.\n */\n\nconst FeatureManifestSchema = z.object({\n streaming: z.boolean(),\n notifications: z.boolean(),\n objectDetection: z.boolean(),\n remoteAccess: z.boolean(),\n agentCluster: z.boolean(),\n smartHome: z.boolean(),\n recordings: z.boolean(),\n backup: z.boolean(),\n repl: z.boolean(),\n})\n\nconst HealthStatusSchema = z.object({\n status: z.literal('ok'),\n uptime: z.number(),\n})\n\nconst NetworkAddressSchema = z.object({\n name: z.string(),\n address: z.string(),\n family: z.string(),\n internal: z.boolean(),\n})\n\nexport const systemCapability = {\n name: 'system',\n scope: 'system',\n mode: 'singleton',\n methods: {\n info: method(z.void(), FeatureManifestSchema),\n health: method(z.void(), HealthStatusSchema),\n featureFlags: method(z.void(), FeatureManifestSchema),\n networkAddresses: method(z.void(), z.array(NetworkAddressSchema).readonly()),\n // Retention config is opaque on the wire — the analytics-suite owns the\n // schema. `getRetentionConfig` returns null when the analytics addon\n // is not loaded; `setRetentionConfig` accepts a partial patch.\n getRetentionConfig: method(z.void(), z.unknown().nullable(), { auth: 'admin' }),\n setRetentionConfig: method(\n z.record(z.string(), z.unknown()),\n z.null(),\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n forceRetentionCleanup: method(z.void(), z.void(), { kind: 'mutation', auth: 'superAdmin' }),\n },\n} as const satisfies CapabilityDefinition\n\nexport type ISystemProvider = InferProvider<typeof systemCapability>\n\nexport {\n FeatureManifestSchema,\n HealthStatusSchema,\n NetworkAddressSchema,\n}\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n/**\n * network-quality — system-scoped singleton capability tracking RTT,\n * jitter, and observed/peak bandwidth per device + per client.\n *\n * Implementation lives in the server's `NetworkQualityService` (thin\n * wrapper over the shared `NetworkQualityTracker` from `@camstack/core`).\n * The provider is registered from `trpc.router.ts` against the existing\n * service instance — no addon owns this state.\n *\n * Phase E of the API consolidation: previously a hand-written core\n * router. Cap conversion lets the same codegen pipeline produce both\n * the tRPC router and the canonical UI hooks\n * (`useNetworkQualityGetDeviceStats`, …).\n */\n\nconst StreamNetworkStatsSchema = z.object({\n nominalBitrateKbps: z.number(),\n observedBitrateKbps: z.number(),\n peakBitrateKbps: z.number(),\n packetLossPercent: z.number(),\n lastUpdated: z.number(),\n})\n\nconst ClientNetworkStatsSchema = z.object({\n rttMs: z.number(),\n jitterMs: z.number(),\n estimatedBandwidthKbps: z.number(),\n lastUpdated: z.number(),\n})\n\nconst DeviceNetworkStatsSchema = z.object({\n deviceId: z.number(),\n streams: z.record(z.string(), StreamNetworkStatsSchema),\n client: ClientNetworkStatsSchema.optional(),\n})\n\nexport const networkQualityCapability = {\n name: 'network-quality',\n scope: 'system',\n mode: 'singleton',\n methods: {\n getDeviceStats: method(\n z.object({ deviceId: z.number() }),\n DeviceNetworkStatsSchema.nullable(),\n ),\n getAllStats: method(\n z.void(),\n z.array(DeviceNetworkStatsSchema).readonly(),\n ),\n reportClientStats: method(\n z.object({\n deviceId: z.number(),\n rttMs: z.number().min(0).max(60000),\n jitterMs: z.number().min(0).max(10000),\n estimatedBandwidthKbps: z.number().min(0).max(1000000),\n }),\n z.void(),\n { kind: 'mutation' },\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type INetworkQualityProvider = InferProvider<typeof networkQualityCapability>\n\nexport {\n StreamNetworkStatsSchema,\n ClientNetworkStatsSchema,\n DeviceNetworkStatsSchema,\n}\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n/**\n * toast — system-scoped singleton capability that streams toast\n * notifications from the hub to connected admin-UI clients.\n *\n * Single push subscription (`onToast`). The provider lives in the\n * server's `ToastService` (always available after boot) and is\n * registered from `trpc.router.ts` against that service. No addon\n * owns this state — toasts are server-broadcasted side-effects of\n * other admin actions.\n *\n * Phase E of the API consolidation: previously a hand-written core\n * router (re-introduced after a brief detour as a cap years ago).\n * Cap conversion unifies the codegen pipeline so admin-ui consumers\n * pick up the standard `useToastOnToast` hook through the same\n * generator that emits every other system-cap subscription wrapper.\n */\n\nconst ToastSchema = z.object({\n title: z.string(),\n message: z.string(),\n severity: z.enum(['info', 'warning', 'critical']),\n duration: z.number().optional(),\n action: z\n .object({\n label: z.string(),\n url: z.string(),\n })\n .optional(),\n})\n\nexport const toastCapability = {\n name: 'toast',\n scope: 'system',\n mode: 'singleton',\n methods: {\n onToast: method(z.void(), ToastSchema, { kind: 'subscription' }),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IToastProvider = InferProvider<typeof toastCapability>\n\nexport { ToastSchema }\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n/**\n * nodes — system-scoped singleton capability for cluster topology\n * queries and remote addon lifecycle operations.\n *\n * Implementation lives in the server's `AgentRegistryService`,\n * `MoleculerService`, and `AddonRegistryService`. The provider is\n * registered from `trpc.router.ts` against those services — no addon\n * owns the cluster topology view.\n *\n * Phase E of the API consolidation: previously a hand-written core\n * router. Cap conversion lets `useNodesTopology`, `useNodesRestartNode`,\n * etc. flow through the same codegen pipeline as every other cap.\n */\n\n// ── Topology ─────────────────────────────────────────────────────────\n\nconst TopologyServiceSchema = z.object({\n addonId: z.string(),\n capabilities: z.array(z.string()).readonly(),\n status: z.string(),\n})\n\nconst TopologyProcessSchema = z.object({\n pid: z.number(),\n name: z.string(),\n state: z.string(),\n cpuPercent: z.number(),\n memoryRss: z.number(),\n uptimeSeconds: z.number(),\n services: z.array(TopologyServiceSchema).readonly(),\n groupId: z.string().optional(),\n})\n\nconst TopologyNodeSchema = z.object({\n id: z.string(),\n name: z.string(),\n hostname: z.string(),\n platform: z.string(),\n arch: z.string(),\n cpuModel: z.string().nullable(),\n cpuCores: z.number(),\n memoryMB: z.number(),\n engines: z.array(z.string()).readonly(),\n isHub: z.boolean(),\n isOnline: z.boolean(),\n cpuPercent: z.number(),\n memoryPercent: z.number(),\n uptime: z.number(),\n lastSeen: z.string(),\n localIps: z.array(z.string()).readonly(),\n addons: z.array(\n z.object({\n id: z.string(),\n capabilities: z.array(z.string()).readonly(),\n status: z.string(),\n }),\n ).readonly(),\n processes: z.array(TopologyProcessSchema).readonly(),\n})\n\n// ── Cluster addon-status ────────────────────────────────────────────\n\nconst ClusterAddonNodeDeploymentSchema = z.object({\n nodeId: z.string(),\n name: z.string(),\n version: z.string(),\n status: z.string(),\n synced: z.boolean(),\n})\n\nconst ClusterAddonStatusEntrySchema = z.object({\n hubVersion: z.string(),\n nodes: z.array(ClusterAddonNodeDeploymentSchema),\n})\n\n// ── Method input/output shapes ──────────────────────────────────────\n\nconst NodeAddonInputSchema = z.object({\n nodeId: z.string(),\n addonId: z.string(),\n})\n\nconst SuccessSchema = z.object({ success: z.boolean() })\n\nconst RestartProcessResultSchema = z.object({\n success: z.boolean(),\n reason: z.string().optional(),\n})\n\nconst RestartNodeResultSchema = z.object({\n restarted: z.array(z.string()).readonly(),\n failed: z.array(z.string()).readonly(),\n})\n\nconst RenameNodeResultSchema = z.object({\n nodeId: z.string(),\n name: z.string(),\n})\n\nexport const nodesCapability = {\n name: 'nodes',\n scope: 'system',\n mode: 'singleton',\n methods: {\n topology: method(\n z.void(),\n z.array(TopologyNodeSchema).readonly(),\n { auth: 'admin' },\n ),\n deployAddon: method(NodeAddonInputSchema, SuccessSchema, {\n kind: 'mutation',\n auth: 'superAdmin',\n }),\n undeployAddon: method(NodeAddonInputSchema, SuccessSchema, {\n kind: 'mutation',\n auth: 'superAdmin',\n }),\n restartAddon: method(NodeAddonInputSchema, SuccessSchema, {\n kind: 'mutation',\n auth: 'superAdmin',\n }),\n restartProcess: method(\n z.object({ nodeId: z.string(), processName: z.string() }),\n RestartProcessResultSchema,\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n restartNode: method(\n z.object({ nodeId: z.string() }),\n RestartNodeResultSchema,\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n shutdownNode: method(\n z.object({ nodeId: z.string() }),\n SuccessSchema,\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n renameNode: method(\n z.object({ nodeId: z.string(), name: z.string().min(1).max(64) }),\n RenameNodeResultSchema,\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n clusterAddonStatus: method(\n z.void(),\n z.record(z.string(), ClusterAddonStatusEntrySchema),\n { auth: 'superAdmin' },\n ),\n setProcessLogLevel: method(\n z.object({ nodeId: z.string(), level: z.string() }),\n SuccessSchema,\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n executeQuery: method(\n z.object({\n nodeId: z.string(),\n addonId: z.string(),\n queryName: z.string(),\n params: z.record(z.string(), z.unknown()).optional(),\n }),\n z.unknown(),\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type INodesProvider = InferProvider<typeof nodesCapability>\n\nexport {\n TopologyNodeSchema,\n TopologyProcessSchema,\n TopologyServiceSchema,\n ClusterAddonStatusEntrySchema,\n ClusterAddonNodeDeploymentSchema,\n}\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n/**\n * integrations — system-scoped singleton capability for integration\n * (provider-instance) lifecycle. Integrations are typically per-addon\n * data records that pin a device-provider addon to a concrete config\n * (Reolink credentials, ONVIF endpoint, etc.).\n *\n * Implementation lives in the server's `AddonRegistryService`\n * (specifically `getIntegrationRegistry()`). The provider is registered\n * from `trpc.router.ts` against that service plus the event bus and\n * logger — no addon owns this end-to-end.\n *\n * Phase E of the API consolidation: previously a hand-written core\n * router. Cap conversion lets `useIntegrationsList`,\n * `useIntegrationsCreate`, `useIntegrationsTestConnection` and\n * friends flow through the same codegen pipeline as every other cap.\n */\n\n// ── Schemas ─────────────────────────────────────────────────────────\n\nconst IntegrationWithStateSchema = z.object({\n id: z.string(),\n addonId: z.string(),\n name: z.string(),\n enabled: z.boolean(),\n info: z.record(z.string(), z.unknown()).readonly(),\n createdAt: z.number(),\n updatedAt: z.number(),\n processState: z.string(),\n})\n\nconst IntegrationLiteSchema = z.object({\n id: z.string(),\n addonId: z.string(),\n name: z.string(),\n enabled: z.boolean(),\n info: z.record(z.string(), z.unknown()).readonly(),\n createdAt: z.number(),\n updatedAt: z.number(),\n})\n\nconst AvailableIntegrationTypeSchema = z.object({\n addonId: z.string(),\n name: z.string(),\n description: z.string(),\n iconUrl: z.string().nullable(),\n color: z.string(),\n instanceMode: z.string(),\n discoveryMode: z.string(),\n existingInstances: z.array(z.object({ id: z.string(), name: z.string() })),\n canAdd: z.boolean(),\n})\n\nconst TestConnectionResultSchema = z.object({\n success: z.boolean(),\n error: z.string().optional(),\n})\n\n// ── Method I/O ──────────────────────────────────────────────────────\n\nconst CreateIntegrationInputSchema = z.object({\n addonId: z.string(),\n name: z.string(),\n enabled: z.boolean().optional(),\n info: z.record(z.string(), z.unknown()).optional(),\n settings: z.record(z.string(), z.unknown()).optional(),\n skipRestart: z.boolean().optional(),\n})\n\nconst UpdateIntegrationInputSchema = z.object({\n id: z.string(),\n name: z.string().optional(),\n enabled: z.boolean().optional(),\n info: z.record(z.string(), z.unknown()).optional(),\n})\n\nconst DeleteIntegrationResultSchema = z.object({\n success: z.boolean(),\n deletedId: z.string(),\n})\n\nexport const integrationsCapability = {\n name: 'integrations',\n scope: 'system',\n mode: 'singleton',\n methods: {\n list: method(z.void(), z.array(IntegrationWithStateSchema)),\n get: method(z.object({ id: z.string() }), IntegrationWithStateSchema),\n getByAddonId: method(\n z.object({ addonId: z.string() }),\n IntegrationLiteSchema.nullable(),\n ),\n create: method(\n CreateIntegrationInputSchema,\n IntegrationLiteSchema,\n { kind: 'mutation', auth: 'admin' },\n ),\n update: method(\n UpdateIntegrationInputSchema,\n IntegrationLiteSchema,\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n delete: method(\n z.object({ id: z.string() }),\n DeleteIntegrationResultSchema,\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n getSettings: method(\n z.object({ id: z.string() }),\n z.record(z.string(), z.unknown()),\n { auth: 'admin' },\n ),\n setSettings: method(\n z.object({\n id: z.string(),\n settings: z.record(z.string(), z.unknown()),\n }),\n z.object({ success: z.boolean() }),\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n getAvailableTypes: method(\n z.void(),\n z.array(AvailableIntegrationTypeSchema),\n { auth: 'admin' },\n ),\n testConnection: method(\n z.object({\n addonId: z.string(),\n settings: z.record(z.string(), z.unknown()),\n }),\n TestConnectionResultSchema,\n { kind: 'mutation', auth: 'admin' },\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IIntegrationsProvider = InferProvider<typeof integrationsCapability>\n\nexport {\n IntegrationWithStateSchema,\n IntegrationLiteSchema,\n AvailableIntegrationTypeSchema,\n TestConnectionResultSchema,\n CreateIntegrationInputSchema,\n UpdateIntegrationInputSchema,\n DeleteIntegrationResultSchema,\n}\n","import { z } from 'zod'\nimport { method, type CapabilityDefinition, type InferProvider } from './capability-definition.js'\n\n/**\n * addons — system-scoped singleton capability for addon package\n * management (install, update, configure, restart) and per-addon log\n * streaming.\n *\n * Implementation lives in the server's `AddonRegistryService`,\n * `AddonPackageService`, and `LoggingService`. The provider is\n * registered from `trpc.router.ts` against those services — no addon\n * owns this surface end-to-end (it manages addons themselves).\n *\n * Phase E of the API consolidation: previously a hand-written core\n * router. Cap conversion lets `useAddonsList`, `useAddonsInstallPackage`,\n * `useAddonsOnAddonLogs`, etc. flow through the same codegen pipeline\n * as every other cap.\n */\n\n// ── Loose-shape Zod helpers ─────────────────────────────────────────\n//\n// The `addons` surface ships rich runtime objects (manifests, addon\n// declarations, package metadata) whose precise shapes already live in\n// `@camstack/types/interfaces`. We deliberately keep the cap schemas\n// loose — `z.record(z.string(), z.unknown())` plus a few well-known\n// fields — so admin-ui consumers can keep using the existing\n// `AddonListItem` interface via cast, and so we don't risk inflating\n// the inferred AppRouter type past the TypeScript inference budget.\n\nconst LogLevelSchema = z.enum(['debug', 'info', 'warn', 'error'])\nconst ChannelSchema = z.enum(['off', 'latest', 'beta'])\nconst ChannelWithInheritSchema = z.enum(['off', 'latest', 'beta', 'inherit'])\n\n// Mirrors `AddonListItem` from interfaces/api-responses.ts. Schema is\n// intentionally loose — `z.unknown()` slots accept any runtime shape so\n// admin-ui can keep using the `AddonListItem` interface via cast.\nconst ManifestShapeSchema = z.object({\n id: z.string(),\n name: z.string().optional(),\n version: z.string().optional(),\n description: z.string().optional(),\n icon: z.string().optional(),\n color: z.string().optional(),\n // Loose schema for `manifest.capabilities` — runtime entries are\n // either kebab-case strings (legacy form) or `CapabilityDeclaration`\n // objects. The cap output schema deliberately keeps it as\n // `readonly unknown[]` so admin-ui consumers cast to the canonical\n // `AddonListItem` (from `@camstack/types`) before reading fields.\n capabilities: z.array(z.unknown()).readonly().optional(),\n packageName: z.string(),\n packageVersion: z.string(),\n packageDisplayName: z.string().optional(),\n protected: z.boolean().optional(),\n removable: z.boolean().optional(),\n})\n\nconst AddonProcessSchema = z.object({\n pid: z.number().optional(),\n mode: z.string(),\n state: z.string(),\n})\n\nconst AddonListItemSchema = z.object({\n manifest: ManifestShapeSchema,\n declaration: z.unknown().optional(),\n source: z.string(),\n installSource: z.string().optional(),\n process: AddonProcessSchema.optional(),\n})\n\nconst InstalledPackageSchema = z.object({\n name: z.string(),\n version: z.string(),\n dir: z.string(),\n installSource: z.string().optional(),\n})\n\nconst PackageUpdateSchema = z.object({\n name: z.string(),\n currentVersion: z.string(),\n latestVersion: z.string(),\n category: z.enum(['addon', 'core']),\n requiresRestart: z.boolean(),\n})\n\nconst PackageVersionInfoSchema = z.object({\n version: z.string(),\n publishedAt: z.string(),\n deprecated: z.string().optional(),\n distTags: z.array(z.string()).readonly(),\n})\n\nconst SearchResultSchema = z.object({\n name: z.string(),\n version: z.string(),\n description: z.string(),\n keywords: z.array(z.string()).readonly(),\n publishedAt: z.string(),\n author: z.string(),\n installed: z.boolean(),\n installedVersion: z.string().optional(),\n})\n\nconst AutoUpdateSettingsSchema = z.object({\n channel: ChannelSchema,\n intervalSeconds: z.number(),\n})\n\nconst AddonAutoUpdateSchema = ChannelWithInheritSchema\n\nconst RestartAddonResultSchema = z.unknown()\n\nconst InstallPackageResultSchema = z.unknown()\nconst ReloadPackagesResultSchema = z.unknown()\n\n// LogStream entry — mirrors LoggingService output.\nconst LogStreamEntrySchema = z.object({\n timestamp: z.string(),\n level: z.string(),\n message: z.string(),\n scope: z.string().optional(),\n})\n\n// Generic log query result — admin-ui treats it as the same schema.\nconst LogQueryEntrySchema = z.unknown()\n\n// Custom action dispatcher — pass-through. Used by `bindAddonActions`\n// helper which downcasts to `(input: unknown) => Promise<unknown>` and\n// stamps the per-action types on its own.\nconst CustomActionInputSchema = z.object({\n addonId: z.string().min(1),\n action: z.string().min(1),\n input: z.unknown(),\n})\n\nexport const addonsCapability = {\n name: 'addons',\n scope: 'system',\n mode: 'singleton',\n methods: {\n // ── Listing ──────────────────────────────────────────────────────\n list: method(z.void(), z.array(AddonListItemSchema).readonly()),\n\n // ── Logs (query) ────────────────────────────────────────────────\n getLogs: method(\n z.object({\n addonId: z.string(),\n limit: z.number().min(1).max(500).default(100),\n level: LogLevelSchema.optional(),\n }),\n z.array(LogQueryEntrySchema),\n { auth: 'admin' },\n ),\n\n // ── Packages ────────────────────────────────────────────────────\n listPackages: method(z.void(), z.array(InstalledPackageSchema).readonly()),\n installPackage: method(\n z.object({ packageName: z.string(), version: z.string().optional() }),\n InstallPackageResultSchema,\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n installFromWorkspace: method(\n z.object({ packageName: z.string() }),\n InstallPackageResultSchema,\n { kind: 'mutation', auth: 'admin' },\n ),\n isWorkspaceAvailable: method(z.void(), z.boolean()),\n listWorkspacePackages: method(z.void(), z.array(z.unknown()).readonly()),\n uninstallPackage: method(\n z.object({ packageName: z.string() }),\n z.unknown(),\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n reloadPackages: method(z.void(), ReloadPackagesResultSchema, {\n kind: 'mutation', auth: 'admin',\n }),\n // Note: original router declared `searchAvailable` input as optional\n // outer object. The cap codegen requires a stable input shape — we\n // make `query` optional inside a required object to preserve client\n // call shape (`{ query?: string }`).\n searchAvailable: method(\n z.object({ query: z.string().optional() }),\n z.array(SearchResultSchema),\n ),\n listUpdates: method(\n z.void(),\n z.array(PackageUpdateSchema).readonly(),\n { auth: 'admin' },\n ),\n updatePackage: method(\n z.object({ name: z.string().min(1), version: z.string().optional() }),\n z.unknown(),\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n forceRefresh: method(z.void(), z.unknown(), { kind: 'mutation', auth: 'admin' }),\n restartServer: method(\n z.object({ confirm: z.literal(true) }),\n z.unknown(),\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n getVersions: method(\n z.object({ name: z.string() }),\n z.array(PackageVersionInfoSchema).readonly(),\n ),\n restartAddon: method(\n z.object({ addonId: z.string() }),\n RestartAddonResultSchema,\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n\n // ── Auto-update ─────────────────────────────────────────────────\n getAutoUpdateSettings: method(\n z.void(),\n AutoUpdateSettingsSchema,\n { auth: 'admin' },\n ),\n setAutoUpdateSettings: method(\n z.object({\n channel: ChannelSchema,\n intervalSeconds: z.number().min(300).max(86400).optional(),\n }),\n z.unknown(),\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n getAddonAutoUpdate: method(\n z.object({ addonId: z.string() }),\n AddonAutoUpdateSchema,\n { auth: 'admin' },\n ),\n setAddonAutoUpdate: method(\n z.object({ addonId: z.string(), channel: ChannelWithInheritSchema }),\n z.unknown(),\n { kind: 'mutation', auth: 'admin' },\n ),\n applyAutoUpdateToAll: method(\n z.object({ channel: ChannelSchema }),\n z.object({ success: z.literal(true) }),\n { kind: 'mutation', auth: 'superAdmin' },\n ),\n\n // ── Custom action dispatcher ────────────────────────────────────\n // Generic dispatcher used by `bindAddonActions`. Per-action auth\n // is enforced inside the provider; the outer cap auth is\n // `protected` (any authenticated user) so individual addons can\n // gate their own actions to public/protected/admin/superAdmin.\n custom: method(CustomActionInputSchema, z.unknown(), { kind: 'mutation' }),\n\n // ── Log streaming ───────────────────────────────────────────────\n onAddonLogs: method(\n z.object({\n addonId: z.string(),\n level: LogLevelSchema.optional(),\n }),\n LogStreamEntrySchema,\n { kind: 'subscription' },\n ),\n },\n} as const satisfies CapabilityDefinition\n\nexport type IAddonsProvider = InferProvider<typeof addonsCapability>\n\nexport {\n AddonListItemSchema,\n InstalledPackageSchema,\n PackageUpdateSchema,\n PackageVersionInfoSchema,\n SearchResultSchema,\n AutoUpdateSettingsSchema,\n AddonAutoUpdateSchema,\n LogStreamEntrySchema,\n CustomActionInputSchema,\n LogLevelSchema,\n ChannelSchema,\n ChannelWithInheritSchema,\n}\n","/**\n * Capability definitions — Zod-schema-first, single source of truth.\n *\n * Each capability has its own .cap.ts file. Shared schemas live in schemas/.\n * TypeScript interfaces are inferred via z.infer<> — zero duplication.\n */\n\n// ── Pipeline capability roster ──────────────────────────────────────\n//\n// Canonical names of the capabilities considered \"pipeline-owning\":\n// anything under this list is an addon whose `getConfigSchema()` is\n// rendered on the Pipeline Defaults / per-device Detection tab, and\n// whose per-device settings changes trigger an `OrchestrationSettingsUpdated`\n// event so the orchestrator can restart detection.\n//\n// Consumers (backend + admin-ui) import this list instead of hardcoding\n// addon ids. Any new addon that declares one of these caps automatically\n// participates in the pipeline surface without code changes.\n\n/** Caps that show up in the canonical flow strip (decode → motion → detect → audio → analyze → notify). */\nexport const PIPELINE_FLOW_CAPABILITY_NAMES: readonly string[] = [\n 'decoder',\n 'motion-detection',\n 'pipeline-executor',\n 'audio-analyzer',\n 'pipeline-analytics',\n 'notification-output',\n]\n\n/**\n * Superset that also includes the control-plane capabilities (orchestrator\n * + runner). Used to enumerate addons whose settings belong to the pipeline\n * page — not just flow providers.\n */\nexport const PIPELINE_OWNER_CAPABILITY_NAMES: readonly string[] = [\n ...PIPELINE_FLOW_CAPABILITY_NAMES,\n 'pipeline-orchestrator',\n 'pipeline-runner',\n]\n\n// Core types\nexport type {\n CapabilityDefinition,\n CapabilityMethodSchema,\n CapabilityMethodKind,\n CapabilityMethodAuth,\n CapabilityMethodOptions,\n CapabilityEventSchema,\n InferProvider,\n InferNativeProvider,\n InferEvents,\n InferName,\n InferDeviceProxyCap,\n InferRuntimeState,\n DeviceSettingsContribution,\n} from './capability-definition.js'\nexport { method, event, expandCapMethods, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD } from './capability-definition.js'\n\nexport * from './custom-actions.js'\n\n// ── Shared Schemas ───────────────────────────────────────────────────\nexport {\n FrameInputSchema, BoundingBoxSchema, SpatialDetectionSchema,\n AudioChunkInputSchema, AudioLevelSchema, AudioClassificationLabelSchema,\n} from './schemas/detection-shared.js'\n\nexport {\n StreamSourceEntrySchema, StreamSourceSchema, EncodedPacketSchema, DecodedFrameSchema,\n BrokerStatusSchema, BrokerStatsSchema,\n CamProfileSchema, CAM_PROFILE_ORDER,\n CamStreamKindSchema, CamStreamResolutionSchema,\n CameraStreamSchema, ProfileSlotStatusSchema, ProfileSlotSchema,\n} from './schemas/streaming-shared.js'\nexport type {\n CamProfile, CamStreamKind, CameraStream, ProfileSlotStatus, ProfileSlot,\n} from './schemas/streaming-shared.js'\n\n// ── Addon Settings ──────────────────────────────────────────────────\nexport {\n addonSettingsCapability, type IAddonSettingsProvider,\n SettingsSchemaWithValuesSchema, ConfigSectionWithValuesSchema, ConfigTabDeclarationSchema,\n SettingsPatchSchema, SettingsUpdateResultSchema,\n} from './addon-settings.cap.js'\n\n// ── Alerts ──────────────────────────────────────────────────────────\nexport { alertsCapability, AlertSeveritySchema, AlertStatusSchema, AlertSourceSchema, AlertSchema } from './alerts.cap.js'\nexport type { AlertSeverity, AlertStatus, Alert } from './alerts.cap.js'\n\n// ── Infrastructure ───────────────────────────────────────────────────\nexport { storageCapability, StorageLocationTypeSchema, type IStorageCapProvider } from './storage.cap.js'\nexport { backupCapability, type IBackupProvider } from './backup.cap.js'\nexport {\n settingsStoreCapability, type ISettingsStoreProvider, type SettingsStoreClient,\n QueryFilterSchema, SettingsRecordSchema,\n CollectionColumnSchema, CollectionIndexSchema,\n type CollectionColumn, type CollectionIndex,\n} from './settings-store.cap.js'\nexport { logDestinationCapability, LogEntrySchema, LogLevelSchema } from './log-destination.cap.js'\nexport { adminUiCapability } from './admin-ui.cap.js'\nexport { addonPagesCapability, AddonPageInfoSchema } from './addon-pages.cap.js'\nexport type { IAddonPagesAggregatorProvider } from './addon-pages.cap.js'\nexport { addonPagesSourceCapability, AddonPageDeclarationSchema } from './addon-pages-source.cap.js'\nexport type { IAddonPagesSourceProvider } from './addon-pages-source.cap.js'\nexport { addonWidgetsCapability, EnrichedWidgetMetadataSchema } from './addon-widgets.cap.js'\nexport type { IAddonWidgetsAggregatorProvider } from './addon-widgets.cap.js'\nexport {\n addonWidgetsSourceCapability,\n WidgetMetadataSchema,\n WidgetHostEnum,\n WidgetSizeEnum,\n} from './addon-widgets-source.cap.js'\nexport type { IAddonWidgetsSourceProvider } from './addon-widgets-source.cap.js'\nexport { addonRoutesCapability } from './addon-routes.cap.js'\n\n// ── Streaming ────────────────────────────────────────────────────────\nexport {\n streamBrokerCapability,\n RtspRestreamEntrySchema,\n BrokerRtspClientSchema,\n BrokerDecodedClientSchema,\n BrokerAudioClientSchema,\n BrokerClientsSchema,\n PlaceholderReasonSchema,\n} from './stream-broker.cap.js'\nexport type {\n BrokerRtspClient,\n BrokerDecodedClient,\n BrokerAudioClient,\n BrokerClients,\n PlaceholderReason,\n} from './stream-broker.cap.js'\nexport {\n decoderCapability,\n DecoderSessionConfigSchema,\n HWACCEL_OPTIONS,\n DEFAULT_DECODER_HWACCEL_CONFIG,\n} from './decoder.cap.js'\nexport type {\n IDecoderCapProvider,\n HwAccelChoice,\n DecoderHwAccelConfig,\n} from './decoder.cap.js'\nexport { restreamerCapability, RegisteredStreamSchema, ExposedResourceSchema } from './restreamer.cap.js'\nexport { webrtcCapability, webrtcClientHintsSchema, type IWebrtcProvider, type WebrtcClientHints } from './webrtc.cap.js'\nexport { webrtcSessionCapability, type IWebrtcSessionProvider, type WebrtcStreamChoice, WebrtcStreamChoiceSchema, type WebrtcStreamTarget, WebrtcStreamTargetSchema } from './webrtc-session.cap.js'\nexport { cameraStreamsCapability, type ICameraStreamsProvider } from './camera-streams.cap.js'\nexport { streamingEngineCapability, StreamFormatSchema, StreamInfoSchema } from './streaming-engine.cap.js'\n\n// ── Detection ────────────────────────────────────────────────────────\nexport { motionDetectionCapability, MotionRegionSchema, MotionAnalysisResultSchema } from './motion-detection.cap.js'\nexport type { MotionRegion, MotionAnalysisResult, IMotionDetectionProvider } from './motion-detection.cap.js'\nexport {\n pipelineExecutorCapability,\n PipelineEngineChoiceSchema,\n PipelineDefaultStepSchema,\n DetectorOutputSchema,\n PipelineStepInputSchema,\n PipelineRunResultBridge,\n} from './pipeline-executor.cap.js'\nexport type { PipelineStepInputOutput } from './pipeline-executor.cap.js'\nexport { pipelineRunnerCapability, RunnerCameraConfigSchema, RunnerLocalLoadSchema, RunnerLocalMetricsSchema, MotionSourceEnum, MotionSourcesSchema, ReportMotionInputSchema, RunnerCameraDeviceUIFields } from './pipeline-runner.cap.js'\nexport type { MotionSource, MotionSources, ReportMotionInput } from './pipeline-runner.cap.js'\nexport { pipelineOrchestratorCapability, PipelineAssignmentSchema, DecoderAssignmentSchema, AgentLoadSummarySchema, GlobalMetricsSchema, CapabilityBindingsSchema } from './pipeline-orchestrator.cap.js'\nexport { OrchestratorMetricsSchema, CameraMetricsSchema, CameraMetricsWithDeviceIdSchema } from './schemas/orchestrator-metrics.js'\nexport {\n audioAnalyzerCapability,\n AUDIO_BACKEND_CHOICES,\n DEFAULT_AUDIO_ANALYZER_CONFIG,\n AudioAnalysisResultSchema,\n AudioAnalysisSettingsSchema,\n AudioClassificationResultSchema,\n} from './audio-analyzer.cap.js'\nexport type {\n IAudioAnalyzerProvider,\n AudioBackendChoice,\n AudioAnalyzerGlobalConfig,\n} from './audio-analyzer.cap.js'\nexport { audioAnalysisCapability, type IAudioAnalysisProvider } from './audio-analysis.cap.js'\nexport {\n audioCodecCapability,\n AudioCodecInfoSchema,\n AudioDecodeSessionConfigSchema,\n AudioEncodeSessionConfigSchema,\n AudioPcmChunkSchema,\n AudioEncodedChunkSchema,\n PcmSampleFormatSchema,\n type IAudioCodecCapProvider,\n} from './audio-codec.cap.js'\nexport { embeddingEncoderCapability, EmbeddingResultSchema, EmbeddingInfoSchema } from './embedding-encoder.cap.js'\n\n// ── Providers & Integrations ─────────────────────────────────────────\nexport { deviceProviderCapability, ProviderStatusSchema, DiscoveredDeviceSchema } from './device-provider.cap.js'\nexport {\n deviceManagerCapability,\n type IDeviceManagerProvider,\n DeviceInfoSchema,\n ConfigEntrySchema,\n} from './device-manager.cap.js'\nexport type { DeviceInfo } from './device-manager.cap.js'\nexport { deviceStateCapability } from './device-state.cap.js'\nexport { authProviderCapability, AuthResultSchema } from './auth-provider.cap.js'\nexport { networkAccessCapability, NetworkEndpointSchema, NetworkAccessStatusSchema } from './network-access.cap.js'\nexport { turnProviderCapability, TurnServerSchema } from './turn-provider.cap.js'\nexport type { ITurnProvider } from './turn-provider.cap.js'\nexport { snapshotCapability, type ISnapshotOrchestrator, SnapshotImageSchema } from './snapshot.cap.js'\nexport { snapshotProviderCapability, type ISnapshotProvider } from './snapshot-provider.cap.js'\nexport { notificationOutputCapability, NotificationSchema } from './notification-output.cap.js'\nexport { advancedNotifierCapability, NotificationRuleSchema, NotificationHistoryEntrySchema } from './advanced-notifier.cap.js'\nexport { recordingEngineCapability } from './recording-engine.cap.js'\nexport { detectionPipelineCapability, type IDetectionPipelineProvider } from './detection-pipeline.cap.js'\n// analysis-pipeline + analysis-data-persistence caps removed in P12b —\n// addon-pipeline-analytics owns post-detection refinement end-to-end\n// (Track + per-kind events + media) via its own single cap. See\n// pipeline-analytics.cap.ts. track-trail cap removed in P12a — trails\n// are `track.positions[]` on the Track schema.\nexport {\n pipelineAnalyticsCapability,\n type IPipelineAnalyticsProvider,\n type Track, type TrackState,\n type MotionEvent, type ObjectEvent, type AudioEvent,\n type MediaFile, type EventKind,\n TrackSchema, TrackStateSchema,\n MotionEventSchema, ObjectEventSchema, AudioEventSchema,\n MediaFileSchema, EventKindSchema, TrackedDetectionSchema,\n} from './pipeline-analytics.cap.js'\nexport { metricsProviderCapability, SystemMetricsSchema, type IMetricsProvider } from './metrics-provider.cap.js'\n// scene-intelligence cap removed in P12a — no provider was ever registered\n// and no admin UI/addon consumer. If scene queries come back, reintroduce\n// as part of the future embedding addon.\n\n\n// ── Device-Scoped Camera Caps ───────────────────────────────────────\nexport { ptzCapability, PtzPresetSchema, PtzPositionSchema, PtzMoveCommandSchema, type IPtzProvider } from './ptz.cap.js'\nexport {\n ptzAutotrackCapability,\n PtzAutotrackSettingsSchema,\n PtzAutotrackStatusSchema,\n PtzAutotrackTargetOptionSchema,\n PtzAutotrackRuntimeStateSchema,\n type PtzAutotrackSettings,\n type PtzAutotrackStatus,\n type PtzAutotrackTargetOption,\n type PtzAutotrackRuntimeState,\n type IPtzAutotrackProvider,\n} from './ptz-autotrack.cap.js'\nexport { eventsCapability, EventItemSchema, type IEventsProvider } from './events.cap.js'\nexport {\n zonesCapability,\n ZoneSchema,\n ZoneKindEnum,\n PolygonPointSchema,\n type Zone,\n type ZoneKind,\n type PolygonPoint,\n type IZonesProvider,\n} from './zones.cap.js'\nexport {\n ZoneRuleSchema,\n ZoneRuleModeEnum,\n ZoneRulesArraySchema,\n type ZoneRule,\n type ZoneRuleMode,\n type ZoneRules,\n} from './schemas/zone-rule.js'\nexport {\n zoneRulesCapability,\n ZoneRuleStageEnum,\n type ZoneRuleStage,\n type IZoneRulesProvider,\n} from './zone-rules.cap.js'\nexport {\n zoneAnalyticsCapability,\n HistoryResolutionEnum,\n HistoryPointSchema,\n ZoneScopeBreakdownSchema,\n PerScopeBreakdownSchema,\n type CameraOccupancySnapshot,\n type ZoneScopeBreakdown,\n type PerScopeBreakdown,\n type HistoryPoint,\n type HistoryResolution,\n type IZoneAnalyticsProvider,\n} from './zone-analytics.cap.js'\nexport {\n audioMetricsCapability,\n AudioMetricsSnapshotSchema,\n AudioClassSummarySchema,\n AudioMetricsHistoryPointSchema,\n AudioMetricsHistorySchema,\n type AudioMetricsSnapshot,\n type AudioClassSummary,\n type AudioMetricsHistoryPoint,\n type AudioMetricsHistory,\n type IAudioMetricsProvider,\n} from './audio-metrics.cap.js'\nexport { motionCapability, MotionStatusSchema, MotionOnMotionChangedDataSchema, type MotionStatus, type MotionOnMotionChangedData, type IMotionProvider } from './motion.cap.js'\nexport { recordingCapability, SegmentSchema, type IRecordingProvider } from './recording.cap.js'\nexport { deviceOpsCapability, type IDeviceOpsProvider } from './device-ops.cap.js'\nexport { batteryCapability, BatteryStatusSchema, type BatteryStatus, type IBatteryProvider } from './battery.cap.js'\nexport { deviceStatusCapability, DeviceStatusSchema, type DeviceStatus, type IDeviceStatusProvider } from './device-status.cap.js'\nexport { featureProbeCapability, FeatureProbeStatusSchema, type FeatureProbeStatus, type IFeatureProbeProvider } from './feature-probe.cap.js'\nexport { cameraCredentialsCapability, CameraCredentialsSchema, CameraCredentialsStatusSchema, type CameraCredentials, type CameraCredentialsStatus, type ICameraCredentialsProvider } from './camera-credentials.cap.js'\nexport { rebootCapability, type IRebootProvider } from './reboot.cap.js'\nexport {\n deviceDiscoveryCapability,\n DeviceDiscoveryStatusSchema,\n DiscoveredChildDeviceSchema,\n DiscoveredChildStatusSchema,\n type DeviceDiscoveryStatus,\n type DiscoveredChildDevice,\n type DiscoveredChildStatus,\n type IDeviceDiscoveryProvider,\n type IDeviceDiscoveryNativeProvider,\n} from './device-discovery.cap.js'\nexport { brightnessCapability, BrightnessStatusSchema, type BrightnessStatus, type IBrightnessProvider } from './brightness.cap.js'\nexport {\n motionTriggerCapability,\n MotionTriggerStatusSchema,\n MotionTriggerRuntimeStateSchema,\n type MotionTriggerStatus,\n type MotionTriggerRuntimeState,\n type IMotionTriggerProvider,\n} from './motion-trigger.cap.js'\nexport {\n osdCapability, OsdOverlaySchema, OsdOverlayKindEnum, OsdPositionEnum, OsdStatusSchema, OsdOverlayPatchSchema,\n type OsdOverlay, type OsdOverlayKind, type OsdPosition, type OsdStatus, type IOsdProvider,\n} from './osd.cap.js'\nexport { accessoriesCapability, AccessoriesStatusSchema, type AccessoriesStatus, type IAccessoriesProvider } from './accessories.cap.js'\nexport { switchCapability, SwitchStatusSchema, type SwitchStatus, type ISwitchProvider } from './switch.cap.js'\nexport {\n intercomCapability, IntercomAbilitySchema, IntercomStatusSchema,\n type IntercomAbility, type IntercomStatus, type IIntercomProvider,\n} from './intercom.cap.js'\nexport {\n doorbellCapability, DoorbellStatusSchema, DoorbellPressEventSchema,\n type DoorbellStatus, type DoorbellPressEvent, type IDoorbellProvider,\n} from './doorbell.cap.js'\nexport {\n nativeObjectDetectionCapability, NativeObjectClassEnum, NativeDetectionSchema, NativeObjectDetectionStatusSchema,\n type NativeObjectClass, type NativeDetection, type NativeObjectDetectionStatus, type INativeObjectDetectionProvider,\n} from './native-object-detection.cap.js'\n\n\n// ── Platform probe (per-node hardware + inference backend scoring) ─\nexport { platformProbeCapability, type IPlatformProbeProvider } from './platform-probe.cap.js'\n\n\n// ── User Management ─────────────────────────────────────────────────\nexport { userManagementCapability, type IUserManagementProvider } from './user-management.cap.js'\n\n// ── Core/Server Caps (Phase E — formerly hand-written core routers) ─\nexport {\n systemCapability, type ISystemProvider,\n FeatureManifestSchema, HealthStatusSchema, NetworkAddressSchema,\n} from './system.cap.js'\nexport {\n networkQualityCapability, type INetworkQualityProvider,\n StreamNetworkStatsSchema, ClientNetworkStatsSchema, DeviceNetworkStatsSchema,\n} from './network-quality.cap.js'\nexport { toastCapability, type IToastProvider, ToastSchema } from './toast.cap.js'\nexport {\n nodesCapability, type INodesProvider,\n TopologyNodeSchema, TopologyProcessSchema, TopologyServiceSchema,\n ClusterAddonStatusEntrySchema, ClusterAddonNodeDeploymentSchema,\n} from './nodes.cap.js'\nexport {\n integrationsCapability, type IIntegrationsProvider,\n IntegrationWithStateSchema, IntegrationLiteSchema,\n AvailableIntegrationTypeSchema, TestConnectionResultSchema,\n CreateIntegrationInputSchema, UpdateIntegrationInputSchema,\n DeleteIntegrationResultSchema,\n} from './integrations.cap.js'\nexport {\n addonsCapability, type IAddonsProvider,\n AddonListItemSchema, InstalledPackageSchema, PackageUpdateSchema,\n PackageVersionInfoSchema, SearchResultSchema, AutoUpdateSettingsSchema,\n AddonAutoUpdateSchema, LogStreamEntrySchema, CustomActionInputSchema,\n} from './addons.cap.js'\nexport {\n UserSummarySchema, CreateUserInputSchema, UpdateUserInputSchema,\n ApiKeySummarySchema, CreateApiKeyInputSchema, CreateApiKeyResultSchema,\n ScopedTokenSummarySchema, CreateScopedTokenInputSchema, CreateScopedTokenResultSchema,\n} from './user-management.cap.js'\n\n// ── Strongly-typed readiness registry ───────────────────────────────\n//\n// `CapabilityName` is the exhaustive union of every registered capability's\n// `.name` literal. Passing it to `IReadinessRegistry<CapabilityName>` means\n// the compiler rejects any unknown string (e.g. a stale 'detection-pipeline'\n// instead of 'pipeline-executor') at call sites.\nimport type { addonSettingsCapability } from './addon-settings.cap.js'\nimport type { alertsCapability } from './alerts.cap.js'\nimport type { storageCapability } from './storage.cap.js'\nimport type { backupCapability } from './backup.cap.js'\nimport type { settingsStoreCapability } from './settings-store.cap.js'\nimport type { logDestinationCapability } from './log-destination.cap.js'\nimport type { adminUiCapability } from './admin-ui.cap.js'\nimport type { addonPagesCapability } from './addon-pages.cap.js'\nimport type { addonPagesSourceCapability } from './addon-pages-source.cap.js'\nimport type { addonWidgetsCapability } from './addon-widgets.cap.js'\nimport type { addonWidgetsSourceCapability } from './addon-widgets-source.cap.js'\nimport type { addonRoutesCapability } from './addon-routes.cap.js'\nimport type { streamBrokerCapability } from './stream-broker.cap.js'\nimport type { decoderCapability } from './decoder.cap.js'\nimport type { restreamerCapability } from './restreamer.cap.js'\nimport type { webrtcCapability } from './webrtc.cap.js'\nimport type { webrtcSessionCapability } from './webrtc-session.cap.js'\nimport type { cameraStreamsCapability } from './camera-streams.cap.js'\nimport type { streamingEngineCapability } from './streaming-engine.cap.js'\nimport type { motionDetectionCapability } from './motion-detection.cap.js'\nimport type { pipelineExecutorCapability } from './pipeline-executor.cap.js'\nimport type { detectionPipelineCapability } from './detection-pipeline.cap.js'\nimport type { pipelineRunnerCapability } from './pipeline-runner.cap.js'\nimport type { pipelineOrchestratorCapability } from './pipeline-orchestrator.cap.js'\nimport type { audioAnalyzerCapability } from './audio-analyzer.cap.js'\nimport type { audioAnalysisCapability } from './audio-analysis.cap.js'\nimport type { audioCodecCapability } from './audio-codec.cap.js'\nimport type { embeddingEncoderCapability } from './embedding-encoder.cap.js'\nimport type { deviceProviderCapability } from './device-provider.cap.js'\nimport type { deviceManagerCapability } from './device-manager.cap.js'\nimport type { deviceStateCapability } from './device-state.cap.js'\nimport type { authProviderCapability } from './auth-provider.cap.js'\nimport type { networkAccessCapability } from './network-access.cap.js'\nimport type { turnProviderCapability } from './turn-provider.cap.js'\nimport type { snapshotCapability } from './snapshot.cap.js'\nimport type { snapshotProviderCapability } from './snapshot-provider.cap.js'\nimport type { notificationOutputCapability } from './notification-output.cap.js'\nimport type { advancedNotifierCapability } from './advanced-notifier.cap.js'\nimport type { recordingEngineCapability } from './recording-engine.cap.js'\nimport type { pipelineAnalyticsCapability } from './pipeline-analytics.cap.js'\nimport type { metricsProviderCapability } from './metrics-provider.cap.js'\nimport type { ptzCapability } from './ptz.cap.js'\nimport type { ptzAutotrackCapability } from './ptz-autotrack.cap.js'\nimport type { rebootCapability } from './reboot.cap.js'\nimport type { deviceDiscoveryCapability } from './device-discovery.cap.js'\nimport type { brightnessCapability } from './brightness.cap.js'\nimport type { motionTriggerCapability } from './motion-trigger.cap.js'\nimport type { eventsCapability } from './events.cap.js'\nimport type { zonesCapability } from './zones.cap.js'\nimport type { zoneRulesCapability } from './zone-rules.cap.js'\nimport type { zoneAnalyticsCapability } from './zone-analytics.cap.js'\nimport type { audioMetricsCapability } from './audio-metrics.cap.js'\nimport type { motionCapability } from './motion.cap.js'\nimport type { recordingCapability } from './recording.cap.js'\nimport type { deviceOpsCapability } from './device-ops.cap.js'\nimport type { platformProbeCapability } from './platform-probe.cap.js'\nimport type { userManagementCapability } from './user-management.cap.js'\nimport type { systemCapability } from './system.cap.js'\nimport type { networkQualityCapability } from './network-quality.cap.js'\nimport type { toastCapability } from './toast.cap.js'\nimport type { nodesCapability } from './nodes.cap.js'\nimport type { integrationsCapability } from './integrations.cap.js'\nimport type { addonsCapability } from './addons.cap.js'\nimport type { IReadinessRegistry } from '../interfaces/readiness.js'\n\ntype AnyCapability =\n | typeof addonSettingsCapability\n | typeof alertsCapability\n | typeof storageCapability\n | typeof backupCapability\n | typeof settingsStoreCapability\n | typeof logDestinationCapability\n | typeof adminUiCapability\n | typeof addonPagesCapability\n | typeof addonPagesSourceCapability\n | typeof addonWidgetsCapability\n | typeof addonWidgetsSourceCapability\n | typeof addonRoutesCapability\n | typeof streamBrokerCapability\n | typeof decoderCapability\n | typeof restreamerCapability\n | typeof webrtcCapability\n | typeof webrtcSessionCapability\n | typeof cameraStreamsCapability\n | typeof streamingEngineCapability\n | typeof motionDetectionCapability\n | typeof pipelineExecutorCapability\n | typeof detectionPipelineCapability\n | typeof pipelineRunnerCapability\n | typeof pipelineOrchestratorCapability\n | typeof audioAnalyzerCapability\n | typeof audioAnalysisCapability\n | typeof audioCodecCapability\n | typeof embeddingEncoderCapability\n | typeof deviceProviderCapability\n | typeof deviceManagerCapability\n | typeof deviceStateCapability\n | typeof authProviderCapability\n | typeof networkAccessCapability\n | typeof turnProviderCapability\n | typeof snapshotCapability\n | typeof snapshotProviderCapability\n | typeof notificationOutputCapability\n | typeof advancedNotifierCapability\n | typeof recordingEngineCapability\n | typeof pipelineAnalyticsCapability\n | typeof metricsProviderCapability\n | typeof ptzCapability\n | typeof ptzAutotrackCapability\n | typeof rebootCapability\n | typeof deviceDiscoveryCapability\n | typeof brightnessCapability\n | typeof motionTriggerCapability\n | typeof eventsCapability\n | typeof zonesCapability\n | typeof zoneRulesCapability\n | typeof zoneAnalyticsCapability\n | typeof audioMetricsCapability\n | typeof motionCapability\n | typeof recordingCapability\n | typeof deviceOpsCapability\n | typeof platformProbeCapability\n | typeof userManagementCapability\n | typeof systemCapability\n | typeof networkQualityCapability\n | typeof toastCapability\n | typeof nodesCapability\n | typeof integrationsCapability\n | typeof addonsCapability\n\nexport type CapabilityName = AnyCapability['name']\n\nexport type ITypedReadinessRegistry = IReadinessRegistry<CapabilityName>\n","// AUTO-GENERATED by scripts/generate-capability-router-types.ts — DO NOT EDIT\n// Re-run after adding/modifying capability definitions.\n//\n// Generated: 2026-05-07T06:37:43.648Z\n// Capabilities: 73\n\n// ── Capability Definition Imports ────────────────────────────────────\n\nexport { accessoriesCapability } from '../capabilities/accessories.cap.js'\nexport { addonPagesCapability } from '../capabilities/addon-pages.cap.js'\nexport { addonPagesSourceCapability } from '../capabilities/addon-pages-source.cap.js'\nexport { addonRoutesCapability } from '../capabilities/addon-routes.cap.js'\nexport { addonSettingsCapability } from '../capabilities/addon-settings.cap.js'\nexport { addonWidgetsCapability } from '../capabilities/addon-widgets.cap.js'\nexport { addonWidgetsSourceCapability } from '../capabilities/addon-widgets-source.cap.js'\nexport { addonsCapability } from '../capabilities/addons.cap.js'\nexport { adminUiCapability } from '../capabilities/admin-ui.cap.js'\nexport { advancedNotifierCapability } from '../capabilities/advanced-notifier.cap.js'\nexport { alertsCapability } from '../capabilities/alerts.cap.js'\nexport { audioAnalysisCapability } from '../capabilities/audio-analysis.cap.js'\nexport { audioAnalyzerCapability } from '../capabilities/audio-analyzer.cap.js'\nexport { audioCodecCapability } from '../capabilities/audio-codec.cap.js'\nexport { audioMetricsCapability } from '../capabilities/audio-metrics.cap.js'\nexport { authProviderCapability } from '../capabilities/auth-provider.cap.js'\nexport { backupCapability } from '../capabilities/backup.cap.js'\nexport { batteryCapability } from '../capabilities/battery.cap.js'\nexport { brightnessCapability } from '../capabilities/brightness.cap.js'\nexport { cameraCredentialsCapability } from '../capabilities/camera-credentials.cap.js'\nexport { cameraStreamsCapability } from '../capabilities/camera-streams.cap.js'\nexport { decoderCapability } from '../capabilities/decoder.cap.js'\nexport { detectionPipelineCapability } from '../capabilities/detection-pipeline.cap.js'\nexport { deviceDiscoveryCapability } from '../capabilities/device-discovery.cap.js'\nexport { deviceManagerCapability } from '../capabilities/device-manager.cap.js'\nexport { deviceOpsCapability } from '../capabilities/device-ops.cap.js'\nexport { deviceProviderCapability } from '../capabilities/device-provider.cap.js'\nexport { deviceStateCapability } from '../capabilities/device-state.cap.js'\nexport { deviceStatusCapability } from '../capabilities/device-status.cap.js'\nexport { doorbellCapability } from '../capabilities/doorbell.cap.js'\nexport { embeddingEncoderCapability } from '../capabilities/embedding-encoder.cap.js'\nexport { eventsCapability } from '../capabilities/events.cap.js'\nexport { featureProbeCapability } from '../capabilities/feature-probe.cap.js'\nexport { integrationsCapability } from '../capabilities/integrations.cap.js'\nexport { intercomCapability } from '../capabilities/intercom.cap.js'\nexport { logDestinationCapability } from '../capabilities/log-destination.cap.js'\nexport { metricsProviderCapability } from '../capabilities/metrics-provider.cap.js'\nexport { motionCapability } from '../capabilities/motion.cap.js'\nexport { motionDetectionCapability } from '../capabilities/motion-detection.cap.js'\nexport { motionTriggerCapability } from '../capabilities/motion-trigger.cap.js'\nexport { nativeObjectDetectionCapability } from '../capabilities/native-object-detection.cap.js'\nexport { networkAccessCapability } from '../capabilities/network-access.cap.js'\nexport { networkQualityCapability } from '../capabilities/network-quality.cap.js'\nexport { nodesCapability } from '../capabilities/nodes.cap.js'\nexport { notificationOutputCapability } from '../capabilities/notification-output.cap.js'\nexport { osdCapability } from '../capabilities/osd.cap.js'\nexport { pipelineAnalyticsCapability } from '../capabilities/pipeline-analytics.cap.js'\nexport { pipelineExecutorCapability } from '../capabilities/pipeline-executor.cap.js'\nexport { pipelineOrchestratorCapability } from '../capabilities/pipeline-orchestrator.cap.js'\nexport { pipelineRunnerCapability } from '../capabilities/pipeline-runner.cap.js'\nexport { platformProbeCapability } from '../capabilities/platform-probe.cap.js'\nexport { ptzCapability } from '../capabilities/ptz.cap.js'\nexport { ptzAutotrackCapability } from '../capabilities/ptz-autotrack.cap.js'\nexport { rebootCapability } from '../capabilities/reboot.cap.js'\nexport { recordingCapability } from '../capabilities/recording.cap.js'\nexport { recordingEngineCapability } from '../capabilities/recording-engine.cap.js'\nexport { restreamerCapability } from '../capabilities/restreamer.cap.js'\nexport { settingsStoreCapability } from '../capabilities/settings-store.cap.js'\nexport { snapshotCapability } from '../capabilities/snapshot.cap.js'\nexport { snapshotProviderCapability } from '../capabilities/snapshot-provider.cap.js'\nexport { storageCapability } from '../capabilities/storage.cap.js'\nexport { streamBrokerCapability } from '../capabilities/stream-broker.cap.js'\nexport { streamingEngineCapability } from '../capabilities/streaming-engine.cap.js'\nexport { switchCapability } from '../capabilities/switch.cap.js'\nexport { systemCapability } from '../capabilities/system.cap.js'\nexport { toastCapability } from '../capabilities/toast.cap.js'\nexport { turnProviderCapability } from '../capabilities/turn-provider.cap.js'\nexport { userManagementCapability } from '../capabilities/user-management.cap.js'\nexport { webrtcCapability } from '../capabilities/webrtc.cap.js'\nexport { webrtcSessionCapability } from '../capabilities/webrtc-session.cap.js'\nexport { zoneAnalyticsCapability } from '../capabilities/zone-analytics.cap.js'\nexport { zoneRulesCapability } from '../capabilities/zone-rules.cap.js'\nexport { zonesCapability } from '../capabilities/zones.cap.js'\n\n// ── Capability Names (for registry key constants) ────────────────────\n\nexport const CAPABILITY_NAMES = {\n accessories: 'accessories' as const,\n addonPages: 'addon-pages' as const,\n addonPagesSource: 'addon-pages-source' as const,\n addonRoutes: 'addon-routes' as const,\n addonSettings: 'addon-settings' as const,\n addonWidgets: 'addon-widgets' as const,\n addonWidgetsSource: 'addon-widgets-source' as const,\n addons: 'addons' as const,\n adminUi: 'admin-ui' as const,\n advancedNotifier: 'advanced-notifier' as const,\n alerts: 'alerts' as const,\n audioAnalysis: 'audio-analysis' as const,\n audioAnalyzer: 'audio-analyzer' as const,\n audioCodec: 'audio-codec' as const,\n audioMetrics: 'audio-metrics' as const,\n authProvider: 'auth-provider' as const,\n backup: 'backup' as const,\n battery: 'battery' as const,\n brightness: 'brightness' as const,\n cameraCredentials: 'camera-credentials' as const,\n cameraStreams: 'camera-streams' as const,\n decoder: 'decoder' as const,\n detectionPipeline: 'detection-pipeline' as const,\n deviceDiscovery: 'device-discovery' as const,\n deviceManager: 'device-manager' as const,\n deviceOps: 'device-ops' as const,\n deviceProvider: 'device-provider' as const,\n deviceState: 'device-state' as const,\n deviceStatus: 'device-status' as const,\n doorbell: 'doorbell' as const,\n embeddingEncoder: 'embedding-encoder' as const,\n events: 'events' as const,\n featureProbe: 'feature-probe' as const,\n integrations: 'integrations' as const,\n intercom: 'intercom' as const,\n logDestination: 'log-destination' as const,\n metricsProvider: 'metrics-provider' as const,\n motion: 'motion' as const,\n motionDetection: 'motion-detection' as const,\n motionTrigger: 'motion-trigger' as const,\n nativeObjectDetection: 'native-object-detection' as const,\n networkAccess: 'network-access' as const,\n networkQuality: 'network-quality' as const,\n nodes: 'nodes' as const,\n notificationOutput: 'notification-output' as const,\n osd: 'osd' as const,\n pipelineAnalytics: 'pipeline-analytics' as const,\n pipelineExecutor: 'pipeline-executor' as const,\n pipelineOrchestrator: 'pipeline-orchestrator' as const,\n pipelineRunner: 'pipeline-runner' as const,\n platformProbe: 'platform-probe' as const,\n ptz: 'ptz' as const,\n ptzAutotrack: 'ptz-autotrack' as const,\n reboot: 'reboot' as const,\n recording: 'recording' as const,\n recordingEngine: 'recording-engine' as const,\n restreamer: 'restreamer' as const,\n settingsStore: 'settings-store' as const,\n snapshot: 'snapshot' as const,\n snapshotProvider: 'snapshot-provider' as const,\n storage: 'storage' as const,\n streamBroker: 'stream-broker' as const,\n streamingEngine: 'streaming-engine' as const,\n switch: 'switch' as const,\n system: 'system' as const,\n toast: 'toast' as const,\n turnProvider: 'turn-provider' as const,\n userManagement: 'user-management' as const,\n webrtc: 'webrtc' as const,\n webrtcSession: 'webrtc-session' as const,\n zoneAnalytics: 'zone-analytics' as const,\n zoneRules: 'zone-rules' as const,\n zones: 'zones' as const,\n} as const\n\n/** All known capability names. */\nexport type CapabilityName = typeof CAPABILITY_NAMES[keyof typeof CAPABILITY_NAMES]\n\n/** Router key → capability name mapping for auto-mount. */\nexport const CAPABILITY_ROUTER_KEYS: ReadonlyArray<{ readonly key: string; readonly name: string }> = [\n { key: 'accessories', name: 'accessories' },\n { key: 'addonPages', name: 'addon-pages' },\n { key: 'addonPagesSource', name: 'addon-pages-source' },\n { key: 'addonRoutes', name: 'addon-routes' },\n { key: 'addonSettings', name: 'addon-settings' },\n { key: 'addonWidgets', name: 'addon-widgets' },\n { key: 'addonWidgetsSource', name: 'addon-widgets-source' },\n { key: 'addons', name: 'addons' },\n { key: 'adminUi', name: 'admin-ui' },\n { key: 'advancedNotifier', name: 'advanced-notifier' },\n { key: 'alerts', name: 'alerts' },\n { key: 'audioAnalysis', name: 'audio-analysis' },\n { key: 'audioAnalyzer', name: 'audio-analyzer' },\n { key: 'audioCodec', name: 'audio-codec' },\n { key: 'audioMetrics', name: 'audio-metrics' },\n { key: 'authProvider', name: 'auth-provider' },\n { key: 'backup', name: 'backup' },\n { key: 'battery', name: 'battery' },\n { key: 'brightness', name: 'brightness' },\n { key: 'cameraCredentials', name: 'camera-credentials' },\n { key: 'cameraStreams', name: 'camera-streams' },\n { key: 'decoder', name: 'decoder' },\n { key: 'detectionPipeline', name: 'detection-pipeline' },\n { key: 'deviceDiscovery', name: 'device-discovery' },\n { key: 'deviceManager', name: 'device-manager' },\n { key: 'deviceOps', name: 'device-ops' },\n { key: 'deviceProvider', name: 'device-provider' },\n { key: 'deviceState', name: 'device-state' },\n { key: 'deviceStatus', name: 'device-status' },\n { key: 'doorbell', name: 'doorbell' },\n { key: 'embeddingEncoder', name: 'embedding-encoder' },\n { key: 'events', name: 'events' },\n { key: 'featureProbe', name: 'feature-probe' },\n { key: 'integrations', name: 'integrations' },\n { key: 'intercom', name: 'intercom' },\n { key: 'logDestination', name: 'log-destination' },\n { key: 'metricsProvider', name: 'metrics-provider' },\n { key: 'motion', name: 'motion' },\n { key: 'motionDetection', name: 'motion-detection' },\n { key: 'motionTrigger', name: 'motion-trigger' },\n { key: 'nativeObjectDetection', name: 'native-object-detection' },\n { key: 'networkAccess', name: 'network-access' },\n { key: 'networkQuality', name: 'network-quality' },\n { key: 'nodes', name: 'nodes' },\n { key: 'notificationOutput', name: 'notification-output' },\n { key: 'osd', name: 'osd' },\n { key: 'pipelineAnalytics', name: 'pipeline-analytics' },\n { key: 'pipelineExecutor', name: 'pipeline-executor' },\n { key: 'pipelineOrchestrator', name: 'pipeline-orchestrator' },\n { key: 'pipelineRunner', name: 'pipeline-runner' },\n { key: 'platformProbe', name: 'platform-probe' },\n { key: 'ptz', name: 'ptz' },\n { key: 'ptzAutotrack', name: 'ptz-autotrack' },\n { key: 'reboot', name: 'reboot' },\n { key: 'recording', name: 'recording' },\n { key: 'recordingEngine', name: 'recording-engine' },\n { key: 'restreamer', name: 'restreamer' },\n { key: 'settingsStore', name: 'settings-store' },\n { key: 'snapshot', name: 'snapshot' },\n { key: 'snapshotProvider', name: 'snapshot-provider' },\n { key: 'storage', name: 'storage' },\n { key: 'streamBroker', name: 'stream-broker' },\n { key: 'streamingEngine', name: 'streaming-engine' },\n { key: 'switch', name: 'switch' },\n { key: 'system', name: 'system' },\n { key: 'toast', name: 'toast' },\n { key: 'turnProvider', name: 'turn-provider' },\n { key: 'userManagement', name: 'user-management' },\n { key: 'webrtc', name: 'webrtc' },\n { key: 'webrtcSession', name: 'webrtc-session' },\n { key: 'zoneAnalytics', name: 'zone-analytics' },\n { key: 'zoneRules', name: 'zone-rules' },\n { key: 'zones', name: 'zones' },\n]\n// ── Typed Router Map (for AppRouter) ─────────────────────────────────\n//\n// Import CapabilityTRPCRouter from the server to type the map.\n// This type is consumed by trpc.router.ts for typed spread.\n\n/**\n * Map of {name} → TRouter for typed AppRouter spread.\n * Generic TRouter defaults to unknown — the server layer resolves it\n * to the generated capability router type.\n */\nexport interface CapabilityRouterMap<TRouter = unknown> {\n readonly accessories: TRouter\n readonly addonPages: TRouter\n readonly addonPagesSource: TRouter\n readonly addonRoutes: TRouter\n readonly addonSettings: TRouter\n readonly addonWidgets: TRouter\n readonly addonWidgetsSource: TRouter\n readonly addons: TRouter\n readonly adminUi: TRouter\n readonly advancedNotifier: TRouter\n readonly alerts: TRouter\n readonly audioAnalysis: TRouter\n readonly audioAnalyzer: TRouter\n readonly audioCodec: TRouter\n readonly audioMetrics: TRouter\n readonly authProvider: TRouter\n readonly backup: TRouter\n readonly battery: TRouter\n readonly brightness: TRouter\n readonly cameraCredentials: TRouter\n readonly cameraStreams: TRouter\n readonly decoder: TRouter\n readonly detectionPipeline: TRouter\n readonly deviceDiscovery: TRouter\n readonly deviceManager: TRouter\n readonly deviceOps: TRouter\n readonly deviceProvider: TRouter\n readonly deviceState: TRouter\n readonly deviceStatus: TRouter\n readonly doorbell: TRouter\n readonly embeddingEncoder: TRouter\n readonly events: TRouter\n readonly featureProbe: TRouter\n readonly integrations: TRouter\n readonly intercom: TRouter\n readonly logDestination: TRouter\n readonly metricsProvider: TRouter\n readonly motion: TRouter\n readonly motionDetection: TRouter\n readonly motionTrigger: TRouter\n readonly nativeObjectDetection: TRouter\n readonly networkAccess: TRouter\n readonly networkQuality: TRouter\n readonly nodes: TRouter\n readonly notificationOutput: TRouter\n readonly osd: TRouter\n readonly pipelineAnalytics: TRouter\n readonly pipelineExecutor: TRouter\n readonly pipelineOrchestrator: TRouter\n readonly pipelineRunner: TRouter\n readonly platformProbe: TRouter\n readonly ptz: TRouter\n readonly ptzAutotrack: TRouter\n readonly reboot: TRouter\n readonly recording: TRouter\n readonly recordingEngine: TRouter\n readonly restreamer: TRouter\n readonly settingsStore: TRouter\n readonly snapshot: TRouter\n readonly snapshotProvider: TRouter\n readonly storage: TRouter\n readonly streamBroker: TRouter\n readonly streamingEngine: TRouter\n readonly switch: TRouter\n readonly system: TRouter\n readonly toast: TRouter\n readonly turnProvider: TRouter\n readonly userManagement: TRouter\n readonly webrtc: TRouter\n readonly webrtcSession: TRouter\n readonly zoneAnalytics: TRouter\n readonly zoneRules: TRouter\n readonly zones: TRouter\n}\n\n// ── Singleton / Collection split (derived from cap.mode) ─────────────\n\n/** Capability names whose mode is `singleton` (59 caps). */\nexport const SINGLETON_CAPABILITY_NAMES = [\n 'accessories',\n 'addon-pages',\n 'addon-settings',\n 'addon-widgets',\n 'addons',\n 'admin-ui',\n 'advanced-notifier',\n 'alerts',\n 'audio-analysis',\n 'audio-analyzer',\n 'audio-codec',\n 'audio-metrics',\n 'backup',\n 'battery',\n 'brightness',\n 'camera-credentials',\n 'camera-streams',\n 'decoder',\n 'detection-pipeline',\n 'device-discovery',\n 'device-manager',\n 'device-ops',\n 'device-state',\n 'device-status',\n 'doorbell',\n 'events',\n 'feature-probe',\n 'integrations',\n 'intercom',\n 'metrics-provider',\n 'motion',\n 'motion-detection',\n 'motion-trigger',\n 'native-object-detection',\n 'network-quality',\n 'nodes',\n 'osd',\n 'pipeline-analytics',\n 'pipeline-executor',\n 'pipeline-orchestrator',\n 'pipeline-runner',\n 'platform-probe',\n 'ptz',\n 'ptz-autotrack',\n 'reboot',\n 'recording',\n 'recording-engine',\n 'settings-store',\n 'snapshot',\n 'stream-broker',\n 'streaming-engine',\n 'switch',\n 'system',\n 'toast',\n 'user-management',\n 'webrtc-session',\n 'zone-analytics',\n 'zone-rules',\n 'zones',\n] as const\n\n/** Union of singleton capability names (literal string union). */\nexport type SingletonCapabilityName = typeof SINGLETON_CAPABILITY_NAMES[number]\n\n/** Capability names whose mode is `collection` (14 caps). */\nexport const COLLECTION_CAPABILITY_NAMES = [\n 'addon-pages-source',\n 'addon-routes',\n 'addon-widgets-source',\n 'auth-provider',\n 'device-provider',\n 'embedding-encoder',\n 'log-destination',\n 'network-access',\n 'notification-output',\n 'restreamer',\n 'snapshot-provider',\n 'storage',\n 'turn-provider',\n 'webrtc',\n] as const\n\n/** Union of collection capability names (literal string union). */\nexport type CollectionCapabilityName = typeof COLLECTION_CAPABILITY_NAMES[number]\n\n/** Capability mode lookup at runtime — mirrors the `.cap.ts` definitions. */\nexport const CAPABILITY_MODE: Readonly<Record<string, 'singleton' | 'collection'>> = {\n 'accessories': 'singleton',\n 'addon-pages': 'singleton',\n 'addon-pages-source': 'collection',\n 'addon-routes': 'collection',\n 'addon-settings': 'singleton',\n 'addon-widgets': 'singleton',\n 'addon-widgets-source': 'collection',\n 'addons': 'singleton',\n 'admin-ui': 'singleton',\n 'advanced-notifier': 'singleton',\n 'alerts': 'singleton',\n 'audio-analysis': 'singleton',\n 'audio-analyzer': 'singleton',\n 'audio-codec': 'singleton',\n 'audio-metrics': 'singleton',\n 'auth-provider': 'collection',\n 'backup': 'singleton',\n 'battery': 'singleton',\n 'brightness': 'singleton',\n 'camera-credentials': 'singleton',\n 'camera-streams': 'singleton',\n 'decoder': 'singleton',\n 'detection-pipeline': 'singleton',\n 'device-discovery': 'singleton',\n 'device-manager': 'singleton',\n 'device-ops': 'singleton',\n 'device-provider': 'collection',\n 'device-state': 'singleton',\n 'device-status': 'singleton',\n 'doorbell': 'singleton',\n 'embedding-encoder': 'collection',\n 'events': 'singleton',\n 'feature-probe': 'singleton',\n 'integrations': 'singleton',\n 'intercom': 'singleton',\n 'log-destination': 'collection',\n 'metrics-provider': 'singleton',\n 'motion': 'singleton',\n 'motion-detection': 'singleton',\n 'motion-trigger': 'singleton',\n 'native-object-detection': 'singleton',\n 'network-access': 'collection',\n 'network-quality': 'singleton',\n 'nodes': 'singleton',\n 'notification-output': 'collection',\n 'osd': 'singleton',\n 'pipeline-analytics': 'singleton',\n 'pipeline-executor': 'singleton',\n 'pipeline-orchestrator': 'singleton',\n 'pipeline-runner': 'singleton',\n 'platform-probe': 'singleton',\n 'ptz': 'singleton',\n 'ptz-autotrack': 'singleton',\n 'reboot': 'singleton',\n 'recording': 'singleton',\n 'recording-engine': 'singleton',\n 'restreamer': 'collection',\n 'settings-store': 'singleton',\n 'snapshot': 'singleton',\n 'snapshot-provider': 'collection',\n 'storage': 'collection',\n 'stream-broker': 'singleton',\n 'streaming-engine': 'singleton',\n 'switch': 'singleton',\n 'system': 'singleton',\n 'toast': 'singleton',\n 'turn-provider': 'collection',\n 'user-management': 'singleton',\n 'webrtc': 'collection',\n 'webrtc-session': 'singleton',\n 'zone-analytics': 'singleton',\n 'zone-rules': 'singleton',\n 'zones': 'singleton',\n}\n\n// ── All Capability Definitions (for boot-time declaration) ───────────\n\nimport type { CapabilityDefinition } from '../capabilities/capability-definition.js'\nimport { accessoriesCapability as _accessoriesCapability } from '../capabilities/accessories.cap.js'\nimport { addonPagesCapability as _addonPagesCapability } from '../capabilities/addon-pages.cap.js'\nimport { addonPagesSourceCapability as _addonPagesSourceCapability } from '../capabilities/addon-pages-source.cap.js'\nimport { addonRoutesCapability as _addonRoutesCapability } from '../capabilities/addon-routes.cap.js'\nimport { addonSettingsCapability as _addonSettingsCapability } from '../capabilities/addon-settings.cap.js'\nimport { addonWidgetsCapability as _addonWidgetsCapability } from '../capabilities/addon-widgets.cap.js'\nimport { addonWidgetsSourceCapability as _addonWidgetsSourceCapability } from '../capabilities/addon-widgets-source.cap.js'\nimport { addonsCapability as _addonsCapability } from '../capabilities/addons.cap.js'\nimport { adminUiCapability as _adminUiCapability } from '../capabilities/admin-ui.cap.js'\nimport { advancedNotifierCapability as _advancedNotifierCapability } from '../capabilities/advanced-notifier.cap.js'\nimport { alertsCapability as _alertsCapability } from '../capabilities/alerts.cap.js'\nimport { audioAnalysisCapability as _audioAnalysisCapability } from '../capabilities/audio-analysis.cap.js'\nimport { audioAnalyzerCapability as _audioAnalyzerCapability } from '../capabilities/audio-analyzer.cap.js'\nimport { audioCodecCapability as _audioCodecCapability } from '../capabilities/audio-codec.cap.js'\nimport { audioMetricsCapability as _audioMetricsCapability } from '../capabilities/audio-metrics.cap.js'\nimport { authProviderCapability as _authProviderCapability } from '../capabilities/auth-provider.cap.js'\nimport { backupCapability as _backupCapability } from '../capabilities/backup.cap.js'\nimport { batteryCapability as _batteryCapability } from '../capabilities/battery.cap.js'\nimport { brightnessCapability as _brightnessCapability } from '../capabilities/brightness.cap.js'\nimport { cameraCredentialsCapability as _cameraCredentialsCapability } from '../capabilities/camera-credentials.cap.js'\nimport { cameraStreamsCapability as _cameraStreamsCapability } from '../capabilities/camera-streams.cap.js'\nimport { decoderCapability as _decoderCapability } from '../capabilities/decoder.cap.js'\nimport { detectionPipelineCapability as _detectionPipelineCapability } from '../capabilities/detection-pipeline.cap.js'\nimport { deviceDiscoveryCapability as _deviceDiscoveryCapability } from '../capabilities/device-discovery.cap.js'\nimport { deviceManagerCapability as _deviceManagerCapability } from '../capabilities/device-manager.cap.js'\nimport { deviceOpsCapability as _deviceOpsCapability } from '../capabilities/device-ops.cap.js'\nimport { deviceProviderCapability as _deviceProviderCapability } from '../capabilities/device-provider.cap.js'\nimport { deviceStateCapability as _deviceStateCapability } from '../capabilities/device-state.cap.js'\nimport { deviceStatusCapability as _deviceStatusCapability } from '../capabilities/device-status.cap.js'\nimport { doorbellCapability as _doorbellCapability } from '../capabilities/doorbell.cap.js'\nimport { embeddingEncoderCapability as _embeddingEncoderCapability } from '../capabilities/embedding-encoder.cap.js'\nimport { eventsCapability as _eventsCapability } from '../capabilities/events.cap.js'\nimport { featureProbeCapability as _featureProbeCapability } from '../capabilities/feature-probe.cap.js'\nimport { integrationsCapability as _integrationsCapability } from '../capabilities/integrations.cap.js'\nimport { intercomCapability as _intercomCapability } from '../capabilities/intercom.cap.js'\nimport { logDestinationCapability as _logDestinationCapability } from '../capabilities/log-destination.cap.js'\nimport { metricsProviderCapability as _metricsProviderCapability } from '../capabilities/metrics-provider.cap.js'\nimport { motionCapability as _motionCapability } from '../capabilities/motion.cap.js'\nimport { motionDetectionCapability as _motionDetectionCapability } from '../capabilities/motion-detection.cap.js'\nimport { motionTriggerCapability as _motionTriggerCapability } from '../capabilities/motion-trigger.cap.js'\nimport { nativeObjectDetectionCapability as _nativeObjectDetectionCapability } from '../capabilities/native-object-detection.cap.js'\nimport { networkAccessCapability as _networkAccessCapability } from '../capabilities/network-access.cap.js'\nimport { networkQualityCapability as _networkQualityCapability } from '../capabilities/network-quality.cap.js'\nimport { nodesCapability as _nodesCapability } from '../capabilities/nodes.cap.js'\nimport { notificationOutputCapability as _notificationOutputCapability } from '../capabilities/notification-output.cap.js'\nimport { osdCapability as _osdCapability } from '../capabilities/osd.cap.js'\nimport { pipelineAnalyticsCapability as _pipelineAnalyticsCapability } from '../capabilities/pipeline-analytics.cap.js'\nimport { pipelineExecutorCapability as _pipelineExecutorCapability } from '../capabilities/pipeline-executor.cap.js'\nimport { pipelineOrchestratorCapability as _pipelineOrchestratorCapability } from '../capabilities/pipeline-orchestrator.cap.js'\nimport { pipelineRunnerCapability as _pipelineRunnerCapability } from '../capabilities/pipeline-runner.cap.js'\nimport { platformProbeCapability as _platformProbeCapability } from '../capabilities/platform-probe.cap.js'\nimport { ptzCapability as _ptzCapability } from '../capabilities/ptz.cap.js'\nimport { ptzAutotrackCapability as _ptzAutotrackCapability } from '../capabilities/ptz-autotrack.cap.js'\nimport { rebootCapability as _rebootCapability } from '../capabilities/reboot.cap.js'\nimport { recordingCapability as _recordingCapability } from '../capabilities/recording.cap.js'\nimport { recordingEngineCapability as _recordingEngineCapability } from '../capabilities/recording-engine.cap.js'\nimport { restreamerCapability as _restreamerCapability } from '../capabilities/restreamer.cap.js'\nimport { settingsStoreCapability as _settingsStoreCapability } from '../capabilities/settings-store.cap.js'\nimport { snapshotCapability as _snapshotCapability } from '../capabilities/snapshot.cap.js'\nimport { snapshotProviderCapability as _snapshotProviderCapability } from '../capabilities/snapshot-provider.cap.js'\nimport { storageCapability as _storageCapability } from '../capabilities/storage.cap.js'\nimport { streamBrokerCapability as _streamBrokerCapability } from '../capabilities/stream-broker.cap.js'\nimport { streamingEngineCapability as _streamingEngineCapability } from '../capabilities/streaming-engine.cap.js'\nimport { switchCapability as _switchCapability } from '../capabilities/switch.cap.js'\nimport { systemCapability as _systemCapability } from '../capabilities/system.cap.js'\nimport { toastCapability as _toastCapability } from '../capabilities/toast.cap.js'\nimport { turnProviderCapability as _turnProviderCapability } from '../capabilities/turn-provider.cap.js'\nimport { userManagementCapability as _userManagementCapability } from '../capabilities/user-management.cap.js'\nimport { webrtcCapability as _webrtcCapability } from '../capabilities/webrtc.cap.js'\nimport { webrtcSessionCapability as _webrtcSessionCapability } from '../capabilities/webrtc-session.cap.js'\nimport { zoneAnalyticsCapability as _zoneAnalyticsCapability } from '../capabilities/zone-analytics.cap.js'\nimport { zoneRulesCapability as _zoneRulesCapability } from '../capabilities/zone-rules.cap.js'\nimport { zonesCapability as _zonesCapability } from '../capabilities/zones.cap.js'\n\n/**\n * Every CapabilityDefinition shipped by `@camstack/types`. The hub\n * iterates this array at boot to declare each cap on the registry\n * before addons (in-process or via the Moleculer bridge) attempt\n * `registerProvider`. Adding a new cap means dropping a `*.cap.ts`\n * file in `packages/types/src/capabilities/` and re-running\n * `npx tsx scripts/generate-capability-router-types.ts` — no manual\n * edit to `main.ts` required.\n */\nexport const ALL_CAPABILITY_DEFINITIONS: readonly CapabilityDefinition[] = [\n _accessoriesCapability as CapabilityDefinition,\n _addonPagesCapability as CapabilityDefinition,\n _addonPagesSourceCapability as CapabilityDefinition,\n _addonRoutesCapability as CapabilityDefinition,\n _addonSettingsCapability as CapabilityDefinition,\n _addonWidgetsCapability as CapabilityDefinition,\n _addonWidgetsSourceCapability as CapabilityDefinition,\n _addonsCapability as CapabilityDefinition,\n _adminUiCapability as CapabilityDefinition,\n _advancedNotifierCapability as CapabilityDefinition,\n _alertsCapability as CapabilityDefinition,\n _audioAnalysisCapability as CapabilityDefinition,\n _audioAnalyzerCapability as CapabilityDefinition,\n _audioCodecCapability as CapabilityDefinition,\n _audioMetricsCapability as CapabilityDefinition,\n _authProviderCapability as CapabilityDefinition,\n _backupCapability as CapabilityDefinition,\n _batteryCapability as CapabilityDefinition,\n _brightnessCapability as CapabilityDefinition,\n _cameraCredentialsCapability as CapabilityDefinition,\n _cameraStreamsCapability as CapabilityDefinition,\n _decoderCapability as CapabilityDefinition,\n _detectionPipelineCapability as CapabilityDefinition,\n _deviceDiscoveryCapability as CapabilityDefinition,\n _deviceManagerCapability as CapabilityDefinition,\n _deviceOpsCapability as CapabilityDefinition,\n _deviceProviderCapability as CapabilityDefinition,\n _deviceStateCapability as CapabilityDefinition,\n _deviceStatusCapability as CapabilityDefinition,\n _doorbellCapability as CapabilityDefinition,\n _embeddingEncoderCapability as CapabilityDefinition,\n _eventsCapability as CapabilityDefinition,\n _featureProbeCapability as CapabilityDefinition,\n _integrationsCapability as CapabilityDefinition,\n _intercomCapability as CapabilityDefinition,\n _logDestinationCapability as CapabilityDefinition,\n _metricsProviderCapability as CapabilityDefinition,\n _motionCapability as CapabilityDefinition,\n _motionDetectionCapability as CapabilityDefinition,\n _motionTriggerCapability as CapabilityDefinition,\n _nativeObjectDetectionCapability as CapabilityDefinition,\n _networkAccessCapability as CapabilityDefinition,\n _networkQualityCapability as CapabilityDefinition,\n _nodesCapability as CapabilityDefinition,\n _notificationOutputCapability as CapabilityDefinition,\n _osdCapability as CapabilityDefinition,\n _pipelineAnalyticsCapability as CapabilityDefinition,\n _pipelineExecutorCapability as CapabilityDefinition,\n _pipelineOrchestratorCapability as CapabilityDefinition,\n _pipelineRunnerCapability as CapabilityDefinition,\n _platformProbeCapability as CapabilityDefinition,\n _ptzCapability as CapabilityDefinition,\n _ptzAutotrackCapability as CapabilityDefinition,\n _rebootCapability as CapabilityDefinition,\n _recordingCapability as CapabilityDefinition,\n _recordingEngineCapability as CapabilityDefinition,\n _restreamerCapability as CapabilityDefinition,\n _settingsStoreCapability as CapabilityDefinition,\n _snapshotCapability as CapabilityDefinition,\n _snapshotProviderCapability as CapabilityDefinition,\n _storageCapability as CapabilityDefinition,\n _streamBrokerCapability as CapabilityDefinition,\n _streamingEngineCapability as CapabilityDefinition,\n _switchCapability as CapabilityDefinition,\n _systemCapability as CapabilityDefinition,\n _toastCapability as CapabilityDefinition,\n _turnProviderCapability as CapabilityDefinition,\n _userManagementCapability as CapabilityDefinition,\n _webrtcCapability as CapabilityDefinition,\n _webrtcSessionCapability as CapabilityDefinition,\n _zoneAnalyticsCapability as CapabilityDefinition,\n _zoneRulesCapability as CapabilityDefinition,\n _zonesCapability as CapabilityDefinition,\n]\n\n","/* AUTO-GENERATED by scripts/generate-cap-status-types.ts. DO NOT EDIT. */\n/* eslint-disable */\n\nimport type { z } from 'zod'\n\nimport { AccessoriesStatusSchema } from '../capabilities/accessories.cap.js'\nimport { BatteryStatusSchema } from '../capabilities/battery.cap.js'\nimport { BrightnessStatusSchema } from '../capabilities/brightness.cap.js'\nimport { CameraCredentialsStatusSchema } from '../capabilities/camera-credentials.cap.js'\nimport { DeviceDiscoveryStatusSchema } from '../capabilities/device-discovery.cap.js'\nimport { deviceStatusCapability } from '../capabilities/device-status.cap.js'\nimport { DoorbellStatusSchema } from '../capabilities/doorbell.cap.js'\nimport { FeatureProbeStatusSchema } from '../capabilities/feature-probe.cap.js'\nimport { IntercomStatusSchema } from '../capabilities/intercom.cap.js'\nimport { MotionStatusSchema } from '../capabilities/motion.cap.js'\nimport { MotionTriggerStatusSchema } from '../capabilities/motion-trigger.cap.js'\nimport { NativeObjectDetectionStatusSchema } from '../capabilities/native-object-detection.cap.js'\nimport { OsdStatusSchema } from '../capabilities/osd.cap.js'\nimport { ptzCapability } from '../capabilities/ptz.cap.js'\nimport { PtzAutotrackStatusSchema } from '../capabilities/ptz-autotrack.cap.js'\nimport { SnapshotStatusSchema } from '../capabilities/snapshot.cap.js'\nimport { SwitchStatusSchema } from '../capabilities/switch.cap.js'\n\n/**\n * Lookup from cap name (literal) → the TypeScript type of that\n * capability's `status.schema`. Populated at codegen time from every\n * `*.cap.ts` file that declares a `status` block.\n */\nexport type CapStatusTypeMap = {\n readonly 'accessories': z.infer<typeof AccessoriesStatusSchema>\n readonly 'battery': z.infer<typeof BatteryStatusSchema>\n readonly 'brightness': z.infer<typeof BrightnessStatusSchema>\n readonly 'camera-credentials': z.infer<typeof CameraCredentialsStatusSchema>\n readonly 'device-discovery': z.infer<typeof DeviceDiscoveryStatusSchema>\n readonly 'device-status': z.infer<(typeof deviceStatusCapability)['status']['schema']>\n readonly 'doorbell': z.infer<typeof DoorbellStatusSchema>\n readonly 'feature-probe': z.infer<typeof FeatureProbeStatusSchema>\n readonly 'intercom': z.infer<typeof IntercomStatusSchema>\n readonly 'motion': z.infer<typeof MotionStatusSchema>\n readonly 'motion-trigger': z.infer<typeof MotionTriggerStatusSchema>\n readonly 'native-object-detection': z.infer<typeof NativeObjectDetectionStatusSchema>\n readonly 'osd': z.infer<typeof OsdStatusSchema>\n readonly 'ptz': z.infer<(typeof ptzCapability)['status']['schema']>\n readonly 'ptz-autotrack': z.infer<typeof PtzAutotrackStatusSchema>\n readonly 'snapshot': z.infer<typeof SnapshotStatusSchema>\n readonly 'switch': z.infer<typeof SwitchStatusSchema>\n}\n\n/** Union of every cap name that has a typed status block. */\nexport type CapNameWithStatus = keyof CapStatusTypeMap\n\n/**\n * Runtime list of cap names with status. Used by the settings\n * aggregator to enumerate caps whose `status` should be polled +\n * streamed via `subscribeDeviceStatusAggregate`.\n */\nexport const CAP_NAMES_WITH_STATUS = [\n 'accessories',\n 'battery',\n 'brightness',\n 'camera-credentials',\n 'device-discovery',\n 'device-status',\n 'doorbell',\n 'feature-probe',\n 'intercom',\n 'motion',\n 'motion-trigger',\n 'native-object-detection',\n 'osd',\n 'ptz',\n 'ptz-autotrack',\n 'snapshot',\n 'switch',\n] as const satisfies readonly CapNameWithStatus[]\n","/**\n * Zod schemas for persisted record types.\n *\n * These schemas serve as the single source of truth for types that are\n * stored in the settings-store backend and retrieved via tRPC. They\n * replace the manual TypeScript interfaces with schema-derived types,\n * enabling runtime validation when reading from the backend.\n *\n * Convention: each schema is named `<Type>Schema`, the inferred TS type\n * keeps the original name for backward compatibility.\n */\nimport { z } from 'zod'\n\n// ── Auth ────────────────────────────────────────────────────────────\n\nexport const UserRoleSchema = z.enum(['super_admin', 'admin', 'viewer', 'agent'])\nexport type UserRole = z.infer<typeof UserRoleSchema>\n\nconst AllowedProviderSchema = z.union([z.literal('*'), z.array(z.string())])\nconst AllowedDevicesSchema = z.record(z.string(), z.union([z.literal('*'), z.array(z.string())]))\n\nexport const UserRecordSchema = z.object({\n id: z.string(),\n username: z.string(),\n passwordHash: z.string(),\n role: UserRoleSchema,\n allowedProviders: AllowedProviderSchema,\n allowedDevices: AllowedDevicesSchema,\n createdAt: z.number(),\n updatedAt: z.number(),\n})\nexport type UserRecord = z.infer<typeof UserRecordSchema>\n\nexport const ApiKeyRecordSchema = z.object({\n id: z.string(),\n label: z.string(),\n role: UserRoleSchema,\n allowedProviders: AllowedProviderSchema,\n allowedDevices: AllowedDevicesSchema,\n tokenHash: z.string(),\n tokenPrefix: z.string(),\n createdAt: z.number(),\n lastUsedAt: z.number().optional(),\n})\nexport type ApiKeyRecord = z.infer<typeof ApiKeyRecordSchema>\n\n// ── Scoped Tokens ───────────────────────────────────────────────────\n\nexport const TokenScopeSchema = z.object({\n type: z.enum(['addon', 'route-prefix', 'capability']),\n target: z.string(),\n})\nexport type TokenScope = z.infer<typeof TokenScopeSchema>\n\nexport const ScopedTokenSchema = z.object({\n id: z.string(),\n userId: z.string(),\n name: z.string(),\n tokenHash: z.string(),\n tokenPrefix: z.string(),\n scopes: z.array(TokenScopeSchema),\n expiresAt: z.number().optional(),\n lastUsedAt: z.number().optional(),\n createdAt: z.number(),\n})\nexport type ScopedToken = z.infer<typeof ScopedTokenSchema>\n","/**\n * Strip the `userinfo` (`user:password@`) component from any URL we\n * surface in logs or telemetry. Camera credentials live inside RTSP /\n * RTMP / HTTP URLs by convention; emitting them verbatim leaks\n * plaintext secrets into log files, support transcripts, and shared\n * diagnostics. Returns the original string when the input is not a\n * parseable URL — a log helper must never throw.\n */\nexport function maskUrlCredentials(rawUrl: string): string {\n try {\n const u = new URL(rawUrl)\n if (!u.username && !u.password) return rawUrl\n u.username = ''\n u.password = ''\n return u.toString()\n } catch {\n return rawUrl\n }\n}\n","/**\n * Fixed-capacity ring buffer. When full, push() overwrites the oldest entry.\n * drain() returns up to maxCount items in FIFO order and removes them.\n */\nexport class RingBuffer<T> {\n private readonly items: Array<T | undefined>\n private head = 0\n private tail = 0\n private count = 0\n\n constructor(private readonly capacity: number) {\n this.items = Array.from<T | undefined>({ length: capacity })\n }\n\n get size(): number { return this.count }\n\n push(item: T): void {\n this.items[this.tail] = item\n this.tail = (this.tail + 1) % this.capacity\n if (this.count < this.capacity) {\n this.count++\n } else {\n this.head = (this.head + 1) % this.capacity\n }\n }\n\n drain(maxCount: number): T[] {\n const result: T[] = []\n const n = Math.min(maxCount, this.count)\n for (let i = 0; i < n; i++) {\n result.push(this.items[this.head]!)\n this.items[this.head] = undefined\n this.head = (this.head + 1) % this.capacity\n }\n this.count -= n\n return result\n }\n}\n","import type { z } from 'zod'\nimport type { CustomActionsSpec } from '../capabilities/custom-actions.js'\nimport type { AddonApi } from '../generated/addon-api.js'\n\n/**\n * Bind an addon's custom-action catalog to its tRPC surface, returning a\n * typed object with one method per action. Each method:\n * - Dispatches via `api.addons.custom.mutate({ addonId, action, input })`\n * - Inputs are typed as `z.infer<spec.input>`\n * - Outputs are typed as `z.infer<spec.output>`\n *\n * Example:\n * import { benchmarkActions } from '@camstack/addon-benchmark'\n * const benchmark = bindAddonActions(ctx.api, 'benchmark', benchmarkActions)\n * const { runId } = await benchmark.runBenchmark({ iterations: 100, target: 'cam-01' })\n */\nexport function bindAddonActions<T extends CustomActionsSpec>(\n api: AddonApi,\n addonId: string,\n catalog: T,\n): { [K in keyof T]: (input: z.infer<T[K]['input']>) => Promise<z.infer<T[K]['output']>> } {\n const out: Record<string, (input: unknown) => Promise<unknown>> = {}\n for (const action of Object.keys(catalog)) {\n out[action] = (input: unknown) => {\n const dispatcher = (\n api as unknown as {\n addons: {\n custom: {\n mutate: (args: { addonId: string; action: string; input: unknown }) => Promise<unknown>\n }\n }\n }\n ).addons.custom\n return dispatcher.mutate({ addonId, action, input })\n }\n }\n return out as never\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oCAAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAAAC;A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","names":["AddonPageDeclarationSchema","TokenScopeSchema","UserRoleSchema","EventCategory","event","event","event","streams","EventSourceType","DeviceType","DeviceFeature","ChargingStatus","DeviceRole","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","field","method","z","method","withTimeout","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","AddonPageDeclarationSchema","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","PipelineTemplateSchema","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","StreamSourceEntrySchema","ConfigEntrySchema","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","ModelFormatSchema","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","LogLevelSchema","import_zod","UserRoleSchema","TokenScopeSchema"]}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/disposer-chain.ts","../src/interfaces/addon.ts","../src/enums/event-category.ts","../src/interfaces/event-bus.ts","../src/addon/base-addon.ts","../src/readiness/readiness-registry.ts","../src/interfaces/storage.ts","../src/interfaces/device-capabilities/camera.ts","../src/interfaces/feature-flags.ts","../src/interfaces/server-analysis.ts","../src/interfaces/analysis-persistence.ts","../src/enums/event-source-type.ts","../src/constants.ts","../src/utils/json-safe.ts","../src/utils/hf-url.ts","../src/utils/cosine-similarity.ts","../src/utils/element-config-store.ts","../src/utils/runtime-mapping.ts","../src/utils/run-inference-step.ts","../src/catalogs/coco-classmap.ts","../src/types/device-type.ts","../src/device/device-config.ts","../src/device/device-runtime-state.ts","../src/device/runtime-state-helpers.ts","../src/generated/device-local-state.ts","../src/device/base-device.ts","../src/device/base-device-provider.ts","../src/device/zod-to-config-ui.ts","../src/device/device-state-handle.ts","../src/generated/device-proxy.ts","../src/utils/zone-rule-eval.ts","../src/generated/system-proxy.ts","../src/device/system-mirror.ts","../src/capabilities/custom-actions.ts","../src/generated/capability-router-map.ts","../src/generated/cap-status-types.ts","../src/utils/mask-url.ts","../src/utils/ring-buffer.ts","../src/helpers/bind-addon-actions.ts"],"sourcesContent":["// =============================================================================\n// DisposerChain — minimal LIFO cleanup registry used to back\n// `AddonContext.addDisposer`.\n//\n// Owned by whoever constructs an AddonContext (the addon host on the\n// hub, the worker host in forks). At shutdown / restart the host calls\n// `dispose()` once; this drains the chain in LIFO order so resources\n// registered later (which may depend on earlier ones) tear down first.\n//\n// Errors thrown by individual disposers are logged via the optional\n// onError callback but never abort the rest of the chain — partial\n// cleanup is always better than half-stopped state on the next restart.\n// =============================================================================\n\nexport type DisposerFn = () => void | Promise<void>\n\nexport interface DisposerChainOptions {\n /** Logged when an individual disposer throws. Defaults to console.error. */\n onError?: (err: unknown, index: number) => void\n}\n\nexport class DisposerChain {\n private disposers: DisposerFn[] = []\n private disposed = false\n private readonly onError: (err: unknown, index: number) => void\n\n constructor(opts: DisposerChainOptions = {}) {\n this.onError =\n opts.onError ??\n ((err, index) => {\n // eslint-disable-next-line no-console\n console.error(`[DisposerChain] disposer #${index} threw`, err)\n })\n }\n\n /**\n * Register a teardown callback. Returns an unregister function so\n * callers can drop a single disposer without disposing the whole\n * chain.\n *\n * If the chain has already been disposed, the callback runs immediately\n * (sync) — this matches the “register-after-shutdown” edge case where\n * an addon's late initialization races with kernel restart.\n */\n add(fn: DisposerFn): () => void {\n if (this.disposed) {\n try {\n const result = fn()\n if (result && typeof (result as Promise<void>).then === 'function') {\n ;(result as Promise<void>).catch((err) => this.onError(err, -1))\n }\n } catch (err) {\n this.onError(err, -1)\n }\n return () => undefined\n }\n\n this.disposers.push(fn)\n return () => {\n const idx = this.disposers.indexOf(fn)\n if (idx >= 0) this.disposers.splice(idx, 1)\n }\n }\n\n /** True after `dispose()` has been called at least once. */\n get isDisposed(): boolean {\n return this.disposed\n }\n\n /** Number of disposers currently registered. */\n get size(): number {\n return this.disposers.length\n }\n\n /**\n * Run every registered disposer in LIFO order. Idempotent: subsequent\n * calls do nothing. Awaits async disposers so callers can sequence\n * shutdown → restart correctly.\n */\n async dispose(): Promise<void> {\n if (this.disposed) return\n this.disposed = true\n // Snapshot + clear so concurrent `add()` from a disposer can't\n // re-enter the same array we're draining.\n const drain = this.disposers.slice().reverse()\n this.disposers = []\n\n for (let i = 0; i < drain.length; i++) {\n const fn = drain[i]!\n try {\n const result = fn()\n if (result && typeof (result as Promise<void>).then === 'function') {\n await result\n }\n } catch (err) {\n this.onError(err, drain.length - 1 - i)\n }\n }\n }\n}\n","import type { PipelineSlot } from '../types/pipeline.js'\nimport type { ConfigUISchemaWithValues, FieldProbeResult } from './config-ui.js'\nimport type { IScopedLogger } from './logging.js'\nimport type { IEventBus, ReadinessScope } from './event-bus.js'\nimport type { ICapabilityHandle } from './readiness.js'\nimport type { CapabilityDeclaration } from './capability.js'\nimport type { ICapabilityRegistry } from './kernel-abstractions.js'\nimport type { CapabilityDefinition, InferProvider } from '../capabilities/capability-definition.js'\nimport type { CustomActionsSpec } from '../capabilities/custom-actions.js'\nimport type { z } from 'zod'\n/** Sub-process info (inlined from deleted worker-protocol.ts) */\nexport interface SubProcessInfo {\n readonly pid: number\n readonly name: string\n readonly command: string\n readonly state: 'running' | 'stopped' | 'crashed'\n readonly cpuPercent: number\n readonly memoryRss: number\n readonly uptimeSeconds: number\n}\n\n/** Worker process stats (inlined from deleted worker-protocol.ts) */\nexport interface WorkerProcessStats {\n readonly pid: number\n readonly cpuPercent: number\n readonly memoryRss: number\n readonly heapUsed?: number\n readonly uptimeSeconds: number\n readonly restartCount: number\n readonly state: 'starting' | 'running' | 'stopping' | 'stopped' | 'crashed'\n}\n\n/** Storage interface for addon file operations */\nexport interface IAddonFileStorage {\n readFile(path: string): Promise<Buffer>\n writeFile(path: string, data: Buffer): Promise<void>\n deleteFile(path: string): Promise<void>\n listFiles(prefix?: string): Promise<readonly string[]>\n exists(path: string): Promise<boolean>\n}\n\nexport interface RequiredStep {\n readonly slot: PipelineSlot\n readonly outputClasses: readonly string[]\n readonly description: string\n}\n\n/**\n * Minimal model-management API exposed to addons via AddonContext.\n */\nexport interface IAddonModelManager {\n /** Ensure a model is downloaded. Returns the local file path. */\n ensure(modelId: string, format?: import('../types/models.js').ModelFormat): Promise<string>\n\n /** Ensure extra files for a model are downloaded. Returns paths. */\n ensureExtraFiles(modelId: string): Promise<readonly string[]>\n\n /** Absolute path to the shared models directory. */\n getModelsDir(): string\n\n /** Check if a model is already downloaded. */\n isDownloaded(modelId: string, format?: import('../types/models.js').ModelFormat): boolean\n\n}\n\n/** Process management for addon sub-processes (ffmpeg, python, etc.) */\nexport interface IAddonProcessManager {\n /** Spawn a child process managed by this addon's worker */\n spawn(config: SubProcessConfig): Promise<IManagedSubProcess>\n /** List all sub-processes spawned by this addon */\n listProcesses(): readonly SubProcessInfo[]\n /** Get worker stats (this addon's worker process) */\n getWorkerStats(): WorkerProcessStats\n}\n\nexport interface SubProcessConfig {\n readonly name: string\n readonly command: string\n readonly args?: readonly string[]\n readonly cwd?: string\n readonly env?: Readonly<Record<string, string>>\n readonly autoRestart?: boolean\n readonly maxRestarts?: number\n}\n\nexport interface IManagedSubProcess {\n readonly pid: number\n readonly name: string\n getStats(): WorkerProcessStats\n write(data: Buffer): void\n readonly stdout: AsyncIterable<Buffer>\n readonly stderr: AsyncIterable<Buffer>\n kill(signal?: NodeJS.Signals): void\n wait(): Promise<{ code: number | null; signal: string | null }>\n onExit(handler: (code: number | null) => void): void\n onError(handler: (error: Error) => void): void\n}\n\n/** Dependency manager — ensures binaries/tools are available for addons */\nexport interface IAddonDepsManager {\n /** Ensure a named binary is available (check local -> PATH -> download) */\n ensureBinary(opts: {\n readonly name: string\n readonly downloadUrl: string\n readonly isArchive?: boolean\n readonly archiveFormat?: 'zip' | 'tar.gz' | 'tar.xz'\n readonly archiveInnerPath?: string\n }): Promise<string>\n\n /** Ensure ffmpeg is available */\n ensureFfmpeg(): Promise<string>\n\n /** Ensure Python is available, returns path or null if unavailable */\n ensurePython(): Promise<string | null>\n\n /** Install Python packages in the managed Python environment */\n installPythonPackages(packages: readonly string[]): Promise<void>\n\n /**\n * Install a pip requirements file into the embedded Python.\n * Idempotent: keyed on (file basename + sha256 of contents). Marker\n * lives under the python install dir so re-downloading python wipes\n * everything together.\n */\n installPythonRequirements(requirementsFile: string): Promise<void>\n\n /** Get the deps directory path */\n getDepsDir(): string\n}\n\n/**\n * AddonContext -- injected into every addon at initialize().\n *\n * The context includes both the CamstackContext fields (id, logger, eventBus, storage, config)\n * and addon-specific extras (addonConfig, models, locationPaths, router, network).\n */\n/**\n * AddonContext -- injected into every addon at initialize().\n *\n * The `api` field is typed as `AddonApi` — a generated interface that\n * mirrors the server's tRPC router namespaces. This gives addons type-safe\n * access to server procedures without depending on the server package.\n *\n * To regenerate after changing routers: npx tsx scripts/generate-api-types.ts\n */\n// ── Provider registration (return from initialize) ──────────────────────\n/**\n * A capability provider binding returned from `ICamstackAddon.initialize()`.\n * The kernel registers each entry in the CapabilityRegistry after init completes.\n */\nexport interface ProviderRegistration<TCap extends CapabilityDefinition = CapabilityDefinition> {\n /** Capability definition this provider implements. Read `capability.name` to look up by name. */\n readonly capability: TCap\n /**\n * The provider object implementing the capability interface.\n *\n * - With a specific `TCap` (e.g. `ProviderRegistration<typeof metricsProviderCapability>`)\n * the provider is strictly checked against `InferProvider<TCap>`.\n * - With the default `TCap = CapabilityDefinition` (used by heterogeneous arrays like\n * `ProviderRegistration[]` returned from `onInitialize()`) the provider is typed as\n * `object`: a mapped type over the default `Record<string, CapabilityMethodSchema>`\n * collapses to an index signature that class instances cannot satisfy structurally.\n * The runtime capability router enforces the contract; the strict compile-time check\n * is applied at the specific-cap boundary (ProviderRegistration<typeof xxxCap>) instead.\n */\n readonly provider: CapabilityDefinition extends TCap ? object : InferProvider<TCap>\n /** 'native' (default) — absolute provider.\n * 'wrapper' — user-toggleable decorator that delegates to a native via `ctx.getNativeProvider`. */\n readonly kind?: 'native' | 'wrapper'\n /** Wrapper only — active by default for every compatible device. */\n readonly defaultActive?: boolean\n}\n\n/**\n * Return value of `ICamstackAddon.initialize()`. Both sections are optional —\n * addons that provide only capabilities omit `customActions`; addons that only\n * expose actions omit `providers`; pure consumers may return void.\n */\nexport interface AddonInitResult<TCatalog extends CustomActionsSpec = CustomActionsSpec> {\n readonly providers?: readonly ProviderRegistration[]\n readonly customActions?: TCatalog\n /**\n * Required iff `customActions` is set. One async handler per catalog entry —\n * a typed dispatch map rather than a single generic function so that each\n * handler's input/output types collapse to the concrete `z.infer<...>` of\n * its schema at the provider site (TypeScript cannot unify the output of a\n * generic `<K>(action: K, input) => Promise<...>` signature with a concrete\n * per-action return type, so the map form is strictly more typeable).\n */\n readonly actionHandlers?: {\n readonly [K in keyof TCatalog & string]: (\n input: z.infer<TCatalog[K]['input']>,\n ) => Promise<z.infer<TCatalog[K]['output']>>\n }\n}\n\n// ── Kernel services ─────────────────────────────────────────────────────\n/**\n * Infrastructure services injected by the kernel at boot time.\n * Grouped under `ctx.kernel` to separate kernel plumbing from\n * addon-level concerns (logger, settings, devices, api).\n */\nexport interface IKernelServices {\n /**\n * The Moleculer nodeID for this process (e.g. `'hub'` on the hub, or the\n * agent's own name on remote nodes). Addons use this to distinguish local\n * dispatch from remote dispatch without a direct Moleculer dependency.\n */\n readonly localNodeId?: string\n\n /**\n * Local storage provider — direct filesystem access with zero serialization.\n * Use for file I/O (write/read with Buffer data) that can't go through tRPC.\n * Always co-located: storage is a kernel-level service injected at boot.\n */\n readonly storage?: import('./storage.js').IStorageProvider\n\n /**\n * Per-process system-readiness tracker. One `ReadinessRegistry` is\n * created per broker by the kernel at boot and shared across every\n * addon on that broker — consumers that need `awaitReady` /\n * `onReadyState` should use this singleton rather than constructing\n * their own so subscriptions on the event bus stay de-duplicated and\n * the snapshot is consistent across the process.\n *\n * Tests that run without a real kernel (no `ctx.kernel`) should\n * either inject a mock or fall back to creating a local\n * `ReadinessRegistry`; the production code in kernel always\n * populates this field.\n */\n readonly readinessRegistry?: import('../capabilities/index.js').ITypedReadinessRegistry\n\n /**\n * Global device registry — read + mutate devices across all addons.\n * Hub-only: workers don't have a local registry (use `ctx.devices`\n * for per-addon scoped management, or `ctx.api.deviceManager.*` for\n * cross-process access).\n */\n readonly deviceRegistry?: import('../device/device-context.js').IDeviceRegistry\n\n /**\n * Per-addon scoped device management — create, register, remove, list devices.\n * Used by device provider addons (rtsp, onvif, frigate) to manage cameras.\n */\n readonly devices: import('../device/device-context.js').DeviceManagerApi\n\n /**\n * Cluster runtime — exposes the underlying message broker for addons that\n * need to participate in cluster-wide RPC outside the capability/tRPC\n * surface (e.g. log forwarding, hub readiness probes).\n *\n * Optional: only the agent and hub processes populate this. Forked workers\n * receive their broker through their own runner harness — they do not see\n * `cluster.broker` on ctx.kernel.\n */\n readonly cluster?: {\n readonly broker: IClusterBroker\n }\n\n /**\n * Kernel stream-probe bundle. Both entrypoints land on the same\n * hub-side `StreamProbeService` (ffprobe + HTTP reachability check\n * with a 1h cache). Hub resolves them directly; forked workers +\n * remote agents route through the `$stream-probe.*` Moleculer\n * broker service. Providers that call\n * `ctx.kernel.streamProbe.probe(url)` don't need to know where\n * they run.\n */\n readonly streamProbe?: IKernelStreamProbe\n\n /**\n * Kernel hardware-accel resolver. Platform-probe that picks an\n * ordered preference list of hw decode backends for the **local\n * host**. Every node (hub + forked worker + remote agent) runs its\n * own probe because hwaccel is inherently hardware-bound: decoder\n * addons on an NVIDIA agent get `['cuda', 'nvdec']`, the same addon\n * on a Mac hub gets `['videotoolbox']`. Cross-node queries for the\n * admin UI go via the `$hwaccel.resolve` Moleculer service\n * registered on every node.\n */\n readonly hwaccel?: IKernelHwAccel\n\n /**\n * Capability registry — provider lookups, native-cap resolution, wrapper listing.\n * Hub-only: forked workers don't see this (they use `ctx.api` for cross-process calls).\n */\n readonly capabilityRegistry?: ICapabilityRegistry\n}\n\n/**\n * Canonical hwaccel backend names. Accepted by both the `ffmpeg` CLI\n * (`-hwaccel <name>`) and node-av `HardwareDeviceContext.create()`\n * (`AV_HWDEVICE_TYPE_<upper>`), so a single string drives both layers.\n */\nexport type HwAccelBackend =\n | 'videotoolbox'\n | 'cuda'\n | 'nvdec'\n | 'vaapi'\n | 'qsv'\n | 'd3d11va'\n | 'dxva2'\n | 'amf'\n | 'vdpau'\n | 'drm'\n\n/** Resolution output — preference list + rationale for observability. */\nexport interface HwAccelResolution {\n readonly preferred: readonly HwAccelBackend[]\n readonly rationale: string\n}\n\nexport interface IKernelHwAccel {\n /**\n * Probe the local host and return the preferred backends.\n *\n * `prefer` accepts:\n * - `null` / `undefined` → auto, use platform probe\n * - `'none'` → hwaccel disabled; returns empty list\n * - an explicit backend name → single-entry list (skip probe)\n *\n * Implementations are pure functions over the host — safe to call\n * repeatedly; results are deterministic per host.\n */\n readonly resolve: (prefer?: HwAccelBackend | 'none' | null) => Promise<HwAccelResolution>\n}\n\nexport interface IKernelStreamProbe {\n /**\n * Run ffprobe on an RTSP / HTTP stream URL and return the raw\n * metadata. Use this when you need the width/height/codec/fps data\n * for profile classification. `classifyStream` / `classifyStreams`\n * in `@camstack/types` turn the metadata into a `StreamQuality`.\n */\n readonly probe: (url: string, options?: { force?: boolean }) => Promise<import('./device-capabilities/camera.js').StreamMetadata>\n /**\n * Generic field probe dispatcher — keys starting with `stream` run\n * ffprobe, others run an HTTP GET that aborts at response headers.\n * Returns a `FieldProbeResult` suitable for the admin UI's \"Test\"\n * button on any `probe`-typed form field.\n */\n readonly probeField: (key: string, value: unknown) => Promise<FieldProbeResult>\n}\n\n/**\n * Minimal structural shape of a cluster-message-broker (Moleculer in the\n * current implementation). Captured in @camstack/types so cluster-aware\n * addons can consume it without pulling a moleculer dependency.\n *\n * Add new methods sparingly — every addition becomes a contract the broker\n * implementation must satisfy.\n */\nexport interface IClusterBroker {\n readonly nodeID: string\n call<TParams = unknown, TResult = unknown>(\n action: string,\n params?: TParams,\n opts?: { nodeID?: string; timeout?: number },\n ): Promise<TResult>\n waitForServices(service: string | readonly string[], timeout?: number): Promise<void>\n readonly localBus: {\n on(event: string, handler: (payload: { node: { id: string } }) => void): void\n }\n}\n\nexport interface AddonContext<TConfig = Record<string, unknown>> {\n /** Immutable progressive ID */\n readonly id: string\n /** Pre-scoped logger */\n readonly logger: IScopedLogger\n /** System event bus */\n readonly eventBus: IEventBus\n /** Bootstrap configuration from server settings (read-only) */\n readonly addonConfig: Readonly<TConfig>\n /**\n * Private data directory for this addon.\n * Resolved via storageProvider.resolve('addons-data', '{addonId}/').\n * The addon owns this directory exclusively.\n */\n readonly dataDir: string\n\n // --- Kernel services ---\n\n /** Infrastructure services provided by the kernel. */\n readonly kernel: IKernelServices\n\n // --- Settings ---\n\n /**\n * Capability settings API — 3-level resolution (defaults → global → per-device).\n * Replaces context.config (IElementConfig) and context.addonConfig.\n */\n /**\n * Three-level settings store API.\n *\n * Raw, non-merging accessors for the addon's `addon_settings` row and\n * per-device overrides, plus a `(getSection, setSection)` pair for the\n * cluster-wide yml-backed sections consumed by the built-in\n * `system-config` addon.\n *\n * The addon combines these raw reads with its own schema via\n * `hydrateSchema()` inside `getAddonSettings / getGlobalSettings /\n * getDeviceSettings` on `ICamstackAddon`. There is no defaults\n * injection or cross-level merge at this layer.\n *\n * Cleanup note: the earlier `getGlobal / getDevice / updateGlobal /\n * updateDevice` trio (with a polymorphic `getGlobal({ section })`\n * overload) was removed after every caller migrated. The only\n * consumer of the yml-section path was `system-config`, which now\n * goes through the explicit `getSection / setSection` pair below.\n */\n readonly settings?: {\n /**\n * Read the raw addon store for this addon. Holds both `addon`-level\n * and `global`-level values; they're disjoint by schema invariant so\n * they can share one physical store. No defaults merged in. Returns\n * an empty object if the addon has never written anything.\n */\n readAddonStore(): Promise<Record<string, unknown>>\n\n /**\n * Write a patch into the addon store. Keys not in the patch are\n * preserved. Keys explicitly set to `null` are preserved as-is (they\n * do NOT fall back to schema default on subsequent reads — that\n * layering happens only at `hydrateSchema` time).\n */\n writeAddonStore(patch: Record<string, unknown>): Promise<void>\n\n /**\n * Read the raw per-device store for this addon + device. No defaults,\n * no merge with the addon store. Returns `{}` when no overrides exist.\n */\n readDeviceStore(deviceId: number): Promise<Record<string, unknown>>\n\n /**\n * Write a patch into the per-device store. Does NOT touch the\n * addon-level store. Keys preserved as in `writeAddonStore`.\n */\n writeDeviceStore(deviceId: number, patch: Record<string, unknown>): Promise<void>\n\n /**\n * Delete all keys for a device from the per-device store.\n * Use on device removal to guarantee no orphaned settings rows remain.\n */\n clearDeviceStore(deviceId: number): Promise<void>\n\n /**\n * Read a device's runtime-state blob — separate namespace from\n * `readDeviceStore` (which is the addon's config blob). Holds\n * mutable runtime signals discovered after boot (battery\n * snapshot, sleep flag, last-seen) that survive restart. Stored\n * under the kernel's reserved `__device-state` namespace so the\n * addon's config schema never sees it.\n */\n readDeviceRuntimeState(deviceId: number): Promise<Record<string, unknown>>\n\n /**\n * Replace the runtime-state blob for a device. The kernel's\n * `DeviceRuntimeState` always hands over the FULL persistent\n * slice — no shallow merge here, the latest blob wins.\n */\n writeDeviceRuntimeState(deviceId: number, data: Record<string, unknown>): Promise<void>\n\n /**\n * Delete the device's runtime-state blob. Use on device removal\n * so a recreated device with the same id starts clean instead\n * of inheriting stale runtime state from the previous lifetime.\n */\n clearDeviceRuntimeState(deviceId: number): Promise<void>\n\n /**\n * Read a cluster-wide yml-backed section (server, auth, ffmpeg,\n * logging, recording, retention — whatever\n * `ConfigManager.getSection` recognises). Returns the raw section\n * record with no schema merging. Used by the built-in\n * `system-config` addon to surface the legacy `config.yaml`\n * sections through its `getGlobalSettings()` method.\n */\n getSection(section: string): Promise<Record<string, unknown>>\n\n /**\n * Write a cluster-wide yml-backed section. Shallow-merges the patch\n * into the existing section so unrelated keys are preserved.\n * Hub-only — agents have no concept of yml sections and will\n * throw. Used by the `system-config` addon's\n * `updateGlobalSettings()` implementation.\n */\n setSection(section: string, patch: Record<string, unknown>): Promise<void>\n }\n\n /**\n * Full tRPC client — same API as the frontend.\n * Transport is transparent: direct caller (in-process), WSS (worker), or WSS (remote agent).\n * Use this for all server interactions: storage, events, devices, streaming, etc.\n */\n readonly api: import('../generated/addon-api.js').AddonApi\n\n /**\n * Binary / tool dependency manager. Addons call\n * `ctx.deps.ensureBinary(...)` / `ensureFfmpeg()` / `ensurePython()` to\n * materialise per-addon runtime deps under the shared `data/deps` tree.\n * Injected by the addon host so addons never import the concrete\n * implementation from `@camstack/core` directly.\n */\n readonly deps: IAddonDepsManager\n\n /**\n * Typed handle to the native provider of `cap` for `deviceId`. Bypasses the\n * currently-active wrapper — call this ONLY from the wrapper that owns\n * `cap`. Every other consumer should use `fetchDevice(id).<cap>.<method>()`\n * instead, which routes through the cap-router and respects the wrapper\n * chain.\n *\n * Wrapper-vs-consumer rule (memorise this):\n * - \"I am the wrapper for this cap and I need to delegate to the camera\n * driver\" → `getNativeProvider(cap, id)` (bypasses self, no recursion).\n * - \"I am consuming someone else's cap\" → `fetchDevice(id).<cap>...`\n * (uses the wrapper chain — cache, fallback, validation, etc.).\n *\n * Calling `fetchDevice` from inside the cap's own wrapper would re-enter\n * the wrapper and produce infinite recursion through the cap-router.\n *\n * Returns `null` when no addon has published a native provider for this\n * `(cap, deviceId)` — e.g. a camera driver that doesn't implement the cap\n * natively (RtspCamera without `snapshotUrl` does not register snapshot).\n * Wrappers use this to decide between native delegation and their own\n * fallback strategy; they MUST check for null.\n *\n * When the native is registered in this process, returns the local object\n * directly (zero serialization). When it lives in a forked worker, returns\n * a Moleculer-backed proxy constructed by the hub's native-cap fallback\n * (see `CapabilityRegistry.setNativeFallback`) — standard\n * `<addonId>.native-provider.<capName>.<method>` RPC path.\n */\n getNativeProvider<TCap extends CapabilityDefinition>(\n cap: TCap,\n deviceId: number,\n ): InferProvider<TCap> | null\n\n /**\n * Fetch a typed proxy for a device. THE canonical entry point for any\n * consumer that wants to read state, subscribe to changes, or dispatch\n * cap methods on a device — equivalent to `BackendClient.fetchDevice(id)`\n * on the client side.\n *\n * What you can do with the returned proxy:\n * - Read live state slices: `dev.state.battery.value` (typed\n * `BatteryStatus | undefined`, no provider call — reads the kernel's\n * mirrored snapshot).\n * - Subscribe to slice changes: `dev.state.battery.subscribe(cb)` —\n * refcounted, auto-seeds the callback with the current value.\n * - Invoke cap methods through the wrapper chain:\n * `await dev.snapshot.getSnapshot({...})`. Methods are typed against\n * each cap's definition; absent caps appear as `undefined`.\n *\n * Routing semantics: every method call on the returned proxy goes through\n * the tRPC cap-router → the active wrapper (if any) → the native provider.\n * That means a wrapper consuming its OWN cap via `fetchDevice` would\n * recurse — wrappers must use `getNativeProvider` instead. See the rule\n * documented on `getNativeProvider` above.\n *\n * Bindings are cached per-addon-context: the first call resolves bindings\n * via `deviceManager.getBindings.query`, subsequent calls reuse the cache.\n * The cache is invalidated implicitly when the device is removed.\n */\n fetchDevice(deviceId: number): Promise<import('../generated/device-proxy.js').DeviceProxy>\n\n /**\n * Runtime accessor for the capability registry — exposed to addons that\n * need to enumerate peers of a collection cap (e.g. `turn-provider`) or\n * grab the active singleton for a system cap. Injected by the kernel at\n * addon instantiation; absent when the addon is loaded in isolation\n * (tests, tooling), which is why the field is optional.\n */\n readonly capabilities?: CapabilitiesAccess\n\n /**\n * Returns a capability handle immediately (non-blocking). The handle tracks\n * ready/down state via the ReadinessRegistry and gates calls accordingly.\n * Repeated calls with the same `(capName, scope)` return the same cached instance.\n *\n * Use for runtime cap consumption where the cap may not be ready yet and\n * you want calls to block transparently via `handle.call(fn)`.\n */\n useCapability<T = unknown>(capName: string, scope?: ReadinessScope): ICapabilityHandle<T>\n\n /**\n * Blocks until the capability is ready, then returns the cached handle.\n * Throws `CapabilityUnavailableError` if the cap does not become ready\n * within `timeoutMs` (default 15 000ms).\n *\n * Use for boot sequencing where downstream work must not start until\n * the cap is confirmed available.\n */\n acquireCapability<T = unknown>(\n capName: string,\n scope?: ReadinessScope,\n opts?: { timeoutMs?: number },\n ): Promise<ICapabilityHandle<T>>\n\n /**\n * Subscribe to capability state changes (ready / down).\n * Returns an unsubscribe function. Thin wrapper over `ReadinessRegistry.onReadyState`.\n */\n onCapabilityStateChange(\n capName: string,\n scope: ReadinessScope,\n handler: (state: 'ready' | 'down') => void,\n ): () => void\n\n /**\n * Register a teardown callback that runs automatically when this\n * addon is shut down or restarted (e.g. by `restartAddon` after a\n * runtime update from the admin UI). Disposers run in LIFO order so\n * later registrations clean up before the resources they depend on.\n *\n * Use this for any side effect that survives across function calls\n * — `setInterval`, native socket listeners, watchers, file handles.\n * Capability/event subscriptions returned by `onCapabilityStateChange`\n * / `eventBus.subscribe` are unsubscribe functions you can pass\n * straight to `addDisposer`. Returns a manual unsubscribe so the\n * addon can drop the disposer early if needed.\n *\n * const stopTimer = setInterval(...);\n * ctx.addDisposer(() => clearInterval(stopTimer));\n *\n * const unsub = ctx.eventBus.subscribe('motion', cb);\n * ctx.addDisposer(unsub);\n *\n * The kernel calls each disposer once during `addon.shutdown()`. A\n * disposer that throws is logged and skipped — subsequent disposers\n * still run.\n */\n addDisposer(fn: () => void | Promise<void>): () => void\n}\n\n/**\n * Runtime-only capability registry surface — kept minimal on purpose.\n * `getCollection` returns every registered provider for a collection cap\n * (order-unstable); `get` returns the active provider for a singleton.\n * Both return `undefined` when the cap isn't declared or has no provider.\n */\nexport interface CapabilitiesAccess {\n /** All providers registered on a collection capability (by cap name). */\n getCollection<T = unknown>(name: string): readonly T[] | undefined\n /**\n * Like `getCollection` but returns `[addonId, provider]` tuples so\n * callers can attribute work back to the contributing addon. The\n * `addonId` for cap-routed remote providers is `<addonName>@<workerNodeId>`\n * (e.g. `decoder-nodeav@dev-agent-1/decoder-nodeav`); local providers\n * are just `<addonName>` (no `@`). Used by stream-broker to filter the\n * decoder collection by the orchestrator's per-camera placement\n * decision (`getDecoderAssignment.decoderNodeId`).\n */\n getCollectionEntries<T = unknown>(name: string): readonly (readonly [string, T])[] | undefined\n /** The active provider of a singleton capability (by cap name). */\n get<T = unknown>(name: string): T | undefined\n}\n\nexport interface ICamstackAddon {\n readonly id?: string\n /** Addon declaration — injected by the framework from package.json. Do not declare in addon class. */\n readonly manifest?: AddonDeclaration\n /**\n * Initialize the addon. Return capability provider bindings for the kernel\n * to register in the CapabilityRegistry. Returning `void` or an empty array\n * is valid for addons that don't provide capabilities (e.g. pure consumers).\n *\n * The kernel validates that every capability declared in `package.json`\n * has a corresponding entry in the returned array.\n *\n * @example\n * ```ts\n * async initialize(ctx: AddonContext): Promise<AddonInitResult> {\n * this.detector = new WasmMotionDetector()\n * await this.detector.load()\n * return { providers: [{ capability: motionDetectionCapability, provider: this }] }\n * }\n * ```\n */\n initialize(context: AddonContext): Promise<ProviderRegistration[] | AddonInitResult | void>\n /**\n * Called by the isolated-process runner after `broker.start()`.\n * In-process addons never need this — the hub broker is already running\n * when `initialize()` fires. Forked children emit readiness inside\n * `initialize()` before the broker is live; this re-emits it once the\n * transport is ready so consumers actually receive the event.\n */\n postBrokerStart(): void\n /**\n * Optional hook. Fires on forked workers / remote agents once the\n * broker has started AND the hub node has been discovered via the\n * Moleculer `$node.connected` event — the moment at which\n * `ctx.api.*` calls to hub-provided capabilities become safe.\n *\n * Use this instead of `initialize()` for any bootstrap work that\n * needs to query the hub (e.g. restoring persisted state, reading\n * hub-owned settings). Calling `ctx.api.*` from `initialize()` on a\n * worker is a documented foot-gun: the broker is not connected yet\n * and requests either time out or throw \"Service not found\".\n *\n * On the hub itself this never fires (the hub is its own node; there\n * is no separate hub to wait for).\n */\n onHubReachable?(): Promise<void> | void\n shutdown(): Promise<void>\n\n // Cleanup: the legacy `getConfigSchema / getConfig / onConfigChange`\n // trio was removed. Every addon implements the three-level settings\n // API below and nothing on the server reads the legacy shape any\n // more — the adapter shim in `addon-registry.service.ts` and the\n // `addons.getConfigSchema / getConfig / updateConfig` tRPC endpoints\n // are gone.\n\n // -- Three-level settings API --\n //\n // An addon implements only the levels it needs. Each level has a\n // disjoint schema — field keys must not collide across levels. Each\n // getter returns a hydrated `ConfigUISchemaWithValues` (schema + values\n // inline) so the admin UI can render in one pass.\n //\n // Level 1 — addon settings: pipeline/context-specific fields, rendered\n // by whatever page knows the addon belongs to it (e.g. the\n // Pipeline page hardcodes PIPELINE_CAPABILITIES and iterates\n // providers).\n // Level 2 — node-global settings: node-level fields shown in Cluster →\n // NodeDetailPanel → Settings. Dynamic discovery: an addon\n // that doesn't implement `getGlobalSettings` doesn't appear\n // there.\n // Level 3 — device settings: per-camera fields shown in Device\n // Overrides.\n //\n // All six methods are OPTIONAL. They will become the canonical way\n // addons expose settings once Phase 3 removes the deprecated trio\n // above. See docs/superpowers/specs/2026-04-11-settings-redesign-design.md.\n\n /** Level 1 — node-global settings (schema + values). Appears in\n * Cluster → Settings tab. `overlay` is an optional preview merge\n * consumed by override-mode UIs (benchmark) so cascade-aware\n * addons can re-derive dependent options without touching the\n * persisted store. */\n getGlobalSettings?(overlay?: Record<string, unknown>): Promise<ConfigUISchemaWithValues>\n updateGlobalSettings?(patch: Record<string, unknown>): Promise<void>\n\n /** Level 2 — per-device settings (schema + values). Appears in\n * Device Overrides. */\n getDeviceSettings?(deviceId: number): Promise<ConfigUISchemaWithValues>\n updateDeviceSettings?(deviceId: number, patch: Record<string, unknown>): Promise<void>\n\n /**\n * Called at boot after initialize() with all previously persisted devices.\n * The addon should re-instantiate device objects and register them via context.devices.register().\n */\n restoreDevices?(savedDevices: readonly import('../device/device-management.js').SavedDevice[]): Promise<void>\n\n // -- Model catalog (optional — only for inference addons) --\n getModelCatalog?(): unknown[]\n // `getModelRequirements` and `configure` were removed — inference addons\n // now resolve their own config inside `initialize()` by calling\n // `ctx.api.platformProbe.resolveInferenceConfig.query({ requirements })`.\n\n // -- Inference methods (optional — only for detection/classification addons) --\n\n /** Load/prepare a model engine for a given modelId. Called before process()/classifyAudio(). */\n ensureEngine?(modelId: string): Promise<void>\n\n /** Unified vision inference — handles detection, cropping, classification, refinement.\n * Input is FrameInput (root) or CropInput (child node). Output shape determines slot. */\n process?(input: unknown): Promise<unknown>\n\n /** Audio classification — separate from vision pipeline */\n classifyAudio?(input: unknown): Promise<unknown>\n}\n\n/** Declaration of a UI page provided by an addon */\nexport interface AddonPageDeclaration {\n /** Unique page ID (scoped to addon) */\n readonly id: string\n /** Display label for sidebar */\n readonly label: string\n /** Lucide icon name for sidebar */\n readonly icon: string\n /** Route path (e.g., '/benchmark') */\n readonly path: string\n /**\n * Module Federation remote name — must match the `name` field on the\n * page addon's `federation()` plugin config. Used by admin-ui's\n * `<AddonPageLoader>` to call `loadRemote('<remoteName>/page')`.\n * Conventionally `addon_<id>_page` (snake_case; MF names cannot\n * contain hyphens).\n */\n readonly remoteName: string\n /**\n * Bundle filename inside the addon's `dist/` dir served at\n * `/api/addon-pages/<addonId>/<bundle>`. With Module Federation this\n * is always `'remoteEntry.js'`.\n */\n readonly bundle: string\n}\n\n/** Provider interface for addons that expose UI pages */\nexport interface IAddonPageProvider {\n readonly id: string\n listPages(): readonly AddonPageDeclaration[]\n}\n\n/** Provider interface for the admin UI shell (singleton capability) */\nexport interface IAdminUI {\n getStaticDir(): string\n getVersion(): string\n}\n\n/**\n * Full addon declaration — lives in package.json `camstack.addons[]`.\n * This is the SINGLE SOURCE OF TRUTH for addon identity and metadata.\n * Addon classes no longer declare a `manifest` property.\n */\nexport interface AddonDeclaration {\n // ── Identity ────────────────────────────────────────────────────────\n readonly id: string\n /** JS entry point relative to package root (e.g., \"./dist/addon.js\") */\n readonly entry?: string\n /** Human-readable name */\n readonly name?: string\n /** Semver version */\n readonly version?: string\n /** Short description */\n readonly description?: string\n\n // ── Display ────────────────────────────────────────────────────────\n /** Relative path to SVG icon asset within the addon package */\n readonly icon?: string\n /** Brand hex color for UI display (e.g., \"#3b82f6\") */\n readonly color?: string\n\n // ── Runtime ────────────────────────────────────────────────────────\n readonly slot?: PipelineSlot | null\n /** Instance mode: 'unique' or 'multiple'. Default: 'multiple' */\n readonly instanceMode?: 'unique' | 'multiple'\n /** Whether this addon is protected (required by the system, cannot be uninstalled) */\n readonly protected?: boolean\n /**\n * Group-runner execution model.\n *\n * Every addon lives in a forked subprocess; the question is which one.\n * Addons sharing the same `group` value share one subprocess and one\n * Moleculer broker, so cap calls between them resolve in-process via\n * `localProviderLink` (zero IPC). Different groups speak via Moleculer\n * TCP.\n *\n * Defaults (when `execution` is omitted entirely):\n * - `placement: 'hub-only'` — addon does NOT deploy to agents.\n * - `group: 'main-group'` — joins the catch-all subprocess.\n *\n * Examples:\n * ```jsonc\n * // hub-only addon, joins main-group (most common)\n * \"execution\": {}\n *\n * // deployable to any node (cluster scenario)\n * \"execution\": { \"placement\": \"any-node\" }\n *\n * // bundle detection on a dedicated subprocess\n * \"execution\": { \"placement\": \"any-node\", \"group\": \"detection\" }\n *\n * // hardware-bound, only runs on agents (no hub instance)\n * \"execution\": { \"placement\": \"agent-only\" }\n *\n * // crash-isolated (private subprocess; unique group per addon)\n * \"execution\": { \"group\": \"untrusted-foo\" }\n * ```\n */\n readonly execution?: AddonExecution\n\n // ── Capabilities ───────────────────────────────────────────────────\n /** Capabilities this addon provides */\n readonly capabilities?: readonly CapabilityDeclaration[]\n /** UI pages provided by this addon */\n readonly pages?: readonly AddonPageDeclaration[]\n\n // ── Pipeline-specific ──────────────────────────────────────────────\n readonly requiredFeatures?: readonly string[]\n readonly inputClasses?: readonly string[]\n readonly outputClasses?: readonly string[]\n readonly requiredSteps?: readonly RequiredStep[]\n readonly supportsCustomModels?: boolean\n readonly mayRequirePython?: boolean\n /** Whether this addon performs active inference. Passive addons are excluded from inference pipeline. Default: true. */\n readonly passive?: boolean\n /**\n * Label output type for classifier/recognizer addons.\n *\n * `classification` — generic class name (e.g. `'bird'`, `'labrador'`)\n * `face` — recognised face identity\n * `plate` — recognised licence plate OCR\n * `recognition` — generic recognition result (embedding gallery)\n */\n readonly labelOutputType?: 'classification' | 'face' | 'plate' | 'recognition'\n\n // ── Python (auto-managed deps) ─────────────────────────────────────\n /**\n * Optional Python runtime dependencies. Declares the pip requirements\n * file the kernel must install into the embedded portable Python\n * before this addon's `onInitialize()` runs. Resolved relative to the\n * addon's package root.\n *\n * Idempotent: install is keyed on (file basename + sha256 of contents)\n * via the marker dir under the python install — back-to-back boots\n * skip the pip subprocess after the first install.\n *\n * Example:\n * ```jsonc\n * \"camstack\": {\n * \"addons\": [{\n * \"id\": \"detection-pipeline\",\n * \"python\": { \"requirements\": \"./python/requirements.txt\" }\n * }]\n * }\n * ```\n *\n * Backend / feature-specific deps that depend on user settings should\n * NOT be listed here — addons install those lazily via\n * `ctx.deps.installPythonRequirements(absolutePath)`.\n */\n readonly python?: AddonPythonRequirements\n\n // ── Config ─────────────────────────────────────────────────────────\n /** Default configuration values */\n readonly defaultConfig?: Readonly<Record<string, unknown>>\n}\n\n/**\n * Manifest declaration for an addon's Python runtime dependencies.\n * See `AddonDeclaration.python`.\n */\nexport interface AddonPythonRequirements {\n /**\n * Path to the pip requirements file the kernel installs into the\n * embedded portable Python before `onInitialize()` runs. Resolved\n * relative to the addon package root.\n */\n readonly requirements: string\n}\n\nexport interface AddonPackageManifest {\n /** Human-readable package name for UI display (e.g., \"CamStack Vision\") */\n readonly displayName?: string\n readonly addons: readonly AddonDeclaration[]\n /**\n * Optional bundle metadata for npm packages that ship multiple addon\n * entries (e.g., `@camstack/addon-pipeline` with 7 entries,\n * `@camstack/addon-remote-storage` with 3 entries). When set, the\n * Addons admin UI renders the entries as collapsible children under a\n * single bundle card. The npm package boundary IS the install/update\n * unit — operator-facing actions (Install, Update, Uninstall) act on\n * the bundle, not on individual children. Per-child enable/disable +\n * settings are still surfaced individually.\n *\n * Single-entry packages omit this field; their UI stays a standalone\n * card. Multi-entry packages WITHOUT this field fall back to deriving\n * displayName from `package.json:name`.\n */\n readonly bundle?: AddonBundleManifest\n /**\n * Native node modules that the addon needs at runtime but cannot be\n * bundled (`.node` binary files require ABI-matched compilation).\n * Phase E of the bundles + builder modernization spec — mirror of\n * the Python `requirements.txt` pattern, but for native Node deps.\n *\n * Format: package name → semver range, exactly like\n * `package.json#dependencies`. NOT listed in the package's regular\n * `dependencies` field (so workspace `npm install` skips them), but\n * the addon installer reads this field at install time and runs:\n *\n * npm install --prefix <addonDir> <name>@<range>\n * electron-rebuild -m <addonDir> -w <name> (for Electron host)\n * npm rebuild --prefix <addonDir> <name> (for plain Node host)\n *\n * The host's runtime ABI (Electron 35 = Node ABI 127, plain Node 22 =\n * ABI 133) is detected at install time. Both targets are first-class.\n *\n * Example:\n * ```jsonc\n * \"camstack\": {\n * \"nativeDependencies\": {\n * \"better-sqlite3\": \"^12.8.0\",\n * \"ssh2\": \"^1.16.0\"\n * }\n * }\n * ```\n *\n * Phase E will also produce prebuilt `.node` binaries for both ABIs\n * during `npm publish`, shipped in the tarball under\n * `dist/native-prebuilds/<runtime>-<abi>-<arch>/`. The installer\n * tries the matching prebuild first; falls back to source rebuild\n * only when no prebuild exists for the host triple.\n */\n readonly nativeDependencies?: Readonly<Record<string, string>>\n}\n\nexport interface AddonBundleManifest {\n /** Display name shown on the bundle card header (e.g., \"Pipeline\"). */\n readonly displayName: string\n /** Optional 1-2 sentence description for the operator. */\n readonly description?: string\n /** Optional icon path relative to the package root. */\n readonly icon?: string\n}\n\n/**\n * Where an addon may be deployed. The kernel honours this when picking\n * which node hosts the group-runner that will load the addon.\n *\n * - `'hub-only'` — runs only on the hub process. Default.\n * - `'agent-only'` — runs only on remote agent processes.\n * - `'any-node'` — eligible to run on either hub or agents.\n */\nexport type AddonPlacement = 'hub-only' | 'agent-only' | 'any-node'\n\n/**\n * Effective execution model for an addon. See `AddonDeclaration.execution`\n * for the full semantics.\n */\nexport interface AddonExecution {\n readonly placement?: AddonPlacement\n /**\n * Subprocess group label. Addons sharing the same value share one\n * forked subprocess + one Moleculer broker. Defaults to `'main-group'`\n * — the catch-all bucket for every addon that doesn't opt out.\n */\n readonly group?: string\n}\n\nexport const DEFAULT_ADDON_GROUP = 'main-group'\nexport const DEFAULT_ADDON_PLACEMENT: AddonPlacement = 'hub-only'\n\n/**\n * Resolve the effective `AddonExecution` for an addon. Returns a fully\n * populated value (placement + group always set) so callers can read\n * either field without a separate fallback.\n */\nexport function resolveAddonExecution(\n decl: Pick<AddonDeclaration, 'execution'>,\n): Required<AddonExecution> {\n return {\n placement: decl.execution?.placement ?? DEFAULT_ADDON_PLACEMENT,\n group: decl.execution?.group ?? DEFAULT_ADDON_GROUP,\n }\n}\n\n/** True when the addon may run on a remote agent (deployable from hub). */\nexport function isDeployableToAgent(decl: Pick<AddonDeclaration, 'execution'>): boolean {\n const placement = resolveAddonExecution(decl).placement\n return placement === 'any-node' || placement === 'agent-only'\n}\n\n/** True when the addon is skipped on the hub (agent-only deployment). */\nexport function isAgentOnlyPlacement(decl: Pick<AddonDeclaration, 'execution'>): boolean {\n return resolveAddonExecution(decl).placement === 'agent-only'\n}\n\n/** Convenience accessor — the resolved subprocess group label. */\nexport function resolveAddonGroup(decl: Pick<AddonDeclaration, 'execution'>): string {\n return resolveAddonExecution(decl).group\n}\n\n/** Convenience accessor — the resolved placement (defaults to `hub-only`). */\nexport function resolveAddonPlacement(decl: Pick<AddonDeclaration, 'execution'>): AddonPlacement {\n return resolveAddonExecution(decl).placement\n}\n\n// ── Kernel-internal context ─────────────────────────────────────────────\n/**\n * Extended AddonContext used exclusively by the kernel (hub + worker boot\n * sequences) to wire providers into the CapabilityRegistry after\n * `initialize()` returns. Addon code never sees this — it only receives\n * the public `AddonContext`.\n */\nexport interface InternalAddonContext extends AddonContext {\n /** Register a provider in the local capability registry. Kernel-only. */\n registerProvider(capabilityName: string, provider: unknown): void\n\n /** Resolve the preferred provider for a capability. Kernel-only. */\n resolveProvider<T = unknown>(capabilityName: string): T | null\n}\n","export enum EventCategory {\n // System\n SystemBoot = 'system.boot',\n SystemAddonsReady = 'system.addons-ready',\n SystemRestarting = 'system.restarting',\n /**\n * Readiness transition for a capability provider. Every producer emits\n * this event on `onInitialize` completion, `onDestroy`, and\n * `$node.reconnect`; every consumer that needs to gate on a cross-process\n * cap subscribes via the kernel's readiness module (`awaitReady` /\n * `onReadyState`) instead of polling. Payload is\n * `SystemReadyStatePayload` — see event-bus.ts.\n */\n SystemReadyState = 'system.ready-state',\n\n // Addon lifecycle\n AddonStarted = 'addon.started',\n AddonStopped = 'addon.stopped',\n AddonRestarted = 'addon.restarted',\n AddonUpdated = 'addon.updated',\n AddonInstalled = 'addon.installed',\n AddonUninstalled = 'addon.uninstalled',\n AddonCrashed = 'addon.crashed',\n AddonError = 'addon.error',\n AddonPageReady = 'addon.page-ready',\n AddonWidgetReady = 'addon.widget-ready',\n /**\n * Addon failed to load (import or initialize). Emitted by the kernel's\n * AddonHealthMonitor only AFTER the boot grace period ends — failures\n * during the first 5 minutes are silently retried without alerting\n * (slow-starting addons must have time to come up). Post-grace, this\n * event is emitted exactly once per failure-streak; AlertCenter\n * consumes it to create a persistent operator-visible alert.\n *\n * Payload: `{ packageName, addonId?, error: { message, stack }, retryCount, nextRetryAt }`.\n */\n AddonLoadFailed = 'addon.load-failed',\n /**\n * Addon recovered from a previous failure. Emitted when an addon\n * transitions from `failed` back to `healthy` (typically via the\n * monitor's auto-retry loop, or after manual `addons.retryLoad`).\n * AlertCenter dismisses the corresponding `AddonLoadFailed` alert\n * on this event.\n */\n AddonLoadRecovered = 'addon.load-recovered',\n /**\n * Monitor scheduled the next retry for a failed addon. Transient —\n * surfaced to the UI for live-updating the \"next retry in Ns\"\n * countdown on the Addons page row, NOT persisted as an alert.\n */\n AddonRetryScheduled = 'addon.retry-scheduled',\n /**\n * Monitor is attempting to reload a failed addon NOW. UI uses this\n * to show a spinner during the retry attempt. Same transient nature\n * as AddonRetryScheduled.\n */\n AddonRetryAttempting = 'addon.retry-attempting',\n\n // Device\n DeviceRegistered = 'device.registered',\n DeviceUnregistered = 'device.unregistered',\n DeviceEnabled = 'device.enabled',\n DeviceDisabled = 'device.disabled',\n DeviceSettingsUpdated = 'device.settings-updated',\n /**\n * Emitted when the set of native capability providers bound to a device\n * changes — e.g. an addon registers a new native cap via\n * `DeviceContext.registerNativeCap`, or all native bindings for a device\n * are cleared on removal. Hub consumers re-resolve device-proxy routes\n * when this fires.\n */\n DeviceBindingsChanged = 'device.bindings-changed',\n /**\n * Emitted when the operator-organisational meta surface changes\n * (`name` / `location` / `disabled`). Payload: `{deviceId, field,\n * value}`. Live consumers (UI device list, alert center) react\n * without polling. Distinct from `DeviceSettingsUpdated` which\n * fires on hardware-config changes (host/port/credentials/etc).\n */\n DeviceMetaChanged = 'device.meta-changed',\n /**\n * Emitted by DeviceStreamWiringService after a successful\n * `stream-broker.registerDeviceStreams` call. Payload includes\n * deviceId — consumers look up the full registered device info via\n * `brokerManager.getRegisteredDevice(deviceId)`.\n *\n * Replaces the legacy `StreamRouterService.onDeviceRegistered` callback.\n */\n DeviceStreamsRegistered = 'device.streams-registered',\n\n // Integration\n IntegrationEnabled = 'integration.enabled',\n IntegrationDisabled = 'integration.disabled',\n IntegrationDeleted = 'integration.deleted',\n\n // Provider\n ProviderStarted = 'provider.started',\n ProviderStopped = 'provider.stopped',\n\n // Process\n ProcessCrashed = 'process.crashed',\n ProcessRestartScheduled = 'process.restart_scheduled',\n ProcessRestarted = 'process.restarted',\n\n // Recording\n RecordingStarted = 'recording.started',\n RecordingStopped = 'recording.stopped',\n RecordingError = 'recording.error',\n RecordingHealthDegraded = 'recording.health.degraded',\n RecordingStorageCritical = 'recording.storage.critical',\n RecordingSegmentWritten = 'recording.segment.written',\n RecordingPolicyFallback = 'recording.policy.fallback',\n RecordingRetentionCompleted = 'recording.retention.completed',\n\n // Detection & analysis\n DetectionEvent = 'detection.event',\n\n // Session tracking\n SessionTrackNew = 'session.track.new',\n SessionTrackExpired = 'session.track.expired',\n\n // Benchmark\n BenchmarkProgress = 'benchmark.progress',\n\n // Platform probe\n PlatformProbePhase = 'platform-probe.phase',\n\n // Pipeline & inference\n PipelineProgress = 'pipeline.progress',\n /** Per-frame execution trace emitted by the pipeline executor for live observability. */\n PipelineTrace = 'pipeline.trace',\n /**\n * Raw inference output emitted by `addon-pipeline-runner` after running the\n * detection pipeline on a frame. Carries the `FrameResult` (with\n * `detections[]`, `width`/`height`, timing debug) — never the frame\n * buffer itself. Hub-side consumers (analysis pipeline, class filters,\n * notifications) subscribe to this and re-emit `detection.result` after\n * post-processing.\n */\n PipelineInferenceResult = 'pipeline.inference-result',\n /**\n * Camera lifecycle event emitted by `addon-pipeline-orchestrator` when it\n * assigns or unassigns a camera to/from an agent. Carries no frame data;\n * pure observability for UI dashboards and metrics consumers.\n */\n PipelineCameraAssigned = 'pipeline.camera-assigned',\n PipelineCameraUnassigned = 'pipeline.camera-unassigned',\n /**\n * Per-camera pipeline config was mutated by the orchestrator\n * (3-level settings change via `setAgentAddonDefaults` /\n * `setCameraStepToggle` / `setCameraPipelineForAgent` or a\n * pipeline-scoped `applyDeviceSettingsPatch`). Orchestrator\n * subscribes to its own emission to hot-reload the assigned runner\n * via `attachCamera` so the next frame executes against the new\n * engine/steps without waiting for a rebalance or the next\n * `DeviceStreamsRegistered` cycle.\n */\n PipelineCameraUpdated = 'pipeline.camera-updated',\n /**\n * Periodic snapshot of per-node pipeline-runner load\n * (`RunnerLocalLoad`). Emitted ~1Hz by every runner so UI dashboards\n * subscribe instead of polling `pipelineRunner.getLocalLoad`.\n * `nodeId` carried in the payload + on `event.source.nodeId`.\n */\n PipelineRunnerLoadSnapshot = 'pipeline.runner-load-snapshot',\n /**\n * Periodic snapshot of per-camera pipeline metrics (`CameraMetrics`\n * + `deviceId` + `nodeId`). Emitted ~1Hz by every runner for each\n * attached camera. UI subscribes to drive overlay phase / fps /\n * inference time without polling `getCameraMetrics`.\n */\n PipelineCameraMetricsSnapshot = 'pipeline.camera-metrics-snapshot',\n /**\n * Periodic snapshot of stream-broker per-broker statistics (input\n * fps, decoded fps, bitrate, codec). Emitted ~1Hz by every\n * stream-broker process for each active broker so the UI can drive\n * the Stream / Cluster dashboards without polling\n * `streamBroker.listAllProfileSlots` and friends.\n */\n StreamBrokerMetricsSnapshot = 'stream-broker.metrics-snapshot',\n /**\n * Cap event fired by `stream-broker` when a profile slot enters\n * \"demanded\" state — a cam stream has been assigned and at least one\n * consumer (RTSP restream, decoded subscriber, WebRTC session, …) is\n * present. Camera-provider addons (Reolink Baichuan push, …)\n * subscribe to this category to start their underlying transport\n * lazily. Payload: `{ deviceId, camStreamId, profile }`.\n */\n StreamBrokerOnCamStreamDemand = 'stream-broker.onCamStreamDemand',\n /**\n * Cap event fired by `stream-broker` when the last consumer leaves a\n * previously-demanded cam stream. Providers tear down their\n * underlying transport on receipt. Payload: `{ deviceId, camStreamId }`.\n */\n StreamBrokerOnCamStreamIdle = 'stream-broker.onCamStreamIdle',\n /**\n * Cap event fired by `stream-broker` when a broker fails to dial a\n * managed-loopback source (today: `pull-rfc4571`) and the publisher\n * needs to refresh the cached URL. Mirrors Scrypted's\n * `ensureRfcServer` self-heal pattern: the lib's TCP server\n * idle-tears-down on its own schedule, so a re-publish with a fresh\n * `host:port` is the only way to keep the broker dialable. Camera\n * providers (Reolink Baichuan native, …) subscribe and respond by\n * re-running their publish pipeline.\n * Payload: `{ deviceId, camStreamId, brokerId }`.\n */\n StreamBrokerOnRequestStreamSourceRefresh = 'stream-broker.onRequestStreamSourceRefresh',\n /**\n * Generic per-device runtime-state change. Fired by `device-manager`\n * whenever a persisted slice in any cap's `runtimeState` shape\n * mutates. Payload: `{deviceId, capName, slice}`. Subscribers are\n * the `deviceState` cap router (cross-process listeners) and the\n * deviceProxy reactive bindings (`device.state.<capName>.value`).\n * Cap-specific events (`battery.onStatusChanged`, …) still fire\n * — they're authoritative for callers that want a typed payload\n * without filtering on `capName`.\n */\n DeviceStateChanged = 'device.state-changed',\n /**\n * Cap event fired by every device that registers the `battery`\n * capability. Mirrors the cap definition's `onStatusChanged`. Carries\n * `{ deviceId, status: BatteryStatus }`. Subscribers (alert center,\n * snapshot wrapper, UI) react to charge/sleep transitions without\n * polling `batteryCapability.getStatus`.\n */\n BatteryOnStatusChanged = 'battery.onStatusChanged',\n /**\n * Cap event fired by every device that registers the `doorbell`\n * capability. Mirrors `doorbellCapability.events.onPressed`. Carries\n * `{ deviceId, timestamp }`. Operators consuming the UI subscribe\n * here to render transient ring toasts and a \"Recent presses\" row\n * on the device detail page.\n */\n DoorbellOnPressed = 'doorbell.onPressed',\n /**\n * Periodic snapshot of the per-node detection-pipeline engine\n * registry (loaded engines, models resident, in-use cameras, idle\n * TTL). Emitted ~0.2Hz (every 5 s) by every detection-pipeline\n * process. The Engines tab subscribes to drive its inventory view\n * without polling `pipelineExecutor.listLoadedEngines`.\n */\n PipelineEngineMetricsSnapshot = 'pipeline.engine-metrics-snapshot',\n /**\n * Cluster topology snapshot. Carries the same payload returned by\n * `nodes.topology` (every reachable node + addons + processes).\n * Emitted by the hub on any agent / addon lifecycle change\n * (debounced) plus a periodic safety net. Replaces UI polling on\n * `nodes.topology` — admin-ui dashboards subscribe to drive the\n * cluster view directly from the event payload.\n */\n ClusterTopologySnapshot = 'cluster.topology-snapshot',\n /**\n * Periodic per-node system metrics snapshot (CPU / memory / GPU /\n * disk / network). Emitted ~0.2 Hz by the metrics-provider addon\n * for each node. Drives the dashboard SystemStatus / ProcessResources\n * widgets without polling `metricsProvider.getCurrent`.\n */\n MetricsNodeResourcesSnapshot = 'metrics.node-resources-snapshot',\n /**\n * Periodic per-node process-tree snapshot (camstack-related pids\n * with ghost / managed / root classification). Emitted ~0.2 Hz by\n * the metrics-provider addon. Drives the Cluster → Processes tab\n * without polling `metricsProvider.listNodeProcesses`.\n */\n MetricsNodeProcessesSnapshot = 'metrics.node-processes-snapshot',\n /**\n * Capability binding change event emitted by `addon-pipeline-orchestrator`\n * when a user changes which addon implements a cap on a node. Subscribed\n * by every kernel process to update its local `preferredProviderRegistry`\n * so future capability lookups respect the new binding.\n */\n /**\n * A capability binding was changed for a node — addon X now provides\n * capability `cap` on node `nodeId`. Lives under the generic\n * `capability.*` namespace because capability bindings are a kernel-\n * level concept used by many addons, not strictly pipeline-scoped.\n */\n CapabilityBindingChanged = 'capability.binding-changed',\n ModelDownloadProgress = 'model.download.progress',\n\n // Agent\n AgentRegistered = 'agent.registered',\n AgentUnregistered = 'agent.unregistered',\n AgentOnline = 'agent.online',\n AgentOffline = 'agent.offline',\n /** Forked worker process (e.g. hub/pipeline) connected to the broker. */\n WorkerOnline = 'worker.online',\n /** Forked worker process disconnected from the broker. */\n WorkerOffline = 'worker.offline',\n AgentTaskDispatched = 'agent.task.dispatched',\n AgentTaskAssigned = 'agent.task.assigned',\n AgentTrpcConnected = 'agent.trpc.connected',\n AgentWsConnected = 'agent.ws.connected',\n AgentWsDisconnected = 'agent.ws.disconnected',\n AgentBackupActivated = 'agent.backup.activated',\n\n // Detection settings\n OrchestrationSettingsUpdated = 'orchestration.settings-updated',\n\n /**\n * Per-agent hwaccel preference changed (user override set, cleared, or\n * re-probed). Observability event — decoders pull the current pref at\n * `createSession`, so running sessions keep their current backend until\n * they rotate naturally (camera add/remove, stream restart). Future\n * work can wire a listener in stream-broker that force-rotates live\n * sessions; for now this event powers logs + admin-UI toast feedback.\n */\n PipelineAgentHwaccelChanged = 'pipeline.agent-hwaccel-changed',\n\n // Motion analysis\n MotionAnalysis = 'detection.motion-analysis',\n /** All raw motion zones from CCL before minArea filter — for UI debug overlay. */\n MotionZonesRaw = 'detection.motion-zones-raw',\n /**\n * Per-camera motion phase transition (`watching ↔ active`) emitted\n * by the runner. Mirrors the `motion.onMotionChanged` cap event\n * surface — payload `MotionOnMotionChangedPayload` carries\n * `{deviceId, detected, timestamp, source, regions?}`. Subscribers\n * include addons that need to react to motion state without\n * polling the runtime-state mirror.\n */\n MotionOnMotionChanged = 'motion.on-motion-changed',\n\n // Detection extended\n DetectionResult = 'detection.result',\n DetectionRaw = 'detection.raw',\n DetectionCameraNative = 'detection.camera-native',\n /**\n * Canonical per-chunk live audio pipeline output. Payload is\n * `PipelineAudioInferenceResultPayload` carrying a full `AudioResult`\n * (level + detections + debug). Lives on the pipeline.* namespace\n * alongside `pipeline.inference-result` (video) for symmetry.\n */\n PipelineAudioInferenceResult = 'pipeline.audio-inference-result',\n DetectionPhaseTransition = 'detection.phase-transition',\n ProviderMotion = 'provider.motion',\n ProviderDetection = 'provider.detection',\n\n // Enrichment\n EnrichmentEmbeddingStored = 'enrichment.embedding.stored',\n EnrichmentSceneStateChanged = 'enrichment.scene.state-changed',\n EnrichmentActivitySummary = 'enrichment.activity.summary',\n\n // Pipeline analytics\n PipelineAnalyticsTrackStarted = 'pipeline-analytics.track-started',\n PipelineAnalyticsTrackEnded = 'pipeline-analytics.track-ended',\n PipelineAnalyticsDetectionEvent = 'pipeline-analytics.detection-event',\n PipelineAnalyticsFrameTracked = 'pipeline-analytics.frame-tracked',\n\n // Provider-specific\n FrigateLiveEvent = 'frigate.live-event',\n\n // Camera streams\n CameraStreamsProfileSlotsChanged = 'camera-streams.onProfileSlotsChanged',\n /**\n * Stream-broker health watchdog. Per-broker (deviceId/profile) emission.\n * `stream.offline` fires after STREAM_STALE_TIMEOUT_MS without an encoded\n * packet on an active broker. `stream.online` fires on first packet\n * after a stale gap (or on initial first packet). Payload includes\n * the assigned camStreamId as `profileKey`.\n */\n StreamOnline = 'stream.online',\n StreamOffline = 'stream.offline',\n\n // Network\n NetworkTunnelStarted = 'network.tunnel.started',\n NetworkTunnelStopped = 'network.tunnel.stopped',\n /** Fired by the `local-network` cap when the host's interface set\n * changes (new IP from DHCP, VPN connect, docker bridge added). */\n LocalNetworkChanged = 'network.local.changed',\n\n // Backup\n BackupCompleted = 'backup.completed',\n BackupRestored = 'backup.restored',\n\n // Notification\n NotificationDispatched = 'notification.dispatched',\n NotificationFailed = 'notification.failed',\n\n // Device extended\n DeviceUpdated = 'device.updated',\n /**\n * Transport-level connectivity. Emitted by the device driver when\n * the underlying control socket actually connects / disconnects\n * (Baichuan TCP, ONVIF probe response, RTSP DESCRIBE, …) — NOT for\n * power-state transitions on a battery camera. For battery wake /\n * doze cycles see `DeviceAwake` / `DeviceSleeping`.\n */\n DeviceOnline = 'device.online',\n /**\n * Stream-broker watchdog — emitted when no encoded packet has been\n * received for STREAM_STALE_TIMEOUT_MS on an active broker (rtsp or\n * push). Paired with DeviceOnline which fires on first packet after\n * a stale gap. Payload: DeviceStreamHealthPayload.\n */\n DeviceOffline = 'device.offline',\n /**\n * Battery cam woke up — physical power-state transition reported\n * by the device firmware. Distinct from `DeviceOnline` so a UI panel\n * watching power state doesn't flap on every UDP socket reconnect.\n */\n DeviceAwake = 'device.awake',\n /**\n * Battery cam went to sleep. See `DeviceAwake`.\n */\n DeviceSleeping = 'device.sleeping',\n\n // Retention\n RetentionCleanup = 'retention.cleanup',\n}\n","import type { FrameResult, AudioResult } from '../types/detection.js'\nimport type { PipelineExecutionTrace } from '../types/pipeline-step.js'\nimport type { MotionRegion } from '../capabilities/motion-detection.cap.js'\nimport type { CameraPipelineConfig } from '../types/camera-pipeline.js'\nimport type { CameraMetrics } from './api-shared.js'\nimport type { RunnerLocalLoad } from './pipeline-runner-capability.js'\nimport type { BrokerStats } from './stream-broker.js'\nimport type { PipelineEngineChoice } from '../types/pipeline.js'\nimport type { NodeProcess, SystemResourceSnapshot } from './metrics-provider.js'\n\n// ---------------------------------------------------------------------------\n// Event source\n// ---------------------------------------------------------------------------\n\nexport interface EventSource {\n /** Primary source type: 'core', 'addon', 'device', 'pipeline', etc. */\n type: string\n /** Primary identifier — addonId when type='addon', deviceId when type='device', etc. */\n id: string | number\n /** Agent/node that originated the event (e.g. 'hub', 'agent-a1b2c3'). */\n nodeId?: string\n /** Addon that originated the event (populated even when type='device'). */\n addonId?: string\n /** Device the event relates to (populated even when type='addon'). */\n deviceId?: number\n}\n\n// ---------------------------------------------------------------------------\n// Detection event payloads\n// ---------------------------------------------------------------------------\n\n// MotionAnalysisRegion removed (2026-04-14) — consumers now use\n// `MotionRegion` from the motion-detection capability directly. The two\n// interfaces had identical shapes; keeping both was a duplication leak.\n\n/**\n * One detection entry emitted by a camera's firmware (not by the local\n * AI pipeline). Carried inside `detection.camera-native` events —\n * native providers fan out to this category for each ring/motion/AI\n * alarm push they receive from the camera.\n */\nexport interface CameraNativeDetection {\n /**\n * Firmware-reported class. Loose string to accommodate heterogeneous\n * firmwares (Reolink uses 'people'/'vehicle'/'animal'/…; ONVIF uses\n * 'PeopleDetect'; etc.). Common values: 'motion', 'person', 'vehicle',\n * 'animal', 'face', 'package', 'other', 'doorbell'.\n */\n readonly class: string\n /** Ms epoch when the server observed the push from the camera. */\n readonly timestamp: number\n /** Optional firmware-provided confidence [0..1]. Most firmwares don't expose it. */\n readonly confidence?: number\n /** Optional bbox [x, y, w, h] normalised [0..1]. Rare on native events. */\n readonly bbox?: readonly [number, number, number, number]\n}\n\nexport interface MotionAnalysisPayload {\n detected: boolean\n regionCount: number\n regions: readonly MotionRegion[]\n frameWidth: number\n frameHeight: number\n analysisMs: number\n [key: string]: unknown\n}\n\n/**\n * Motion phase transition payload. Single source of truth lives in\n * `motion.cap.ts` as `MotionOnMotionChangedDataSchema` — this alias\n * just re-exports the inferred type with the `[key: string]: unknown`\n * loose-index pattern the bus uses for forward-compat. Don't add\n * fields here; extend the schema in motion.cap.ts.\n */\nexport type MotionOnMotionChangedPayload =\n import('../capabilities/motion.cap.js').MotionOnMotionChangedData\n & { [key: string]: unknown }\n\n/** Raw motion zone from CCL (before minArea filter). */\nexport interface MotionRawZone {\n readonly bbox: readonly [number, number, number, number] // [x1, y1, x2, y2]\n readonly pixelCount: number\n readonly changeScore: number // 0-1 intensity\n}\n\n/** All raw motion zones — emitted for UI debug overlay. */\nexport interface MotionZonesRawPayload {\n readonly deviceId: number\n readonly zones: readonly MotionRawZone[]\n readonly frameSize: { readonly width: number; readonly height: number }\n readonly timestamp: number\n [key: string]: unknown\n}\n\nexport interface DetectionResultPayload {\n /**\n * The post-processed frame result the frontend consumes. Already\n * contains `width`/`height` + `detections[]` + optional debug. No\n * pipeline-raw wrapper — the new `FrameResult` shape IS the payload.\n */\n frame: FrameResult\n /** Events emitted by the analysis pipeline (tracking, scene state, face rec). */\n analysisResults: readonly unknown[]\n [key: string]: unknown\n}\n\n/**\n * Raw inference output emitted by `addon-pipeline-runner` per detection\n * frame. Carries the FrameResult produced by the runner — the hub-side\n * wiring service subscribes, applies the analysis pipeline +\n * notifications, and re-emits as `detection.result`.\n */\nexport interface PipelineInferenceResultPayload {\n readonly deviceId: number\n readonly frame: FrameResult\n /** The Moleculer node id of the runner that produced this result. */\n readonly nodeId: string\n readonly [key: string]: unknown\n}\n\n/**\n * Live per-audio-chunk output emitted by the pipeline-orchestrator for\n * each camera with audio analysis enabled. Mirrors `PipelineInferenceResultPayload`\n * but for audio: carries the canonical `AudioResult` produced by running\n * the audio-analyzer + audio-classifier inline on the hub.\n *\n * Replaces the legacy split `detection.audio.level` /\n * `detection.audio.classification` events — consumers should read\n * `frame.level` for dBFS/RMS and `frame.detections` for classifier\n * matches (both on the same single event).\n */\nexport interface PipelineAudioInferenceResultPayload {\n readonly deviceId: number\n readonly frame: AudioResult\n /** Node id of the host that ran the analyzer — always `'hub'` today\n * because audio runs inline on the hub, but the field is kept so the\n * event shape matches `PipelineInferenceResultPayload`. */\n readonly nodeId: string\n readonly [key: string]: unknown\n}\n\n/**\n * Camera assignment lifecycle payload emitted by `addon-pipeline-orchestrator`\n * when a camera is assigned to or unassigned from an agent runner. Used by\n * the UI / metrics dashboard. No frame data.\n */\nexport interface PipelineCameraAssignmentPayload {\n readonly deviceId: number\n readonly agentNodeId: string\n /** True when the assignment was set manually (preferredAgent setting), false when chosen by the load balancer. */\n readonly pinned: boolean\n readonly reason: 'manual' | 'capacity' | 'hardware-affinity' | 'failover' | 'rebalance' | 'unassigned'\n readonly [key: string]: unknown\n}\n\n/**\n * Capability binding change payload emitted whenever an operator picks\n * a different addon to implement a capability on a node. Each kernel\n * process subscribes to this event and updates its local\n * `preferredProviderRegistry` so subsequent capability lookups return\n * the newly chosen provider.\n *\n * The event lives under `capability.binding-changed` because binding\n * is a kernel-level concept used by any cap provider (not just the\n * pipeline flow). It was renamed from `pipeline.binding-changed` to\n * reflect that broader scope.\n */\nexport interface CapabilityBindingChangedPayload {\n readonly nodeId: string\n readonly capName: string\n /** New preferred addon id, or null when the binding was cleared. */\n readonly addonId: string | null\n readonly [key: string]: unknown\n}\n\nexport interface PhaseTransitionPayload {\n deviceId: number\n from: 'watching' | 'active'\n to: 'watching' | 'active'\n reason: 'motion_detected' | 'cooldown_expired'\n /** Motion source that armed the cooldown — present on both ON and OFF. */\n source?: 'onboard' | 'analyzer'\n /** Cooldown window in ms that was/is active for this transition. */\n cooldownMs?: number\n /** Ms epoch of the transition. */\n timestamp?: number\n [key: string]: unknown\n}\n\n// Legacy `AudioLevelPayload` / `AudioClassificationPayload` were removed\n// when the live audio path was migrated to the canonical `AudioResult`\n// shape — consumers now subscribe to `pipeline.audio-inference-result`\n// and read level + detections from the single payload.\n\n// ---------------------------------------------------------------------------\n// System readiness protocol — see docs/superpowers/specs/2026-04-19-system-readiness-design.md\n// ---------------------------------------------------------------------------\n\n/**\n * Scope of a readiness transition — the \"who does this ready/down apply to\".\n *\n * Two shapes today:\n * - `global` for singletons that are cluster-wide (there is only one hub).\n * - `node` for per-process providers (one readiness per broker nodeID).\n *\n * `device` scope covers per-device native caps registered via\n * `DeviceContext.registerNativeCap(cap, provider)`. Consumers of cross-\n * process per-device caps (stream-broker, orchestrator, snapshot, webrtc)\n * `awaitReady(capName, {type:'device', deviceId})` before calling the\n * native-cap bridge so they don't race the service-advertise window.\n * On worker disconnect the hub-side registry's `agent.offline` demux\n * synthesises `down` for every device-scoped cap whose `sourceNodeId`\n * matches the offline node — same pattern as node-scoped synthesis.\n */\nexport type ReadinessScope =\n | { readonly type: 'global' }\n | { readonly type: 'node'; readonly nodeId: string }\n | { readonly type: 'device'; readonly deviceId: number }\n\n/** States a capability provider transitions through. */\nexport type ReadinessState = 'starting' | 'ready' | 'down'\n\n/**\n * Payload for `system.ready-state` events.\n *\n * `generation` is a per-process random identifier that stays constant\n * for the producer's lifetime and changes whenever the producer process\n * is restarted. The kernel's local `ReadinessRegistry` derives a\n * monotonic `epoch` per `(capName, scope)` by counting generation\n * transitions — emitters never stamp epoch themselves. Consumers that\n * hold long-lived state compare `transition.epoch > lastSeenEpoch` to\n * decide whether to rebuild.\n *\n * Same-generation repeated `ready` events are idempotent keepalives\n * (e.g. re-emitted on every `$node.connected`) — the registry keeps\n * epoch stable.\n */\nexport interface SystemReadyStatePayload {\n readonly capName: string\n readonly scope: ReadinessScope\n readonly state: ReadinessState\n /** Per-process random id; changes on producer restart. */\n readonly generation: string\n readonly sourceNodeId: string\n readonly ts: number\n readonly [key: string]: unknown\n}\n\n// ---------------------------------------------------------------------------\n// Cluster topology snapshot shape — matches `nodes.topology` cap output\n// ---------------------------------------------------------------------------\n\n/** One service entry inside a topology process — addon + capabilities. */\nexport interface TopologyService {\n readonly addonId: string\n readonly capabilities: readonly string[]\n readonly status: string\n}\n\n/** One process under a topology node (main process + isolated workers). */\nexport interface TopologyProcess {\n readonly pid: number\n readonly name: string\n readonly state: string\n readonly cpuPercent: number\n readonly memoryRss: number\n readonly uptimeSeconds: number\n readonly services: readonly TopologyService[]\n readonly groupId?: string\n}\n\n/** Top-level cluster node — hub or remote agent. */\nexport interface TopologyNode {\n readonly id: string\n readonly name: string\n readonly hostname: string\n readonly platform: string\n readonly arch: string\n readonly cpuModel: string | null\n readonly cpuCores: number\n readonly memoryMB: number\n readonly engines: readonly string[]\n readonly isHub: boolean\n readonly isOnline: boolean\n readonly cpuPercent: number\n readonly memoryPercent: number\n readonly uptime: number\n readonly lastSeen: string\n /** Local IP addresses visible on the network (non-internal, IPv4/IPv6). */\n readonly localIps: readonly string[]\n readonly addons: ReadonlyArray<{ readonly id: string; readonly capabilities: readonly string[]; readonly status: string }>\n readonly processes: readonly TopologyProcess[]\n}\n\n// ---------------------------------------------------------------------------\n// Known event catalog — typed category → payload mapping\n// ---------------------------------------------------------------------------\n\n/** All known event categories with their typed payloads */\nexport interface EventCatalog {\n // ── System ──────────────────────────────────────────────────────────────\n 'system.boot': { mode: string }\n 'system.addons-ready': { activeAddons: readonly string[] }\n 'system.restarting': Record<string, never>\n 'system.ready-state': SystemReadyStatePayload\n\n // ── Addon lifecycle ─────────────────────────────────────────────────────\n 'addon.started': { addonId: string; packageName?: string; packageVersion?: string; agent?: string }\n 'addon.stopped': { addonId: string; packageName?: string; packageVersion?: string; agent?: string }\n 'addon.restarted': { addonId: string; packageName?: string; packageVersion?: string; agent?: string }\n 'addon.updated': { addonId: string; packageName?: string; packageVersion?: string; agent?: string; fromVersion?: string; toVersion?: string }\n 'addon.installed': { addonId: string; packageName?: string; packageVersion?: string; agent?: string }\n 'addon.uninstalled': { addonId: string; packageName?: string; packageVersion?: string; agent?: string }\n 'addon.crashed': { addonId: string; packageName?: string; packageVersion?: string; agent?: string; error?: string }\n 'addon.error': { addonId: string; packageName?: string; packageVersion?: string; agent?: string; error?: string; action?: string; phase?: string }\n\n // ── Device ──────────────────────────────────────────────────────────────\n 'device.registered': { deviceId: number; providerId: string; name?: string }\n 'device.unregistered': { deviceId: number; providerId: string }\n 'device.streams-registered': { deviceId: number; providerId: string }\n 'device.streams-unregistered': { deviceId: number }\n 'device.enabled': { deviceId: number; integrationId: string }\n 'device.disabled': { deviceId: number; integrationId: string }\n 'device.settings-updated': { deviceId: number; integrationId: string; keys: string[] }\n /**\n * Device online/offline aggregate. Emitted by the device's owning\n * provider (rtsp / reolink / onvif / frigate) when the union of its\n * stream-broker profile health flips. `online` fires when at least\n * one profile becomes healthy after all were offline; `offline` fires\n * when the last healthy profile goes stale (no packets for\n * STREAM_STALE_TIMEOUT_MS).\n */\n 'device.online': { deviceId: number; providerId: string; profileCount?: number; reason?: string }\n 'device.offline': { deviceId: number; providerId: string; reason?: string }\n 'device.awake': { deviceId: number; providerId: string; reason?: string }\n 'device.sleeping': { deviceId: number; providerId: string; reason?: string }\n /**\n * Emitted whenever the set of (device, capability) native providers or\n * wrapper activations changes. Hub subscribers use this to keep a\n * cross-process view of which addon/node currently serves each cap for\n * each device. `nodeId` is the broker nodeID where the provider lives;\n * 'hub' for hub-local. `addonId` is the provider (native or wrapper).\n */\n 'device.bindings-changed': {\n deviceId: number\n capName: string\n reason: 'native-registered' | 'native-unregistered' | 'wrapper-activated' | 'wrapper-deactivated'\n addonId: string\n nodeId: string\n }\n 'device.meta-changed': {\n deviceId: number\n field: 'name' | 'location' | 'disabled'\n value: string | null | boolean\n }\n\n // ── Integration ────────────────────────────────────────────────────────\n 'integration.enabled': { integrationId: string; addonId: string }\n 'integration.disabled': { integrationId: string; addonId: string }\n\n // ── Provider ────────────────────────────────────────────────────────────\n 'provider.started': { providerId: string; type?: string }\n 'provider.stopped': { providerId: string; reason?: string }\n\n // ── Process ─────────────────────────────────────────────────────────────\n 'process.crashed': { processId: string; exitCode?: number; signal?: string }\n 'process.restart_scheduled': { processId: string; delayMs: number }\n 'process.restarted': { processId: string }\n\n // ── Recording ───────────────────────────────────────────────────────────\n 'recording.started': { deviceId: number; streamId?: string }\n 'recording.stopped': { deviceId: number; reason?: string }\n 'recording.error': { deviceId: number; error: string }\n 'recording.health.degraded': { deviceId: number; message: string }\n 'recording.storage.critical': { deviceId: number; usagePercent?: number }\n 'recording.segment.written': { deviceId: number; path?: string; durationSec?: number; sizeMB?: number }\n 'recording.policy.fallback': { deviceId: number; reason: string }\n 'recording.retention.completed': { deletedCount?: number; freedMB?: number }\n\n // ── Detection & analysis ────────────────────────────────────────────────\n 'detection.event': { deviceId: number; detections?: unknown[]; [key: string]: unknown }\n 'detection.result': DetectionResultPayload\n 'detection.motion-analysis': MotionAnalysisPayload\n 'detection.motion-zones-raw': MotionZonesRawPayload\n 'motion.on-motion-changed': MotionOnMotionChangedPayload\n /**\n * On-board detection coming straight from the camera firmware (Reolink\n * AI alarms, ONVIF analytics, etc.) — as opposed to `detection.result`\n * which is produced by the pipeline running locally.\n *\n * `source` discriminates the origin when multiple pipelines coexist for\n * the same camera: `'onboard'` for native firmware events, `'camera-native'`\n * kept as an alias for backwards compatibility with pre-Reolink emitters.\n *\n * `detections` is tightened from `unknown[]` to a structured shape. Each\n * entry describes one firmware-reported class ('motion', 'person',\n * 'vehicle', 'animal', 'face', 'package', 'other', …) at a point in time.\n */\n 'detection.camera-native': {\n cameraId: number\n detections: readonly CameraNativeDetection[]\n source: 'onboard' | 'camera-native'\n }\n 'pipeline.audio-inference-result': PipelineAudioInferenceResultPayload\n 'detection.phase-transition': PhaseTransitionPayload\n /**\n * Emitted whenever a per-device override is written or cleared for any\n * pipeline-participating addon (pipeline-orchestrator, motion-wasm,\n * detection-pipeline, audio-analyzer, audio-classifier). The wiring\n * service subscribes to this event and restarts detection for the\n * affected camera so the new values take effect without a full reboot.\n * `addonId` is informational — most consumers only care about\n * `deviceId` and will rebuild the full RunnerCameraConfig anyway.\n */\n 'orchestration.settings-updated': { deviceId: number; addonId?: string }\n 'provider.motion': { active: boolean }\n 'provider.detection': { detections: unknown }\n\n // ── Session tracking ────────────────────────────────────────────────────\n 'session.track.new': { deviceId: number; trackId: string; label?: string }\n 'session.track.expired': { deviceId: number; trackId: string; durationMs?: number }\n\n // ── Benchmark ───────────────────────────────────────────────────────────\n /**\n * Progress from a running benchmark (pipeline image test, decoder perf test,\n * …). The payload is intentionally open (`kind` discriminator + free-form\n * additional fields) so different benchmark shapes share the same bus\n * category and a single UI subscriber can filter by `kind` + `sessionId`.\n */\n 'benchmark.progress': {\n kind: string\n sessionId: string\n phase?: string\n tSec?: number\n sample?: Record<string, unknown>\n message?: string\n }\n\n // ── Pipeline & inference ────────────────────────────────────────────────\n 'pipeline.progress': {\n /** Node that executed the pipeline step. Same value is also set on `event.source.nodeId`\n * but carried in the payload so admin-ui filters don't need to peek at the source shape. */\n nodeId: string\n /** Stable identifier per `runPipeline()` invocation — every progress event from the same\n * run shares this id so the UI can correlate a burst of messages into a single run card. */\n sessionId: string\n step: string\n addonId?: string\n modelId?: string\n ms?: number\n message?: string\n }\n /** Per-frame execution trace emitted by the pipeline executor for live observability. */\n 'pipeline.trace': PipelineExecutionTrace\n /** Raw inference output emitted by addon-pipeline-runner (no frame buffer). */\n 'pipeline.inference-result': PipelineInferenceResultPayload\n /** Camera assigned to an agent runner by addon-pipeline-orchestrator. */\n 'pipeline.camera-assigned': PipelineCameraAssignmentPayload\n /** Camera released from an agent runner. */\n 'pipeline.camera-unassigned': PipelineCameraAssignmentPayload\n /** Per-camera pipeline config changed — orchestrator hot-reloads the assigned runner. */\n 'pipeline.camera-updated': {\n readonly deviceId: number\n readonly config: CameraPipelineConfig\n }\n /**\n * Periodic per-runner load snapshot (~1 Hz). Replaces UI polling on\n * `pipelineRunner.getLocalLoad`. UI subscribes per agent node.\n */\n 'pipeline.runner-load-snapshot': {\n readonly nodeId: string\n readonly load: RunnerLocalLoad\n /** Wall-clock ms when the snapshot was sampled. */\n readonly timestamp: number\n }\n /**\n * Periodic per-camera metrics snapshot (~1 Hz). Replaces UI polling\n * on `pipelineOrchestrator.getCameraMetrics` /\n * `pipelineRunner.getCameraMetrics`. One event per attached camera\n * per tick. UI consumers filter by `deviceId`.\n */\n 'pipeline.camera-metrics-snapshot': {\n readonly deviceId: number\n readonly nodeId: string\n readonly metrics: CameraMetrics\n readonly timestamp: number\n }\n /**\n * Periodic per-broker stats snapshot (~1 Hz). Replaces polling on\n * `streamBroker.getBrokerStats` and `streamBroker.listAllProfileSlots`.\n * Carries the full `BrokerStats` payload so UI consumers can render\n * the panel directly from the event without round-tripping the cap.\n */\n 'stream-broker.metrics-snapshot': {\n readonly brokerId: string\n readonly deviceId: number\n readonly profile: string\n readonly nodeId: string\n readonly stats: BrokerStats\n readonly timestamp: number\n }\n /**\n * Cap event: stream-broker signals that a profile slot now has at\n * least one consumer. Camera-provider addons (Reolink Baichuan push,\n * etc.) start their underlying transport on receipt — see\n * `EventCategory.StreamBrokerOnCamStreamDemand`.\n */\n 'stream-broker.onCamStreamDemand': {\n readonly deviceId: number\n readonly camStreamId: string\n readonly profile: 'high' | 'mid' | 'low'\n }\n /**\n * Cap event: stream-broker signals the last consumer left. Providers\n * tear down their transport — see `EventCategory.StreamBrokerOnCamStreamIdle`.\n */\n 'stream-broker.onCamStreamIdle': {\n readonly deviceId: number\n readonly camStreamId: string\n }\n /**\n * Cap event: device's battery status changed (firmware push or\n * provider-side observation). Mirrors `batteryCapability.onStatusChanged`.\n * Payload shape duplicated inline (rather than importing from\n * `capabilities/battery.cap`) to avoid a cycle between the cap\n * definitions and the event bus typing — they're kept in lock-step\n * by hand (see also `BatteryStatus` in `capabilities/battery.cap.ts`).\n */\n 'battery.onStatusChanged': {\n readonly deviceId: number\n readonly status: {\n readonly percentage: number\n readonly charging: 'dc' | 'solar' | 'none'\n readonly sleeping: boolean\n readonly lastUpdated: number\n }\n }\n /**\n * Doorbell button press — emitted by every device that registers the\n * `doorbell` capability. Mirrors `doorbellCapability.events.onPressed`.\n * Subscribers (UI toast, advanced-notifier) react to physical rings\n * without holding a cap reference.\n */\n 'doorbell.onPressed': {\n readonly deviceId: number\n readonly timestamp: number\n }\n /**\n * Periodic per-node engine inventory snapshot (~0.2 Hz). Replaces\n * polling on `pipelineExecutor.listLoadedEngines`. One event per\n * detection-pipeline process per tick, carrying every loaded engine\n * with the same shape the cap returns.\n */\n 'pipeline.engine-metrics-snapshot': {\n readonly nodeId: string\n readonly engines: ReadonlyArray<{\n readonly engineKey: string\n readonly engine: PipelineEngineChoice\n readonly modelsLoaded: readonly string[]\n readonly inUseByCameras: readonly number[]\n readonly kind: 'runtime' | 'warm-override'\n readonly poolPid: number | null\n readonly idleMs: number | null\n readonly idleTtlMs: number | null\n }>\n readonly timestamp: number\n }\n /**\n * Cluster topology snapshot — same payload shape that\n * `nodes.topology` returns. Emitted by the hub on any agent /\n * addon lifecycle change (debounced ~200ms) plus a periodic safety\n * net. UI dashboards subscribe to drive their cluster view\n * directly from the event payload — zero round-trip.\n */\n 'cluster.topology-snapshot': {\n readonly nodes: ReadonlyArray<TopologyNode>\n readonly timestamp: number\n }\n /**\n * Periodic per-node system metrics snapshot. Carries the full\n * `SystemResourceSnapshot` returned by\n * `metricsProvider.getCached()` so dashboards render CPU /\n * memory / GPU / disk / network without polling.\n */\n 'metrics.node-resources-snapshot': {\n readonly nodeId: string\n readonly snapshot: SystemResourceSnapshot\n readonly timestamp: number\n }\n /**\n * Periodic per-node process-tree snapshot (`NodeProcess[]` —\n * camstack-related pids with ghost / managed / root classification).\n * One event per node per tick. Replaces polling on\n * `metricsProvider.listNodeProcesses`.\n */\n 'metrics.node-processes-snapshot': {\n readonly nodeId: string\n readonly processes: ReadonlyArray<NodeProcess>\n readonly timestamp: number\n }\n /**\n * Per-agent hwaccel override changed (set / cleared / re-probed). Payload\n * carries the new effective preference so UI consumers can toast or\n * refresh their pipeline view without re-fetching. Decoders still pull\n * from `pipeline-orchestrator.getAgentSettings` on session creation;\n * this event is additive observability.\n */\n 'pipeline.agent-hwaccel-changed': {\n readonly agentNodeId: string\n readonly userChoice: 'auto' | 'none' | string | null\n readonly probedBest: string\n readonly reason: 'user-set' | 'user-cleared' | 'reprobed' | 'seeded'\n }\n /** Capability binding changed for a node — kernels update their preferred-provider registry. */\n 'capability.binding-changed': CapabilityBindingChangedPayload\n 'model.download.progress': { modelId: string; progress: number; totalMB?: number }\n\n // ── Agent ───────────────────────────────────────────────────────────────\n 'agent.online': { agentId: string }\n 'agent.offline': { agentId: string }\n 'worker.online': { workerId: string }\n 'worker.offline': { workerId: string }\n 'agent.task.assigned': { agentId: string; taskId: string; taskType: string; payload?: unknown }\n\n // ── Enrichment ──────────────────────────────────────────────────────────\n 'enrichment.embedding.stored': {\n readonly deviceId: number\n readonly trackId: string\n readonly class: string\n readonly embeddingId: string\n readonly modelId: string\n readonly embeddingDim: number\n readonly inferenceMs: number\n readonly timestamp: number\n }\n 'enrichment.scene.state-changed': {\n readonly deviceId: number\n readonly monitorId: string\n readonly monitorLabel: string\n readonly previousState: string\n readonly currentState: string\n readonly confidence: number\n readonly timestamp: number\n }\n 'enrichment.activity.summary': {\n readonly deviceId: number\n readonly periodStart: number\n readonly periodEnd: number\n readonly objectCounts: Readonly<Record<string, number>>\n readonly zoneActivity: readonly { readonly zoneId: string; readonly entries: number; readonly exits: number; readonly avgDwellMs: number }[]\n readonly stateChanges: readonly { readonly monitorId: string; readonly from: string; readonly to: string; readonly timestamp: number }[]\n readonly activityLevel: 'none' | 'low' | 'medium' | 'high'\n }\n\n // ── Alerts ──────────────────────────────────────────────────────────────\n 'alert.created': { id: string; category: string; severity: string; title: string; status: string }\n 'alert.updated': { alertId: string; patch: Record<string, unknown> }\n\n // ── Stream broker health ────────────────────────────────────────────────\n /**\n * Per-broker stream health transition. Fired by the stream-broker\n * watchdog. `camStreamId` is the canonical identity of the source\n * (every broker is keyed by its cam stream now); `profile` is the\n * profile slot currently bound to it (or `null` if the broker is\n * only kept alive by a manual activation).\n */\n 'stream.online': {\n readonly deviceId: number\n readonly camStreamId: string\n readonly profile: 'high' | 'mid' | 'low' | null\n readonly brokerId: string\n readonly sourceType: string\n readonly lastPacketAt: number\n readonly reason?: string\n }\n 'stream.offline': {\n readonly deviceId: number\n readonly camStreamId: string\n readonly profile: 'high' | 'mid' | 'low' | null\n readonly brokerId: string\n readonly sourceType: string\n readonly lastPacketAt: number\n readonly reason?: string\n }\n\n // ── Retention ───────────────────────────────────────────────────────────\n 'retention.cleanup': {\n readonly deletedEvents?: number\n readonly deletedAudioRecords?: number\n readonly deletedSnapshots?: number\n readonly deletedCount?: number\n readonly freedMB?: number\n }\n}\n\n/** All known event category strings (derived from EventCatalog keys) */\nexport type KnownEventCategory = keyof EventCatalog\n\n// ---------------------------------------------------------------------------\n// SystemEvent — backward-compatible base type\n// ---------------------------------------------------------------------------\n\n/**\n * System event — `data` is `Record<string, unknown>` for backward compatibility.\n * Use `TypedSystemEvent<C>` or `narrowEvent()` for typed access to data.\n */\nexport interface SystemEvent {\n id: string\n timestamp: Date\n source: EventSource\n category: string\n data: Record<string, unknown>\n /**\n * Propagation chain when the event was re-emitted by the\n * `DeviceEventPropagator`. `via[0]` is the originating source (the\n * child that produced the event); subsequent entries walk up the\n * parent chain. Absent on the original emission and on events that\n * don't belong to a device-rooted source.\n *\n * Consumers that want ONLY direct events filter `ev.via === undefined`.\n * Consumers that want everything reaching a device (incl. children)\n * filter by `source.id === parentId` and accept any `via`.\n */\n via?: readonly EventSource[]\n}\n\n/**\n * A system event with a known category — `data` is typed.\n * Use this when you know the exact category at compile time.\n */\nexport type TypedSystemEvent<C extends KnownEventCategory> = {\n id: string\n timestamp: Date\n source: EventSource\n category: C\n data: EventCatalog[C]\n via?: readonly EventSource[]\n}\n\n// ---------------------------------------------------------------------------\n// Event filter\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Event filter — accepts known categories (strict) or strings (globs/custom)\n// ---------------------------------------------------------------------------\n\n/** A category filter value: a known category, a glob string, or an array of either */\nexport type EventCategoryFilter = KnownEventCategory | (string & {}) | readonly (KnownEventCategory | (string & {}))[]\n\nexport interface EventFilter {\n source?: EventSource\n /** Filter by top-level agent (e.g. 'hub', 'agent-a1b2c3'). Matches source.nodeId with prefix match so 'hub' includes 'hub/pipeline'. Same semantics as logs tags.agentId. */\n agentId?: string\n /** Filter by addon that originated the event. Matches source.addonId or source.id when type='addon'. */\n addonId?: string\n /** Filter by device the event relates to. Matches source.deviceId or source.id when type='device'. */\n deviceId?: number\n /** Category — known category (typed), glob (e.g. 'device.*'), or array */\n category?: EventCategoryFilter\n since?: Date\n}\n\n// ---------------------------------------------------------------------------\n// Typed event filter — for subscribe overloads\n// ---------------------------------------------------------------------------\n\nexport interface TypedEventFilter<C extends KnownEventCategory> {\n source?: EventSource\n category: C | readonly C[]\n since?: Date\n}\n\n// ---------------------------------------------------------------------------\n// IEventBus — emit and subscribe are typed when using known categories\n// ---------------------------------------------------------------------------\n\nexport interface IEventBus {\n /** Emit a known-category event with typed payload */\n emit<C extends KnownEventCategory>(event: TypedSystemEvent<C>): void\n /** Emit an arbitrary event (custom/unknown category) */\n emit(event: SystemEvent): void\n\n /** Subscribe to a known category — handler receives typed event */\n subscribe<C extends KnownEventCategory>(filter: TypedEventFilter<C>, handler: (event: TypedSystemEvent<C>) => void): () => void\n /** Subscribe with a generic filter — handler receives base SystemEvent */\n subscribe(filter: EventFilter, handler: (event: SystemEvent) => void): () => void\n\n /** Get recent events */\n getRecent(filter?: EventFilter, limit?: number): readonly SystemEvent[]\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Narrow a SystemEvent to a typed event by checking its category.\n * Returns `true` (and narrows the type) if the category matches.\n *\n * @example\n * ```typescript\n * eventBus.subscribe({ category: 'addon.started' }, (event) => {\n * if (isEvent(event, 'addon.started')) {\n * event.data.addonId // ✓ typed as string\n * }\n * })\n * ```\n */\nexport function isEvent<C extends KnownEventCategory>(\n event: SystemEvent,\n category: C,\n): event is TypedSystemEvent<C> {\n return event.category === category\n}\n\n/**\n * Create a typed event with less boilerplate.\n *\n * @example\n * ```typescript\n * eventBus.emit(createEvent('addon.started', { type: 'addon', id: 'pipeline' }, {\n * addonId: 'pipeline',\n * packageVersion: '0.1.8',\n * }))\n * ```\n */\nexport function createEvent<C extends KnownEventCategory>(\n category: C,\n source: EventSource,\n data: EventCatalog[C],\n): TypedSystemEvent<C> {\n return {\n id: typeof crypto !== 'undefined' && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2),\n timestamp: new Date(),\n source,\n category,\n data,\n }\n}\n\n// ---------------------------------------------------------------------------\n// System readiness protocol — low-level producer emission helper.\n// Consumers (kernel `ReadinessRegistry`) and their `awaitReady` /\n// `onReadyState` APIs live in `@camstack/kernel/src/readiness/`.\n// ---------------------------------------------------------------------------\n\n/**\n * Emit a `system.ready-state` event for a capability. Caller supplies a\n * per-process `generation` string — stable across a single process\n * lifetime, changes on restart — which consumer-side registries use to\n * derive a monotonic `epoch` without requiring the emitter to\n * coordinate.\n */\nexport function emitReadiness(\n bus: IEventBus,\n params: {\n readonly capName: string\n readonly scope: ReadinessScope\n readonly state: ReadinessState\n readonly generation: string\n readonly sourceNodeId: string\n readonly ts?: number\n },\n): void {\n const ts = params.ts ?? Date.now()\n bus.emit(createEvent(\n 'system.ready-state',\n { type: 'capability', id: params.capName, nodeId: params.sourceNodeId },\n {\n capName: params.capName,\n scope: params.scope,\n state: params.state,\n generation: params.generation,\n sourceNodeId: params.sourceNodeId,\n ts,\n },\n ))\n}\n","import type { AddonContext, AddonInitResult, CapabilitiesAccess, ProviderRegistration } from '../interfaces/addon.js'\nimport { EventCategory } from '../enums/event-category.js'\nimport type {\n ConfigUISchema, ConfigUISchemaWithValues,\n ConfigField, ConfigSection,\n} from '../interfaces/config-ui.js'\nimport { hydrateSchema } from '../interfaces/config-ui.js'\nimport { emitReadiness } from '../interfaces/event-bus.js'\n\nexport type { CapabilitiesAccess }\n\n// ── Typed field helper ──────────────────────────────────────────────────\n/**\n * Utility type that constrains a ConfigField's `key` to only accept\n * keys of TConfig. Usage inside schema builders:\n *\n * ```ts\n * protected globalSettingsSchema() {\n * return this.schema({\n * sections: [{\n * id: 'main',\n * title: 'Settings',\n * fields: [\n * this.field({ type: 'number', key: 'maxRetries', label: 'Max Retries' }),\n * // ^^^^^^^^^^^ — autocomplete + compile error if wrong\n * ],\n * }],\n * })\n * }\n * ```\n */\ntype TypedConfigField<TConfig extends object> =\n ConfigField extends infer F\n ? F extends { readonly key: string }\n ? Omit<F, 'key'> & { readonly key: keyof TConfig & string }\n : F // valueless fields (separator, info) pass through\n : never\n\n/**\n * A ConfigSection whose fields are key-constrained to TConfig.\n */\ninterface TypedConfigSection<TConfig extends object> extends Omit<ConfigSection, 'fields'> {\n readonly fields: ReadonlyArray<TypedConfigField<TConfig> | ConfigField>\n}\n\n/**\n * A ConfigUISchema whose sections use typed fields.\n */\ninterface TypedConfigUISchema<TConfig extends object> extends Omit<ConfigUISchema, 'sections'> {\n readonly sections: ReadonlyArray<TypedConfigSection<TConfig>>\n}\n\n// ── BaseAddon ───────────────────────────────────────────────────────────\n\n/**\n * Base class for CamStack addons. Eliminates settings boilerplate:\n *\n * - Typed `config` property with automatic resolution from store + defaults\n * - `getGlobalSettings()` / `updateGlobalSettings()` auto-implemented\n * - `getAddonSettings()` / `updateAddonSettings()` auto-implemented\n * - `getDeviceSettings()` / `updateDeviceSettings()` auto-implemented\n * - `ctx` accessor for the AddonContext (no manual `this.ctxRef` storage)\n * - `field()` helper that constrains field keys to TConfig keys\n * - `schema()` helper that validates the full schema structure\n *\n * Subclasses override:\n * - `onInitialize()` — addon-specific init logic, return ProviderRegistration[]\n * - `onShutdown()` — cleanup\n * - `globalSettingsSchema()` / `deviceSettingsSchema()` — UI schemas\n *\n * @example\n * ```ts\n * interface MyConfig {\n * maxRetries: number\n * endpoint: string\n * }\n *\n * export default class MyAddon extends BaseAddon<MyConfig> {\n * constructor() {\n * super({ maxRetries: 3, endpoint: 'http://localhost' })\n * }\n *\n * protected globalSettingsSchema() {\n * return this.schema({\n * sections: [{\n * id: 'main', title: 'Settings',\n * fields: [\n * this.field({ type: 'number', key: 'maxRetries', label: 'Max Retries', default: 3 }),\n * this.field({ type: 'text', key: 'endpoint', label: 'Endpoint' }),\n * ],\n * }],\n * })\n * }\n *\n * protected async onInitialize(): Promise<ProviderRegistration[]> {\n * const client = new Client(this.config.endpoint, this.config.maxRetries)\n * return [{ capability: 'my-feature', provider: client }]\n * }\n * }\n * ```\n */\nexport abstract class BaseAddon<TConfig extends object = Record<string, unknown>> {\n private _ctx: AddonContext | null = null\n private _config: TConfig\n /**\n * Per-process random id used as the `generation` stamp on every\n * `system.ready-state` event this addon emits. Constant for the\n * lifetime of this addon instance (== one process boot); consumer-\n * side registries derive a monotonic `epoch` by watching for\n * generation transitions.\n */\n private readonly _readinessGeneration: string =\n typeof crypto !== 'undefined' && crypto.randomUUID\n ? crypto.randomUUID()\n : Math.random().toString(36).slice(2, 14)\n /** Capability names this addon registered at init — used to emit matching `down` events on shutdown. */\n private _registeredCapNames: readonly string[] = []\n\n /** Default config values. Provided via constructor. */\n protected readonly defaults: TConfig\n\n constructor(defaults: TConfig) {\n this.defaults = defaults\n this._config = { ...defaults }\n }\n\n /**\n * Override to opt out of the automatic `system.ready-state` emission.\n * Returns `true` by default — addons that don't map cleanly to the\n * readiness protocol (e.g. pure collection providers whose readiness\n * is already reported per-device by upstream) can override to `false`\n * and emit manually.\n */\n protected get autoEmitReadiness(): boolean { return true }\n\n // ── Public accessors ──────────────────────────────────────────────────\n\n /** The AddonContext, available after initialize(). */\n get ctx(): AddonContext {\n if (!this._ctx) throw new Error(`${this.constructor.name}: ctx accessed before initialize()`)\n return this._ctx\n }\n\n /**\n * Non-throwing ctx accessor for code paths that can legitimately run\n * before `initialize()` has resolved — most commonly cap handlers the\n * hub invokes eagerly at page load (device-details aggregator pings\n * every addon's `getDeviceSettingsContribution` as soon as the page\n * mounts). Prefer `ctx` for the normal case; reach for this only in\n * capability methods that may be queried before the addon is wired up.\n */\n protected get ctxIfReady(): AddonContext | null {\n return this._ctx\n }\n\n /** Current resolved config (defaults merged with persisted store values). */\n get config(): Readonly<TConfig> {\n return this._config\n }\n\n // ── ICamstackAddon lifecycle ──────────────────────────────────────────\n\n async initialize(context: AddonContext): Promise<AddonInitResult | void> {\n this._ctx = context\n await this.resolveConfig()\n const result = await this.onInitialize()\n this.emitLifecycle(EventCategory.AddonStarted)\n const normalized = normalizeAddonInitResult(result)\n const providers: readonly ProviderRegistration[] =\n normalized && 'providers' in normalized && normalized.providers ? normalized.providers : []\n this._registeredCapNames = providers.map(p => p.capability.name)\n return normalized\n }\n\n /**\n * Called by the isolated-process runner AFTER `broker.start()`.\n * In-process addons never need this because the hub broker is already\n * running when `initialize()` fires. For forked children the broker\n * starts AFTER `initialize()`, so the readiness emit inside initialize()\n * fires before the broker can broadcast it. This method re-emits the\n * ready state once the transport is live.\n */\n postBrokerStart(): void {\n if (this.autoEmitReadiness && this._registeredCapNames.length > 0) {\n this.emitReadinessForProviders('ready')\n }\n }\n\n /**\n * Called by the isolated-process runner / agent bootstrap once the broker\n * has started AND the hub node is connected — the moment `ctx.api.*` calls\n * to hub-provided capabilities become safe. Wrap any bootstrap work that\n * must query the hub (device restore, settings fetch, initial sync) in\n * `onHubConnected()` rather than `onInitialize()` — during `initialize()`\n * on a worker the broker is not yet connected and remote cap calls either\n * time out or throw \"Service not found\".\n *\n * Default implementation is a no-op. Override in subclasses that need it.\n * Never fires on hub-local in-process addons (the hub is its own node).\n */\n async onHubReachable(): Promise<void> {\n // no-op — override in subclasses\n }\n\n async shutdown(): Promise<void> {\n this.emitLifecycle(EventCategory.AddonStopped)\n if (this.autoEmitReadiness) this.emitReadinessForProviders('down')\n await this.onShutdown()\n for (const unsub of this._subscriptions) unsub()\n this._subscriptions = []\n this._ctx = null\n }\n\n // ── Subclass hooks ────────────────────────────────────────────────────\n\n /**\n * Addon-specific initialization. Called after config is resolved.\n *\n * Subclasses may return:\n * - an array of `ProviderRegistration` (back-compat, most common),\n * - an `AddonInitResult` envelope to also declare `customActions`,\n * - `void` for pure consumers.\n */\n protected abstract onInitialize(): Promise<ProviderRegistration[] | AddonInitResult | void>\n\n /** Addon-specific cleanup. Override if needed. */\n protected async onShutdown(): Promise<void> { /* no-op by default */ }\n\n /**\n * Called after config is resolved during updateGlobalSettings/updateAddonSettings.\n * Override to react to config changes (e.g. restart a sampler, reconnect a service).\n * Not called during initialize() — use onInitialize() for initial setup.\n */\n protected async onConfigChanged(): Promise<void> { /* no-op by default */ }\n\n // ── Schema helpers (typed) ────────────────────────────────────────────\n\n /**\n * Create a ConfigField with `key` constrained to keys of TConfig.\n * Provides autocomplete and compile-time validation.\n */\n protected field<F extends ConfigField>(\n field: F extends { readonly key: string }\n ? Omit<F, 'key'> & { readonly key: keyof TConfig & string }\n : F\n ): ConfigField {\n return field as ConfigField\n }\n\n /**\n * Create a full ConfigUISchema with typed sections.\n * Fields created via `this.field()` get key validation automatically.\n */\n protected schema(schema: TypedConfigUISchema<TConfig>): ConfigUISchema {\n return schema as unknown as ConfigUISchema\n }\n\n // ── Settings schemas (override to provide UI) ─────────────────────────\n\n /** Override to provide global-level settings UI schema. */\n protected globalSettingsSchema(): ConfigUISchema | null { return null }\n\n /** Override to provide device-level settings UI schema. */\n protected deviceSettingsSchema(): ConfigUISchema | null { return null }\n\n // ── Two-level settings API (auto-implemented) ────────────────────────\n //\n // Note: the former three-level split (addon / global / device) collapsed\n // to two. `addon` and `global` both wrote to the same `writeAddonStore`\n // blob and every addon used exactly one of them; the distinction was\n // never semantically load-bearing. `global` won because it was the\n // widely-used one and the name reads naturally (per-node addon config).\n\n async getGlobalSettings(overlay?: Record<string, unknown>): Promise<ConfigUISchemaWithValues> {\n const schema = this.globalSettingsSchema()\n if (!schema) return { sections: [] }\n const raw = (await this._ctx?.settings?.readAddonStore()) ?? {}\n return hydrateSchema(schema, overlay ? { ...raw, ...overlay } : raw)\n }\n\n async updateGlobalSettings(patch: Partial<TConfig>): Promise<void> {\n await this._ctx?.settings?.writeAddonStore(patch as Record<string, unknown>)\n await this.resolveConfig()\n await this.onConfigChanged()\n this.emitLifecycle(EventCategory.AddonUpdated, { level: 'global' })\n this.maybeAutoRestart(patch, this.globalSettingsSchema())\n }\n\n /**\n * If any field in `patch` is marked `requiresRestart` in `schema`,\n * schedule an addon restart for the next tick. Deferred via\n * `setImmediate` so the tRPC mutation that triggered the write has\n * time to return its response before the addon is torn down and\n * re-initialised by `AddonRegistryService.restartAddon`.\n */\n private maybeAutoRestart(\n patch: Partial<TConfig>,\n schema: ConfigUISchema | null,\n ): void {\n if (!schema) return\n const restartKeys = new Set<string>()\n for (const section of schema.sections) {\n for (const field of section.fields) {\n if (field.type === 'separator' || field.type === 'info') continue\n if ((field as { readonly requiresRestart?: boolean }).requiresRestart) {\n restartKeys.add((field as { readonly key: string }).key)\n }\n }\n }\n if (restartKeys.size === 0) return\n const changed = Object.keys(patch).some((k) => restartKeys.has(k))\n if (!changed) return\n const ctx = this._ctx\n if (!ctx) return\n const addonId = ctx.id\n setImmediate(() => {\n const api = ctx.api as unknown as {\n addons?: { restartAddon?: { mutate: (input: { addonId: string }) => Promise<unknown> } }\n }\n api.addons?.restartAddon?.mutate({ addonId })\n .then(() => {\n ctx.logger.info('addon auto-restart triggered by restart-required setting change', {\n meta: { changedFields: Object.keys(patch).filter((k) => restartKeys.has(k)) },\n })\n })\n .catch((err: unknown) => {\n ctx.logger.error('addon auto-restart failed', {\n meta: { error: err instanceof Error ? err.message : String(err) },\n })\n })\n })\n }\n\n async getDeviceSettings(deviceId: number): Promise<ConfigUISchemaWithValues> {\n const schema = this.deviceSettingsSchema()\n if (!schema) return { sections: [] }\n const raw = (await this._ctx?.settings?.readDeviceStore(deviceId)) ?? {}\n return hydrateSchema(schema, raw)\n }\n\n async updateDeviceSettings(deviceId: number, patch: Record<string, unknown>): Promise<void> {\n await this._ctx?.settings?.writeDeviceStore(deviceId, patch)\n }\n\n // ── Event subscriptions (auto-cleanup on shutdown) ────────────────────\n\n private _subscriptions: Array<() => void> = []\n\n /**\n * Subscribe to an event bus category. The subscription is automatically\n * unsubscribed on shutdown — no manual cleanup needed.\n *\n * @example\n * ```ts\n * this.subscribe({ category: EventCategory.DeviceRegistered }, (event) => {\n * void this.handleDevice(event)\n * })\n * ```\n */\n /**\n * Subscribe to `system.ready-state` events for one or more capabilities.\n * Abstracts the boilerplate type-narrowing + nodeId extraction that every\n * resilience subscription duplicates. Cleanup is automatic (registered on\n * `_subscriptions` like a normal `subscribe` call).\n */\n protected watchCapability(\n capNames: string | readonly string[],\n handlers: {\n readonly onDown?: (nodeId: string, capName: string) => void\n readonly onReady?: (nodeId: string, capName: string) => void\n },\n ): void {\n const names = Array.isArray(capNames) ? capNames : [capNames]\n const nameSet = new Set<string>(names as string[])\n this.subscribe(\n { category: 'system.ready-state' },\n (event) => {\n const data = event.data as {\n readonly capName?: unknown\n readonly state?: unknown\n readonly scope?: { readonly type?: unknown; readonly nodeId?: unknown }\n }\n if (typeof data.capName !== 'string') return\n if (!nameSet.has(data.capName)) return\n if (data.scope?.type !== 'node') return\n const nodeId = data.scope.nodeId\n if (typeof nodeId !== 'string' || nodeId.length === 0) return\n const capName = data.capName\n if (data.state === 'down') {\n handlers.onDown?.(nodeId, capName)\n } else if (data.state === 'ready') {\n handlers.onReady?.(nodeId, capName)\n }\n },\n )\n }\n\n protected subscribe<C extends import('../interfaces/event-bus.js').KnownEventCategory>(\n filter: import('../interfaces/event-bus.js').TypedEventFilter<C>,\n handler: (event: import('../interfaces/event-bus.js').TypedSystemEvent<C>) => void,\n ): void\n protected subscribe(\n filter: import('../interfaces/event-bus.js').EventFilter,\n handler: (event: import('../interfaces/event-bus.js').SystemEvent) => void,\n ): void\n protected subscribe(\n filter: import('../interfaces/event-bus.js').EventFilter,\n handler: (event: import('../interfaces/event-bus.js').SystemEvent) => void,\n ): void {\n const unsub = this.ctx.eventBus.subscribe(filter, handler)\n this._subscriptions.push(unsub)\n }\n\n // ── Lifecycle event emission ────────────────────────────────────────────\n\n private emitLifecycle(category: EventCategory, data?: Record<string, unknown>): void {\n try {\n this._ctx?.eventBus.emit({\n id: `${this._ctx.id}-${Date.now()}`,\n timestamp: new Date(),\n source: { type: 'addon', id: this._ctx.id, nodeId: this._ctx.kernel.localNodeId ?? 'hub' },\n category,\n data: data ?? {},\n })\n } catch { /* best-effort — don't crash addon if event bus is unavailable */ }\n }\n\n /**\n * Emit a `system.ready-state` event for every capability this addon\n * registered at init. Scope is `{type:'node', nodeId}` — readiness is\n * tied to the node that hosts the provider. Consumers that care about\n * per-device readiness can subscribe with `{type:'device', ...}` if\n * the provider emits at finer granularity (collection addons may\n * opt-out via `autoEmitReadiness` and emit manually).\n */\n private emitReadinessForProviders(state: 'ready' | 'down'): void {\n const ctx = this._ctx\n if (!ctx) return\n if (this._registeredCapNames.length === 0) return\n // Forked child processes have a hierarchical nodeId (e.g. 'hub/detection-pipeline').\n // Readiness must be scoped to the logical parent node so orchestrators that\n // subscribe to 'hub' or 'dev-agent-0' receive the event from their children too.\n const rawNodeId = ctx.kernel?.localNodeId ?? 'hub'\n const nodeId = rawNodeId.includes('/') ? rawNodeId.split('/')[0]! : rawNodeId\n for (const capName of this._registeredCapNames) {\n try {\n emitReadiness(ctx.eventBus, {\n capName,\n scope: { type: 'node', nodeId },\n state,\n generation: this._readinessGeneration,\n sourceNodeId: nodeId,\n })\n } catch { /* best-effort — a broken bus must not take the addon down */ }\n }\n }\n\n // ── Common helpers ─────────────────────────────────────────────────────\n\n /**\n * Resolve the shared models directory path via the storage capability.\n * Falls back to `camstack-data/models` if storage is unavailable.\n * Used by inference addons (detection-pipeline, audio-classifier, embedding-encoder).\n */\n protected async resolveModelsDir(): Promise<string> {\n return this.ctx.api.storage.resolve.query({ location: 'models', relativePath: '' })\n .catch(() => 'camstack-data/models')\n }\n\n /**\n * Access the runtime capability registry for in-process provider lookups.\n * Returns null if the registry is not available (e.g. on agents).\n * Used by addons that consume other capabilities directly (snapshot, stream-broker, enrichment).\n */\n protected get capabilities(): CapabilitiesAccess | null {\n const capCtx = this.ctx as { capabilities?: CapabilitiesAccess }\n return capCtx.capabilities ?? null\n }\n\n // ── Config resolution ─────────────────────────────────────────────────\n\n /**\n * Resolve config by merging defaults with persisted store values.\n * Called automatically during initialize() and after every updateSettings().\n *\n * The merge is shallow: each key in `defaults` is checked against the store.\n * Only keys present in defaults are read — the store can contain extra keys\n * (e.g. from older versions) without polluting the typed config.\n */\n protected async resolveConfig(): Promise<void> {\n const stored = (await this._ctx?.settings?.readAddonStore()) ?? {}\n const resolved = { ...this.defaults }\n\n for (const key of Object.keys(this.defaults) as Array<keyof TConfig & string>) {\n const storedValue = stored[key]\n if (storedValue !== undefined && storedValue !== null) {\n const defaultType = typeof this.defaults[key]\n if (typeof storedValue === defaultType) {\n ;(resolved as Record<string, unknown>)[key] = storedValue\n }\n }\n }\n\n this._config = resolved\n }\n}\n\n/**\n * Normalize an `ICamstackAddon.initialize()` return value into the\n * `AddonInitResult` envelope. Arrays are wrapped into `{ providers }`;\n * envelopes pass through; void stays void.\n *\n * Exported so the kernel boot path and the backend addon registry can\n * share the same normalizer instead of duplicating the shim. Addons that\n * extend `BaseAddon` already emit the envelope, so this helper is only a\n * safety net for direct `ICamstackAddon` implementations (mostly tests).\n */\nexport function normalizeAddonInitResult(\n result: ProviderRegistration[] | AddonInitResult | void,\n): AddonInitResult | void {\n if (result == null) return\n if (Array.isArray(result)) return { providers: result }\n return result\n}\n\n","/**\n * ReadinessRegistry — kernel-side tracker for capability readiness\n * transitions. Spec: `docs/superpowers/specs/2026-04-19-system-readiness-design.md`.\n *\n * Each process owns one registry. The registry:\n * - Listens to `system.ready-state` events on the event bus.\n * - Maintains a `Map<key, ReadinessRecord>` snapshot of the most\n * recently observed state + generation + derived epoch.\n * - Exposes `emitReady` / `emitStarting` / `emitDown` helpers for\n * local producers (which stamp the process-wide `generation`).\n * - Exposes `awaitReady(capName, scope, {timeoutMs, signal})` and\n * `onReadyState(capName, scope, handler)` for consumers.\n *\n * Epoch derivation:\n * - First `ready` observed for a `(capName, scope)` → epoch = 1.\n * - `ready` received with a generation different from the last\n * `currentGeneration` → epoch++.\n * - Same-generation repeated `ready` events → epoch unchanged\n * (idempotent keepalive; e.g. re-emit on `$node.connected`).\n *\n * Not persisted. Rebuilt from the event stream + optional boot-time\n * snapshot rehydration by the caller.\n */\nimport type {\n IEventBus,\n SystemReadyStatePayload,\n ReadinessScope,\n ReadinessState,\n} from '../interfaces/event-bus.js'\nimport type { IScopedLogger } from '../interfaces/logging.js'\nimport type {\n IReadinessRegistry,\n IReadinessHandler,\n IAwaitReadyOptions,\n IReadinessTransition,\n} from '../interfaces/readiness.js'\nimport { createEvent } from '../interfaces/event-bus.js'\n\n/**\n * Concrete types live here; `interfaces/readiness.ts` declares the\n * matching narrow interfaces (`IReadinessTransition`,\n * `IReadinessHandler`, `IAwaitReadyOptions`) used by `AddonContext`\n * and other consumer-facing types.\n */\nexport type ReadinessTransition = IReadinessTransition\nexport type ReadinessHandler = IReadinessHandler\nexport type AwaitReadyOptions = IAwaitReadyOptions\n\nexport class ReadinessTimeoutError extends Error {\n readonly capName: string\n readonly scope: ReadinessScope\n readonly waitedMs: number\n constructor(capName: string, scope: ReadinessScope, waitedMs: number) {\n super(`Timed out waiting for ${capName} (${scopeKey(scope)}) to become ready after ${waitedMs}ms`)\n this.name = 'ReadinessTimeoutError'\n this.capName = capName\n this.scope = scope\n this.waitedMs = waitedMs\n }\n}\n\ninterface ReadinessRecord {\n capName: string\n scope: ReadinessScope\n state: ReadinessState\n generation: string\n epoch: number\n lastChange: number\n /**\n * Node that emitted the latest transition for this record. Needed for\n * `agent.offline` demux of `device`-scoped caps (scope itself carries\n * no node info). For `node`-scoped caps this matches `scope.nodeId`.\n */\n sourceNodeId: string\n}\n\ninterface Subscription {\n readonly capName: string\n readonly scope: ReadinessScope\n readonly handler: ReadinessHandler\n}\n\n/**\n * Build a canonical string key for a `(capName, scope)` pair. Used as\n * the snapshot map key and for log/debug output.\n */\nexport function readinessKey(capName: string, scope: ReadinessScope): string {\n return `${capName}|${scopeKey(scope)}`\n}\n\nfunction scopeKey(scope: ReadinessScope): string {\n switch (scope.type) {\n case 'global': return 'global'\n case 'node': return `node:${scope.nodeId}`\n case 'device': return `device:${scope.deviceId}`\n }\n}\n\nfunction scopesEqual(a: ReadinessScope, b: ReadinessScope): boolean {\n if (a.type !== b.type) return false\n if (a.type === 'global' || b.type === 'global') return true\n if (a.type === 'node' && b.type === 'node') return a.nodeId === b.nodeId\n if (a.type === 'device' && b.type === 'device') return a.deviceId === b.deviceId\n return false\n}\n\nexport interface ReadinessRegistryOptions {\n readonly eventBus: IEventBus\n readonly sourceNodeId: string\n /**\n * Per-process generation id — stamped on every emit made via this\n * registry's `emitReady`/`emitStarting`/`emitDown` helpers. Caller\n * owns the value so it can survive across subsystem re-bindings\n * within the same process. Default: a random 12-char id.\n */\n readonly generation?: string\n readonly logger?: IScopedLogger\n /**\n * Clock source. Injectable for tests.\n */\n readonly now?: () => number\n}\n\nexport class ReadinessRegistry implements IReadinessRegistry {\n private readonly bus: IEventBus\n private readonly sourceNodeId: string\n private readonly logger: IScopedLogger | undefined\n private readonly now: () => number\n private readonly generation: string\n private readonly snapshot = new Map<string, ReadinessRecord>()\n private readonly subscriptions = new Set<Subscription>()\n private readonly unsubscribeBus: () => void\n private readonly unsubscribeAgentOffline: () => void\n\n constructor(options: ReadinessRegistryOptions) {\n this.bus = options.eventBus\n this.sourceNodeId = options.sourceNodeId\n this.logger = options.logger\n this.now = options.now ?? (() => Date.now())\n this.generation = options.generation ?? randomGeneration()\n\n this.unsubscribeBus = this.bus.subscribe(\n { category: 'system.ready-state' },\n (event) => this.ingest(event.data as SystemReadyStatePayload),\n )\n // Auto-heal on agent disconnect: when `agent.offline` fires, walk\n // our own snapshot and synthesize `down` transitions for every\n // node-scoped cap bound to the disconnected nodeId. This covers\n // ungraceful producer deaths (process crash, network blip,\n // SIGKILL) where the producer's own shutdown hook never fires —\n // subscribers would otherwise keep waiting on a stale `ready`.\n // Synthesized transitions are local-only (we don't re-emit on the\n // bus) — every registry reacts independently to the same agent.offline.\n this.unsubscribeAgentOffline = this.bus.subscribe(\n { category: 'agent.offline' },\n (event) => this.synthesizeDownForNode((event.data as { agentId: string }).agentId),\n )\n // Hydrate from recent bus events so a late-starting registry\n // (e.g. an addon subscribed mid-session, or a hub reboot where\n // producers haven't re-emitted yet) picks up already-fired\n // readiness transitions. Safe to run after subscribe: ingest()\n // is idempotent for same-generation replays.\n if (typeof this.bus.getRecent === 'function') {\n try {\n const recent = this.bus.getRecent({ category: 'system.ready-state' })\n for (const event of recent) {\n this.ingest(event.data as SystemReadyStatePayload)\n }\n } catch {\n // getRecent is optional — a minimal test bus may not support it.\n }\n }\n }\n\n /** Release the event-bus subscription. Idempotent. */\n close(): void {\n this.unsubscribeBus()\n this.unsubscribeAgentOffline()\n this.subscriptions.clear()\n }\n\n /** Current snapshot for a `(capName, scope)` pair, or `null` if never seen. */\n get(capName: string, scope: ReadinessScope): ReadinessRecord | null {\n return this.snapshot.get(readinessKey(capName, scope)) ?? null\n }\n\n /**\n * Serializable snapshot for cross-process transport. Returns an array\n * of `ReadinessRecord` plain objects — safe for MsgPack / JSON\n * transport. Used by the hub's `$readiness.getSnapshot` Moleculer\n * action; consumers hydrate their local registry from the result.\n */\n getSnapshotForTransport(): readonly ReadinessRecord[] {\n return Array.from(this.snapshot.values())\n }\n\n /**\n * Hydrate the snapshot from an authoritative source. Entries already\n * present locally are skipped — live deltas (received via the event\n * bus subscription) always take precedence over the snapshot. For\n * each newly hydrated entry, a one-shot transition is dispatched to\n * matching subscriptions so pending `awaitReady` callers unblock\n * without having to wait for a fresh event.\n *\n * Local `epoch` is reset to 1 per entry — consumer-side epoch is\n * derived from observed generation transitions, so this mirrors the\n * value that would have been assigned had the consumer observed the\n * first `ready` event directly.\n */\n hydrate(records: readonly ReadinessRecord[]): void {\n const now = this.now()\n for (const record of records) {\n const key = readinessKey(record.capName, record.scope)\n if (this.snapshot.has(key)) continue\n const hydrated: ReadinessRecord = {\n capName: record.capName,\n scope: record.scope,\n state: record.state,\n generation: record.generation,\n epoch: 1,\n lastChange: now,\n sourceNodeId: record.sourceNodeId,\n }\n this.snapshot.set(key, hydrated)\n if (this.logger) {\n this.logger.debug(\n `readiness: ${record.capName} (${scopeKey(record.scope)}) → ${record.state} (hydrated, gen=${record.generation.slice(0, 6)})`,\n )\n }\n const transition: ReadinessTransition = {\n capName: record.capName,\n scope: record.scope,\n state: record.state,\n epoch: 1,\n generation: record.generation,\n sourceNodeId: 'hydrated',\n ts: now,\n durationInPrevState: 0,\n }\n for (const sub of this.subscriptions) {\n if (sub.capName !== record.capName) continue\n if (!scopesEqual(sub.scope, record.scope)) continue\n try {\n sub.handler(transition)\n } catch (err) {\n this.logger?.warn(\n `readiness hydrate handler threw for ${record.capName}: ${(err as Error).message ?? String(err)}`,\n )\n }\n }\n }\n }\n\n /** Shallow copy of the full snapshot — mainly for diagnostics/tests. */\n getAll(): ReadonlyMap<string, ReadinessRecord> {\n return new Map(this.snapshot)\n }\n\n /**\n * Emit a `ready` transition for a locally-owned capability. The\n * payload carries this registry's `generation` so remote registries\n * can derive their own `epoch`.\n */\n emitReady(capName: string, scope: ReadinessScope): void {\n this.emitTransition(capName, scope, 'ready')\n }\n\n emitStarting(capName: string, scope: ReadinessScope): void {\n this.emitTransition(capName, scope, 'starting')\n }\n\n emitDown(capName: string, scope: ReadinessScope): void {\n this.emitTransition(capName, scope, 'down')\n }\n\n /**\n * One-shot: resolve once the cap is `ready`. Reads the snapshot\n * first — if already ready, resolves synchronously on the next tick.\n *\n * Default behaviour is **wait indefinitely** (timeoutMs = `Infinity`):\n * the orchestrator and other callers never want to attach a camera\n * with empty steps just because a cap took longer than 30s to come\n * up. Pass an explicit finite `timeoutMs` to bound the wait, or an\n * `AbortSignal` to cancel externally. `Infinity` is honoured natively\n * — no `setTimeout` is registered (Node's setTimeout silently clamps\n * values above ~24.8d, so we must skip the timer entirely).\n */\n awaitReady(capName: string, scope: ReadinessScope, opts: AwaitReadyOptions = {}): Promise<void> {\n const timeoutMs = opts.timeoutMs ?? Number.POSITIVE_INFINITY\n const start = this.now()\n const current = this.get(capName, scope)\n if (current?.state === 'ready') {\n return Promise.resolve()\n }\n if (opts.signal?.aborted) {\n return Promise.reject(opts.signal.reason ?? new Error('aborted'))\n }\n return new Promise<void>((resolve, reject) => {\n let settled = false\n const unsubscribe = this.onReadyState(capName, scope, (t) => {\n if (t.state !== 'ready') return\n if (settled) return\n settled = true\n cleanup()\n resolve()\n })\n const isInfinite = !Number.isFinite(timeoutMs)\n const timer: ReturnType<typeof setTimeout> | null = isInfinite\n ? null\n : setTimeout(() => {\n if (settled) return\n settled = true\n cleanup()\n reject(new ReadinessTimeoutError(capName, scope, this.now() - start))\n }, timeoutMs)\n const onAbort = (): void => {\n if (settled) return\n settled = true\n cleanup()\n reject(opts.signal?.reason ?? new Error('aborted'))\n }\n opts.signal?.addEventListener('abort', onAbort, { once: true })\n function cleanup(): void {\n unsubscribe()\n if (timer !== null) clearTimeout(timer)\n opts.signal?.removeEventListener('abort', onAbort)\n }\n })\n }\n\n /**\n * Observable: every transition (starting/ready/down) dispatches to\n * `handler`. On subscription, if the snapshot has a current state,\n * the handler fires ONCE asynchronously with that state as the\n * initial transition (duration = 0) so late subscribers can pick up\n * current state without racing the next transition.\n *\n * Returns an unsubscribe function.\n */\n onReadyState(capName: string, scope: ReadinessScope, handler: ReadinessHandler): () => void {\n const sub: Subscription = { capName, scope, handler }\n this.subscriptions.add(sub)\n const current = this.get(capName, scope)\n if (current !== null) {\n queueMicrotask(() => {\n if (!this.subscriptions.has(sub)) return\n handler({\n capName,\n scope,\n state: current.state,\n epoch: current.epoch,\n generation: current.generation,\n sourceNodeId: this.sourceNodeId,\n ts: current.lastChange,\n durationInPrevState: 0,\n })\n })\n }\n return () => { this.subscriptions.delete(sub) }\n }\n\n // ── Internals ─────────────────────────────────────────────────────────\n\n private emitTransition(capName: string, scope: ReadinessScope, state: ReadinessState): void {\n const ts = this.now()\n this.bus.emit(createEvent(\n 'system.ready-state',\n { type: 'capability', id: capName, nodeId: this.sourceNodeId },\n {\n capName,\n scope,\n state,\n generation: this.generation,\n sourceNodeId: this.sourceNodeId,\n ts,\n },\n ))\n }\n\n /**\n * Update snapshot + dispatch to subscribers. Idempotent: same\n * `generation + state` replay is a no-op for both snapshot and\n * subscribers.\n *\n * Defensive against malformed payloads (legal reason: a mock bus's\n * `getRecent` may ignore the category filter and replay unrelated\n * events when we hydrate at construction time).\n */\n private ingest(payload: SystemReadyStatePayload): void {\n if (typeof payload?.capName !== 'string') return\n if (payload.state !== 'ready' && payload.state !== 'starting' && payload.state !== 'down') return\n if (typeof payload.generation !== 'string') return\n if (payload.scope?.type !== 'global' && payload.scope?.type !== 'node' && payload.scope?.type !== 'device') return\n\n const key = readinessKey(payload.capName, payload.scope)\n const prev = this.snapshot.get(key) ?? null\n const now = this.now()\n\n let epoch: number\n if (prev === null) {\n epoch = payload.state === 'ready' ? 1 : 0\n } else if (prev.generation !== payload.generation && payload.state === 'ready') {\n epoch = prev.epoch + 1\n } else {\n epoch = prev.epoch\n }\n\n // Idempotent replay: same generation + same state + we've already\n // recorded it — skip both snapshot write and dispatch.\n if (prev !== null && prev.generation === payload.generation && prev.state === payload.state) {\n return\n }\n\n const durationInPrevState = prev === null ? 0 : Math.max(0, now - prev.lastChange)\n const next: ReadinessRecord = {\n capName: payload.capName,\n scope: payload.scope,\n state: payload.state,\n generation: payload.generation,\n epoch,\n lastChange: now,\n sourceNodeId: payload.sourceNodeId,\n }\n this.snapshot.set(key, next)\n\n const transition: ReadinessTransition = {\n capName: payload.capName,\n scope: payload.scope,\n state: payload.state,\n epoch,\n generation: payload.generation,\n sourceNodeId: payload.sourceNodeId,\n ts: payload.ts,\n durationInPrevState,\n }\n\n if (this.logger) {\n this.logger.debug(\n `readiness: ${payload.capName} (${scopeKey(payload.scope)}) → ${payload.state} epoch=${epoch} gen=${payload.generation.slice(0, 6)} (prev ${durationInPrevState}ms)`,\n )\n }\n\n for (const sub of this.subscriptions) {\n if (sub.capName !== payload.capName) continue\n if (!scopesEqual(sub.scope, payload.scope)) continue\n try {\n sub.handler(transition)\n } catch (err) {\n this.logger?.warn(`readiness handler threw for ${payload.capName}: ${(err as Error).message ?? String(err)}`)\n }\n }\n }\n\n /**\n * `agent.offline` demux. When an agent disconnects ungracefully,\n * its BaseAddon's shutdown hook doesn't fire — consumers would\n * otherwise keep waiting on a stale `ready`. Walk the snapshot and\n * synthesize a `down` transition for every node-scoped record bound\n * to the disconnected `nodeId`, skipping records already `down`.\n *\n * Synthesis is LOCAL: we don't re-emit on the bus. Every registry\n * (one per process) receives the same `agent.offline` and reacts\n * independently, which means no duplicated downs and no central\n * supervisor required.\n */\n private synthesizeDownForNode(offlineNodeId: string): void {\n const now = this.now()\n for (const [key, record] of this.snapshot) {\n if (record.state === 'down') continue\n // Node-scoped records: match on scope.nodeId.\n // Device-scoped records: match on sourceNodeId (which node emitted\n // the latest ready) because the scope itself carries no node info.\n // Global-scoped records are skipped — they're not tied to a node.\n const matchesOfflineNode =\n (record.scope.type === 'node' && record.scope.nodeId === offlineNodeId) ||\n (record.scope.type === 'device' && record.sourceNodeId === offlineNodeId)\n if (!matchesOfflineNode) continue\n\n const durationInPrevState = Math.max(0, now - record.lastChange)\n const next: ReadinessRecord = {\n ...record,\n state: 'down',\n lastChange: now,\n }\n this.snapshot.set(key, next)\n\n const transition: ReadinessTransition = {\n capName: record.capName,\n scope: record.scope,\n state: 'down',\n epoch: record.epoch,\n generation: record.generation,\n sourceNodeId: this.sourceNodeId,\n ts: now,\n durationInPrevState,\n }\n if (this.logger) {\n this.logger.debug(\n `readiness: ${record.capName} (${scopeKey(record.scope)}) → down (synthesized from agent.offline ${offlineNodeId})`,\n )\n }\n for (const sub of this.subscriptions) {\n if (sub.capName !== record.capName) continue\n if (!scopesEqual(sub.scope, record.scope)) continue\n try {\n sub.handler(transition)\n } catch (err) {\n this.logger?.warn(`readiness handler threw during agent.offline demux for ${record.capName}: ${(err as Error).message ?? String(err)}`)\n }\n }\n }\n }\n}\n\nfunction randomGeneration(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID()\n }\n return Math.random().toString(36).slice(2, 14)\n}\n\n// ---------------------------------------------------------------------------\n// Helpers for `$node.disconnected` demultiplexing\n// ---------------------------------------------------------------------------\n\n/**\n * Given a list of `(capName, scope)` pairs that a just-disconnected\n * node owned, emit a `down` transition for each. Callers (kernel\n * supervisor, hub `$node.disconnected` handler) wire this up once they\n * know which caps the node held.\n */\nexport function emitDownForOwnedCaps(\n registry: ReadinessRegistry,\n owned: ReadonlyArray<{ readonly capName: string; readonly scope: ReadinessScope }>,\n): void {\n for (const { capName, scope } of owned) {\n registry.emitDown(capName, scope)\n }\n}\n\n// Re-export the scope key helper for consumers that want to\n// collate by key in their own maps (e.g. debug UIs).\nexport { scopeKey }\n","// =============================================================================\n// Storage Location Types\n// =============================================================================\n//\n// `StorageLocationType` is owned by `./storage-location.ts` (Zod enum is\n// the authoritative source). This file used to declare a parallel TS\n// alias which drifted from the Zod enum (the alias had 4 values the enum\n// didn't). Re-exporting the inferred type keeps the wire surface and the\n// legacy `IStorageProvider` interface in lockstep — adding/removing a\n// value in the Zod enum is now the single source of truth.\n\nexport type { StorageLocationType } from './storage-location.js'\nimport type { StorageLocationType } from './storage-location.js'\n\n/** All location types as an array (for iteration) */\nexport const STORAGE_LOCATION_TYPES: readonly StorageLocationType[] = [\n 'data',\n 'media',\n 'recordings',\n 'recordings-high',\n 'recordings-low',\n 'recordings-clips',\n 'event-images',\n 'models',\n 'addons-data',\n 'cache',\n 'logs',\n 'backups',\n] as const\n\n/** Default subdirectory names for filesystem storage */\nexport const DEFAULT_LOCATION_SUBDIRS: Readonly<Record<StorageLocationType, string>> = {\n 'data': 'db',\n 'media': 'media',\n 'recordings': 'recordings',\n 'recordings-high': 'recordings-high',\n 'recordings-low': 'recordings-low',\n 'recordings-clips': 'recordings-clips',\n 'event-images': 'event-images',\n 'models': 'models',\n 'addons-data': 'addons-data',\n 'cache': '/tmp/camstack-cache',\n 'logs': 'logs',\n 'backups': 'backups',\n}\n\n// =============================================================================\n// Storage Provider (capability: 'storage', mode: collection)\n// =============================================================================\n\n/**\n * A storage provider serves file-based storage for one or more location types.\n * Multiple providers can coexist (local filesystem, NAS, S3, etc.).\n * Each addon/system setting selects which provider to use per location type.\n */\n// ── Named input types for IStorageProvider methods ──────────────────────\n\nexport interface StorageResolveInput { readonly location: StorageLocationType; readonly relativePath: string }\nexport interface StorageWriteInput { readonly location: StorageLocationType; readonly relativePath: string; readonly data: Buffer | NodeJS.ReadableStream }\nexport interface StorageReadInput { readonly location: StorageLocationType; readonly relativePath: string }\nexport interface StorageExistsInput { readonly location: StorageLocationType; readonly relativePath: string }\nexport interface StorageListInput { readonly location: StorageLocationType; readonly prefix?: string }\nexport interface StorageDeleteInput { readonly location: StorageLocationType; readonly relativePath: string }\nexport interface StorageAvailableSpaceInput { readonly location: StorageLocationType }\n\nexport interface IStorageProvider {\n readonly id: string\n readonly name: string\n readonly supportedLocations: readonly StorageLocationType[]\n\n resolve(input: StorageResolveInput): string\n write(input: StorageWriteInput): Promise<void>\n read(input: StorageReadInput): Promise<Buffer>\n exists(input: StorageExistsInput): Promise<boolean>\n list(input: StorageListInput): Promise<readonly string[]>\n delete(input: StorageDeleteInput): Promise<void>\n getAvailableSpace(input: StorageAvailableSpaceInput): Promise<number | null>\n}\n\n// =============================================================================\n// Settings Backend (capability: 'settings-store', mode: singleton)\n// =============================================================================\n\n/**\n * All named collections that the settings backend manages.\n * Each collection maps to a logical table/bucket in the backend.\n */\nexport type SettingsCollection =\n | 'system-settings' // Global system config\n | 'addon-settings' // Per-addon config (keyed by addonId)\n | 'provider-settings' // Per-device-provider config (keyed by providerId)\n | 'device-settings' // Per-device config (keyed by deviceId)\n | 'detection-events' // Detection event records\n | 'audio-levels' // Audio level readings\n | 'track-trails' // Object tracking trails\n | 'recording-segments' // Recording segment metadata\n | 'recording-thumbnails' // Thumbnail metadata\n | 'recording-policies' // Per-device recording policies\n | 'recording-storage-config' // Per-device storage + retention\n | 'recording-cleanup-queue' // Cleanup task queue\n | 'known-faces' // Face recognition identities\n | (string & {}) // Allow arbitrary collection names (e.g. addon-defined)\n\n// ── Named input types for ISettingsBackend methods ──────────────────────\n\nexport interface SettingsGetInput { readonly namespace?: string; readonly collection: SettingsCollection; readonly key: string }\nexport interface SettingsSetInput { readonly namespace?: string; readonly collection: SettingsCollection; readonly key: string; readonly value: unknown }\nexport interface SettingsQueryInput { readonly namespace?: string; readonly collection: SettingsCollection; readonly filter?: QueryFilter }\nexport interface SettingsInsertInput<T extends object = Record<string, unknown>> { readonly namespace?: string; readonly collection: SettingsCollection; readonly record: SettingsRecord<T> }\nexport interface SettingsUpdateInput { readonly namespace?: string; readonly collection: SettingsCollection; readonly id: string; readonly data: Record<string, unknown> }\nexport interface SettingsDeleteInput { readonly namespace?: string; readonly collection: SettingsCollection; readonly key: string }\nexport interface SettingsCountInput { readonly namespace?: string; readonly collection: SettingsCollection; readonly filter?: QueryFilter }\nexport interface SettingsIsEmptyInput { readonly namespace?: string; readonly collection: SettingsCollection }\n\n/**\n * Settings backend — persistent key-value and document storage.\n * Default implementation: SQLite. Can be replaced by Postgres, etc.\n * All methods use object-arg signatures for extensibility.\n */\nexport interface ISettingsBackend {\n /** Get a single value by key from a collection */\n get(input: SettingsGetInput): Promise<unknown>\n\n /** Set a value by key in a collection (upsert) */\n set(input: SettingsSetInput): Promise<void>\n\n /** Get all entries matching an optional filter */\n query<T extends object = Record<string, unknown>>(input: SettingsQueryInput): Promise<readonly SettingsRecord<T>[]>\n\n /** Insert a new record */\n insert<T extends object = Record<string, unknown>>(input: SettingsInsertInput<T>): Promise<void>\n\n /** Update an existing record by ID */\n update(input: SettingsUpdateInput): Promise<void>\n\n /** Delete a record by key/ID */\n delete(input: SettingsDeleteInput): Promise<void>\n\n /** Count entries in a collection */\n count(input: SettingsCountInput): Promise<number>\n\n /** Check if a collection is empty (used for first-boot detection) */\n isEmpty(input: SettingsIsEmptyInput): Promise<boolean>\n\n /**\n * Declare a typed (SQL-backed) collection. After declaration, the\n * standard `insert` / `update` / `delete` / `query` methods route to\n * typed columns for this collection instead of the JSON-blob default.\n * Idempotent — re-declaring the same shape is a no-op. Backends\n * without typed-table support should implement this as a no-op so\n * the cap contract stays uniform.\n */\n declareCollection(input: {\n namespace?: string\n collection: string\n columns: readonly import('../capabilities/settings-store.cap.js').CollectionColumn[]\n indexes?: readonly import('../capabilities/settings-store.cap.js').CollectionIndex[]\n }): Promise<void>\n\n // ── Structured tables ────────────────────────────────────────────────\n // Generic SQL-like operations for custom tables with typed columns.\n // Implementations create the table on first use if it doesn't exist.\n\n /** Ensure a structured table exists (CREATE TABLE IF NOT EXISTS) */\n ensureTable?(table: string, schema: TableSchema): Promise<void>\n\n /** Insert a row into a structured table */\n tableInsert?(table: string, row: Record<string, unknown>): Promise<void>\n\n /** Update rows matching a filter */\n tableUpdate?(table: string, filter: Record<string, unknown>, updates: Record<string, unknown>): Promise<number>\n\n /** Delete rows matching a filter. Returns count of deleted rows. */\n tableDelete?(table: string, filter: Record<string, unknown>): Promise<number>\n\n /** Query rows from a structured table */\n tableQuery?(table: string, options?: TableQueryOptions): Promise<readonly Record<string, unknown>[]>\n\n /** Get a single row by primary key or filter */\n tableGet?(table: string, filter: Record<string, unknown>): Promise<Record<string, unknown> | null>\n\n /** Count rows matching a filter */\n tableCount?(table: string, filter?: Record<string, unknown>): Promise<number>\n}\n\nexport interface SettingsRecord<T extends object = Record<string, unknown>> {\n readonly id: string\n readonly data: T\n}\n\nexport interface QueryFilter {\n where?: Record<string, unknown>\n whereIn?: Record<string, unknown[]>\n whereBetween?: Record<string, [unknown, unknown]>\n orderBy?: { field: string; direction: 'asc' | 'desc' }\n limit?: number\n offset?: number\n}\n\n/** Column definition for structured tables */\nexport interface TableColumnSchema {\n readonly name: string\n readonly type: 'TEXT' | 'INTEGER' | 'REAL' | 'JSON'\n readonly primaryKey?: boolean\n readonly notNull?: boolean\n readonly unique?: boolean\n readonly defaultValue?: string | number | null\n}\n\n/** Table schema for structured tables */\nexport interface TableSchema {\n readonly columns: readonly TableColumnSchema[]\n readonly indexes?: readonly TableIndexSchema[]\n}\n\n/** Index definition for structured tables */\nexport interface TableIndexSchema {\n readonly name: string\n readonly columns: readonly string[]\n readonly unique?: boolean\n}\n\n/** Query options for structured tables */\nexport interface TableQueryOptions {\n readonly where?: Record<string, unknown>\n readonly orderBy?: { field: string; direction: 'asc' | 'desc' }\n readonly limit?: number\n readonly offset?: number\n}\n\n// =============================================================================\n// Embeddings Backend (capability: 'embeddings', mode: singleton)\n// =============================================================================\n\n/**\n * Embeddings backend — vector storage with approximate nearest neighbor search.\n * Used for CLIP frame search, face recognition, plate matching.\n * Default implementation: HNSW (usearch/hnswlib). Can be replaced by Qdrant, etc.\n */\nexport interface IEmbeddingsBackend {\n /** Create or open a named vector index */\n openIndex(name: string, dimensions: number): Promise<IVectorIndex>\n\n /** List all index names */\n listIndexes(): Promise<readonly string[]>\n\n /** Delete an index and its data */\n deleteIndex(name: string): Promise<void>\n\n /** Lifecycle */\n initialize(): Promise<void>\n shutdown(): Promise<void>\n}\n\nexport interface IVectorIndex {\n /** Index name */\n readonly name: string\n\n /** Vector dimensions */\n readonly dimensions: number\n\n /** Insert a vector with ID and optional metadata */\n insert(id: string, vector: Float32Array, metadata?: Record<string, unknown>): Promise<void>\n\n /** Batch insert for performance */\n insertBatch(items: readonly VectorEntry[]): Promise<void>\n\n /** Search for nearest neighbors */\n search(query: Float32Array, topK: number, filter?: EmbeddingFilter): Promise<readonly VectorSearchResult[]>\n\n /** Delete by ID */\n delete(id: string): Promise<void>\n\n /** Count entries in the index */\n count(): Promise<number>\n\n /** Flush pending writes to disk */\n flush(): Promise<void>\n}\n\nexport interface VectorEntry {\n readonly id: string\n readonly vector: Float32Array\n readonly metadata?: Record<string, unknown>\n}\n\nexport interface VectorSearchResult {\n readonly id: string\n /** Similarity score (0-1, higher is more similar) */\n readonly score: number\n readonly metadata?: Record<string, unknown>\n}\n\nexport interface EmbeddingFilter {\n /** Filter by metadata key-value before vector search */\n readonly where?: Record<string, unknown>\n /** Filter by timestamp range */\n readonly timestampAfter?: number\n readonly timestampBefore?: number\n /** Filter by device */\n readonly deviceId?: string\n}\n\n// =============================================================================\n// Legacy re-exports (deprecated — migrate to new interfaces)\n// =============================================================================\n\n\n/**\n * A document record in collection-based storage.\n * Used by IStructuredStorage and ElementConfigStore.\n * New code should prefer ISettingsBackend + SettingsRecord.\n */\nexport interface StorageRecord {\n collection: string\n id: string\n data: Record<string, unknown>\n}\n\n/**\n * Collection-based document storage (query, insert, update, delete).\n * Used by ElementConfigStore and StorageManager shim layer.\n * New code should prefer ISettingsBackend.\n */\nexport interface IStructuredStorage {\n query(collection: string, filter?: QueryFilter): Promise<readonly StorageRecord[]>\n insert(record: StorageRecord): Promise<StorageRecord>\n update(collection: string, id: string, data: Record<string, unknown>): Promise<StorageRecord>\n delete(collection: string, id: string): Promise<void>\n count(collection: string, filter?: QueryFilter): Promise<number>\n}\n\n/**\n * File-based storage operations.\n * Used by StorageManager and addons for media/model files.\n * New code should prefer IStorageProvider.\n */\nexport interface IFileStorage {\n readFile(path: string): Promise<Buffer>\n writeFile(path: string, data: Buffer): Promise<void>\n deleteFile(path: string): Promise<void>\n listFiles(prefix?: string): Promise<readonly string[]>\n getFileUrl(path: string): Promise<string>\n exists(path: string): Promise<boolean>\n}\n\n/**\n * Combined storage location with optional structured + file storage.\n * Used by StorageManager.getLocation() and ElementConfigStore.\n * New code should prefer IStorageProvider + ISettingsBackend.\n */\nexport interface IStorageLocation {\n structured?: IStructuredStorage\n files?: IFileStorage\n}\n","import type { StreamSourceEntry } from '../../device/camera-device.js'\n\n// ---------------------------------------------------------------------------\n// Stream metadata — probed (ffprobe) or declared by provider\n// ---------------------------------------------------------------------------\n\nexport interface StreamMetadata {\n width?: number // e.g. 1920\n height?: number // e.g. 1080\n codec?: string // e.g. 'h264', 'h265', 'mjpeg', 'vp8', 'vp9', 'av1'\n fps?: number // e.g. 25\n bitrateKbps?: number // e.g. 4000\n /** Probed audio track. Undefined when stream carries no audio. */\n audio?: StreamAudioMetadata\n}\n\nexport interface StreamAudioMetadata {\n /** Codec name as reported by the demuxer (e.g. 'aac', 'pcm_mulaw', 'opus'). */\n codec?: string\n /** Sample rate in Hz (e.g. 8000, 16000, 44100, 48000). */\n sampleRate?: number\n /** Channel count (1 = mono, 2 = stereo). */\n channels?: number\n /** Stated bitrate in kbps when the demuxer reports one. */\n bitrateKbps?: number\n /** Codec profile/aac-mode (e.g. 'LC', 'HE-AAC') when known. */\n profile?: string\n}\n\n// ---------------------------------------------------------------------------\n// Stream quality — computed from metadata\n// ---------------------------------------------------------------------------\n\nexport type StreamQuality = 'high' | 'mid' | 'low'\n\n/** Friendly display labels for stream quality IDs. */\nexport const STREAM_QUALITY_LABELS: Readonly<Record<string, string>> = {\n high: 'High',\n mid: 'Mid',\n low: 'Low',\n}\n\n/** Get a friendly label for a stream ID. Falls back to capitalised id. */\nexport function streamQualityLabel(id: string): string {\n return STREAM_QUALITY_LABELS[id] ?? (id.charAt(0).toUpperCase() + id.slice(1))\n}\n\n/**\n * Compute pixel count for sorting. Returns w*h, or 0 if unknown.\n */\nexport function streamPixels(meta: StreamMetadata): number {\n return (meta.width ?? 0) * (meta.height ?? 0)\n}\n\n/**\n * Classify streams relative to each other.\n * Highest resolution → high, lowest → low, everything else → mid.\n * With 1 stream: high. With 2: high + low.\n */\nexport function classifyStreams<T extends { metadata?: StreamMetadata }>(\n streams: readonly T[],\n): Array<T & { quality: StreamQuality }> {\n if (streams.length === 0) return []\n\n // Sort by pixel count descending\n const sorted = streams\n .map((s, i) => ({ s, i, px: streamPixels(s.metadata ?? {}) }))\n .sort((a, b) => b.px - a.px)\n\n const result: Array<T & { quality: StreamQuality }> = Array.from<T & { quality: StreamQuality }>({ length: streams.length })\n\n for (let rank = 0; rank < sorted.length; rank++) {\n const { s, i } = sorted[rank]!\n let quality: StreamQuality\n if (rank === 0) quality = 'high'\n else if (rank === sorted.length - 1) quality = 'low'\n else quality = 'mid'\n result[i] = { ...s, quality }\n }\n\n return result\n}\n\n/**\n * Classify a single stream in isolation (no relative context).\n * Use classifyStreams() when you have the full set.\n */\nexport function classifyStream(meta: StreamMetadata): StreamQuality {\n const h = meta.height ?? 0\n const w = meta.width ?? 0\n if (h >= 1080 || w >= 1920) return 'high'\n if (h >= 480 || w >= 640) return 'mid'\n return 'low'\n}\n\n// ---------------------------------------------------------------------------\n// Stream protocol — how to consume a stream\n// ---------------------------------------------------------------------------\n\nexport type StreamProtocolType = 'rtsp' | 'rtmp' | 'http' | 'flv' | 'rtp' | 'raw'\n\nexport interface StreamProtocol {\n type: StreamProtocolType\n /** Source URL. undefined for 'raw' (push-based, e.g. Reolink Baichuan). */\n url?: string\n}\n\n// ---------------------------------------------------------------------------\n// AvailableStream — a physical stream exposed by a camera\n// ---------------------------------------------------------------------------\n\nexport interface AvailableStream {\n /** Unique identifier within the device (e.g. 'main', 'sub', 'ch0_0') */\n id: string\n /** Ways to consume this stream */\n protocols: StreamProtocol[]\n /** Probed or provider-declared stream characteristics */\n metadata?: StreamMetadata\n /** Computed from metadata via classifyStream() */\n quality: StreamQuality\n /** Optional display hint */\n label?: string\n}\n\n/** Convert AvailableStream to StreamSourceEntry for stream-broker consumers. */\nexport function toStreamSourceEntry(stream: AvailableStream): StreamSourceEntry {\n // Pick first URL-bearing protocol, prefer rtsp\n const urlProto = stream.protocols.find((p) => p.type === 'rtsp' && p.url)\n ?? stream.protocols.find((p) => p.url)\n\n const protocolRaw = urlProto?.type\n const protocol: StreamSourceEntry['protocol'] =\n protocolRaw === 'rtsp' ? 'rtsp'\n : protocolRaw === 'http' || protocolRaw === 'flv' ? 'http-mjpeg'\n : 'custom'\n\n return {\n id: stream.id,\n label: stream.label ?? stream.id,\n protocol,\n url: urlProto?.url,\n profileHint: stream.quality,\n }\n}\n\n\n// ---------------------------------------------------------------------------\n// Camera stream settings — stored in device settings by providers\n// ---------------------------------------------------------------------------\n\n/** A single stream entry in device settings. */\nexport interface CameraStreamEntry {\n readonly url: string\n readonly label?: string\n}\n\nexport interface CameraStreamConfig {\n readonly streams: readonly CameraStreamEntry[]\n /**\n * Snapshot source URL (JPEG).\n * Used internally by the provider to implement ICamera.getSnapshot().\n * Clients should call snapshot.getSnapshot() instead of hitting this URL directly.\n */\n readonly snapshot_url?: string\n}\n\nfunction isString(v: unknown): v is string {\n return typeof v === 'string'\n}\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v)\n}\n\nfunction parseStreamEntry(v: unknown): CameraStreamEntry | null {\n // \"rtsp://...\" → { url }\n if (isString(v) && v.trim()) return { url: v }\n // { url: \"rtsp://...\", label?: \"Main\" } → { url, label }\n if (isRecord(v) && isString(v['url']) && v['url'].trim()) {\n return {\n url: v['url'],\n label: isString(v['label']) ? v['label'] : undefined,\n }\n }\n return null\n}\n\n/** Extract CameraStreamConfig from untyped settings record. */\nexport function parseCameraStreamConfig(raw: Record<string, unknown>): CameraStreamConfig {\n const snapshotUrl = isString(raw['snapshot_url']) ? raw['snapshot_url'] : undefined\n\n // Array format: [\"url\"] or [{url, label}]\n if (Array.isArray(raw['streams'])) {\n const streams: CameraStreamEntry[] = []\n for (const item of raw['streams']) {\n const entry = parseStreamEntry(item)\n if (entry) streams.push(entry)\n }\n return { streams, snapshot_url: snapshotUrl }\n }\n\n // Legacy key-based format: main_stream_url, sub_stream_url, third_stream_url\n const streams: CameraStreamEntry[] = []\n\n const mainUrl = isString(raw['main_stream_url']) ? raw['main_stream_url'] : undefined\n if (mainUrl) streams.push({ url: mainUrl, label: isString(raw['main_stream_name']) ? raw['main_stream_name'] : undefined })\n\n const subUrl = isString(raw['sub_stream_url']) ? raw['sub_stream_url'] : undefined\n if (subUrl) streams.push({ url: subUrl, label: isString(raw['sub_stream_name']) ? raw['sub_stream_name'] : undefined })\n\n const thirdUrl = isString(raw['third_stream_url']) ? raw['third_stream_url'] : undefined\n if (thirdUrl) streams.push({ url: thirdUrl, label: isString(raw['third_stream_name']) ? raw['third_stream_name'] : undefined })\n\n return {\n streams,\n snapshot_url: snapshotUrl,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Stream Profile Assignment\n// ---------------------------------------------------------------------------\n\n/**\n * Per-device mapping of quality profile → streamId.\n * Cameras expose N physical streams; the user assigns which stream\n * serves each of the 3 standard CamStack profiles.\n */\nexport interface StreamProfileMap {\n high?: string\n mid?: string\n low?: string\n}\n\n/**\n * Auto-assign profiles based on quality classification.\n * With 1 stream: all profiles point to it.\n * With 2: high + low. With 3+: high + mid + low.\n */\nexport function autoAssignProfiles(streams: readonly AvailableStream[]): StreamProfileMap {\n if (streams.length === 0) return {}\n\n const classified = classifyStreams(streams)\n const map: StreamProfileMap = {}\n\n // Assign by quality label, not array position (classifyStreams preserves original order)\n const high = classified.find((s) => s.quality === 'high')\n const mid = classified.find((s) => s.quality === 'mid')\n const low = classified.find((s) => s.quality === 'low')\n\n if (high) map.high = high.id\n if (mid) map.mid = mid.id\n if (low) map.low = low.id\n\n // Fallback: fill missing profiles from what's available\n const fallback = high ?? mid ?? low ?? classified[0]\n if (fallback) {\n if (!map.high) map.high = fallback.id\n if (!map.mid) map.mid = fallback.id\n if (!map.low) map.low = fallback.id\n }\n\n return map\n}\n\n// ---------------------------------------------------------------------------\n","export interface FeatureManifest {\n streaming: boolean\n notifications: boolean\n objectDetection: boolean\n remoteAccess: boolean\n agentCluster: boolean\n smartHome: boolean\n recordings: boolean\n backup: boolean\n repl: boolean\n}\n\nexport type FeatureFlag = keyof FeatureManifest\n\nexport const DEFAULT_FEATURES: FeatureManifest = {\n streaming: true,\n notifications: true,\n objectDetection: false,\n remoteAccess: true,\n agentCluster: false,\n smartHome: true,\n recordings: true,\n backup: true,\n repl: true,\n}\n","/**\n * Detection Analysis Pipeline -- types for tracked detections, sub-detections,\n * recognition results, and audio classification.\n */\n\nimport type { VideoFrame } from './camera-pipeline.js'\n\n/**\n * A single detection entry consumed by the analysis pipeline (tracking,\n * zones, session aggregation).\n *\n * Intentionally DIFFERENT from `SpatialDetection` (the engine-level\n * detector output in `types/detection.ts`):\n * - `SpatialDetection` is raw model output: `{class, bbox:{x,y,w,h},\n * landmarks?, mask?}`.\n * - `AnalysisDetection` is the pipeline's view: tuple-bbox\n * `[x1,y1,x2,y2]`, optional enrichment (`id`, `label`, `zones`,\n * `previousZones`) added by upstream stages.\n *\n * Renamed from the ambiguous `Detection` on 2026-04-14 to disambiguate\n * from the other Detection types in the codebase (`ObjectDetection`\n * for UI payloads, `SpatialDetection` for engine output).\n */\nexport interface AnalysisDetection {\n className: string\n score: number\n boundingBox?: [number, number, number, number]\n id?: string\n label?: string\n labelScore?: number\n zones?: string[]\n previousZones?: string[]\n}\n\n// --- Detection type const unions ---\n\nexport const SUB_DETECTION_TYPES = ['face', 'plate'] as const\nexport type SubDetectionType = typeof SUB_DETECTION_TYPES[number]\n\nexport const RECOGNITION_TYPES = ['face', 'plate', 'clip', 'custom'] as const\nexport type RecognitionType = typeof RECOGNITION_TYPES[number]\n\n// --- Analysis Context ---\n\nexport interface AnalysisContext {\n readonly deviceId: string\n readonly frame: VideoFrame\n readonly timestamp: number\n readonly rawDetections: readonly AnalysisDetection[]\n readonly trackedDetections: readonly ServerTrackedDetection[]\n readonly events: readonly AnalysisEvent[]\n readonly metadata: Readonly<Record<string, unknown>>\n}\n\n// --- Tracked Detection ---\n\nexport interface ServerTrackedDetection {\n readonly trackId: string\n readonly detection: AnalysisDetection\n readonly crop?: Buffer\n readonly tracking: TrackingInfo\n readonly subDetections: readonly SubDetection[]\n readonly recognitions: readonly RecognitionResult[]\n readonly zones: readonly string[]\n readonly previousZones: readonly string[]\n}\n\nexport interface TrackingInfo {\n readonly age: number\n readonly state: 'moving' | 'stationary' | 'new' | 'lost'\n readonly stationaryDuration: number\n readonly velocity: { readonly dx: number; readonly dy: number }\n readonly positionHistory: ReadonlyArray<{ readonly x: number; readonly y: number; readonly t: number }>\n}\n\n// --- Sub-Detection ---\n\nexport interface SubDetection {\n readonly detectionType: SubDetectionType\n readonly boundingBox: readonly [number, number, number, number]\n readonly score: number\n readonly crop?: Buffer\n}\n\n// --- Recognition ---\n\nexport interface RecognitionResult {\n readonly recognitionType: RecognitionType\n readonly label: string\n readonly score: number\n readonly embedding?: readonly number[]\n readonly metadata?: Readonly<Record<string, unknown>>\n}\n\n// --- Analysis Events ---\n\nexport interface AnalysisEvent {\n readonly category: string\n readonly severity: 'info' | 'warning' | 'alert'\n readonly detection: ServerTrackedDetection\n readonly description: string\n readonly data: Readonly<Record<string, unknown>>\n}\n\n// --- Audio Classifier ---\n//\n// The canonical `IAudioClassifier` lives in `./audio-analyzer.ts` and is\n// derived from the capability definition. The legacy interface that lived\n// here had a different shape (readonly ready + release()) and was never\n// actually consumed outside of this file — removed to avoid confusion.\n","/**\n * Analysis Persistence Types — interfaces for event persistence, track trails,\n * retention, session tracking, and known faces.\n *\n * These interfaces define the contracts used by the server; concrete\n * implementations live in addon-analytics and are received via CapabilityRegistry.\n */\n\nimport type { ServerTrackedDetection } from './server-analysis.js'\n\n// ---------------------------------------------------------------------------\n// Event Persistence\n// ---------------------------------------------------------------------------\n\nexport interface ObjectSnapshotResult {\n readonly trackId: string\n readonly thumbnail?: Buffer\n readonly fullCrop?: Buffer\n}\n\nexport interface AnnotatedSnapshotResult {\n readonly thumbnail: Buffer\n readonly full: Buffer\n}\n\nexport interface PersistableEvent {\n readonly id: string\n readonly timestamp: number\n readonly deviceId: string\n readonly category: string\n readonly className: string\n readonly score: number\n readonly trackId: string\n readonly severity: string\n readonly description: string\n readonly data: Record<string, unknown>\n readonly mediaFiles: readonly string[]\n}\n\nexport interface EventBufferStatus {\n readonly eventCount: number\n readonly mediaCount: number\n readonly mediaSizeMB: number\n}\n\nexport type TrackMediaType =\n | 'crop-thumb'\n | 'crop-full'\n | 'debug-annotated-thumb'\n | 'debug-annotated-full'\n | 'original'\n | 'original-thumb'\n | 'inline-crop'\n | 'unknown'\n\nexport interface TrackMediaFile {\n readonly path: string\n readonly type: TrackMediaType\n readonly data: Buffer\n readonly source: 'buffer' | 'storage'\n}\n\n// ---------------------------------------------------------------------------\n// Track Trail\n// ---------------------------------------------------------------------------\n\n// F15c: `enabled` removed — trail capture on/off lives on the\n// `track-trail` wrapper binding. See capabilities/track-trail.cap.ts.\nexport interface TrackCaptureConfig {\n readonly snapshotIntervalMs: number\n readonly maxTrailLength: number\n readonly saveThumbnails: boolean\n readonly thumbnailSize: { readonly width: number; readonly height: number }\n}\n\nexport interface TrackPosition {\n readonly x: number\n readonly y: number\n readonly timestamp: number\n readonly bbox: [number, number, number, number]\n}\n\nexport interface TrackSnapshot {\n readonly timestamp: number\n readonly position: TrackPosition\n readonly thumbnailPath: string\n}\n\nexport interface TrackTrail {\n readonly trackId: string\n readonly deviceId: number\n readonly className: string\n readonly label?: string\n readonly firstSeen: number\n readonly lastSeen: number\n readonly positions: readonly TrackPosition[]\n readonly snapshots: readonly TrackSnapshot[]\n readonly totalDistance: number\n readonly zonesVisited: readonly string[]\n readonly active: boolean\n}\n\n// ---------------------------------------------------------------------------\n// Retention\n// ---------------------------------------------------------------------------\n\nexport interface RetentionConfig {\n readonly cleanupIntervalMs: number\n readonly detectionEventsDays: number\n readonly audioLevelsDays: number\n /** @deprecated — snapshots are tied to events, use detectionEventsDays */\n readonly snapshotsDays: number\n readonly deviceOverrides?: Readonly<Record<string, Partial<Pick<RetentionConfig, 'detectionEventsDays' | 'audioLevelsDays' | 'snapshotsDays'>>>>\n}\n\nexport const DEFAULT_RETENTION: RetentionConfig = {\n cleanupIntervalMs: 60 * 60 * 1000,\n detectionEventsDays: 30,\n audioLevelsDays: 7,\n snapshotsDays: 14,\n}\n\nexport interface RetentionReport {\n readonly deletedEvents: number\n readonly deletedAudioRecords: number\n readonly deletedSnapshots: number\n}\n\n// ---------------------------------------------------------------------------\n// Session Tracker\n// ---------------------------------------------------------------------------\n\nexport interface SessionTrack {\n readonly trackId: string\n readonly deviceId: string\n readonly className: string\n readonly label?: string\n readonly firstSeen: number\n readonly lastSeen: number\n readonly totalFrames: number\n readonly lastDetection: ServerTrackedDetection\n readonly state: string\n readonly positions: ReadonlyArray<{ readonly x: number; readonly y: number; readonly t: number }>\n readonly embedding?: Float32Array\n readonly globalId?: string\n readonly bestCrop?: Buffer\n}\n\nexport interface GlobalIdentity {\n readonly globalId: string\n readonly embedding: Float32Array\n readonly label?: string\n readonly firstSeen: number\n readonly lastSeen: number\n readonly deviceIds: ReadonlyArray<string>\n}\n\n// ---------------------------------------------------------------------------\n// Known Faces\n// ---------------------------------------------------------------------------\n\nexport interface ClipRecognizer {\n getEmbedding(imageBuffer: Buffer): Promise<Float32Array>\n}\n\nexport interface KnownFaceEntry {\n readonly id: string\n readonly label: string\n readonly group?: string\n readonly embedding: readonly number[]\n readonly cropBase64: string\n readonly createdAt: number\n readonly updatedAt: number\n readonly source?: string\n readonly metadata?: Readonly<Record<string, unknown>>\n}\n\n// ---------------------------------------------------------------------------\n// Recording Addon (generic interface for recording engine access)\n// ---------------------------------------------------------------------------\n\n/**\n * Interface for the recording addon — the server uses this instead of\n * importing RecordingAddon directly from addon-recording.\n */\nexport interface IRecordingAddon {\n getCoordinator(): IRecordingCoordinator\n getRecordingDb(): IRecordingDb\n}\n\n/**\n * Minimal coordinator interface for the server's recording router.\n */\nexport interface IRecordingCoordinator {\n enableRecording(deviceId: string, options: {\n policy: unknown\n ffmpegOverrides?: unknown\n }): Promise<void>\n disableRecording(deviceId: string): Promise<void>\n isRecording(deviceId: string): boolean\n readonly playlistGenerator: {\n generate(\n deviceId: string,\n streamId: string,\n startTime: number,\n endTime: number,\n options?: { live?: boolean },\n ): unknown\n }\n readonly storageEstimator: {\n estimateForDevice(\n deviceId: string,\n motionInput?: { avgEventsPerDay: number; avgDurationSec: number },\n ): { totalEstimatedGb: number; [key: string]: unknown }\n }\n}\n\n/**\n * Minimal recording database interface for the server's recording router.\n */\nexport interface IRecordingDb {\n upsertStorageConfig(config: {\n deviceId: string\n dataCategory: string\n storageName: string\n subDirectory: string\n retentionDays: number | null\n retentionGb: number | null\n }): void\n getPolicy(deviceId: string): { readonly enabled: boolean; readonly mode: string; [key: string]: unknown } | null\n getEnabledPolicies(): Array<{ deviceId: string; [key: string]: unknown }>\n querySegments(deviceId: string, streamId: string, startTime: number, endTime: number): unknown\n getAvailability(deviceId: string, startTime: number, endTime: number): unknown\n getStorageUsage(deviceId: string, streamId: string): unknown\n upsertPolicy(policy: unknown): void\n findNearestThumbnail(deviceId: string, timestamp: number, category: string): unknown\n getMotionStats(deviceId: string, startTime: number, endTime: number): {\n avgEventsPerDay: number\n avgDurationSec: number\n dutyCyclePercent: number\n totalEvents: number\n }\n resolveStorageConfig(deviceId: string, dataCategory: string): unknown\n}\n\n// ---------------------------------------------------------------------------\n// Sub-service interfaces — used by the server's thin NestJS wrappers\n// to receive delegates via CapabilityRegistry.\n// ---------------------------------------------------------------------------\n\nexport interface IEventPersistence {\n start(): void\n stop(): void\n saveDetectionCrops(eventId: string, crops: readonly ObjectSnapshotResult[]): void\n saveAnnotatedFrame(eventId: string, result: AnnotatedSnapshotResult): void\n saveOriginalFrame(eventId: string, frame: import('./camera-pipeline.js').VideoFrame): Promise<void>\n getEventMedia(eventId: string): Promise<readonly TrackMediaFile[]>\n getTrackMedia(trackId: string): Promise<readonly TrackMediaFile[]>\n getDeviceMedia(deviceId: string, since?: number, until?: number): Promise<readonly TrackMediaFile[]>\n getBufferStatus(): { pendingEvents: number; pendingMedia: number; lastFlush?: number }\n flush(): Promise<void>\n}\n\nexport interface ITrackTrail {\n setConfig(deviceId: string, config: Partial<TrackCaptureConfig>): void\n getConfig(deviceId: string): TrackCaptureConfig\n recordFrame(ctx: unknown): Promise<void>\n getActiveTrail(trackId: string): TrackTrail | null\n getActiveTrails(deviceId: string): readonly TrackTrail[]\n getPersistedTrail(trackId: string): Promise<TrackTrail | null>\n getTrail(trackId: string): Promise<TrackTrail | null>\n listTrails(deviceId: string, options?: {\n since?: number\n until?: number\n limit?: number\n className?: string\n }): Promise<readonly TrackTrail[]>\n}\n\nexport interface IRetention {\n start(): void\n stop(): void\n runCleanup(): Promise<unknown>\n setConfig(update: Partial<RetentionConfig>): void\n getConfig(): unknown\n forceCleanup(): Promise<unknown>\n}\n\nexport interface ISessionTracker {\n updateFromAnalysis(deviceId: string, ctx: unknown): void\n getActiveTracks(deviceId: string): readonly SessionTrack[]\n getAllActiveTracks(): readonly SessionTrack[]\n getTrack(deviceId: string, trackId: string): SessionTrack | undefined\n getTrackCounts(): Record<string, number>\n clearDevice(deviceId: string): void\n clearAll(): void\n getGlobalPool(): unknown\n}\n\nexport interface KnownFaceSummary {\n readonly id: string\n readonly label: string\n readonly group?: string\n readonly cropBase64: string\n readonly createdAt: number\n readonly updatedAt: number\n readonly source?: string\n readonly sourceType?: string\n readonly count?: number\n}\n\nexport interface IKnownFaces {\n register(entry: KnownFaceEntry): Promise<void>\n listAll(): Promise<readonly KnownFaceSummary[]>\n delete(id: string): Promise<void>\n update(id: string, updates: Partial<Pick<KnownFaceEntry, 'label' | 'group'>>): Promise<void>\n recalculateEmbedding(id: string, clipRecognizer: ClipRecognizer): Promise<void>\n findMatch(embedding: Float32Array, threshold: number): Promise<unknown>\n batchRegister(\n entries: ReadonlyArray<{ readonly label: string; readonly cropBase64: string; readonly group?: string }>,\n clipRecognizer: ClipRecognizer,\n ): Promise<unknown>\n}\n\n/**\n * Composite interface exposed via CapabilityRegistry as the\n * 'analysis-data-persistence' singleton. Each sub-service is wired\n * individually to the corresponding NestJS wrapper service.\n */\nexport interface IAnalysisDataPersistence {\n readonly eventPersistence: IEventPersistence\n readonly knownFaces: IKnownFaces\n readonly sessionTracker: ISessionTracker\n readonly retention: IRetention\n readonly trackTrail: ITrackTrail\n}\n\n// ---------------------------------------------------------------------------\n// Provider Connection Testing\n// ---------------------------------------------------------------------------\n\nexport interface TestConnectionResult {\n readonly success: boolean\n readonly version?: string\n readonly cameraCount?: number\n readonly error?: string\n}\n\n/**\n * Generic interface for testing provider connections.\n * Each provider addon can expose a connection tester.\n */\nexport interface IProviderConnectionTester {\n testConnection(): Promise<TestConnectionResult>\n}\n","export enum EventSourceType {\n Addon = 'addon',\n Core = 'core',\n Device = 'device',\n Provider = 'provider',\n System = 'system',\n}\n","export const HF_REPO = 'camstack/camstack-models'\nexport const HF_BASE_URL = `https://huggingface.co/${HF_REPO}/resolve/main`\n\n/**\n * Shape of {@link RUNTIME_DEFAULTS}. Every key/value is typed explicitly so\n * consumers (ConfigManager.raw, feature accessors, settings-store seeder)\n * can read fields without `as` casts.\n *\n * Iteration via `Object.entries` still yields `[string, RuntimeDefaultsShape[keyof RuntimeDefaultsShape]]`\n * which is assignable to `[string, unknown]` — no change for consumers that\n * only need the iteration behaviour.\n */\nexport interface RuntimeDefaultsProvider {\n id: string\n type: string\n name: string\n}\n\nexport interface RuntimeDefaultsShape {\n /** Index signature for dynamic string-path lookups (e.g. ConfigManager.get).\n * Explicit keys below override this with their precise types. */\n [key: string]: unknown\n 'features.streaming': boolean\n 'features.notifications': boolean\n 'features.objectDetection': boolean\n 'features.remoteAccess': boolean\n 'features.agentCluster': boolean\n 'features.smartHome': boolean\n 'features.recordings': boolean\n 'features.backup': boolean\n 'features.repl': boolean\n 'retention.detectionEventsDays': number\n 'retention.audioLevelsDays': number\n 'logging.level': string\n 'logging.retentionDays': number\n 'eventBus.ringBufferSize': number\n 'storage.provider': string\n 'storage.locations': Record<string, string>\n 'providers': RuntimeDefaultsProvider[]\n 'recording.segmentDurationSeconds': number\n 'recording.defaultRetentionDays': number\n 'ffmpeg.binaryPath': string\n 'ffmpeg.hwAccel': string\n 'ffmpeg.threadCount': number\n 'auth.tokenExpiry': string\n}\n\n/**\n * Runtime defaults -- used by ConfigManager.get() for backward compatibility\n * until Plan B wires all runtime settings to the system_settings SQL table.\n *\n * Moved from @camstack/kernel/config-schema to @camstack/types so that\n * @camstack/core can reference it without a cross-package kernel import.\n */\nexport const RUNTIME_DEFAULTS: RuntimeDefaultsShape = {\n 'features.streaming': true,\n 'features.notifications': true,\n 'features.objectDetection': false,\n 'features.remoteAccess': true,\n 'features.agentCluster': false,\n 'features.smartHome': true,\n 'features.recordings': true,\n 'features.backup': true,\n 'features.repl': true,\n 'retention.detectionEventsDays': 30,\n 'retention.audioLevelsDays': 7,\n 'logging.level': 'info',\n 'logging.retentionDays': 30,\n 'eventBus.ringBufferSize': 10000,\n 'storage.provider': 'sqlite-storage',\n 'storage.locations': {\n data: 'camstack-data/data',\n media: 'camstack-data/media',\n recordings: 'camstack-data/recordings',\n cache: '/tmp/camstack-cache',\n logs: 'camstack-data/logs',\n models: 'camstack-data/models',\n },\n 'providers': [],\n // Recording\n 'recording.segmentDurationSeconds': 4,\n 'recording.defaultRetentionDays': 30,\n // Streaming ports are addon-specific (go2rtc owns its defaults)\n // FFmpeg\n 'ffmpeg.binaryPath': 'ffmpeg',\n 'ffmpeg.hwAccel': 'auto',\n 'ffmpeg.threadCount': 0,\n // Detection / motion / audio settings are owned by their respective addons\n // (pipeline-orchestrator, motion-wasm, audio-analyzer/classifier, detection-pipeline\n // step schemas). No detection defaults at this level.\n // Backup retention is addon-specific (local-backup owns its default)\n // Auth (runtime)\n 'auth.tokenExpiry': '24h',\n}\n","/**\n * Type-safe JSON parsing helpers.\n *\n * `JSON.parse` is typed as `any` in lib.es5.d.ts, which triggers\n * `no-unsafe-*` ESLint rules and destroys downstream inference. These\n * wrappers return `unknown` — callers narrow structurally via type\n * guards, `typeof` checks, or helpers like `asRecord`/`asString`.\n */\n\n/**\n * Parse JSON and return it as `unknown` — the only entry point for untrusted JSON.\n *\n * The optional generic overload `parseJsonUnknown<T>(text)` returns `T` for\n * call sites that know the shape at parse time (e.g. MQTT payloads with a\n * known protocol schema). This is a **type-level bridge only** — no runtime\n * validation is performed. Callers that need runtime validation should parse\n * as `unknown` and narrow via Zod or structural guards.\n */\nexport function parseJsonUnknown<T = unknown>(text: string): T {\n // Isolate JSON.parse's `any` to this single statement.\n const parsed: unknown = JSON.parse(text)\n return parsed as T\n}\n\n/** Narrow an unknown value to a plain `Record<string, unknown>` or return null. */\nexport function asJsonObject(value: unknown): Record<string, unknown> | null {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n return null\n }\n return { ...value }\n}\n\n/** Narrow an unknown value to a `readonly unknown[]` or return an empty array. */\nexport function asJsonArray(value: unknown): readonly unknown[] {\n return Array.isArray(value) ? value : []\n}\n\n/** Safe string extraction from an unknown record field. */\nexport function asString(value: unknown, fallback = ''): string {\n return typeof value === 'string' ? value : fallback\n}\n\n/** Safe number extraction from an unknown record field. */\nexport function asNumber(value: unknown, fallback = 0): number {\n return typeof value === 'number' ? value : fallback\n}\n\n/** Safe boolean extraction from an unknown record field. */\nexport function asBoolean(value: unknown, fallback = false): boolean {\n return typeof value === 'boolean' ? value : fallback\n}\n\n/** Parse JSON + narrow to object in one step. */\nexport function parseJsonObject(text: string): Record<string, unknown> | null {\n try {\n return asJsonObject(parseJsonUnknown(text))\n } catch {\n return null\n }\n}\n\n/** Parse JSON + narrow to array in one step. */\nexport function parseJsonArray(text: string): readonly unknown[] | null {\n try {\n const parsed = parseJsonUnknown(text)\n return Array.isArray(parsed) ? parsed : null\n } catch {\n return null\n }\n}\n","export function hfModelUrl(repo: string, path: string): string {\n return `https://huggingface.co/${repo}/resolve/main/${path}`\n}\n","/** Cosine similarity between two embedding vectors */\nexport function cosineSimilarity(a: Float32Array, b: Float32Array): number {\n if (a.length !== b.length) return 0\n let dotProduct = 0\n let normA = 0\n let normB = 0\n for (let i = 0; i < a.length; i++) {\n dotProduct += a[i]! * b[i]!\n normA += a[i]! * a[i]!\n normB += b[i]! * b[i]!\n }\n const denom = Math.sqrt(normA) * Math.sqrt(normB)\n return denom === 0 ? 0 : dotProduct / denom\n}\n","import type { IElementConfig } from '../interfaces/context.js'\nimport type { ISettingsBackend } from '../interfaces/storage.js'\n\n/**\n * Persisted config store for a single element.\n * Reads/writes to the element's scoped storage under the 'config' collection.\n * Notifies listeners on every change.\n */\nexport class ElementConfigStore implements IElementConfig {\n private cache: Record<string, unknown> = {}\n private listeners: Set<(config: Record<string, unknown>) => void> = new Set()\n private loaded = false\n\n private readonly getBackend: () => ISettingsBackend | null\n\n constructor(\n private readonly elementId: string,\n settingsBackend: ISettingsBackend | (() => ISettingsBackend | null) | null,\n ) {\n // Accept either a direct backend or a lazy getter for late-wired backends\n this.getBackend = typeof settingsBackend === 'function'\n ? settingsBackend\n : () => settingsBackend\n }\n\n /** Load config from storage into cache. Called once on first access. */\n private async ensureLoaded(): Promise<void> {\n if (this.loaded) return\n const backend = this.getBackend()\n if (!backend) {\n throw new Error(`ElementConfigStore(${this.elementId}): settings backend not available`)\n }\n\n const records = await backend.query({ collection: 'config', filter: {\n where: { id: this.elementId },\n limit: 1,\n } })\n if (records.length > 0) {\n this.cache = records[0]!.data ?? {}\n }\n this.loaded = true\n }\n\n getAll(): Record<string, unknown> {\n return { ...this.cache }\n }\n\n get<T = unknown>(key: string): T | undefined {\n const parts = key.split('.')\n let current: unknown = this.cache\n for (const part of parts) {\n if (current === null || typeof current !== 'object' || Array.isArray(current)) return undefined\n current = Reflect.get(current, part)\n }\n // Type-level bridge: callers supply T based on their knowledge of the\n // stored schema — the runtime has no way to prove the shape matches.\n return current as T | undefined\n }\n\n async set(key: string, value: unknown): Promise<void> {\n await this.ensureLoaded()\n setNestedValue(this.cache, key, value)\n await this.persist()\n this.notifyListeners()\n }\n\n async setAll(config: Record<string, unknown>): Promise<void> {\n await this.ensureLoaded()\n this.cache = { ...config }\n await this.persist()\n this.notifyListeners()\n }\n\n onChange(callback: (config: Record<string, unknown>) => void): () => void {\n this.listeners.add(callback)\n return () => { this.listeners.delete(callback) }\n }\n\n /** Initialize from storage — called by ContextFactory after creation */\n async load(): Promise<void> {\n await this.ensureLoaded()\n }\n\n /** Initialize with default values (doesn't overwrite existing) */\n async loadDefaults(defaults: Record<string, unknown>): Promise<void> {\n await this.ensureLoaded()\n if (Object.keys(this.cache).length === 0) {\n this.cache = { ...defaults }\n await this.persist()\n }\n }\n\n private async persist(): Promise<void> {\n const backend = this.getBackend()\n if (!backend) {\n throw new Error(`ElementConfigStore(${this.elementId}): settings backend not available — cannot persist config`)\n }\n\n // Use set() for upsert semantics — avoids race condition where two\n // concurrent persist() calls both see \"no existing row\" and both insert.\n await backend.set({ collection: 'config', key: this.elementId, value: this.cache })\n }\n\n private notifyListeners(): void {\n const snapshot = this.getAll()\n for (const listener of this.listeners) {\n try {\n listener(snapshot)\n } catch {\n // Don't let one bad listener kill others\n }\n }\n }\n}\n\nfunction setNestedValue(obj: Record<string, unknown>, path: string, value: unknown): void {\n const parts = path.split('.')\n let current: Record<string, unknown> = obj\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]!\n const existing = current[part]\n if (existing === null || typeof existing !== 'object' || Array.isArray(existing)) {\n const fresh: Record<string, unknown> = {}\n current[part] = fresh\n current = fresh\n } else {\n current = existing as Record<string, unknown>\n }\n }\n current[parts[parts.length - 1]!] = value\n}\n","/**\n * Canonical runtime/backend/format mapping utilities.\n *\n * This is the SINGLE SOURCE OF TRUTH for mapping between:\n * - Pipeline config (runtime: 'node'|'python', backend: 'cpu'|'coreml'|'cuda'|...)\n * - DetectionRuntime ('onnx'|'coreml'|'pytorch'|'openvino'|'tflite')\n * - ModelFormat ('onnx'|'coreml'|'openvino'|'tflite'|'pt')\n *\n * Import from '@camstack/types' — do NOT duplicate these mappings anywhere.\n */\nimport type { ModelFormat } from '../types/models.js'\nimport type { DetectionRuntime } from '../types/config.js'\n\n// ---------------------------------------------------------------------------\n// Pipeline runtime: the two-level abstraction used in pipeline config\n// ---------------------------------------------------------------------------\n\n/** Pipeline-level runtime: 'node' (ONNX Runtime in Node.js) or 'python' (Python inference) */\nexport type PipelineRuntime = 'node' | 'python'\n\n// ---------------------------------------------------------------------------\n// Backend → Format: what model file format does a backend require?\n// ---------------------------------------------------------------------------\n\n/**\n * Map a backend ID to the model format it requires.\n *\n * Node.js backends (cpu, coreml, cuda, tensorrt) all use ONNX format\n * because onnxruntime-node loads .onnx and uses execution providers internally.\n *\n * Python backends use their native format.\n */\nconst BACKEND_TO_FORMAT: Readonly<Record<string, ModelFormat>> = {\n // Node.js backends — all ONNX (onnxruntime-node execution providers)\n cpu: 'onnx',\n coreml: 'onnx', // onnxruntime CoreML EP loads .onnx, not .mlpackage\n cuda: 'onnx',\n tensorrt: 'onnx',\n 'onnx-py': 'onnx',\n // Python native backends\n pytorch: 'pt',\n openvino: 'openvino',\n}\n\n/**\n * Map DetectionRuntime to ModelFormat.\n * Used when the addon receives an explicit runtime (not 'auto').\n */\nconst RUNTIME_TO_FORMAT: Readonly<Record<DetectionRuntime, ModelFormat>> = {\n onnx: 'onnx',\n coreml: 'coreml',\n openvino: 'openvino',\n tflite: 'tflite',\n pytorch: 'pt',\n}\n\n/**\n * Map a Python backend to the Python inference script name.\n */\nconst PYTHON_SCRIPT: Readonly<Record<string, string>> = {\n coreml: 'coreml_inference.py',\n pytorch: 'pytorch_inference.py',\n openvino: 'openvino_inference.py',\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve pipeline config (runtime + backend) to a DetectionRuntime.\n *\n * Pipeline config uses two levels:\n * runtime: 'node' | 'python'\n * backend: 'cpu' | 'coreml' | 'cuda' | 'openvino' | 'pytorch' | ...\n *\n * Addons expect a DetectionRuntime:\n * 'onnx' | 'coreml' | 'pytorch' | 'openvino' | 'tflite'\n *\n * Mapping rules:\n * node + any backend → 'onnx' (onnxruntime-node handles backend via EP)\n * python + coreml → 'coreml' (native .mlpackage via coremltools)\n * python + openvino → 'openvino'\n * python + pytorch → 'pytorch'\n * python + onnx-py → 'onnx'\n * python + <other> → backend as-is\n */\nexport function resolveDetectionRuntime(\n pipelineRuntime: PipelineRuntime | string,\n backend: string,\n): DetectionRuntime {\n if (pipelineRuntime === 'node') return 'onnx'\n // Python: backend IS the runtime (coreml, openvino, pytorch, etc.)\n const map: Record<string, DetectionRuntime> = {\n coreml: 'coreml',\n openvino: 'openvino',\n pytorch: 'pytorch',\n 'onnx-py': 'onnx',\n cpu: 'onnx',\n }\n return map[backend] ?? (backend as DetectionRuntime)\n}\n\n/**\n * Resolve pipeline config (runtime + backend) to a ModelFormat.\n *\n * Determines which model file format is needed (.onnx, .mlpackage, etc.)\n */\nexport function resolveModelFormat(\n pipelineRuntime: PipelineRuntime | string,\n backend: string,\n): ModelFormat {\n if (pipelineRuntime === 'node') {\n return BACKEND_TO_FORMAT[backend] ?? 'onnx'\n }\n // Python: derive format from backend\n const map: Record<string, ModelFormat> = {\n coreml: 'coreml',\n openvino: 'openvino',\n pytorch: 'pt',\n 'onnx-py': 'onnx',\n cpu: 'onnx',\n }\n return map[backend] ?? 'onnx'\n}\n\n/**\n * Resolve pipeline runtime string to 'auto' | DetectionRuntime for addon consumption.\n * Used when building addon addonConfig from pipeline step config.\n *\n * 'python' + 'coreml' → 'coreml'\n * 'node' + 'coreml' → 'onnx'\n * 'node' + 'cpu' → 'onnx'\n * 'auto' → 'auto'\n */\nexport function resolveAddonRuntime(\n pipelineRuntime: string | undefined,\n backend: string | undefined,\n): DetectionRuntime | 'auto' {\n if (!pipelineRuntime || pipelineRuntime === 'auto') return 'auto'\n return resolveDetectionRuntime(pipelineRuntime, backend ?? 'cpu')\n}\n\n/**\n * Get the model format needed for a given backend.\n * Convenience wrapper for backend-only lookup (e.g., UI components).\n */\nexport function formatForBackend(backend: string): ModelFormat {\n return BACKEND_TO_FORMAT[backend] ?? 'onnx'\n}\n\n/**\n * Get the model format for a given DetectionRuntime.\n */\nexport function formatForRuntime(runtime: DetectionRuntime): ModelFormat {\n return RUNTIME_TO_FORMAT[runtime]\n}\n\n/**\n * Get the Python inference script name for a backend.\n * Returns undefined if no Python script is needed (e.g., 'cpu' uses ONNX).\n */\nexport function pythonScriptForBackend(backend: string): string | undefined {\n return PYTHON_SCRIPT[backend]\n}\n\n/**\n * Check if a DetectionRuntime requires a Python binary.\n * 'coreml', 'pytorch', 'openvino' need Python; 'onnx' and 'tflite' don't.\n */\nexport function requiresPython(runtime: DetectionRuntime | string): boolean {\n return runtime === 'coreml' || runtime === 'pytorch' || runtime === 'openvino'\n}\n\n// Re-export constants for consumers that need the raw maps (e.g., UI filtering)\nexport { BACKEND_TO_FORMAT, RUNTIME_TO_FORMAT, PYTHON_SCRIPT }\n","import { errMsg } from './err-msg.js'\n\n/**\n * runInferenceStep — shared utility for executing a single inference call\n * with timing, error capture, and optional timeout.\n *\n * Used by: pipeline-executor, benchmark-executor, benchmark.service,\n * inference-engine-adapter — eliminating duplicated timing/error patterns.\n */\n\nexport interface InferenceStepResult<T> {\n /** The inference output, or undefined if the call failed */\n readonly output: T | undefined\n /** Wall-clock duration in ms (rounded to 2 decimals) */\n readonly durationMs: number\n /** True if the call succeeded */\n readonly ok: boolean\n /** Error message if the call failed */\n readonly error?: string\n}\n\n/**\n * Execute an inference function with timing and error capture.\n *\n * @param fn - The inference call (e.g. `() => engine.infer(frame)`)\n * @param timeoutMs - Optional timeout in ms. If exceeded, rejects with timeout error.\n * @returns InferenceStepResult with output, timing, and error info\n */\nexport async function runInferenceStep<T>(\n fn: () => Promise<T>,\n timeoutMs?: number,\n): Promise<InferenceStepResult<T>> {\n const t0 = performance.now()\n\n try {\n const output = timeoutMs !== undefined\n ? await withTimeout(fn(), timeoutMs)\n : await fn()\n\n return {\n output,\n durationMs: roundMs(performance.now() - t0),\n ok: true,\n }\n } catch (err) {\n return {\n output: undefined,\n durationMs: roundMs(performance.now() - t0),\n ok: false,\n error: errMsg(err),\n }\n }\n}\n\n/** Round to 2 decimal places */\nfunction roundMs(ms: number): number {\n return Math.round(ms * 100) / 100\n}\n\n/** Reject a promise if it exceeds the given timeout */\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(`Inference timeout after ${ms}ms`)), ms)\n promise\n .then((v) => { clearTimeout(timer); resolve(v) })\n .catch((e: unknown) => { clearTimeout(timer); reject(e) })\n })\n}\n","import type { LabelDefinition, ClassMapDefinition } from '../types/labels.js'\n\nexport const COCO_80_LABELS: readonly LabelDefinition[] = [\n { id: 'person', name: 'Person' },\n { id: 'bicycle', name: 'Bicycle' },\n { id: 'car', name: 'Car' },\n { id: 'motorcycle', name: 'Motorcycle' },\n { id: 'airplane', name: 'Airplane' },\n { id: 'bus', name: 'Bus' },\n { id: 'train', name: 'Train' },\n { id: 'truck', name: 'Truck' },\n { id: 'boat', name: 'Boat' },\n { id: 'traffic light', name: 'Traffic Light' },\n { id: 'fire hydrant', name: 'Fire Hydrant' },\n { id: 'stop sign', name: 'Stop Sign' },\n { id: 'parking meter', name: 'Parking Meter' },\n { id: 'bench', name: 'Bench' },\n { id: 'bird', name: 'Bird' },\n { id: 'cat', name: 'Cat' },\n { id: 'dog', name: 'Dog' },\n { id: 'horse', name: 'Horse' },\n { id: 'sheep', name: 'Sheep' },\n { id: 'cow', name: 'Cow' },\n { id: 'elephant', name: 'Elephant' },\n { id: 'bear', name: 'Bear' },\n { id: 'zebra', name: 'Zebra' },\n { id: 'giraffe', name: 'Giraffe' },\n { id: 'backpack', name: 'Backpack' },\n { id: 'umbrella', name: 'Umbrella' },\n { id: 'handbag', name: 'Handbag' },\n { id: 'tie', name: 'Tie' },\n { id: 'suitcase', name: 'Suitcase' },\n { id: 'frisbee', name: 'Frisbee' },\n { id: 'skis', name: 'Skis' },\n { id: 'snowboard', name: 'Snowboard' },\n { id: 'sports ball', name: 'Sports Ball' },\n { id: 'kite', name: 'Kite' },\n { id: 'baseball bat', name: 'Baseball Bat' },\n { id: 'baseball glove', name: 'Baseball Glove' },\n { id: 'skateboard', name: 'Skateboard' },\n { id: 'surfboard', name: 'Surfboard' },\n { id: 'tennis racket', name: 'Tennis Racket' },\n { id: 'bottle', name: 'Bottle' },\n { id: 'wine glass', name: 'Wine Glass' },\n { id: 'cup', name: 'Cup' },\n { id: 'fork', name: 'Fork' },\n { id: 'knife', name: 'Knife' },\n { id: 'spoon', name: 'Spoon' },\n { id: 'bowl', name: 'Bowl' },\n { id: 'banana', name: 'Banana' },\n { id: 'apple', name: 'Apple' },\n { id: 'sandwich', name: 'Sandwich' },\n { id: 'orange', name: 'Orange' },\n { id: 'broccoli', name: 'Broccoli' },\n { id: 'carrot', name: 'Carrot' },\n { id: 'hot dog', name: 'Hot Dog' },\n { id: 'pizza', name: 'Pizza' },\n { id: 'donut', name: 'Donut' },\n { id: 'cake', name: 'Cake' },\n { id: 'chair', name: 'Chair' },\n { id: 'couch', name: 'Couch' },\n { id: 'potted plant', name: 'Potted Plant' },\n { id: 'bed', name: 'Bed' },\n { id: 'dining table', name: 'Dining Table' },\n { id: 'toilet', name: 'Toilet' },\n { id: 'tv', name: 'TV' },\n { id: 'laptop', name: 'Laptop' },\n { id: 'mouse', name: 'Mouse' },\n { id: 'remote', name: 'Remote' },\n { id: 'keyboard', name: 'Keyboard' },\n { id: 'cell phone', name: 'Cell Phone' },\n { id: 'microwave', name: 'Microwave' },\n { id: 'oven', name: 'Oven' },\n { id: 'toaster', name: 'Toaster' },\n { id: 'sink', name: 'Sink' },\n { id: 'refrigerator', name: 'Refrigerator' },\n { id: 'book', name: 'Book' },\n { id: 'clock', name: 'Clock' },\n { id: 'vase', name: 'Vase' },\n { id: 'scissors', name: 'Scissors' },\n { id: 'teddy bear', name: 'Teddy Bear' },\n { id: 'hair drier', name: 'Hair Drier' },\n { id: 'toothbrush', name: 'Toothbrush' },\n] as const\n\nexport const MACRO_LABELS: readonly LabelDefinition[] = [\n { id: 'person', name: 'Person' },\n { id: 'vehicle', name: 'Vehicle' },\n { id: 'animal', name: 'Animal' },\n] as const\n\nexport const COCO_TO_MACRO: ClassMapDefinition = {\n mapping: {\n person: 'person',\n bicycle: 'vehicle',\n car: 'vehicle',\n motorcycle: 'vehicle',\n airplane: 'vehicle',\n bus: 'vehicle',\n train: 'vehicle',\n truck: 'vehicle',\n boat: 'vehicle',\n bird: 'animal',\n cat: 'animal',\n dog: 'animal',\n horse: 'animal',\n sheep: 'animal',\n cow: 'animal',\n elephant: 'animal',\n bear: 'animal',\n zebra: 'animal',\n giraffe: 'animal',\n },\n // Today the pipeline only supports the three macro classes. Any other\n // COCO class (carrot, umbrella, spoon, …) is dropped upstream in the\n // executor instead of leaking through as a `macroClass: \"carrot\"`\n // detection with no child routing. When support for additional COCO\n // classes lands, either add them to `mapping` (mapped to a new macro)\n // or flip this back to `true` and teach `matchesMacroFilter` to handle\n // the raw-COCO case.\n preserveOriginal: false,\n}\n","/**\n * @deprecated Use DeviceType from '@camstack/types/device' instead.\n * This file is kept for backwards compatibility during migration.\n */\n\n/* eslint-disable @typescript-eslint/no-deprecated */\n\nexport enum DeviceType {\n Camera = 'camera',\n}\n\nexport interface DeviceTypeInfo {\n readonly type: DeviceType\n readonly label: string\n readonly icon: string // lucide icon name\n}\n\nexport const DEVICE_TYPE_INFO: Record<DeviceType, DeviceTypeInfo> = {\n [DeviceType.Camera]: { type: DeviceType.Camera, label: 'Camera', icon: 'camera' },\n}\n","import { z } from 'zod'\n\n/**\n * Optional callback invoked when `fromSchema` had to drop one or\n * more persisted fields to recover from a Zod validation failure.\n * Used by `BaseDevice` to surface the action via the device logger.\n */\nexport type ConfigRecoveryListener = (info: {\n droppedKeys: readonly string[]\n issues: readonly z.core.$ZodIssue[]\n}) => void\n\nexport class DeviceConfig<T extends z.ZodObject<z.core.$ZodLooseShape>> {\n readonly schema: T\n private data: z.infer<T>\n private readonly persistFn: (data: z.infer<T>) => Promise<void>\n\n private constructor(\n schema: T,\n data: z.infer<T>,\n persist: (data: z.infer<T>) => Promise<void>,\n ) {\n this.schema = schema\n this.data = data\n this.persistFn = persist\n }\n\n /**\n * Build a `DeviceConfig` from a persisted blob, with automatic\n * recovery from schema-validation failures. Boot must never be\n * blocked by stale persisted values: if Zod rejects the blob,\n * we drop every offending top-level field, retry, and persist\n * the cleaned blob so the bad value is healed in the DB on next\n * write. The most common trigger is a tightened range constraint\n * (e.g. `max(100) → max(50)`) on a field that already has an\n * out-of-range value persisted from the previous schema. Without\n * this safety net, the device would fail to instantiate and end\n * up with no caps registered — exactly the failure mode that\n * stranded device 15 when `motionSensitivity: 90` no longer fit\n * the new `1..50` schema.\n *\n * Recovery rules:\n * 1. Try `safeParse(initialData)`. If it succeeds, done.\n * 2. On failure, walk `error.issues`, collect the top-level path\n * of each issue, and drop those keys from `initialData`.\n * 3. Re-run `safeParse`. If the cleaned blob now passes (Zod\n * fills the missing keys with schema defaults / undefined for\n * `.optional()`), persist it via `persist()` so the bad\n * values disappear from the DB, and return the device.\n * 4. If the cleaned blob STILL fails (very rare — would require\n * a non-recoverable required field), fall back to\n * `schema.parse({})` so the device still boots with pure\n * schema defaults. Persist nothing in that path so the next\n * successful `setAll` still writes a coherent blob.\n */\n static fromSchema<T extends z.ZodObject<z.core.$ZodLooseShape>>(\n schema: T,\n persist: (data: z.infer<T>) => Promise<void>,\n initialData: Record<string, unknown> = {},\n onRecover?: ConfigRecoveryListener,\n ): DeviceConfig<T> {\n const first = schema.safeParse(initialData)\n if (first.success) {\n return new DeviceConfig(schema, first.data as z.infer<T>, persist)\n }\n\n const droppedKeys = new Set<string>()\n for (const issue of first.error.issues) {\n const top = issue.path[0]\n if (typeof top === 'string') droppedKeys.add(top)\n }\n\n const cleaned: Record<string, unknown> = { ...initialData }\n for (const k of droppedKeys) delete cleaned[k]\n const second = schema.safeParse(cleaned)\n\n onRecover?.({\n droppedKeys: [...droppedKeys],\n issues: first.error.issues,\n })\n\n if (second.success) {\n // Heal the DB: persist the cleaned blob asynchronously so the\n // offending fields are gone on next read. Best-effort — a\n // persist failure here doesn't block boot, the device still\n // runs from the in-memory cleaned data.\n void persist(second.data as z.infer<T>).catch(() => { /* swallow */ })\n return new DeviceConfig(schema, second.data as z.infer<T>, persist)\n }\n\n // Last-resort fallback: pure schema defaults. This branch should\n // be unreachable for well-formed schemas (every required field\n // must already be in `initialData`, and `.optional()` fields\n // accept undefined), but is here so a malformed blob can't\n // strand the device.\n const defaults = schema.parse({}) as z.infer<T>\n return new DeviceConfig(schema, defaults, persist)\n }\n\n get values(): z.infer<T> {\n return this.data\n }\n\n get<K extends keyof z.infer<T>>(key: K): z.infer<T>[K] {\n return this.data[key]\n }\n\n async set<K extends keyof z.infer<T>>(key: K, value: z.infer<T>[K]): Promise<void> {\n const next = this.schema.parse({ ...this.data, [key]: value })\n this.data = next\n await this.persistFn(this.data)\n }\n\n /**\n * Merge an untyped patch onto the current config and persist. Accepts\n * `Record<string, unknown>` because the patch typically comes from the\n * UI form layer (a `ConfigField.key → value` map) where the caller\n * doesn't hold the Zod schema's static type. Runtime validation is\n * authoritative: `this.schema.parse` rejects unknown keys or invalid\n * shapes before touching storage.\n */\n async setAll(partial: Record<string, unknown>): Promise<void> {\n const next = this.schema.parse({ ...this.data, ...partial })\n this.data = next\n await this.persistFn(this.data)\n }\n\n async deleteKey<K extends keyof z.infer<T>>(key: K): Promise<void> {\n const { [key as string]: _, ...rest } = this.data as Record<string, unknown>\n const next = this.schema.parse(rest)\n this.data = next\n await this.persistFn(this.data)\n }\n\n entries(): Array<{\n key: string\n schema: z.ZodType\n value: unknown\n description?: string\n }> {\n const shape = this.schema.shape as Record<string, z.ZodType>\n return Object.entries(shape).map(([key, fieldSchema]) => ({\n key,\n schema: fieldSchema,\n value: this.data[key as keyof z.infer<T>],\n description: fieldSchema.description,\n }))\n }\n}\n","import { z } from 'zod'\n\n/**\n * Per-device runtime state — cap-keyed. Mutable signals discovered\n * after boot live here, separate from `DeviceConfig` (operator\n * intent) and from `deviceCache` (immutable autodetect / abilities).\n *\n * Shape: `Record<capName, capStateSlice>`. Each slice's schema is\n * declared by the capability itself (`CapabilityDefinition.runtimeState`)\n * so that any provider implementing the cap inherits the same shape —\n * the BatteryStatus shape a Reolink cam emits is the same a Frigate or\n * ONVIF cam emits, no driver-specific re-declaration.\n *\n * Schemas are registered DYNAMICALLY as the device's caps are\n * installed (see `BaseDevice.registerNativeCap`). A slice without a\n * registered schema is rejected on write — the cap must be wired\n * first. Reads return `undefined` for unknown slices.\n *\n * Persistence: only registered slices round-trip to disk. The kernel\n * layer debounces writes; explicit `flush()` awaits in-flight saves\n * (used by the shutdown hook).\n */\nexport interface IDeviceRuntimeState {\n /**\n * Read the slice for `capName`. Three overloads, picked by\n * argument shape:\n *\n * 1. Pass a known cap-name literal (`'battery'`, `'motion'`, …)\n * → return type is auto-inferred from\n * `CapNameToRuntimeStateMap` (codegen output). No generic\n * argument, no `as`-cast.\n * 2. Pass a cap-name with an explicit generic\n * (`getCapState<MyShape>('custom-cap')`) → return that\n * shape. Used for caps the codegen doesn't see (test-only,\n * addon-private).\n * 3. Pass a cap-name with no generic (default `Record<string,\n * unknown>`) → permissive untyped fallback.\n *\n * Returns `undefined` if no slice has been written yet.\n */\n getCapState<K extends keyof import('../generated/device-local-state.js').CapNameToRuntimeStateMap>(\n capName: K,\n ): Readonly<import('../generated/device-local-state.js').CapNameToRuntimeStateMap[K]> | undefined\n getCapState<T extends Record<string, unknown> = Record<string, unknown>>(\n capName: string,\n ): Readonly<T> | undefined\n\n /** Read a single key inside a slice. Convenience for the common\n * case of reading a primitive (`battery.percentage`). */\n getCapField(capName: string, key: string): unknown\n\n /**\n * Replace the slice for `capName`. The schema bound to `capName`\n * (via `installCapSchema`) validates `value`; throws on mismatch.\n * Listeners fire synchronously after the write applies.\n */\n setCapState(capName: string, value: Record<string, unknown>): void\n\n /**\n * Shallow-merge `partial` into the current slice for `capName`.\n * Re-validates the merged result against the cap's schema.\n */\n patchCapState(capName: string, partial: Record<string, unknown>): void\n\n /** Subscribe to ALL state changes. Receives the cap names whose\n * slices changed and the full snapshot. */\n subscribe(cb: (changedCaps: ReadonlyArray<string>, snapshot: Snapshot) => void): () => void\n\n /** Subscribe to a single cap's slice changes. Fires only when that\n * cap's slice is touched; ignores writes against other caps. */\n subscribeCap<T extends Record<string, unknown> = Record<string, unknown>>(\n capName: string,\n cb: (slice: Readonly<T> | undefined) => void,\n ): () => void\n\n /** Frozen snapshot of every cap's slice. Cap names without a\n * written slice are omitted (sparse). */\n snapshot(): Snapshot\n\n /** Flush any pending debounced disk writes. */\n flush(): Promise<void>\n\n /**\n * Register a cap's runtime-state schema. Called by the kernel\n * when `ctx.registerNativeCap(cap, …)` runs and `cap.runtimeState`\n * is defined. Idempotent — repeat installs with the same schema\n * are no-ops; mismatched schemas throw to surface a config bug.\n *\n * Lazily validates any existing in-memory slice for `capName` so\n * a slice loaded from disk before the cap was wired is checked\n * the moment the cap shows up.\n */\n installCapSchema(capName: string, schema: z.ZodObject<z.core.$ZodLooseShape>): void\n}\n\nexport type Snapshot = Readonly<Record<string, Readonly<Record<string, unknown>>>>\n\n/**\n * Concrete implementation. Routes every successful write through\n * `writer(capName, slice)` — the kernel hooks this up to\n * `device-state.setCapSlice`, the canonical cross-layer write\n * entrypoint, which handles disk persistence (debounced on the hub)\n * and mirror updates.\n *\n * Schema validation runs in-process before the writer is called —\n * the round-trip should never carry an invalid slice. `flush()`\n * awaits any in-flight writer promises so shutdown is lossless.\n *\n * `initial` is the persisted blob loaded at boot. Slices for caps\n * whose schema hasn't been installed yet are kept in-memory verbatim\n * and validated when the cap registers later.\n */\nexport class DeviceRuntimeState implements IDeviceRuntimeState {\n private readonly writer: (capName: string, slice: Record<string, unknown>) => Promise<void>\n /** In-flight writer promises tracked so `flush()` can await them. */\n private readonly pendingWrites = new Set<Promise<unknown>>()\n /** Per-cap committed slice — after schema validation when known. */\n private slices: Map<string, Record<string, unknown>>\n /** Per-cap registered schema (set by `installCapSchema`). */\n private readonly schemas = new Map<string, z.ZodObject<z.core.$ZodLooseShape>>()\n private readonly listeners = new Set<(changed: ReadonlyArray<string>, snap: Snapshot) => void>()\n private readonly capListeners = new Map<string, Set<(slice: Readonly<Record<string, unknown>> | undefined) => void>>()\n\n private constructor(\n initial: Record<string, unknown>,\n writer: (capName: string, slice: Record<string, unknown>) => Promise<void>,\n ) {\n this.writer = writer\n // Hydrate slices: every top-level key in `initial` is a cap name,\n // its value should be an object. Non-object values are dropped\n // with no error — the persisted blob is owned by us, so a\n // garbage shape is a kernel bug we'd rather surface elsewhere.\n this.slices = new Map()\n for (const [k, v] of Object.entries(initial)) {\n if (v && typeof v === 'object' && !Array.isArray(v)) {\n this.slices.set(k, { ...v as Record<string, unknown> })\n }\n }\n }\n\n static fromInitial(\n initial: Record<string, unknown>,\n writer: (capName: string, slice: Record<string, unknown>) => Promise<void>,\n ): DeviceRuntimeState {\n return new DeviceRuntimeState(initial, writer)\n }\n\n installCapSchema(capName: string, schema: z.ZodObject<z.core.$ZodLooseShape>): void {\n const existing = this.schemas.get(capName)\n if (existing) {\n // Idempotent: caps register multiple times during the device's\n // lifetime (constructor + post-login retroactive registration).\n // Ignore identical re-registrations; a different schema for the\n // same cap is a programming error worth throwing on.\n if (existing !== schema) {\n throw new Error(\n `[DeviceRuntimeState] capability \"${capName}\" registered a different runtime-state schema; `\n + `each cap must declare ONE shape across every provider`,\n )\n }\n return\n }\n this.schemas.set(capName, schema)\n // Validate any pre-loaded slice now that we have the schema.\n // Reject silently and clear: the persisted blob shouldn't crash\n // the device on boot, just lose stale data the schema rejects.\n const stored = this.slices.get(capName)\n if (stored) {\n const result = schema.safeParse(stored)\n if (result.success) {\n this.slices.set(capName, result.data as Record<string, unknown>)\n } else {\n this.slices.delete(capName)\n }\n }\n }\n\n getCapState<T extends Record<string, unknown> = Record<string, unknown>>(\n capName: string,\n ): Readonly<T> | undefined {\n const slice = this.slices.get(capName)\n if (!slice) return undefined\n return Object.freeze({ ...slice }) as unknown as Readonly<T>\n }\n\n getCapField(capName: string, key: string): unknown {\n return this.slices.get(capName)?.[key]\n }\n\n setCapState(capName: string, value: Record<string, unknown>): void {\n this.applyCapWrite(capName, value, /* merge */ false)\n }\n\n patchCapState(capName: string, partial: Record<string, unknown>): void {\n this.applyCapWrite(capName, partial, /* merge */ true)\n }\n\n /**\n * Internal worker. `merge` controls whether `value` replaces or\n * shallow-merges into the existing slice. Schema validation runs\n * on the FINAL composed object regardless.\n */\n private applyCapWrite(capName: string, value: Record<string, unknown>, merge: boolean): void {\n const schema = this.schemas.get(capName)\n if (!schema) {\n // Refuse: a cap without a registered schema can't have its\n // slice written. Drivers that legitimately need extra\n // ad-hoc state should attach a `runtimeState` schema to the\n // cap definition. The strict refusal catches typos\n // (`'batery'` vs `'battery'`) loudly.\n throw new Error(\n `[DeviceRuntimeState] no schema registered for cap \"${capName}\" — `\n + `did the device register it via ctx.registerNativeCap before writing?`,\n )\n }\n const current = this.slices.get(capName) ?? {}\n const next = merge ? { ...current, ...value } : { ...value }\n const parsed = schema.parse(next) as Record<string, unknown>\n // Equality check before commit — back-to-back identical writes\n // (e.g. battery push every minute with the same percentage)\n // should NOT churn listeners or disk.\n if (shallowEqual(current, parsed)) return\n this.slices.set(capName, parsed)\n this.fireListeners([capName])\n // Kick off the write asynchronously — schema validation already\n // ran, so failure here means a transport / hub issue. We log\n // and drop the error rather than throwing, mirroring the\n // fire-and-forget contract `setCapState` had with the legacy\n // debounced persister.\n const writePromise = this.writer(capName, { ...parsed }).catch(() => {\n /* transport error — caller can re-issue if it cares */\n })\n this.pendingWrites.add(writePromise)\n void writePromise.finally(() => { this.pendingWrites.delete(writePromise) })\n }\n\n private fireListeners(changed: ReadonlyArray<string>): void {\n const snap = this.snapshot()\n for (const cb of this.listeners) {\n try { cb(changed, snap) } catch { /* listener errors don't break the writer */ }\n }\n for (const capName of changed) {\n const subs = this.capListeners.get(capName)\n if (!subs) continue\n const slice = this.getCapState(capName)\n for (const cb of subs) {\n try { cb(slice) } catch { /* idem */ }\n }\n }\n }\n\n subscribe(cb: (changed: ReadonlyArray<string>, snap: Snapshot) => void): () => void {\n this.listeners.add(cb)\n return () => { this.listeners.delete(cb) }\n }\n\n subscribeCap<T extends Record<string, unknown> = Record<string, unknown>>(\n capName: string,\n cb: (slice: Readonly<T> | undefined) => void,\n ): () => void {\n let subs = this.capListeners.get(capName)\n if (!subs) {\n subs = new Set()\n this.capListeners.set(capName, subs)\n }\n const adapter = (slice: Readonly<Record<string, unknown>> | undefined): void => {\n cb(slice as Readonly<T> | undefined)\n }\n subs.add(adapter)\n return () => {\n const set = this.capListeners.get(capName)\n if (!set) return\n set.delete(adapter)\n if (set.size === 0) this.capListeners.delete(capName)\n }\n }\n\n snapshot(): Snapshot {\n const out: Record<string, Record<string, unknown>> = {}\n for (const [k, v] of this.slices) out[k] = Object.freeze({ ...v })\n return Object.freeze(out) as Snapshot\n }\n\n async flush(): Promise<void> {\n if (this.pendingWrites.size === 0) return\n // Snapshot the current set so writes added while we await\n // (e.g. listeners that re-trigger setCapState) settle in a\n // separate flush round if the caller wants strict drainage.\n const inflight = [...this.pendingWrites]\n await Promise.allSettled(inflight)\n }\n}\n\nfunction shallowEqual(a: Record<string, unknown>, b: Record<string, unknown>): boolean {\n const ak = Object.keys(a)\n const bk = Object.keys(b)\n if (ak.length !== bk.length) return false\n for (const k of ak) {\n if (a[k] !== b[k]) return false\n }\n return true\n}\n","import type { z } from 'zod'\nimport type { CapabilityDefinition } from '../capabilities/capability-definition.js'\nimport type { IDeviceRuntimeState } from './device-runtime-state.js'\n\nconst LAST_FETCHED_FIELD = 'lastFetchedAt'\n\n/**\n * Bridge a cap's `runtimeState` slice to its read-side methods.\n *\n * Pattern: provider keeps the camera fetch / write path, but delegates\n * stale-check + slice read + cold-start fallback to this helper. Cuts\n * the boilerplate that every provider would otherwise repeat across\n * `getStatus`, `getSettings`, and any other read-side cap method.\n *\n * Convention: the cap's `runtimeState` schema must include a numeric\n * `lastFetchedAt` field (ms epoch) so the helper can drive the\n * stale-check. The field is stripped from the value returned by\n * `getStatus` so the cap's status schema (which doesn't carry it)\n * still parses cleanly.\n *\n * Usage in a provider:\n * ```ts\n * const bridge = createRuntimeStateBridge({\n * runtimeState: this.runtimeState,\n * cap: ptzAutotrackCapability,\n * ownDeviceId: this.id,\n * refresh: () => this.refreshAutotrackFromCamera(),\n * staleMs: 10_000,\n * empty: () => emptyAutotrackStatus(),\n * })\n *\n * const provider: InferNativeProvider<typeof ptzAutotrackCapability> = {\n * getStatus: bridge.getStatus,\n * getSettings: async ({ deviceId }) => {\n * if (deviceId !== this.id) return null\n * await bridge.ensureFresh()\n * return this.runtimeState.getCapState<...>(...)?.currentSettings ?? null\n * },\n * setEnabled: async (...) => { ... ; await this.refreshAutotrackFromCamera() },\n * setSettings: async (...) => { ... ; await this.refreshAutotrackFromCamera() },\n * }\n * ```\n *\n * Single-flight (collapsing concurrent `refresh()` invocations) lives\n * INSIDE `refresh` — the camera client owns its own promise slot. This\n * helper stays thin so a single provider can host multiple cap-bridged\n * readers without fighting over a shared promise.\n */\nexport interface RuntimeStateBridge<TStatus> {\n /** Run a stale-check; if the slice is missing or older than\n * `staleMs`, await `refresh()`. Idempotent within the freshness\n * window — back-to-back calls touch zero camera I/O. */\n readonly ensureFresh: () => Promise<void>\n /** Drop-in `getStatus` provider method. Includes the cross-device\n * guard + freshness check + status projection from the slice. */\n readonly getStatus: (input: { readonly deviceId: number }) => Promise<TStatus>\n}\n\nexport function createRuntimeStateBridge<\n TCap extends CapabilityDefinition & { status: { schema: z.ZodType } },\n>(params: {\n readonly runtimeState: IDeviceRuntimeState\n readonly cap: TCap\n readonly ownDeviceId: number\n readonly refresh: () => Promise<void>\n readonly staleMs: number\n readonly empty: () => z.infer<TCap['status']['schema']>\n}): RuntimeStateBridge<z.infer<TCap['status']['schema']>> {\n const { runtimeState, cap, ownDeviceId, refresh, staleMs, empty } = params\n\n const ensureFresh = async (): Promise<void> => {\n const slice = runtimeState.getCapState<Record<string, unknown>>(cap.name)\n const fetchedAt = typeof slice?.[LAST_FETCHED_FIELD] === 'number'\n ? (slice[LAST_FETCHED_FIELD] as number)\n : 0\n if (!slice || Date.now() - fetchedAt > staleMs) await refresh()\n }\n\n const projectStatus = (): z.infer<TCap['status']['schema']> => {\n const slice = runtimeState.getCapState<Record<string, unknown>>(cap.name)\n if (!slice) return empty()\n // Strip lastFetchedAt (and any future helper-only fields) before\n // returning. Status schemas don't carry this field; runtime-state\n // schemas extend status with it for stale tracking.\n const { [LAST_FETCHED_FIELD]: _omit, ...rest } = slice\n return rest as z.infer<TCap['status']['schema']>\n }\n\n const getStatus = async ({ deviceId }: { readonly deviceId: number }): Promise<z.infer<TCap['status']['schema']>> => {\n if (deviceId !== ownDeviceId) {\n throw new Error(`${cap.name}: deviceId mismatch, expected ${ownDeviceId}, got ${deviceId}`)\n }\n await ensureFresh()\n return projectStatus()\n }\n\n return { ensureFresh, getStatus }\n}\n","// AUTO-GENERATED — do not edit manually.\n// Regenerate with: npx tsx scripts/generate-device-proxy.ts\n/* eslint-disable */\n\nimport type { CapabilityDefinition, InferRuntimeState } from '../capabilities/capability-definition.js'\nimport { audioMetricsCapability } from '../capabilities/audio-metrics.cap.js'\nimport { batteryCapability } from '../capabilities/battery.cap.js'\nimport { brightnessCapability } from '../capabilities/brightness.cap.js'\nimport { cameraStreamsCapability } from '../capabilities/camera-streams.cap.js'\nimport { deviceDiscoveryCapability } from '../capabilities/device-discovery.cap.js'\nimport { deviceStatusCapability } from '../capabilities/device-status.cap.js'\nimport { doorbellCapability } from '../capabilities/doorbell.cap.js'\nimport { featureProbeCapability } from '../capabilities/feature-probe.cap.js'\nimport { motionCapability } from '../capabilities/motion.cap.js'\nimport { motionTriggerCapability } from '../capabilities/motion-trigger.cap.js'\nimport { ptzAutotrackCapability } from '../capabilities/ptz-autotrack.cap.js'\nimport { switchCapability } from '../capabilities/switch.cap.js'\nimport { zoneAnalyticsCapability } from '../capabilities/zone-analytics.cap.js'\nimport { zoneRulesCapability } from '../capabilities/zone-rules.cap.js'\nimport { zonesCapability } from '../capabilities/zones.cap.js'\n\n/**\n * Server-side, write-capable per-cap state shape for any device that\n * extends `BaseDevice`. One entry per cap with `runtimeState:` declared.\n *\n * Drivers access via `this.state.<capName>.<field>` — both reads and\n * writes route through the device's runtime-state slice (validate,\n * persist, fire `<cap>.onChanged`). No string keys, no manual generic.\n *\n * Adding a new cap with `runtimeState:` auto-extends this interface —\n * regenerate with `npm run codegen`.\n */\nexport interface DeviceLocalState {\n audioMetrics: InferRuntimeState<typeof audioMetricsCapability>\n battery: InferRuntimeState<typeof batteryCapability>\n brightness: InferRuntimeState<typeof brightnessCapability>\n cameraStreams: InferRuntimeState<typeof cameraStreamsCapability>\n deviceDiscovery: InferRuntimeState<typeof deviceDiscoveryCapability>\n deviceStatus: InferRuntimeState<typeof deviceStatusCapability>\n doorbell: InferRuntimeState<typeof doorbellCapability>\n featureProbe: InferRuntimeState<typeof featureProbeCapability>\n motion: InferRuntimeState<typeof motionCapability>\n motionTrigger: InferRuntimeState<typeof motionTriggerCapability>\n ptzAutotrack: InferRuntimeState<typeof ptzAutotrackCapability>\n switch: InferRuntimeState<typeof switchCapability>\n zoneAnalytics: InferRuntimeState<typeof zoneAnalyticsCapability>\n zoneRules: InferRuntimeState<typeof zoneRulesCapability>\n zones: InferRuntimeState<typeof zonesCapability>\n}\n\n/**\n * Runtime registry: cap-property-name → cap definition. `BaseDevice`'s\n * `state` getter looks up the cap definition here to construct a\n * `sliceProxy()` lazily on first access. Generated alongside the type\n * so type and runtime registry can never drift apart.\n */\nexport const DEVICE_LOCAL_STATE_CAPS: Record<keyof DeviceLocalState, CapabilityDefinition> = {\n audioMetrics: audioMetricsCapability,\n battery: batteryCapability,\n brightness: brightnessCapability,\n cameraStreams: cameraStreamsCapability,\n deviceDiscovery: deviceDiscoveryCapability,\n deviceStatus: deviceStatusCapability,\n doorbell: doorbellCapability,\n featureProbe: featureProbeCapability,\n motion: motionCapability,\n motionTrigger: motionTriggerCapability,\n ptzAutotrack: ptzAutotrackCapability,\n switch: switchCapability,\n zoneAnalytics: zoneAnalyticsCapability,\n zoneRules: zoneRulesCapability,\n zones: zonesCapability,\n}\n\n/**\n * Cap-name keyed runtime-state map (kebab-case keys, e.g. `'battery'`,\n * `'device-discovery'`). Companion to `DeviceLocalState` (which uses\n * camelCase property keys). Consumed by the\n * `IDeviceRuntimeState.getCapState` overload so callers passing a\n * cap-name literal get the typed slice back without an explicit\n * generic argument:\n *\n * const slice = this.runtimeState.getCapState('battery')\n * // ^^^^^ inferred as InferRuntimeState<typeof batteryCapability>\n *\n * Eliminates the `as`-cast at every `getCapState<X>('cap-name')` site.\n */\nexport interface CapNameToRuntimeStateMap {\n 'audio-metrics': InferRuntimeState<typeof audioMetricsCapability>\n 'battery': InferRuntimeState<typeof batteryCapability>\n 'brightness': InferRuntimeState<typeof brightnessCapability>\n 'camera-streams': InferRuntimeState<typeof cameraStreamsCapability>\n 'device-discovery': InferRuntimeState<typeof deviceDiscoveryCapability>\n 'device-status': InferRuntimeState<typeof deviceStatusCapability>\n 'doorbell': InferRuntimeState<typeof doorbellCapability>\n 'feature-probe': InferRuntimeState<typeof featureProbeCapability>\n 'motion': InferRuntimeState<typeof motionCapability>\n 'motion-trigger': InferRuntimeState<typeof motionTriggerCapability>\n 'ptz-autotrack': InferRuntimeState<typeof ptzAutotrackCapability>\n 'switch': InferRuntimeState<typeof switchCapability>\n 'zone-analytics': InferRuntimeState<typeof zoneAnalyticsCapability>\n 'zone-rules': InferRuntimeState<typeof zoneRulesCapability>\n 'zones': InferRuntimeState<typeof zonesCapability>\n}\n","import { z } from 'zod'\nimport { DeviceConfig } from './device-config.js'\nimport { DeviceRuntimeState } from './device-runtime-state.js'\nimport type { IDeviceRuntimeState } from './device-runtime-state.js'\nimport type { DeviceType, DeviceFeature, DeviceRole } from './device-type.js'\nimport type { DeviceContext } from './device-context.js'\nimport type { IDevice } from './device.js'\nimport type { ConfigUISchemaWithValues } from '../interfaces/config-ui.js'\nimport { deviceStatusCapability, type DeviceStatus } from '../capabilities/device-status.cap.js'\nimport { featureProbeCapability, type FeatureProbeStatus } from '../capabilities/feature-probe.cap.js'\nimport type { CapabilityDefinition, InferRuntimeState } from '../capabilities/capability-definition.js'\nimport { DEVICE_LOCAL_STATE_CAPS, type DeviceLocalState } from '../generated/device-local-state.js'\n\n// Zod 4's `ZodRawShape = $ZodShape = Record<string, $ZodType<unknown, unknown>>`\n// is too strict for concrete-shape schemas: a `z.object({ host: z.string(), … })`\n// produces `ZodObject<{ host: ZodString, … }>` whose fields' types\n// (`ZodString`, `ZodDefault<ZodNumber>`, …) don't widen to\n// `$ZodType<unknown, unknown>` once a subclass has 30+ fields, so\n// HikvisionCamera fails TS2344 on the constraint.\n//\n// Zod ships `$ZodLooseShape = Record<string, any>` for exactly this\n// pattern — generic constraints that should accept any concrete schema.\n// Using it on the type parameter keeps the typed inference path\n// (`z.infer<T>`, `T['shape']['host']`) intact while admitting concrete\n// schemas from subclasses.\nexport abstract class BaseDevice<T extends z.ZodObject<z.core.$ZodLooseShape> = z.ZodObject<z.ZodRawShape>> implements IDevice {\n readonly id: number\n readonly stableId: string\n readonly type: DeviceType\n readonly name: string\n readonly parentDeviceId: number | null\n readonly role?: DeviceRole\n /**\n * Cap-keyed runtime-state slice is the single source of truth for\n * `online`. Both getter and setter proxy to the slice — drivers can\n * write `this.online = true` ergonomically, and the cap event fires\n * automatically through the runtime-state writer. `markOnline()` is\n * kept as the explicit method form mandated by `IDevice`.\n */\n get online(): boolean {\n const slice = this.runtimeState.getCapState<DeviceStatus>('device-status')\n return slice?.online ?? false\n }\n set online(value: boolean) {\n this.markOnline(value)\n }\n\n /**\n * Generic per-cap runtime-state namespace. One entry per cap with\n * `runtimeState:` declared, auto-generated by codegen — see\n * `device-local-state.ts`. Drivers access via:\n *\n * `this.state.battery.sleeping = true` // patches the battery slice\n * `const pct = this.state.battery.percentage` // reads the battery slice\n * `this.state.deviceStatus.online = true` // mirrors `markOnline(true)`\n *\n * Adding a new cap with `runtimeState:` automatically extends this\n * namespace — drivers don't have to declare proxies. Reads return\n * `undefined` when the slice hasn't been seeded; writes patch via\n * `runtimeState.patchCapState` and validate against the cap's schema\n * (so partial writes need the slice to be seeded with the required\n * fields first — drivers do this on cap registration).\n *\n * For caps not exposed in `DeviceLocalState`, drivers can build their\n * own typed proxy via `this.sliceProxy(cap)`.\n */\n get state(): DeviceLocalState {\n if (!this._stateProxyCache) {\n const cache: Record<string, unknown> = {}\n const handler: ProxyHandler<Record<string, unknown>> = {\n get: (_target, key) => {\n const k = key as string\n if (k in cache) return cache[k]\n const cap = (DEVICE_LOCAL_STATE_CAPS as Record<string, CapabilityDefinition | undefined>)[k]\n if (!cap) return undefined\n const proxy = this.sliceProxy(cap)\n cache[k] = proxy\n return proxy\n },\n }\n this._stateProxyCache = new Proxy(cache, handler) as unknown as DeviceLocalState\n }\n return this._stateProxyCache\n }\n private _stateProxyCache?: DeviceLocalState\n abstract readonly features: readonly DeviceFeature[]\n readonly config: DeviceConfig<T>\n /**\n * Per-device runtime state, cap-keyed. Always installed — slices\n * for individual caps materialise as those caps register their\n * native providers (`ctx.registerNativeCap`). The cap's own\n * `runtimeState` schema is the source of truth for the slice\n * shape; drivers don't redeclare it, they just write through.\n *\n * Read: `this.runtimeState.getCapState('battery')` →\n * `{percentage, charging, sleeping, lastUpdated}` for any\n * provider that registers `batteryCapability`.\n * Write: `this.runtimeState.setCapState('battery', { … })`.\n *\n * Cross-process consumers reach this state through the\n * `deviceState` cap router (or via cap-specific events the driver\n * emits — e.g. `battery.onStatusChanged`). The local handle is\n * accessed in-process by the driver to avoid roundtrips.\n */\n readonly runtimeState: IDeviceRuntimeState\n readonly ctx: DeviceContext\n\n /**\n * Operator-organisational location label (room / area / zone).\n * Read from `ctx.deviceMeta.location`; mutated via\n * `kernel.devices.setLocation(id, value)`. Free-text — providers\n * don't interpret it; the UI groups devices by this for filters\n * like \"show me all cameras in Kitchen\". `null` when unset.\n */\n readonly location: string | null\n /**\n * Soft-disabled flag. When `true`, the device class is still\n * instantiated and visible in the UI (so the operator can flip\n * back on without re-adding) but lifecycle hooks (publishToBroker,\n * alarm-stream subscribe, …) MUST be gated by the driver to skip\n * work. The `BaseDevice` enforces this by exposing the flag here;\n * it does NOT mutate cap behaviour automatically — drivers consult\n * `this.disabled` at the top of their lifecycle methods. Read from\n * `ctx.deviceMeta.disabled`; mutated via\n * `kernel.devices.setDisabled(id, value)`.\n */\n readonly disabled: boolean\n\n constructor(\n ctx: DeviceContext,\n schema: T,\n options: {\n type: DeviceType\n /** Optional semantic role within parent — see `DeviceRole`. */\n role?: DeviceRole\n },\n ) {\n this.ctx = ctx\n this.id = ctx.id\n this.stableId = ctx.stableId\n this.type = options.type\n // Operator-organisational fields (`name` / `location` / `disabled`)\n // come exclusively from the kernel-managed meta surface. Production\n // contexts always populate `ctx.deviceMeta`; test fixtures must\n // supply it explicitly. No fallback to `options.name` — the only\n // way to set the display name is through the meta API.\n if (!ctx.deviceMeta) {\n throw new Error(\n `BaseDevice constructor: ctx.deviceMeta is required (id=${ctx.id} stableId=${ctx.stableId})`,\n )\n }\n this.name = ctx.deviceMeta.name\n this.location = ctx.deviceMeta.location\n this.disabled = ctx.deviceMeta.disabled\n this.role = options.role\n this.parentDeviceId = ctx.parentDeviceId\n // DeviceContext.persistConfig is typed as (data: unknown) => Promise<void>\n // to break the circular dependency between DeviceContext and every schema type T.\n // DeviceConfig.fromSchema requires (data: z.infer<T>) => Promise<void>, which is a\n // subtype of (data: unknown) => Promise<void> at runtime (TypeScript variance rules\n // prevent direct assignment for function parameters). The wrapper below narrows the\n // type without losing safety — the actual data passed is always z.infer<T> because\n // DeviceConfig itself only calls persistFn with validated T values.\n //\n // Self-hydrate: the kernel pre-loads the per-device persisted\n // config blob from the DB and stuffs it into `ctx.persistedConfig`\n // before this constructor runs. We seed `DeviceConfig` from that\n // blob alone — operator-supplied initial config (Add-Device form\n // input) reaches us via the same DB read because providers\n // pre-persist via `kernel.devices.create(stableId, Class, config)`\n // (or `persistInitialConfig` in the manual flow), which writes\n // the blob to the DB BEFORE constructing the device. The device\n // class therefore never sees an `initialData` constructor arg —\n // every config read goes through `this.config.get(...)` which is\n // a thin in-memory cache over the DB row. Schema defaults fill\n // any missing keys via Zod's parse pass.\n const seedData = ctx.persistedConfig ?? {}\n this.config = DeviceConfig.fromSchema(\n schema,\n (data: z.infer<T>) => ctx.persistConfig(data),\n seedData,\n ({ droppedKeys, issues }) => {\n // Stale persisted values that no longer match the schema —\n // logged once at boot so operators can see what got reset.\n // The DB blob is healed asynchronously inside `fromSchema`\n // (it persists the cleaned data), so this log is the only\n // visible trace of the recovery path firing.\n ctx.logger.warn('Device config recovery: dropping invalid persisted fields', {\n tags: { deviceId: ctx.id, stableId: ctx.stableId },\n meta: {\n droppedKeys: [...droppedKeys],\n firstIssue: issues[0]?.message ?? null,\n },\n })\n },\n )\n\n // Always install runtime state — schemas attach lazily as the\n // device's caps register their native providers (see\n // `ctx.registerNativeCap` wiring in the kernel context factory).\n //\n // Writer routes through `fetchDevice(id).deviceState.setCapSlice`\n // so we share the same per-device facade admin-ui + addons use.\n // The DeviceProxy auto-injects deviceId; the dispatch falls\n // through to the local hub provider (or its Moleculer bridge\n // proxy when device-manager runs cross-process).\n //\n // The proxy is fetched lazily on the first write and cached for\n // the device's lifetime — `getBindings` is one cheap query, and\n // `setCapSlice` is a system-cap call that doesn't read binding\n // entries (so cache staleness is irrelevant for this writer).\n let cachedProxy: Promise<import('../generated/device-proxy.js').DeviceProxy> | null = null\n const writer = async (capName: string, slice: Record<string, unknown>): Promise<void> => {\n if (!cachedProxy) cachedProxy = ctx.fetchDevice(ctx.id)\n const dev = await cachedProxy\n await dev.deviceState.setCapSlice({ capName, slice })\n }\n const initial = ctx.initialRuntimeState ?? {}\n this.runtimeState = DeviceRuntimeState.fromInitial(initial, writer)\n // Hand the reference back to the context so subsequent\n // `ctx.registerNativeCap` calls (fired from this constructor's\n // own `registerNativeCapabilities` chain) can install each\n // cap's `runtimeState` schema. Optional hook — test contexts\n // skip it; caps with runtime state in those contexts go memory-\n // only without schema validation.\n ctx.bindRuntimeState?.(this.runtimeState)\n\n // Auto-register the generic `device-status` cap so every device\n // exposes a uniform cap-keyed slice for the base device-level\n // flags (`online`, `lastChangedAt`). Cross-process consumers read\n // via `device-state.getCapSlice({deviceId, capName: 'device-status'})`\n // instead of having to special-case `online` against the device\n // summary RPC. Driver-specific caps (`battery`, `doorbell`, …)\n // own their own slices.\n ctx.registerNativeCap?.(deviceStatusCapability, {})\n // Seed the slice synchronously with the canonical pre-firmware\n // default (`online: false`) so the `online` getter resolves and\n // the first cross-process read returns a populated record.\n const seed: DeviceStatus = { online: false, lastChangedAt: Date.now() }\n this.runtimeState.setCapState('device-status', seed)\n\n // Auto-register the generic `feature-probe` cap. Drivers populate it\n // from `onProbe()` (kernel calls it once after register, before\n // accessory reconciliation). The slice is the single source of truth\n // for `getAccessoryChildren()` decisions and the public `features`\n // array — it replaces the older driver-local `deviceCache.has*`\n // duplication.\n ctx.registerNativeCap?.(featureProbeCapability, {})\n const probeSeed: FeatureProbeStatus = {\n flags: {},\n deviceType: null,\n model: null,\n channelCount: null,\n lastProbedAt: 0,\n lastFetchedAt: 0,\n }\n this.runtimeState.setCapState('feature-probe', probeSeed)\n }\n\n async removeDevice(): Promise<void> {\n // Override in subclass for cleanup (disconnect, stop streams, etc.)\n }\n\n /**\n * Set the device's online flag. Called by `BaseDeviceProvider` after\n * aggregating per-profile stream-broker health, or directly by drivers\n * that have provider-side liveness signals (e.g. ONVIF heartbeats,\n * Reolink Baichuan firmware push events). Mirrors the new value into\n * the `device-status` runtime-state slice so cross-process consumers\n * pick it up via the standard cap-state channel. Subclasses can\n * override to gate side effects on the transition.\n */\n markOnline(online: boolean): void {\n if (this.online === online) return\n const next: DeviceStatus = { online, lastChangedAt: Date.now() }\n this.runtimeState.setCapState('device-status', next)\n }\n\n /**\n * Re-publish the device's current `features` array to the persisted\n * meta blob. Drivers call this after a probe finishes when the live\n * `features` getter has gained new flags (e.g. `hasIntercom` flips\n * to true → `DeviceFeature.TwoWayAudio` joins the list).\n *\n * Without this, only the construction-time snapshot is written —\n * `deviceManager.registerDevice` is invoked once per boot, so probe-\n * driven additions don't reach the persisted index until the next\n * server restart, and `getDevice` / `listAll` keep returning the\n * stale list for forked-worker devices (whose live IDevice instance\n * is invisible to the hub registry).\n *\n * Idempotent: re-calling with the same features just no-ops on the\n * persisted meta. Best-effort: lookup or write failures are logged\n * at debug and swallowed — the live `device.features` getter is\n * still authoritative within this process, so callers never block\n * device boot on a meta refresh.\n */\n protected async refreshFeatures(): Promise<void> {\n const api = this.ctx.api as unknown as {\n deviceManager?: {\n registerDevice?: { mutate: (input: {\n addonId: string\n stableId: string\n id: number\n type: string\n name: string\n parentDeviceId: number | null\n features?: readonly string[]\n config: Record<string, unknown>\n }) => Promise<void> }\n }\n }\n const action = api?.deviceManager?.registerDevice\n if (!action) return\n try {\n await action.mutate({\n addonId: this.ctx.deviceMeta.addonId,\n stableId: this.stableId,\n id: this.id,\n type: this.type,\n name: this.name,\n parentDeviceId: this.parentDeviceId,\n features: [...this.features],\n // Empty config — the kernel's registerDevice ignores the field\n // when there's no payload (the per-device store is the\n // canonical source after construction).\n config: {},\n })\n } catch (err) {\n // No logger on BaseDevice (would require ctx wiring) — drivers\n // that want visibility wrap the call themselves.\n void err\n }\n }\n\n /**\n * Typed read-through to a cap-keyed runtime-state slice. Drivers\n * call `this.getCapSlice(batteryCapability)` and the return type\n * is inferred from the cap's `runtimeState` Zod schema — no string\n * key, no manual generic. Returns `null` when the slice hasn't\n * been written yet (e.g. driver hasn't seeded battery yet).\n */\n protected getCapSlice<TCap extends CapabilityDefinition>(cap: TCap): InferRuntimeState<TCap> | null {\n const slice = this.runtimeState.getCapState(cap.name)\n return (slice as InferRuntimeState<TCap> | undefined) ?? null\n }\n\n /**\n * Typed writer to a cap-keyed runtime-state slice. Routes through\n * the runtime-state writer (validate → persist → emit cap event).\n * Equivalent to `this.runtimeState.setCapState(cap.name, value)`\n * but with the cap's `runtimeState` schema enforcing the value\n * shape at compile time. Mirrors the symmetry of\n * `getCapSlice` / `setCapSlice` for cross-cap consistency.\n */\n protected setCapSlice<TCap extends CapabilityDefinition>(\n cap: TCap,\n value: InferRuntimeState<TCap> & Record<string, unknown>,\n ): void {\n this.runtimeState.setCapState(cap.name, value)\n }\n\n /**\n * Field-level read/write proxy over a cap's runtime-state slice.\n * Drivers that want ergonomic per-field access declare:\n *\n * ```ts\n * protected battery = this.sliceProxy(batteryCapability)\n * // …\n * this.battery.sleeping = true // patches the slice\n * const charging = this.battery.charging // reads the slice\n * ```\n *\n * Reads return `undefined` when the slice hasn't been seeded yet\n * (cap not registered, or seeded but the field is absent). Writes\n * route through `runtimeState.patchCapState` so the cap's `runtimeState`\n * schema validates the merged result and the cap event fires.\n *\n * Pattern is generic — same shape works for `battery`, `device-status`,\n * `motion`, `doorbell`, anything with a `runtimeState:` schema. Drivers\n * declare one proxy per cap they read/write directly.\n */\n protected sliceProxy<TCap extends CapabilityDefinition>(cap: TCap): InferRuntimeState<TCap> {\n const target: Record<string, unknown> = {}\n const handler: ProxyHandler<Record<string, unknown>> = {\n get: (_, key) => {\n const slice = this.runtimeState.getCapState(cap.name)\n return slice?.[key as string]\n },\n set: (_, key, value: unknown) => {\n this.runtimeState.patchCapState(cap.name, { [key as string]: value })\n return true\n },\n has: (_, key) => {\n const slice = this.runtimeState.getCapState(cap.name)\n return slice ? key in slice : false\n },\n ownKeys: () => {\n const slice = this.runtimeState.getCapState(cap.name)\n return slice ? Object.keys(slice) : []\n },\n getOwnPropertyDescriptor: (_, key) => {\n const slice = this.runtimeState.getCapState(cap.name)\n if (!slice || !(key in slice)) return undefined\n return { configurable: true, enumerable: true, value: slice[key as string] }\n },\n }\n return new Proxy(target, handler) as InferRuntimeState<TCap>\n }\n\n /**\n * Default empty settings UI. Drivers override this to expose an\n * editable form in the device-details page. Returning an empty sections\n * array signals \"nothing to contribute\" — the aggregator drops the\n * contribution entirely rather than rendering a blank panel.\n */\n getSettingsUISchema(): ConfigUISchemaWithValues {\n return { sections: [] }\n }\n\n /**\n * Default write path: forward the flat patch directly to storage.\n * Drivers that project a UI shape different from storage (e.g. `RtspCamera`\n * exposing `mainStreamUrl`/`subStreamUrl` over `streams[]`) override this\n * to reshape before `config.setAll`.\n */\n async applySettingsPatch(patch: Record<string, unknown>): Promise<void> {\n await this.config.setAll(patch)\n }\n\n // ── Lifecycle hooks ────────────────────────────────────────────────\n //\n // The kernel orchestrates the device lifecycle in distinct phases.\n // Drivers override only the hooks they need:\n //\n // 1. Construct — `new DeviceClass(ctx)` (sync)\n // 2. RegisterIdentity — kernel writes meta + id to device-manager\n // 3. Probe — `onProbe()` populates `feature-probe` slice\n // 4. ReconcileAccessories — kernel calls `getAccessoryChildren()`\n // (sees post-probe flags), spawns missing,\n // removes orphans, refreshes meta features\n // 5. Activate — `onActivate()` does \"device is live\" work:\n // broker publish, snapshot tabs, watchdogs\n //\n // Failures in `onProbe` / `onActivate` are logged and swallowed — the\n // device IS already registered; partial init shouldn't unwind the\n // create the caller succeeded at.\n\n /**\n * Phase 3 — populate device-scoped state needed by downstream phases\n * (accessory reconciliation, public `features` array, optional cap\n * registration). Called ONCE per construction, after register but\n * before `getAccessoryChildren()`.\n *\n * Drivers write the `feature-probe` runtime-state slice via\n * `this.runtimeState.setCapState('feature-probe', {...})` — flag bag\n * is open (Reolink writes `hasPtz/hasIntercom`, Hikvision writes\n * `hasSupplementalLight/hasAlarmIo`, etc).\n *\n * Default: no-op (driver had no probe to run).\n */\n async onProbe(): Promise<void> {\n /* override in subclass */\n }\n\n /**\n * Phase 5 — fired after the device + its accessories are registered.\n * Drivers publish streams to the broker, kick off background tasks,\n * or subscribe to lib events that need a fully-registered device id.\n *\n * Default: no-op.\n *\n * RENAMED FROM `onCreated` (which still exists for back-compat in this\n * pass). The new name reflects the post-probe, post-accessory contract.\n */\n async onActivate(): Promise<void> {\n /* override in subclass */\n }\n\n /**\n * Re-run the probe + reconcile accessories + refresh features meta.\n * Drivers call this when device-side state changes (battery cam wakes,\n * firmware update, manual operator trigger).\n *\n * The kernel injects `_kernelReprobe` on registration so this method\n * delegates to the same orchestrator that runs the boot-time phase\n * 3 + 4 sequence. Drivers should NOT override this — they override\n * `onProbe()` instead.\n */\n async reprobe(): Promise<void> {\n if (this._kernelReprobe) await this._kernelReprobe()\n else await this.onProbe()\n }\n\n /**\n * Kernel-injected callback that runs the full post-probe orchestration\n * (onProbe → registerDevice meta refresh → accessory reconciliation).\n * Set by `device-cap-proxy.register()`. Drivers should not touch this\n * directly — call `reprobe()` instead.\n */\n _kernelReprobe?: () => Promise<void>\n\n /**\n * Declare accessory child devices the kernel should auto-spawn\n * after `onProbe()` resolves. Each spec fully describes one child\n * — stableId suffix (deterministic per kind for restore-safety),\n * meta (type / name / location), config (initial blob the child\n * self-hydrates), and a factory that constructs the concrete\n * class with whatever closure-captured refs it needs (typically\n * `this` for the parent reference).\n *\n * The kernel handles the rest: allocateDeviceId, persistInitialConfig\n * (skipped on restore when the row already exists),\n * persistInitialMeta, createContext, factory invocation, register,\n * and recursive lifecycle (probe + accessories + activate).\n *\n * Implementations should derive children from\n * `this.runtimeState.getCapState('feature-probe')` (post-probe truth).\n * Drivers can use the `getProbeFlags()` helper to read the flag bag\n * with a typed cast.\n *\n * Default: no children.\n */\n getAccessoryChildren(): readonly AccessoryChildSpec[] {\n return []\n }\n\n /**\n * Read the current feature-probe flag bag with a typed cast. Helper\n * for `getAccessoryChildren()` and `features` getters that derive\n * outputs from the probe results.\n */\n protected getProbeFlags<F extends Record<string, unknown> = Record<string, unknown>>(): F {\n const slice = this.runtimeState.getCapState<FeatureProbeStatus>('feature-probe')\n return (slice?.flags ?? {}) as F\n }\n\n /**\n * Returns true once `onProbe` has completed at least once\n * (`lastProbedAt > 0`). Drivers gate `getAccessoryChildren()` on this\n * to avoid spawning stale accessories on a fresh device whose probe\n * hasn't landed yet.\n */\n protected hasProbed(): boolean {\n const slice = this.runtimeState.getCapState<FeatureProbeStatus>('feature-probe')\n return (slice?.lastProbedAt ?? 0) > 0\n }\n}\n\n/**\n * Specification for one accessory child a parent device wants the\n * kernel to auto-spawn. Returned from `BaseDevice.getAccessoryChildren()`.\n */\nexport interface AccessoryChildSpec {\n /**\n * Stable suffix appended to the parent's stableId to derive the\n * child's stableId (e.g. `siren` → `${parent.stableId}-siren`).\n * Must be deterministic per (parent, accessory kind) so restore\n * resolves the same numeric id and re-instantiates without\n * orphaning the persisted config.\n */\n readonly stableIdSuffix: string\n /** Operator-organisational meta passed to `kernel.devices.create()`'s\n * `initialMeta` arg. The kernel pre-writes the meta row before\n * the child class constructor runs. */\n readonly meta: import('./device-management.js').InitialDeviceMeta\n /** Initial config blob the child self-hydrates from on first\n * create. Empty `{}` on restore (DB row carries the canonical\n * values) — the kernel detects the existing row and skips the\n * pre-persist step. */\n readonly config: Record<string, unknown>\n /**\n * Constructor closure — invoked with the kernel-built context\n * after meta + config are persisted. Closures over the parent\n * reference for child classes that need `parent` as a constructor\n * arg (e.g. accessories that share the parent's connection). The\n * returned IDevice is registered + `onCreated`-fired by the\n * kernel.\n */\n readonly factory: (ctx: DeviceContext) => IDevice\n}\n","import type {\n ProviderRegistration,\n ConfigUISchema,\n SavedDevice,\n IDevice,\n} from '../index.js'\nimport { BaseAddon } from '../addon/base-addon.js'\nimport { deviceProviderCapability } from '../capabilities/device-provider.cap.js'\nimport { DeviceType } from './device-type.js'\nimport type { CreateDeviceSpec } from './device-management.js'\nimport type { DeviceConstructor } from './device-context.js'\n\n// ── Shared interfaces (previously duplicated in each provider) ──────\n\nexport interface DiscoveryCandidate {\n readonly stableId: string\n readonly type: DeviceType\n readonly suggestedName: string\n readonly prefilledConfig: Record<string, unknown>\n}\n\nexport interface DeviceSummary {\n readonly id: number\n readonly stableId: string\n readonly addonId: string\n readonly type: string\n readonly name: string\n readonly parentDeviceId: number | null\n readonly online: boolean\n readonly features: readonly string[]\n readonly config: Record<string, unknown>\n}\n\nexport interface ProviderStatus {\n readonly connected: boolean\n readonly deviceCount: number\n readonly error?: string\n}\n\nexport interface FieldProbeResult {\n readonly status: 'ok' | 'error'\n readonly labels?: readonly string[]\n readonly error?: string\n /**\n * Optional values the provider suggests applying to other form fields\n * after a successful probe. The form-builder merges these into the\n * working snapshot ONLY for fields the operator hasn't filled yet,\n * never overwriting user input. Typical use: a host-probe that\n * autodetects the camera model and proposes it as the device `name`.\n */\n readonly suggestedValues?: Readonly<Record<string, unknown>>\n}\n\n// ── Utility ─────────────────────────────────────────────────────────\n\n/**\n * Convert an IDevice to the flat DeviceSummary shape expected by the\n * device-provider cap router. Shared across all providers.\n */\nexport function toDeviceSummary(device: IDevice, addonId: string): DeviceSummary {\n const config: Record<string, unknown> = {}\n for (const entry of device.config.entries()) {\n config[entry.key] = entry.value\n }\n return {\n id: device.id,\n stableId: device.stableId,\n addonId,\n type: String(device.type),\n name: device.name,\n parentDeviceId: device.parentDeviceId,\n online: device.online,\n features: [...device.features],\n config,\n }\n}\n\n// ── Base class ──────────────────────────────────────────────────────\n\n/**\n * Base class for device-provider addons (rtsp, onvif, frigate).\n *\n * Provides default implementations for the common device-provider cap\n * methods (`start`, `stop`, `getStatus`, `getDevices`, `supportsDiscovery`,\n * `supportsManualCreation`, `toDeviceSummary`). Subclasses override the\n * methods that differ per provider.\n *\n * @example\n * ```ts\n * class RtspProvider extends BaseDeviceProvider {\n * protected readonly addonId = 'provider-rtsp'\n * protected readonly providerName = 'RTSP'\n *\n * protected async onCreateDevice(input) { ... }\n * protected async onGetCreationSchema(type) { ... }\n * protected async onRestoreDevices(saved) { ... }\n * }\n * ```\n */\nexport abstract class BaseDeviceProvider<TConfig extends object = Record<string, unknown>> extends BaseAddon<TConfig> {\n /** Addon ID used in DeviceSummary. Must match package.json id. */\n protected abstract readonly addonId: string\n\n /** Human-readable provider name for log messages. */\n protected abstract readonly providerName: string\n\n // ── Lifecycle (BaseAddon hooks) ─────────────────────────────────────\n\n protected async onInitialize(): Promise<ProviderRegistration[]> {\n this.ctx.logger.info(`${this.providerName} Provider initialized`)\n return [{ capability: deviceProviderCapability, provider: this }]\n }\n\n protected async onShutdown(): Promise<void> {\n // Decommission every device this provider owns BEFORE returning.\n // Mirrors what Moleculer SIGTERM + in-process restart paths\n // expect: each device's `removeDevice()` lifecycle hook fires\n // (closes alarm streams, ISAPI clients, polling timers, intercom\n // sessions, …), native caps unregister cleanly, registry entries\n // drop. The persisted device-meta / config rows stay intact so\n // the next boot's `restoreDevices` rehydrates the same set with\n // freshly-instantiated IDevice classes — that's the whole point\n // of \"decommission, don't delete\".\n //\n // Subclasses that need extra teardown (Moleculer service handle,\n // background workers) should override and call `super.onShutdown()`\n // first so devices are torn down before vendor-specific resources.\n const devices = await this.ctx.kernel.devices?.getAll() ?? []\n for (const device of devices) {\n try {\n await this.ctx.kernel.devices?.decommission(device.id)\n } catch (err) {\n this.ctx.logger.warn(`${this.providerName}: decommission failed`, {\n tags: { deviceId: device.id, stableId: device.stableId },\n meta: { error: err instanceof Error ? err.message : String(err) },\n })\n }\n }\n this.ctx.logger.info(`${this.providerName} Provider shut down`, {\n meta: { decommissionedCount: devices.length },\n })\n }\n\n // ── device-provider cap — lifecycle + introspection ─────────────────\n // Default implementations. Override in subclass if needed.\n\n async start(): Promise<void> {\n /* no-op — providers are passive by default */\n }\n\n async stop(): Promise<void> {\n /* no-op */\n }\n\n async getStatus(): Promise<ProviderStatus> {\n const all = (await this.ctx.kernel.devices?.getAll()) ?? []\n return { connected: true, deviceCount: all.length }\n }\n\n async getDevices(): Promise<ReadonlyArray<{ id: string; name: string; type: string }>> {\n const all = (await this.ctx.kernel.devices?.getAll()) ?? []\n return all.map((d) => ({ id: d.stableId, name: d.name, type: String(d.type) }))\n }\n\n // ── device-provider cap — discovery ─────────────────────────────────\n // Default: no discovery. Override in providers that support it (ONVIF).\n\n async supportsDiscovery(): Promise<boolean> {\n return false\n }\n\n async discoverDevices(): Promise<readonly DiscoveryCandidate[]> {\n return []\n }\n\n async adoptDiscoveredDevice(_input: {\n candidate: DiscoveryCandidate\n }): Promise<DeviceSummary> {\n throw new Error(`${this.providerName} provider does not support discovery-based adoption`)\n }\n\n // ── device-provider cap — manual creation ───────────────────────────\n // Default: supports manual creation. Subclass must implement\n // onGetCreationSchema and onCreateDevice.\n\n async supportsManualCreation(): Promise<boolean> {\n return true\n }\n\n async getChildCreationSchema(input: { type: DeviceType }): Promise<ConfigUISchema | null> {\n return this.onGetCreationSchema(input.type)\n }\n\n /**\n * Default kernel-orchestrated `createDevice` implementation. The\n * subclass's `onCreateDevice` returns a declarative\n * `CreateDeviceSpec` (`{meta, config}`) — this method handles\n * stableId generation, class lookup, kernel.devices.create\n * dispatch, and DeviceSummary mapping. Subclasses should NOT\n * override this method; override `onCreateDevice` and\n * `deviceClasses` instead.\n */\n async createDevice(input: {\n type: DeviceType\n config: Record<string, unknown>\n }): Promise<DeviceSummary> {\n const spec = await this.onCreateDevice(input.type, input.config)\n const Class = this.deviceClasses[spec.meta.type] as DeviceConstructor<IDevice> | undefined\n if (!Class) {\n throw new Error(\n `${this.providerName} provider: no device class registered for type \"${spec.meta.type}\" — add it to the deviceClasses map`,\n )\n }\n const stableId = this.generateStableId(spec.meta.type, spec.config)\n const device = await this.ctx.kernel.devices!.create(\n stableId,\n Class,\n spec.config,\n null,\n spec.meta,\n )\n if (spec.onAfterCreate) {\n try {\n await spec.onAfterCreate(device)\n } catch (err) {\n this.ctx.logger.warn('createDevice: onAfterCreate hook threw — device is already registered', {\n tags: { deviceId: device.id, stableId },\n meta: { error: err instanceof Error ? err.message : String(err) },\n })\n }\n }\n return this.toSummary(device)\n }\n\n /**\n * Generate a stableId for a newly-created device. Default uses the\n * `${addonId}-${Date.now()}` pattern as a unique-but-opaque\n * fallback; any provider that has access to durable hardware\n * identity (UID, MAC, serial) should override and derive from it\n * so re-adding the same physical device reuses its persisted row.\n *\n * `config` is the parsed CreateDeviceSpec.config the subclass\n * returned from `onCreateDevice` — the override has access to\n * every operator-supplied + autodetect-resolved field. Optional\n * for back-compat: existing overrides that take only `type`\n * keep working unchanged.\n */\n protected generateStableId(_type: DeviceType, _config?: Record<string, unknown>): string {\n return `${this.addonId}-${Date.now()}`\n }\n\n async testCreationField(_input: {\n type: DeviceType\n key: string\n value: unknown\n formValues?: Record<string, unknown>\n }): Promise<FieldProbeResult> {\n return { status: 'ok', labels: ['probe not implemented'] }\n }\n\n // ── Boot restore ────────────────────────────────────────────────────\n\n async restoreDevices(savedDevices: readonly SavedDevice[]): Promise<void> {\n await this.onRestoreDevices(savedDevices)\n if (savedDevices.length > 0) {\n this.ctx.logger.info(`Restored ${savedDevices.length} ${this.providerName} device(s)`)\n }\n }\n\n // ── Subclass hooks ──────────────────────────────────────────────────\n\n /**\n * Concrete device classes this provider can spawn, keyed by\n * `DeviceType`. Used by:\n * - `createDevice` to look up the class for the type the operator\n * selected in the Add-Device modal\n * - the default `onRestoreDevices` to instantiate persisted rows\n * based on their `type` field\n *\n * Required for the declarative create + restore flow. Providers\n * that need custom-arg constructors (accessory child devices) wire\n * those up via `BaseDevice.getAccessoryChildren()` instead — the\n * top-level type → class map only handles parent devices.\n */\n protected abstract readonly deviceClasses: Partial<Record<DeviceType, DeviceConstructor<IDevice>>>\n\n /** Return the creation form schema for a given device type, or null if unsupported. */\n protected abstract onGetCreationSchema(type: DeviceType): Promise<ConfigUISchema | null>\n\n /**\n * Build the create spec from operator-supplied form values. Returns\n * `{meta, config}` — kernel handles allocateId, persist, instantiate,\n * register, and accessory auto-spawn. Provider's only job is to:\n * - validate / probe the input\n * - emit the meta (`type`, `name`, optional `location`)\n * - emit the `config` blob the device class will self-hydrate\n */\n protected abstract onCreateDevice(type: DeviceType, config: Record<string, unknown>): Promise<CreateDeviceSpec>\n\n /**\n * Restore devices from persisted state. Two-pass:\n *\n * 1. **Top-level pass** — invokes `kernel.devices.create()` for every\n * `parentDeviceId === null` row using the `deviceClasses` map.\n * The kernel's register flow handles `getAccessoryChildren()` for\n * each parent (siren / floodlight / PIR / etc).\n *\n * 2. **Hub-adopted children pass** — for rows with\n * `parentDeviceId !== null` whose `type` IS in `deviceClasses`\n * (e.g. Reolink hub-adopted cameras under an NVR), spawn them\n * explicitly with the persisted `parentDeviceId`. These are\n * NOT accessory children — they're first-class adopted devices\n * that just happen to have a parent. Without this pass, every\n * server restart would lose hub-adopted cameras (their type is\n * in `deviceClasses` but parent's `getAccessoryChildren` doesn't\n * spawn them — that callback is only for purpose-built\n * accessory roles).\n *\n * Rows whose `type` is NOT in `deviceClasses` are skipped — those\n * are accessory children (siren/light/sensor) that the kernel's\n * accessory-spawn flow handles via the parent's\n * `getAccessoryChildren()`. Override only when the default doesn't\n * fit.\n */\n protected async onRestoreDevices(savedDevices: readonly SavedDevice[]): Promise<void> {\n // Pass 1 — top-level\n const restored = new Set<number>()\n for (const saved of savedDevices) {\n if (saved.parentDeviceId !== null) continue\n const Class = this.deviceClasses[saved.type] as DeviceConstructor<IDevice> | undefined\n if (!Class) {\n this.ctx.logger.warn('No device class registered for restored type — skipping', {\n tags: { stableId: saved.stableId },\n meta: { type: saved.type },\n })\n continue\n }\n try {\n await this.ctx.kernel.devices!.create(saved.stableId, Class, {})\n restored.add(saved.id)\n } catch (err) {\n this.ctx.logger.warn('Failed to restore device', {\n tags: { stableId: saved.stableId },\n meta: { type: saved.type, error: err instanceof Error ? err.message : String(err) },\n })\n }\n }\n // Pass 2 — hub-adopted children (first-class devices with a parent\n // that is itself a registered device class). Iterates in order of\n // declared `parentDeviceId` to handle nested hubs gracefully.\n const childRows = savedDevices.filter(s => s.parentDeviceId !== null)\n for (const saved of childRows) {\n const Class = this.deviceClasses[saved.type] as DeviceConstructor<IDevice> | undefined\n if (!Class) continue // not a first-class type → accessory, skip\n if (saved.parentDeviceId === null) continue\n if (!restored.has(saved.parentDeviceId)) {\n // Parent isn't a known top-level device this provider owns —\n // probably a stale row pointing at a removed parent. Leave it\n // alone; orphan reconciliation runs later.\n continue\n }\n try {\n await this.ctx.kernel.devices!.create(\n saved.stableId,\n Class,\n {},\n saved.parentDeviceId,\n )\n restored.add(saved.id)\n } catch (err) {\n this.ctx.logger.warn('Failed to restore hub-adopted child', {\n tags: { stableId: saved.stableId, parentDeviceId: saved.parentDeviceId },\n meta: { type: saved.type, error: err instanceof Error ? err.message : String(err) },\n })\n }\n }\n }\n\n // ── Utility ─────────────────────────────────────────────────────────\n\n /** Convert an IDevice to the flat DeviceSummary for the cap router. */\n protected toSummary(device: IDevice): DeviceSummary {\n return toDeviceSummary(device, this.addonId)\n }\n}\n","import { z } from 'zod'\nimport type {\n ConfigUISchema,\n ConfigField,\n ConfigTextField,\n ConfigNumberField,\n ConfigBooleanField,\n ConfigSelectField,\n ConfigPasswordField,\n ConfigTextAreaField,\n} from '../interfaces/config-ui.js'\n\n// --- Entry type matching DeviceConfig.entries() output ---\n\nexport interface DeviceConfigEntry {\n key: string\n schema: z.ZodType\n value: unknown\n description?: string\n}\n\n// --- Internal Zod v4 _def shapes (accessed at runtime, not exposed in typings) ---\n\ninterface ZodV4CheckDef {\n check: string\n value?: number\n inclusive?: boolean\n}\n\ninterface ZodV4Check {\n _zod: { def: ZodV4CheckDef }\n}\n\ninterface ZodV4NumberDef {\n type: string\n checks?: ZodV4Check[]\n}\n\ninterface ZodV4DefaultDef {\n type: string\n defaultValue: unknown\n innerType: z.ZodType\n}\n\n/** Access Zod v4 internal .def — not in public typings but stable at runtime */\nfunction zodDef<T>(schema: z.ZodType): T {\n return (schema as unknown as { def: T }).def\n}\n\n/** Access internal properties on a Zod schema instance */\nfunction zodInternals<T>(schema: z.ZodType): T {\n return schema as unknown as T\n}\n\n// --- Public API ---\n\n/**\n * Convert DeviceConfig.entries() output to ConfigUISchema for the admin UI FormBuilder.\n *\n * Each entry's Zod type is inspected to determine the correct ConfigField type:\n * - ZodString → 'text' (or 'password' when key contains \"password\"/\"secret\"/\"token\"/\"apikey\")\n * - ZodNumber → 'number' (extracts min/max/step from Zod v4 checks)\n * - ZodBoolean → 'boolean'\n * - ZodEnum → 'select' (options built from enum values)\n * - Anything else → 'text' fallback\n *\n * Wrapper types ZodDefault, ZodOptional, and ZodNullable are unwrapped transparently.\n * Default values are extracted from ZodDefault wrappers.\n */\nexport function zodEntriesToConfigUI(\n entries: readonly DeviceConfigEntry[],\n sectionTitle = 'Configuration',\n sectionId = 'main',\n): ConfigUISchema {\n const fields: ConfigField[] = entries.map(entry =>\n zodToConfigField(entry.key, entry.schema, entry.description),\n )\n\n return {\n sections: [\n {\n id: sectionId,\n title: sectionTitle,\n fields,\n },\n ],\n }\n}\n\n// --- Internal helpers ---\n\nfunction zodToConfigField(key: string, schema: z.ZodType, description?: string): ConfigField {\n const inner = unwrapZod(schema)\n const defaultValue = getZodDefault(schema)\n const label = description ?? humanizeKey(key)\n\n const base = {\n key,\n label,\n description,\n default: defaultValue,\n } as const\n\n if (inner instanceof z.ZodString) {\n return buildStringField(key, base)\n }\n\n if (inner instanceof z.ZodNumber) {\n return buildNumberField(inner, base)\n }\n\n if (inner instanceof z.ZodBoolean) {\n const field: ConfigBooleanField = { ...base, type: 'boolean' }\n return field\n }\n\n if (inner instanceof z.ZodEnum) {\n return buildEnumField(inner, base)\n }\n\n // Arrays + objects don't fit any primitive field — render as a JSON\n // textarea so the operator at least sees the shape and can copy/edit\n // it, instead of `[object Object],…` produced by the text fallback.\n // `isJson: true` tells the UI + hydrator to round-trip via JSON.\n if (inner instanceof z.ZodArray || inner instanceof z.ZodObject) {\n const field: ConfigTextAreaField = { ...base, type: 'textarea', rows: 6, isJson: true }\n return field\n }\n\n // Fallback — render as plain text\n const fallback: ConfigTextField = { ...base, type: 'text' }\n return fallback\n}\n\nfunction buildStringField(\n key: string,\n base: { key: string; label: string; description?: string; default?: unknown },\n): ConfigTextField | ConfigPasswordField {\n const lowerKey = key.toLowerCase()\n const isSecret =\n lowerKey.includes('password') ||\n lowerKey.includes('secret') ||\n lowerKey.includes('token') ||\n lowerKey.includes('apikey') ||\n lowerKey.includes('api_key')\n\n if (isSecret) {\n const field: ConfigPasswordField = { ...base, type: 'password', showToggle: true }\n return field\n }\n\n const field: ConfigTextField = { ...base, type: 'text' }\n return field\n}\n\nfunction buildNumberField(\n inner: z.ZodNumber,\n base: { key: string; label: string; description?: string; default?: unknown },\n): ConfigNumberField {\n // Zod v4 exposes min/max via public getters minValue/maxValue.\n // When unconstrained, these return -Infinity / Infinity — treat those as absent.\n const anyInner = zodInternals<{ minValue?: number | null; maxValue?: number | null }>(inner)\n const rawMin = anyInner.minValue\n const rawMax = anyInner.maxValue\n const min =\n rawMin != null && isFinite(rawMin) ? rawMin : undefined\n const max =\n rawMax != null && isFinite(rawMax) ? rawMax : undefined\n\n // Step is stored in checks with check name 'multiple_of'\n const step = getMultipleOfStep(inner)\n\n const field: ConfigNumberField = {\n ...base,\n type: 'number',\n ...(min !== undefined ? { min } : {}),\n ...(max !== undefined ? { max } : {}),\n ...(step !== undefined ? { step } : {}),\n }\n return field\n}\n\nfunction getMultipleOfStep(inner: z.ZodNumber): number | undefined {\n const def = zodDef<ZodV4NumberDef>(inner)\n const checks = def.checks ?? []\n for (const check of checks) {\n if (check._zod?.def?.check === 'multiple_of' && check._zod.def.value !== undefined) {\n return check._zod.def.value\n }\n }\n return undefined\n}\n\n// Zod v4: ZodEnum<T> where T extends Readonly<Record<string, string | number>>\n// options returns Array<T[keyof T]> which is (string | number)[]\nfunction buildEnumField(\n inner: z.ZodEnum,\n base: { key: string; label: string; description?: string; default?: unknown },\n): ConfigSelectField {\n const values = (inner.options as (string | number)[]).map(v => String(v))\n\n const field: ConfigSelectField = {\n ...base,\n type: 'select',\n options: values.map(v => ({ label: humanizeKey(v), value: v })),\n }\n return field\n}\n\nfunction unwrapZod(schema: z.ZodType): z.ZodType {\n if (schema instanceof z.ZodDefault) return unwrapZod(zodDef<ZodV4DefaultDef>(schema).innerType)\n if (schema instanceof z.ZodOptional) return unwrapZod(zodDef<{ innerType: z.ZodType }>(schema).innerType)\n if (schema instanceof z.ZodNullable) return unwrapZod(zodDef<{ innerType: z.ZodType }>(schema).innerType)\n return schema\n}\n\nfunction getZodDefault(schema: z.ZodType): unknown {\n if (schema instanceof z.ZodDefault) {\n // Zod v4: def.defaultValue is the literal value (not a function at runtime)\n return zodDef<ZodV4DefaultDef>(schema).defaultValue\n }\n return undefined\n}\n\nfunction humanizeKey(key: string): string {\n return key\n .replace(/([A-Z])/g, ' $1')\n .replace(/[_-]/g, ' ')\n .replace(/^\\w/, c => c.toUpperCase())\n .trim()\n}\n","/**\n * Reactive read handle for one cap-keyed slice of a device's\n * runtime state. Returned by `createDeviceProxy(...).state[capName]`.\n *\n * Three pieces:\n * - `value`: last-known slice. `undefined` until something has\n * populated it (an active subscription, an explicit `refresh()`,\n * or — in the case of the SystemManager mirror source — a\n * warm-boot `getAllSnapshots` payload). Read sync.\n * - `refresh()`: one-shot pull from the underlying source. For\n * the lazy tRPC source this is `deviceState.getCapSlice`; for\n * the SystemManager mirror it's a no-op (the mirror is push-only).\n * - `subscribe(cb)`: hooks into the source's notification channel,\n * filtered by `(deviceId, capName)`. Refcounted — the underlying\n * subscription closes when the last caller unsubscribes.\n *\n * Cross-environment: the same API works in browser (admin-ui via the\n * tRPC client) and on the server (in-process AddonApi). The transport\n * is whatever the supplied source exposes.\n */\nexport interface SliceHandle<T> {\n /** Latest cached slice. Reflects the most recent `refresh()` or\n * push event. `undefined` if neither has happened. */\n readonly value: T | undefined\n /** Force a re-fetch from the hub mirror. Updates `value` + notifies\n * every active subscriber. No-op for the SystemManager mirror\n * source (it's already push-driven). */\n refresh(): Promise<void>\n /** Subscribe to slice changes. Returns the unsubscribe fn.\n * Auto-fires the callback once with the current value (or\n * `undefined`) so the caller sees a snapshot immediately. */\n subscribe(cb: (slice: T | undefined) => void): () => void\n /**\n * Replace the slice on the hub. Routes through\n * `device-state.setCapSlice` — the canonical cross-layer write\n * entrypoint. The local mirror updates via the `onChanged` event\n * (round-trip), so callers should treat the write as eventually\n * consistent and read the new value via `subscribe` rather than\n * synchronously after `await`.\n */\n set(slice: T): Promise<void>\n /**\n * Shallow-merge `partial` into the current slice on the hub.\n * Implemented as read-modify-write client-side: pulls `value`\n * (or refreshes), merges, calls `set()`. Single-writer\n * conventions on each cap make atomic-merge semantics\n * unnecessary — concurrent patches on the same slice from\n * different processes are undefined and should be avoided.\n */\n patch(partial: Partial<T>): Promise<void>\n}\n\n/**\n * Minimal tRPC API surface used by the lazy source. Both `AddonApi`\n * (server) and the tRPC client proxy (browser) satisfy it structurally\n * — we don't import either to avoid pulling them in from a leaf type\n * module.\n */\nexport interface SliceHandleApi {\n readonly deviceState: {\n readonly getCapSlice: {\n query(input: { deviceId: number; capName: string }): Promise<Record<string, unknown> | null>\n }\n readonly setCapSlice: {\n mutate(input: { deviceId: number; capName: string; slice: Record<string, unknown> }): Promise<void>\n }\n }\n readonly live?: {\n readonly onEvent: {\n subscribe(\n input: { category: string },\n opts: { onData: (evt: { data: unknown }) => void; onError?: (err: unknown) => void },\n ): { unsubscribe: () => void }\n }\n }\n}\n\n/**\n * Pluggable state-source contract. `createSliceHandle` is now a thin\n * adapter over this interface — every implementation produces an\n * identical `SliceHandle<T>` shape. Two impls today:\n *\n * - `createLazyTrpcSource(api)`: per-handle local cache, refresh\n * via `deviceState.getCapSlice`, subscribe via `live.onEvent`.\n * Default behavior, used by `createDeviceProxy(api, binding)`\n * when no source is passed.\n * - `createMirrorSource(mirror, listeners)`: reads from a shared\n * `Map<deviceId, Map<capName, slice>>` populated by a\n * `SystemManager` warm-boot. Refresh is a no-op; subscribe\n * registers in a shared listener set that the SystemManager\n * fans out to on every push event.\n *\n * Both produce the same `SliceHandle<T>` API; consumers don't see\n * which source is behind the handle.\n */\nexport interface SliceHandleSource {\n /** Sync read of the last-known slice for `(deviceId, capName)`. */\n read(deviceId: number, capName: string): unknown | undefined\n /** Force a re-fetch (where applicable). No-op when the source is\n * push-only (e.g. the SystemManager mirror). */\n refresh(deviceId: number, capName: string): Promise<void>\n /** Register a listener for slice changes. Returns the unsubscribe\n * fn. Implementations should fan out the latest cached slice to\n * the callback synchronously when seeding is desired (the handle\n * always seeds via a separate `cb(read(...))` call). */\n watch(\n deviceId: number,\n capName: string,\n cb: (slice: unknown | undefined) => void,\n ): () => void\n /** Write the slice for `(deviceId, capName)` to the hub via the\n * canonical `device-state.setCapSlice` entrypoint. Throws if the\n * source has no write transport (e.g. a mirror source built\n * without an api reference). */\n write(deviceId: number, capName: string, slice: Record<string, unknown>): Promise<void>\n}\n\nconst DEVICE_STATE_EVENT_CATEGORY = 'device.state-changed'\n\n/**\n * Lazy tRPC source — the default behavior. Maintains a per-key local\n * cache (`{deviceId}:{capName}` → last slice), one shared\n * `live.onEvent` bridge that fans out into the listener map, and\n * `refresh` round-trips through `deviceState.getCapSlice`.\n *\n * The bridge is opened on first `watch()` and closed when the last\n * watcher unsubscribes — keeps idle handles cheap.\n */\nexport function createLazyTrpcSource(api: SliceHandleApi): SliceHandleSource {\n const cache = new Map<string, unknown>()\n const listeners = new Map<string, Set<(slice: unknown | undefined) => void>>()\n let bridge: { unsubscribe: () => void } | null = null\n\n const keyOf = (deviceId: number, capName: string): string => `${deviceId}:${capName}`\n\n const ensureBridge = (): void => {\n if (bridge) return\n if (!api.live?.onEvent) return\n bridge = api.live.onEvent.subscribe(\n { category: DEVICE_STATE_EVENT_CATEGORY },\n {\n onData: (evt) => {\n const data = evt.data as { deviceId?: number; capName?: string; slice?: unknown } | null\n if (!data || typeof data.deviceId !== 'number' || typeof data.capName !== 'string') return\n const k = keyOf(data.deviceId, data.capName)\n cache.set(k, data.slice)\n const set = listeners.get(k)\n if (!set) return\n for (const cb of set) {\n try { cb(data.slice) } catch { /* listener errors don't break the bridge */ }\n }\n },\n },\n )\n }\n\n const closeBridgeIfIdle = (): void => {\n if (!bridge) return\n if (listeners.size > 0) return\n bridge.unsubscribe()\n bridge = null\n }\n\n return {\n read(deviceId, capName) {\n return cache.get(keyOf(deviceId, capName))\n },\n async refresh(deviceId, capName) {\n const slice = await api.deviceState.getCapSlice.query({ deviceId, capName })\n const k = keyOf(deviceId, capName)\n cache.set(k, slice ?? undefined)\n const set = listeners.get(k)\n if (set) {\n for (const cb of set) {\n try { cb(slice ?? undefined) } catch { /* listener errors don't break refresh */ }\n }\n }\n },\n watch(deviceId, capName, cb) {\n const k = keyOf(deviceId, capName)\n let set = listeners.get(k)\n if (!set) { set = new Set(); listeners.set(k, set) }\n set.add(cb)\n ensureBridge()\n return () => {\n set!.delete(cb)\n if (set!.size === 0) listeners.delete(k)\n closeBridgeIfIdle()\n }\n },\n async write(deviceId, capName, slice) {\n await api.deviceState.setCapSlice.mutate({ deviceId, capName, slice })\n },\n }\n}\n\n/**\n * Mirror source — reads from a shared map populated by a\n * `SystemManager` warm-boot + push event handler. Refresh is a no-op\n * (the SystemManager owns the update loop). `watch()` registers in a\n * shared listener set — the SystemManager calls these from its single\n * `device.state-changed` subscription.\n *\n * The mirror map and listener map are passed in by reference so the\n * SystemManager can mutate both as events arrive.\n */\nexport function createMirrorSource(\n mirror: ReadonlyMap<number, ReadonlyMap<string, unknown>>,\n listeners: Map<string, Set<(slice: unknown | undefined) => void>>,\n api?: SliceHandleApi,\n): SliceHandleSource {\n const keyOf = (deviceId: number, capName: string): string => `${deviceId}:${capName}`\n return {\n read(deviceId, capName) {\n return mirror.get(deviceId)?.get(capName)\n },\n async refresh() {\n // No-op: the mirror is fed by `device.state-changed` events at\n // the SystemManager level. Forcing a re-fetch from a single\n // handle would race with the global update loop and is never\n // what the caller wants.\n },\n watch(deviceId, capName, cb) {\n const k = keyOf(deviceId, capName)\n let set = listeners.get(k)\n if (!set) { set = new Set(); listeners.set(k, set) }\n set.add(cb)\n return () => {\n set!.delete(cb)\n if (set!.size === 0) listeners.delete(k)\n }\n },\n async write(deviceId, capName, slice) {\n if (!api) {\n throw new Error('createMirrorSource: write requires an api reference — pass it as the third argument when constructing the source')\n }\n await api.deviceState.setCapSlice.mutate({ deviceId, capName, slice })\n },\n }\n}\n\n/**\n * Build a `SliceHandle<T>` bound to `(deviceId, capName)`. Caller\n * provides the type parameter — codegen passes\n * `InferRuntimeState<typeof <cap>>` so consumers see the cap's typed\n * shape:\n *\n * const dev = createDeviceProxy(api, binding)\n * dev.state.battery.value // BatteryStatus | undefined\n * dev.state.battery.value?.percentage\n *\n * Two-arg form (deprecated path, kept for spec compatibility):\n * passes the api directly, builds a per-handle lazy source. New\n * code should pre-build a single source and reuse it across handles\n * via the explicit `source` form.\n */\nexport function createSliceHandle<T>(\n source: SliceHandleSource | SliceHandleApi,\n deviceId: number,\n capName: string,\n): SliceHandle<T> {\n // Discriminate between source and api by structure: a source has\n // a `read` method, an api has a `deviceState` namespace. Spec-style\n // tests still pass `api`; production codegen passes a source.\n const src: SliceHandleSource = isSource(source)\n ? source\n : createLazyTrpcSource(source)\n\n return {\n get value() { return src.read(deviceId, capName) as T | undefined },\n refresh() { return src.refresh(deviceId, capName) },\n subscribe(cb) {\n const unwatch = src.watch(deviceId, capName, (slice) => {\n try { cb(slice as T | undefined) } catch { /* listener errors are isolated */ }\n })\n // Seed the listener with the current cached read — sync,\n // deterministic, no transport. Mirror sources serve the\n // canonical value here; lazy sources serve their per-key\n // cache (undefined on cold start).\n try { cb(src.read(deviceId, capName) as T | undefined) } catch { /* ignore */ }\n // Cold-start kick: when the read returned nothing AND the\n // source has a meaningful refresh path (lazy tRPC), pull once\n // in the background. Fan-out via `watch` delivers the result\n // to the same listener — no double-seeding. The mirror\n // source's refresh is a no-op, so this is a cheap miss for\n // SystemManager-backed handles.\n if (src.read(deviceId, capName) === undefined) {\n void src.refresh(deviceId, capName).catch(() => undefined)\n }\n return unwatch\n },\n async set(slice) {\n await src.write(deviceId, capName, slice as Record<string, unknown>)\n },\n async patch(partial) {\n const current = src.read(deviceId, capName) as Record<string, unknown> | undefined\n const next = { ...(current ?? {}), ...partial as Record<string, unknown> }\n await src.write(deviceId, capName, next)\n },\n }\n}\n\nfunction isSource(x: SliceHandleSource | SliceHandleApi): x is SliceHandleSource {\n return typeof (x as SliceHandleSource).read === 'function'\n && typeof (x as SliceHandleSource).watch === 'function'\n}\n","// AUTO-GENERATED — do not edit manually.\n// Regenerate with: npx tsx scripts/generate-device-proxy.ts\n/* eslint-disable */\n\nimport type { InferDeviceProxyCap, InferRuntimeState } from '../capabilities/capability-definition.js'\nimport type { DeviceBinding } from '../device/device-binding.js'\nimport { createSliceHandle, createLazyTrpcSource, type SliceHandle, type SliceHandleApi, type SliceHandleSource } from '../device/device-state-handle.js'\nimport type { AddonApi } from './addon-api.js'\nimport type { accessoriesCapability } from '../capabilities/accessories.cap.js'\nimport type { audioAnalysisCapability } from '../capabilities/audio-analysis.cap.js'\nimport type { audioMetricsCapability } from '../capabilities/audio-metrics.cap.js'\nimport type { batteryCapability } from '../capabilities/battery.cap.js'\nimport type { brightnessCapability } from '../capabilities/brightness.cap.js'\nimport type { cameraCredentialsCapability } from '../capabilities/camera-credentials.cap.js'\nimport type { cameraStreamsCapability } from '../capabilities/camera-streams.cap.js'\nimport type { detectionPipelineCapability } from '../capabilities/detection-pipeline.cap.js'\nimport type { deviceDiscoveryCapability } from '../capabilities/device-discovery.cap.js'\nimport type { deviceOpsCapability } from '../capabilities/device-ops.cap.js'\nimport type { deviceStatusCapability } from '../capabilities/device-status.cap.js'\nimport type { doorbellCapability } from '../capabilities/doorbell.cap.js'\nimport type { eventsCapability } from '../capabilities/events.cap.js'\nimport type { featureProbeCapability } from '../capabilities/feature-probe.cap.js'\nimport type { intercomCapability } from '../capabilities/intercom.cap.js'\nimport type { motionCapability } from '../capabilities/motion.cap.js'\nimport type { motionDetectionCapability } from '../capabilities/motion-detection.cap.js'\nimport type { motionTriggerCapability } from '../capabilities/motion-trigger.cap.js'\nimport type { nativeObjectDetectionCapability } from '../capabilities/native-object-detection.cap.js'\nimport type { osdCapability } from '../capabilities/osd.cap.js'\nimport type { pipelineAnalyticsCapability } from '../capabilities/pipeline-analytics.cap.js'\nimport type { ptzCapability } from '../capabilities/ptz.cap.js'\nimport type { ptzAutotrackCapability } from '../capabilities/ptz-autotrack.cap.js'\nimport type { rebootCapability } from '../capabilities/reboot.cap.js'\nimport type { recordingCapability } from '../capabilities/recording.cap.js'\nimport type { snapshotCapability } from '../capabilities/snapshot.cap.js'\nimport type { switchCapability } from '../capabilities/switch.cap.js'\nimport type { webrtcSessionCapability } from '../capabilities/webrtc-session.cap.js'\nimport type { zoneAnalyticsCapability } from '../capabilities/zone-analytics.cap.js'\nimport type { zoneRulesCapability } from '../capabilities/zone-rules.cap.js'\nimport type { zonesCapability } from '../capabilities/zones.cap.js'\nimport type { addonSettingsCapability } from '../capabilities/addon-settings.cap.js'\nimport type { deviceManagerCapability } from '../capabilities/device-manager.cap.js'\nimport type { deviceStateCapability } from '../capabilities/device-state.cap.js'\nimport type { networkQualityCapability } from '../capabilities/network-quality.cap.js'\nimport type { pipelineExecutorCapability } from '../capabilities/pipeline-executor.cap.js'\nimport type { pipelineOrchestratorCapability } from '../capabilities/pipeline-orchestrator.cap.js'\nimport type { pipelineRunnerCapability } from '../capabilities/pipeline-runner.cap.js'\nimport type { recordingEngineCapability } from '../capabilities/recording-engine.cap.js'\nimport type { snapshotProviderCapability } from '../capabilities/snapshot-provider.cap.js'\nimport type { streamBrokerCapability } from '../capabilities/stream-broker.cap.js'\n\n/**\n * Reactive read handle bag for device runtime state. Each entry mirrors the\n * cap's `runtimeState` schema and stays live via the `device-state` cap's\n * `onChanged` event. See `device-state-handle.ts` for the contract.\n */\nexport interface DeviceProxyState {\n readonly audioMetrics: SliceHandle<InferRuntimeState<typeof audioMetricsCapability>>\n readonly battery: SliceHandle<InferRuntimeState<typeof batteryCapability>>\n readonly brightness: SliceHandle<InferRuntimeState<typeof brightnessCapability>>\n readonly cameraStreams: SliceHandle<InferRuntimeState<typeof cameraStreamsCapability>>\n readonly deviceDiscovery: SliceHandle<InferRuntimeState<typeof deviceDiscoveryCapability>>\n readonly deviceStatus: SliceHandle<InferRuntimeState<typeof deviceStatusCapability>>\n readonly doorbell: SliceHandle<InferRuntimeState<typeof doorbellCapability>>\n readonly featureProbe: SliceHandle<InferRuntimeState<typeof featureProbeCapability>>\n readonly motion: SliceHandle<InferRuntimeState<typeof motionCapability>>\n readonly motionTrigger: SliceHandle<InferRuntimeState<typeof motionTriggerCapability>>\n readonly ptzAutotrack: SliceHandle<InferRuntimeState<typeof ptzAutotrackCapability>>\n readonly switch: SliceHandle<InferRuntimeState<typeof switchCapability>>\n readonly zoneAnalytics: SliceHandle<InferRuntimeState<typeof zoneAnalyticsCapability>>\n readonly zoneRules: SliceHandle<InferRuntimeState<typeof zoneRulesCapability>>\n readonly zones: SliceHandle<InferRuntimeState<typeof zonesCapability>>\n}\n\n/**\n * Unified per-device proxy interface. Each optional property is present at\n * runtime only when the device's binding includes that capability.\n *\n * The optional `binding` field is populated post-construction by callers\n * that own a binding cache (e.g. the SDK's `System` mirror). Consumers\n * that need the full per-device binding map can read it from there\n * without paying for a second `getBindings` round-trip — see Phase 5\n * dedup notes in `scripts/generate-device-proxy.ts`.\n */\nexport interface DeviceProxy {\n readonly deviceId: number\n /** Reactive runtime state, one slot per cap that declares `runtimeState`. */\n readonly state: DeviceProxyState\n /** Resolved binding entry list (or null if the proxy was constructed\n * without a cache-aware caller — defaults to null since\n * `createDeviceProxy` itself does not own the binding). */\n readonly binding: DeviceBinding | null\n readonly accessories?: InferDeviceProxyCap<typeof accessoriesCapability>\n readonly audioAnalysis?: InferDeviceProxyCap<typeof audioAnalysisCapability>\n readonly audioMetrics?: InferDeviceProxyCap<typeof audioMetricsCapability>\n readonly battery?: InferDeviceProxyCap<typeof batteryCapability>\n readonly brightness?: InferDeviceProxyCap<typeof brightnessCapability>\n readonly cameraCredentials?: InferDeviceProxyCap<typeof cameraCredentialsCapability>\n readonly cameraStreams?: InferDeviceProxyCap<typeof cameraStreamsCapability>\n readonly detectionPipeline?: InferDeviceProxyCap<typeof detectionPipelineCapability>\n readonly deviceDiscovery?: InferDeviceProxyCap<typeof deviceDiscoveryCapability>\n readonly deviceOps?: InferDeviceProxyCap<typeof deviceOpsCapability>\n readonly deviceStatus?: InferDeviceProxyCap<typeof deviceStatusCapability>\n readonly doorbell?: InferDeviceProxyCap<typeof doorbellCapability>\n readonly events?: InferDeviceProxyCap<typeof eventsCapability>\n readonly featureProbe?: InferDeviceProxyCap<typeof featureProbeCapability>\n readonly intercom?: InferDeviceProxyCap<typeof intercomCapability>\n readonly motion?: InferDeviceProxyCap<typeof motionCapability>\n readonly motionDetection?: InferDeviceProxyCap<typeof motionDetectionCapability>\n readonly motionTrigger?: InferDeviceProxyCap<typeof motionTriggerCapability>\n readonly nativeObjectDetection?: InferDeviceProxyCap<typeof nativeObjectDetectionCapability>\n readonly osd?: InferDeviceProxyCap<typeof osdCapability>\n readonly pipelineAnalytics?: InferDeviceProxyCap<typeof pipelineAnalyticsCapability>\n readonly ptz?: InferDeviceProxyCap<typeof ptzCapability>\n readonly ptzAutotrack?: InferDeviceProxyCap<typeof ptzAutotrackCapability>\n readonly reboot?: InferDeviceProxyCap<typeof rebootCapability>\n readonly recording?: InferDeviceProxyCap<typeof recordingCapability>\n readonly snapshot?: InferDeviceProxyCap<typeof snapshotCapability>\n readonly switch?: InferDeviceProxyCap<typeof switchCapability>\n readonly webrtcSession?: InferDeviceProxyCap<typeof webrtcSessionCapability>\n readonly zoneAnalytics?: InferDeviceProxyCap<typeof zoneAnalyticsCapability>\n readonly zoneRules?: InferDeviceProxyCap<typeof zoneRulesCapability>\n readonly zones?: InferDeviceProxyCap<typeof zonesCapability>\n readonly addonSettings: Pick<InferDeviceProxyCap<typeof addonSettingsCapability>, 'getDeviceSettings' | 'updateDeviceSettings'>\n readonly deviceManager: Pick<InferDeviceProxyCap<typeof deviceManagerCapability>, 'loadConfig' | 'loadRuntimeState' | 'loadMeta' | 'setName' | 'setLocation' | 'setMetadata' | 'setDisabled' | 'getDevice' | 'getStreamSources' | 'getConfigSchema' | 'getSettingsSchema' | 'updateConfig' | 'enable' | 'disable' | 'remove' | 'getStreamProfileMap' | 'setStreamProfileMap' | 'probeStreams' | 'getBindings' | 'getAllBindings' | 'setWrapperActive' | 'getDeviceSettingsAggregate' | 'getDeviceLiveInfoAggregate' | 'getDeviceAggregate' | 'updateDeviceField' | 'updateDeviceFieldsBatch' | 'testField' | 'getDeviceStatusAggregate'>\n readonly deviceState: Pick<InferDeviceProxyCap<typeof deviceStateCapability>, 'getSnapshot' | 'getCapSlice' | 'setCapSlice'>\n readonly networkQuality: Pick<InferDeviceProxyCap<typeof networkQualityCapability>, 'getDeviceStats' | 'reportClientStats'>\n readonly pipelineExecutor: Pick<InferDeviceProxyCap<typeof pipelineExecutorCapability>, 'runPipeline' | 'runPipelineBatch'>\n readonly pipelineOrchestrator: Pick<InferDeviceProxyCap<typeof pipelineOrchestratorCapability>, 'assignPipeline' | 'unassignPipeline' | 'getPipelineAssignment' | 'getCameraMetrics' | 'assignDecoder' | 'unassignDecoder' | 'assignAudio' | 'unassignAudio' | 'getAudioAssignment' | 'getAudioAssignments' | 'getDecoderAssignment' | 'getCameraSettings' | 'setCameraStepToggle' | 'getCameraStepOverrides' | 'setCameraStepOverride' | 'setCameraPipelineForAgent' | 'resolvePipeline' | 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>\n readonly pipelineRunner: Pick<InferDeviceProxyCap<typeof pipelineRunnerCapability>, 'detachCamera' | 'getCameraMetrics'>\n readonly recordingEngine: Pick<InferDeviceProxyCap<typeof recordingEngineCapability>, 'getPolicyStatus'>\n readonly snapshotProvider: Pick<InferDeviceProxyCap<typeof snapshotProviderCapability>, 'supportsDevice' | 'getSnapshot'>\n readonly streamBroker: Pick<InferDeviceProxyCap<typeof streamBrokerCapability>, 'publishCameraStream' | 'retractCameraStream' | 'assignProfile' | 'unassignProfile' | 'restartProfile' | 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>\n}\n\n/**\n * Build a DeviceProxy that pre-binds deviceId + nodeId on every method call\n * and dispatches through the existing cap-router tRPC procedures.\n *\n * Optional `opts.stateSource` lets a SystemManager pass a shared mirror\n * source so every device proxy reads from the same in-memory map and\n * shares the warm-boot/push-event update loop. When omitted, a per-proxy\n * lazy tRPC source is created — the path used by `ctx.fetchDevice` and\n * `BackendClient.fetchDevice` for one-off reads.\n *\n * The returned proxy's `binding` field is set to the input `binding`\n * by default — callers that want to expose a different value (e.g. the\n * SDK's `System` patches it from a shared cache) can overwrite the\n * field on the returned object.\n */\nexport function createDeviceProxy(\n api: AddonApi,\n binding: DeviceBinding,\n opts?: { stateSource?: SliceHandleSource },\n): DeviceProxy {\n const typedApi = api as unknown as Record<string, Record<string, Record<string, (input?: unknown) => unknown>>>\n // Default lazy source: builds its own cache + bridge on first watch().\n // The SystemManager passes a shared mirror source instead.\n const stateSource: SliceHandleSource = opts?.stateSource\n ?? createLazyTrpcSource(api as unknown as SliceHandleApi)\n\n // ── Dispatch helpers ────────────────────────────────────────────────\n //\n // Every per-cap method below collapses to a single `dispatch(...)` /\n // `dispatchSystem(...)` call. The helpers handle three concerns\n // uniformly so the per-method code reads as a one-line declaration of\n // intent (cap + method + kind) rather than 25 lines of plumbing.\n type Kind = 'query' | 'mutation' | 'subscription'\n\n /** Merge `{deviceId, nodeId?}` into the caller-supplied input. */\n function mergeInput(input: unknown, nodeId: string | undefined): Record<string, unknown> {\n const base = typeof input === 'object' && input !== null ? input as Record<string, unknown> : {}\n return nodeId !== undefined\n ? { ...base, deviceId: binding.deviceId, nodeId }\n : { ...base, deviceId: binding.deviceId }\n }\n\n /**\n * Invoke `api.<capProp>.<method>.{query|mutate|subscribe}(merged)`.\n * Returns `any` so the caller-side per-method declaration assigns\n * cleanly into the strongly-typed `InferDeviceProxyCap<...>` shape on\n * the `DeviceProxy` interface — the proxy's contract is enforced by\n * the interface, not the dispatch helper.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function callLeaf(capProp: string, method: string, kind: Kind, merged: unknown, push: unknown): any {\n const leaf = typedApi[capProp]?.[method]\n if (!leaf) throw new Error(`DeviceProxy: api has no '${capProp}.${method}'`)\n const fn = leaf as unknown as {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n query: (i: unknown) => any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n mutate: (i: unknown) => any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n subscribe: (i: unknown, push: unknown) => any\n }\n if (kind === 'mutation') return fn.mutate(merged)\n if (kind === 'subscription') return fn.subscribe(merged, push)\n return fn.query(merged)\n }\n\n /**\n * Device-scoped cap dispatch. Looks up the binding entry for `capName`\n * to pin the call to the worker that owns the per-device provider; when\n * no entry exists (cluster-wide singletons like `zones` /\n * `zone-rules` / `audio-metrics` that don't register per-device\n * natives), nodeId is omitted and the cap-router's `resolveProvider`\n * falls through to the local provider — a Moleculer bridge proxy when\n * the actual singleton lives in a worker.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function dispatch(capName: string, capProp: string, method: string, kind: Kind, input?: unknown, push?: unknown): any {\n const entry = binding.entries.find((e) => e.capName === capName)\n return callLeaf(capProp, method, kind, mergeInput(input, entry?.providerNodeId), push)\n }\n\n /**\n * System-cap dispatch. No binding gate — system caps are cluster-wide\n * singletons; the nodeId is left absent so caps that load-balance (e.g.\n * `pipeline-runner`) can resolve their own target node.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function dispatchSystem(capProp: string, method: string, kind: Kind, input?: unknown, push?: unknown): any {\n return callLeaf(capProp, method, kind, mergeInput(input, undefined), push)\n }\n\n const accessoriesInterface = {\n getStatus: (input?: unknown) => dispatch('accessories', 'accessories', 'getStatus', 'query', input),\n }\n\n const audioAnalysisInterface = {\n resolveDeviceSettings: (input?: unknown) => dispatch('audio-analysis', 'audioAnalysis', 'resolveDeviceSettings', 'query', input),\n getDeviceSettingsContribution: (input?: unknown) => dispatch('audio-analysis', 'audioAnalysis', 'getDeviceSettingsContribution', 'query', input),\n getDeviceLiveContribution: (input?: unknown) => dispatch('audio-analysis', 'audioAnalysis', 'getDeviceLiveContribution', 'query', input),\n applyDeviceSettingsPatch: (input?: unknown) => dispatch('audio-analysis', 'audioAnalysis', 'applyDeviceSettingsPatch', 'mutation', input),\n }\n\n const audioMetricsInterface = {\n getCurrentSnapshot: (input?: unknown) => dispatch('audio-metrics', 'audioMetrics', 'getCurrentSnapshot', 'query', input),\n getHistory: (input?: unknown) => dispatch('audio-metrics', 'audioMetrics', 'getHistory', 'query', input),\n }\n\n const batteryInterface = {\n getStatus: (input?: unknown) => dispatch('battery', 'battery', 'getStatus', 'query', input),\n }\n\n const brightnessInterface = {\n setBrightness: (input?: unknown) => dispatch('brightness', 'brightness', 'setBrightness', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('brightness', 'brightness', 'getStatus', 'query', input),\n }\n\n const cameraCredentialsInterface = {\n getCredentials: (input?: unknown) => dispatch('camera-credentials', 'cameraCredentials', 'getCredentials', 'query', input),\n getStatus: (input?: unknown) => dispatch('camera-credentials', 'cameraCredentials', 'getStatus', 'query', input),\n }\n\n const cameraStreamsInterface = {\n getCameraStreams: (input?: unknown) => dispatch('camera-streams', 'cameraStreams', 'getCameraStreams', 'query', input),\n getBrokerStreams: (input?: unknown) => dispatch('camera-streams', 'cameraStreams', 'getBrokerStreams', 'query', input),\n getRtspEntries: (input?: unknown) => dispatch('camera-streams', 'cameraStreams', 'getRtspEntries', 'query', input),\n }\n\n const detectionPipelineInterface = {\n getDeviceSettingsContribution: (input?: unknown) => dispatch('detection-pipeline', 'detectionPipeline', 'getDeviceSettingsContribution', 'query', input),\n getDeviceLiveContribution: (input?: unknown) => dispatch('detection-pipeline', 'detectionPipeline', 'getDeviceLiveContribution', 'query', input),\n applyDeviceSettingsPatch: (input?: unknown) => dispatch('detection-pipeline', 'detectionPipeline', 'applyDeviceSettingsPatch', 'mutation', input),\n }\n\n const deviceDiscoveryInterface = {\n listDiscovered: (input?: unknown) => dispatch('device-discovery', 'deviceDiscovery', 'listDiscovered', 'query', input),\n refreshDiscovery: (input?: unknown) => dispatch('device-discovery', 'deviceDiscovery', 'refreshDiscovery', 'mutation', input),\n adoptDevice: (input?: unknown) => dispatch('device-discovery', 'deviceDiscovery', 'adoptDevice', 'mutation', input),\n releaseDevice: (input?: unknown) => dispatch('device-discovery', 'deviceDiscovery', 'releaseDevice', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('device-discovery', 'deviceDiscovery', 'getStatus', 'query', input),\n }\n\n const deviceOpsInterface = {\n getStreamSources: (input?: unknown) => dispatch('device-ops', 'deviceOps', 'getStreamSources', 'query', input),\n getConfigEntries: (input?: unknown) => dispatch('device-ops', 'deviceOps', 'getConfigEntries', 'query', input),\n setConfig: (input?: unknown) => dispatch('device-ops', 'deviceOps', 'setConfig', 'mutation', input),\n removeDevice: (input?: unknown) => dispatch('device-ops', 'deviceOps', 'removeDevice', 'mutation', input),\n getSettingsSchema: (input?: unknown) => dispatch('device-ops', 'deviceOps', 'getSettingsSchema', 'query', input),\n }\n\n const deviceStatusInterface = {\n getStatus: (input?: unknown) => dispatch('device-status', 'deviceStatus', 'getStatus', 'query', input),\n }\n\n const doorbellInterface = {\n getStatus: (input?: unknown) => dispatch('doorbell', 'doorbell', 'getStatus', 'query', input),\n }\n\n const eventsInterface = {\n getEvents: (input?: unknown) => dispatch('events', 'events', 'getEvents', 'query', input),\n getEventThumbnail: (input?: unknown) => dispatch('events', 'events', 'getEventThumbnail', 'query', input),\n getEventClipUrl: (input?: unknown) => dispatch('events', 'events', 'getEventClipUrl', 'query', input),\n }\n\n const featureProbeInterface = {\n getStatus: (input?: unknown) => dispatch('feature-probe', 'featureProbe', 'getStatus', 'query', input),\n }\n\n const intercomInterface = {\n startSession: (input?: unknown) => dispatch('intercom', 'intercom', 'startSession', 'mutation', input),\n handleAnswer: (input?: unknown) => dispatch('intercom', 'intercom', 'handleAnswer', 'mutation', input),\n stopSession: (input?: unknown) => dispatch('intercom', 'intercom', 'stopSession', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('intercom', 'intercom', 'getStatus', 'query', input),\n }\n\n const motionInterface = {\n isDetected: (input?: unknown) => dispatch('motion', 'motion', 'isDetected', 'query', input),\n getStatus: (input?: unknown) => dispatch('motion', 'motion', 'getStatus', 'query', input),\n }\n\n const motionDetectionInterface = {\n analyze: (input?: unknown) => dispatch('motion-detection', 'motionDetection', 'analyze', 'mutation', input),\n removeCamera: (input?: unknown) => dispatch('motion-detection', 'motionDetection', 'removeCamera', 'mutation', input),\n reset: (input?: unknown) => dispatch('motion-detection', 'motionDetection', 'reset', 'mutation', input),\n getDeviceSettingsContribution: (input?: unknown) => dispatch('motion-detection', 'motionDetection', 'getDeviceSettingsContribution', 'query', input),\n getDeviceLiveContribution: (input?: unknown) => dispatch('motion-detection', 'motionDetection', 'getDeviceLiveContribution', 'query', input),\n applyDeviceSettingsPatch: (input?: unknown) => dispatch('motion-detection', 'motionDetection', 'applyDeviceSettingsPatch', 'mutation', input),\n }\n\n const motionTriggerInterface = {\n setMotionTrigger: (input?: unknown) => dispatch('motion-trigger', 'motionTrigger', 'setMotionTrigger', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('motion-trigger', 'motionTrigger', 'getStatus', 'query', input),\n }\n\n const nativeObjectDetectionInterface = {\n getStatus: (input?: unknown) => dispatch('native-object-detection', 'nativeObjectDetection', 'getStatus', 'query', input),\n }\n\n const osdInterface = {\n setOverlay: (input?: unknown) => dispatch('osd', 'osd', 'setOverlay', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('osd', 'osd', 'getStatus', 'query', input),\n }\n\n const pipelineAnalyticsInterface = {\n getActiveTracks: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getActiveTracks', 'query', input),\n getTrack: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getTrack', 'query', input),\n listTracks: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'listTracks', 'query', input),\n clearTracks: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'clearTracks', 'mutation', input),\n getMotionEvents: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getMotionEvents', 'query', input),\n getObjectEvents: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getObjectEvents', 'query', input),\n getAudioEvents: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getAudioEvents', 'query', input),\n getEventMedia: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getEventMedia', 'query', input),\n getTrackMedia: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getTrackMedia', 'query', input),\n getDeviceSettingsContribution: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getDeviceSettingsContribution', 'query', input),\n getDeviceLiveContribution: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'getDeviceLiveContribution', 'query', input),\n applyDeviceSettingsPatch: (input?: unknown) => dispatch('pipeline-analytics', 'pipelineAnalytics', 'applyDeviceSettingsPatch', 'mutation', input),\n }\n\n const ptzInterface = {\n move: (input?: unknown) => dispatch('ptz', 'ptz', 'move', 'mutation', input),\n continuousMove: (input?: unknown) => dispatch('ptz', 'ptz', 'continuousMove', 'mutation', input),\n stop: (input?: unknown) => dispatch('ptz', 'ptz', 'stop', 'mutation', input),\n getPresets: (input?: unknown) => dispatch('ptz', 'ptz', 'getPresets', 'query', input),\n goToPreset: (input?: unknown) => dispatch('ptz', 'ptz', 'goToPreset', 'mutation', input),\n goHome: (input?: unknown) => dispatch('ptz', 'ptz', 'goHome', 'mutation', input),\n getPosition: (input?: unknown) => dispatch('ptz', 'ptz', 'getPosition', 'query', input),\n getStatus: (input?: unknown) => dispatch('ptz', 'ptz', 'getStatus', 'query', input),\n }\n\n const ptzAutotrackInterface = {\n getStatus: (input?: unknown) => dispatch('ptz-autotrack', 'ptzAutotrack', 'getStatus', 'query', input),\n setEnabled: (input?: unknown) => dispatch('ptz-autotrack', 'ptzAutotrack', 'setEnabled', 'mutation', input),\n getSettings: (input?: unknown) => dispatch('ptz-autotrack', 'ptzAutotrack', 'getSettings', 'query', input),\n setSettings: (input?: unknown) => dispatch('ptz-autotrack', 'ptzAutotrack', 'setSettings', 'mutation', input),\n }\n\n const rebootInterface = {\n reboot: (input?: unknown) => dispatch('reboot', 'reboot', 'reboot', 'mutation', input),\n }\n\n const recordingInterface = {\n getSegments: (input?: unknown) => dispatch('recording', 'recording', 'getSegments', 'query', input),\n getPlaybackUrl: (input?: unknown) => dispatch('recording', 'recording', 'getPlaybackUrl', 'query', input),\n getThumbnailAt: (input?: unknown) => dispatch('recording', 'recording', 'getThumbnailAt', 'query', input),\n }\n\n const snapshotInterface = {\n getSnapshot: (input?: unknown) => dispatch('snapshot', 'snapshot', 'getSnapshot', 'query', input),\n invalidateCache: (input?: unknown) => dispatch('snapshot', 'snapshot', 'invalidateCache', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('snapshot', 'snapshot', 'getStatus', 'query', input),\n getDeviceSettingsContribution: (input?: unknown) => dispatch('snapshot', 'snapshot', 'getDeviceSettingsContribution', 'query', input),\n getDeviceLiveContribution: (input?: unknown) => dispatch('snapshot', 'snapshot', 'getDeviceLiveContribution', 'query', input),\n applyDeviceSettingsPatch: (input?: unknown) => dispatch('snapshot', 'snapshot', 'applyDeviceSettingsPatch', 'mutation', input),\n }\n\n const switchInterface = {\n setState: (input?: unknown) => dispatch('switch', 'switch', 'setState', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('switch', 'switch', 'getStatus', 'query', input),\n }\n\n const webrtcSessionInterface = {\n listStreams: (input?: unknown) => dispatch('webrtc-session', 'webrtcSession', 'listStreams', 'query', input),\n createSession: (input?: unknown) => dispatch('webrtc-session', 'webrtcSession', 'createSession', 'mutation', input),\n handleAnswer: (input?: unknown) => dispatch('webrtc-session', 'webrtcSession', 'handleAnswer', 'mutation', input),\n closeSession: (input?: unknown) => dispatch('webrtc-session', 'webrtcSession', 'closeSession', 'mutation', input),\n hasAdaptiveBitrate: (input?: unknown) => dispatch('webrtc-session', 'webrtcSession', 'hasAdaptiveBitrate', 'query', input),\n }\n\n const zoneAnalyticsInterface = {\n getCurrentSnapshot: (input?: unknown) => dispatch('zone-analytics', 'zoneAnalytics', 'getCurrentSnapshot', 'query', input),\n getZoneHistory: (input?: unknown) => dispatch('zone-analytics', 'zoneAnalytics', 'getZoneHistory', 'query', input),\n getCameraHistory: (input?: unknown) => dispatch('zone-analytics', 'zoneAnalytics', 'getCameraHistory', 'query', input),\n getUnzonedHistory: (input?: unknown) => dispatch('zone-analytics', 'zoneAnalytics', 'getUnzonedHistory', 'query', input),\n }\n\n const zoneRulesInterface = {\n listRules: (input?: unknown) => dispatch('zone-rules', 'zoneRules', 'listRules', 'query', input),\n setRules: (input?: unknown) => dispatch('zone-rules', 'zoneRules', 'setRules', 'mutation', input),\n }\n\n const zonesInterface = {\n listZones: (input?: unknown) => dispatch('zones', 'zones', 'listZones', 'query', input),\n addZone: (input?: unknown) => dispatch('zones', 'zones', 'addZone', 'mutation', input),\n removeZone: (input?: unknown) => dispatch('zones', 'zones', 'removeZone', 'mutation', input),\n updateZone: (input?: unknown) => dispatch('zones', 'zones', 'updateZone', 'mutation', input),\n }\n\n const addonSettingsInterface = {\n getDeviceSettings: (input?: unknown) => dispatchSystem('addonSettings', 'getDeviceSettings', 'query', input),\n updateDeviceSettings: (input?: unknown) => dispatchSystem('addonSettings', 'updateDeviceSettings', 'mutation', input),\n }\n\n const deviceManagerInterface = {\n loadConfig: (input?: unknown) => dispatchSystem('deviceManager', 'loadConfig', 'query', input),\n loadRuntimeState: (input?: unknown) => dispatchSystem('deviceManager', 'loadRuntimeState', 'query', input),\n loadMeta: (input?: unknown) => dispatchSystem('deviceManager', 'loadMeta', 'query', input),\n setName: (input?: unknown) => dispatchSystem('deviceManager', 'setName', 'mutation', input),\n setLocation: (input?: unknown) => dispatchSystem('deviceManager', 'setLocation', 'mutation', input),\n setMetadata: (input?: unknown) => dispatchSystem('deviceManager', 'setMetadata', 'mutation', input),\n setDisabled: (input?: unknown) => dispatchSystem('deviceManager', 'setDisabled', 'mutation', input),\n getDevice: (input?: unknown) => dispatchSystem('deviceManager', 'getDevice', 'query', input),\n getStreamSources: (input?: unknown) => dispatchSystem('deviceManager', 'getStreamSources', 'query', input),\n getConfigSchema: (input?: unknown) => dispatchSystem('deviceManager', 'getConfigSchema', 'query', input),\n getSettingsSchema: (input?: unknown) => dispatchSystem('deviceManager', 'getSettingsSchema', 'query', input),\n updateConfig: (input?: unknown) => dispatchSystem('deviceManager', 'updateConfig', 'mutation', input),\n enable: (input?: unknown) => dispatchSystem('deviceManager', 'enable', 'mutation', input),\n disable: (input?: unknown) => dispatchSystem('deviceManager', 'disable', 'mutation', input),\n remove: (input?: unknown) => dispatchSystem('deviceManager', 'remove', 'mutation', input),\n getStreamProfileMap: (input?: unknown) => dispatchSystem('deviceManager', 'getStreamProfileMap', 'query', input),\n setStreamProfileMap: (input?: unknown) => dispatchSystem('deviceManager', 'setStreamProfileMap', 'mutation', input),\n probeStreams: (input?: unknown) => dispatchSystem('deviceManager', 'probeStreams', 'mutation', input),\n getBindings: (input?: unknown) => dispatchSystem('deviceManager', 'getBindings', 'query', input),\n getAllBindings: (input?: unknown) => dispatchSystem('deviceManager', 'getAllBindings', 'query', input),\n setWrapperActive: (input?: unknown) => dispatchSystem('deviceManager', 'setWrapperActive', 'mutation', input),\n getDeviceSettingsAggregate: (input?: unknown) => dispatchSystem('deviceManager', 'getDeviceSettingsAggregate', 'query', input),\n getDeviceLiveInfoAggregate: (input?: unknown) => dispatchSystem('deviceManager', 'getDeviceLiveInfoAggregate', 'query', input),\n getDeviceAggregate: (input?: unknown) => dispatchSystem('deviceManager', 'getDeviceAggregate', 'query', input),\n updateDeviceField: (input?: unknown) => dispatchSystem('deviceManager', 'updateDeviceField', 'mutation', input),\n updateDeviceFieldsBatch: (input?: unknown) => dispatchSystem('deviceManager', 'updateDeviceFieldsBatch', 'mutation', input),\n testField: (input?: unknown) => dispatchSystem('deviceManager', 'testField', 'mutation', input),\n getDeviceStatusAggregate: (input?: unknown) => dispatchSystem('deviceManager', 'getDeviceStatusAggregate', 'query', input),\n }\n\n const deviceStateInterface = {\n getSnapshot: (input?: unknown) => dispatchSystem('deviceState', 'getSnapshot', 'query', input),\n getCapSlice: (input?: unknown) => dispatchSystem('deviceState', 'getCapSlice', 'query', input),\n setCapSlice: (input?: unknown) => dispatchSystem('deviceState', 'setCapSlice', 'mutation', input),\n }\n\n const networkQualityInterface = {\n getDeviceStats: (input?: unknown) => dispatchSystem('networkQuality', 'getDeviceStats', 'query', input),\n reportClientStats: (input?: unknown) => dispatchSystem('networkQuality', 'reportClientStats', 'mutation', input),\n }\n\n const pipelineExecutorInterface = {\n runPipeline: (input?: unknown) => dispatchSystem('pipelineExecutor', 'runPipeline', 'mutation', input),\n runPipelineBatch: (input?: unknown) => dispatchSystem('pipelineExecutor', 'runPipelineBatch', 'mutation', input),\n }\n\n const pipelineOrchestratorInterface = {\n assignPipeline: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'assignPipeline', 'mutation', input),\n unassignPipeline: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'unassignPipeline', 'mutation', input),\n getPipelineAssignment: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getPipelineAssignment', 'query', input),\n getCameraMetrics: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getCameraMetrics', 'query', input),\n assignDecoder: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'assignDecoder', 'mutation', input),\n unassignDecoder: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'unassignDecoder', 'mutation', input),\n assignAudio: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'assignAudio', 'mutation', input),\n unassignAudio: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'unassignAudio', 'mutation', input),\n getAudioAssignment: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getAudioAssignment', 'query', input),\n getAudioAssignments: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getAudioAssignments', 'query', input),\n getDecoderAssignment: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getDecoderAssignment', 'query', input),\n getCameraSettings: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getCameraSettings', 'query', input),\n setCameraStepToggle: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'setCameraStepToggle', 'mutation', input),\n getCameraStepOverrides: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getCameraStepOverrides', 'query', input),\n setCameraStepOverride: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'setCameraStepOverride', 'mutation', input),\n setCameraPipelineForAgent: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'setCameraPipelineForAgent', 'mutation', input),\n resolvePipeline: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'resolvePipeline', 'query', input),\n getDeviceSettingsContribution: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getDeviceSettingsContribution', 'query', input),\n getDeviceLiveContribution: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'getDeviceLiveContribution', 'query', input),\n applyDeviceSettingsPatch: (input?: unknown) => dispatchSystem('pipelineOrchestrator', 'applyDeviceSettingsPatch', 'mutation', input),\n }\n\n const pipelineRunnerInterface = {\n detachCamera: (input?: unknown) => dispatchSystem('pipelineRunner', 'detachCamera', 'mutation', input),\n getCameraMetrics: (input?: unknown) => dispatchSystem('pipelineRunner', 'getCameraMetrics', 'query', input),\n }\n\n const recordingEngineInterface = {\n getPolicyStatus: (input?: unknown) => dispatchSystem('recordingEngine', 'getPolicyStatus', 'query', input),\n }\n\n const snapshotProviderInterface = {\n supportsDevice: (input?: unknown) => dispatchSystem('snapshotProvider', 'supportsDevice', 'query', input),\n getSnapshot: (input?: unknown) => dispatchSystem('snapshotProvider', 'getSnapshot', 'query', input),\n }\n\n const streamBrokerInterface = {\n publishCameraStream: (input?: unknown) => dispatchSystem('streamBroker', 'publishCameraStream', 'mutation', input),\n retractCameraStream: (input?: unknown) => dispatchSystem('streamBroker', 'retractCameraStream', 'mutation', input),\n assignProfile: (input?: unknown) => dispatchSystem('streamBroker', 'assignProfile', 'mutation', input),\n unassignProfile: (input?: unknown) => dispatchSystem('streamBroker', 'unassignProfile', 'mutation', input),\n restartProfile: (input?: unknown) => dispatchSystem('streamBroker', 'restartProfile', 'mutation', input),\n getDeviceSettingsContribution: (input?: unknown) => dispatchSystem('streamBroker', 'getDeviceSettingsContribution', 'query', input),\n getDeviceLiveContribution: (input?: unknown) => dispatchSystem('streamBroker', 'getDeviceLiveContribution', 'query', input),\n applyDeviceSettingsPatch: (input?: unknown) => dispatchSystem('streamBroker', 'applyDeviceSettingsPatch', 'mutation', input),\n }\n\n return {\n deviceId: binding.deviceId,\n binding,\n state: {\n audioMetrics: createSliceHandle<InferRuntimeState<typeof audioMetricsCapability>>(stateSource, binding.deviceId, 'audio-metrics'),\n battery: createSliceHandle<InferRuntimeState<typeof batteryCapability>>(stateSource, binding.deviceId, 'battery'),\n brightness: createSliceHandle<InferRuntimeState<typeof brightnessCapability>>(stateSource, binding.deviceId, 'brightness'),\n cameraStreams: createSliceHandle<InferRuntimeState<typeof cameraStreamsCapability>>(stateSource, binding.deviceId, 'camera-streams'),\n deviceDiscovery: createSliceHandle<InferRuntimeState<typeof deviceDiscoveryCapability>>(stateSource, binding.deviceId, 'device-discovery'),\n deviceStatus: createSliceHandle<InferRuntimeState<typeof deviceStatusCapability>>(stateSource, binding.deviceId, 'device-status'),\n doorbell: createSliceHandle<InferRuntimeState<typeof doorbellCapability>>(stateSource, binding.deviceId, 'doorbell'),\n featureProbe: createSliceHandle<InferRuntimeState<typeof featureProbeCapability>>(stateSource, binding.deviceId, 'feature-probe'),\n motion: createSliceHandle<InferRuntimeState<typeof motionCapability>>(stateSource, binding.deviceId, 'motion'),\n motionTrigger: createSliceHandle<InferRuntimeState<typeof motionTriggerCapability>>(stateSource, binding.deviceId, 'motion-trigger'),\n ptzAutotrack: createSliceHandle<InferRuntimeState<typeof ptzAutotrackCapability>>(stateSource, binding.deviceId, 'ptz-autotrack'),\n switch: createSliceHandle<InferRuntimeState<typeof switchCapability>>(stateSource, binding.deviceId, 'switch'),\n zoneAnalytics: createSliceHandle<InferRuntimeState<typeof zoneAnalyticsCapability>>(stateSource, binding.deviceId, 'zone-analytics'),\n zoneRules: createSliceHandle<InferRuntimeState<typeof zoneRulesCapability>>(stateSource, binding.deviceId, 'zone-rules'),\n zones: createSliceHandle<InferRuntimeState<typeof zonesCapability>>(stateSource, binding.deviceId, 'zones'),\n },\n accessories: accessoriesInterface,\n audioAnalysis: audioAnalysisInterface,\n audioMetrics: audioMetricsInterface,\n battery: batteryInterface,\n brightness: brightnessInterface,\n cameraCredentials: cameraCredentialsInterface,\n cameraStreams: cameraStreamsInterface,\n detectionPipeline: detectionPipelineInterface,\n deviceDiscovery: deviceDiscoveryInterface,\n deviceOps: deviceOpsInterface,\n deviceStatus: deviceStatusInterface,\n doorbell: doorbellInterface,\n events: eventsInterface,\n featureProbe: featureProbeInterface,\n intercom: intercomInterface,\n motion: motionInterface,\n motionDetection: motionDetectionInterface,\n motionTrigger: motionTriggerInterface,\n nativeObjectDetection: nativeObjectDetectionInterface,\n osd: osdInterface,\n pipelineAnalytics: pipelineAnalyticsInterface,\n ptz: ptzInterface,\n ptzAutotrack: ptzAutotrackInterface,\n reboot: rebootInterface,\n recording: recordingInterface,\n snapshot: snapshotInterface,\n switch: switchInterface,\n webrtcSession: webrtcSessionInterface,\n zoneAnalytics: zoneAnalyticsInterface,\n zoneRules: zoneRulesInterface,\n zones: zonesInterface,\n addonSettings: addonSettingsInterface,\n deviceManager: deviceManagerInterface,\n deviceState: deviceStateInterface,\n networkQuality: networkQualityInterface,\n pipelineExecutor: pipelineExecutorInterface,\n pipelineOrchestrator: pipelineOrchestratorInterface,\n pipelineRunner: pipelineRunnerInterface,\n recordingEngine: recordingEngineInterface,\n snapshotProvider: snapshotProviderInterface,\n streamBroker: streamBrokerInterface,\n }\n}\n","/**\n * Pure rules-driven zone evaluator. Shared between every consumer\n * that gates items (motion regions, detections, future audio events,\n * …) by `(zones, rules)` pairs. Lives in `@camstack/types/utils` so\n * addon-motion-wasm + addon-detection-pipeline share one canonical\n * implementation.\n *\n * Semantics — match the analytics zone-engine introduced in Phase 2a:\n * - any active include rule fires ⇒ whitelist mode (only items\n * satisfying at least one include rule pass)\n * - otherwise ⇒ blacklist mode (items in any exclude rule are\n * dropped, the rest pass)\n * - inactive rules (`enabled: false`) are skipped before the gate\n * - a rule's `classFilter` narrows it to the listed classes; an\n * item whose class isn't in the filter is invisible to that rule\n *\n * Test point: each item provides a normalised (0–1) center via the\n * `getCenter` accessor; rules fire when the center lies inside any\n * of the rule's referenced zone polygons (ray-cast point-in-polygon).\n * Bbox-area overlap would be marginally more intuitive on tiny\n * items but doubles the per-frame cost; the center test keeps the\n * hot path cheap and matches the operator's intuition for\n * \"where is the activity centered\".\n */\nimport type { Zone } from '../capabilities/zones.cap.js'\nimport type { ZoneRule } from '../capabilities/schemas/zone-rule.js'\n\nexport interface ZoneRuleEvalResult<T> {\n readonly passed: readonly T[]\n readonly excluded: readonly T[]\n}\n\n/**\n * Evaluate `rules` against `items`. Returns the items partitioned\n * into `passed` (kept by the gate) and `excluded` (dropped). When\n * `rules` is empty or `zones` is empty everything passes — the gate\n * is \"off\" without explicit configuration.\n *\n * `getCenter` returns the item's normalised (0–1) center point.\n * `getClassName` is optional — when omitted, every rule's\n * `classFilter` is treated as matching all classes (motion-stage\n * semantics). Provide it for object detections so per-class rules\n * narrow correctly.\n */\nexport function evaluateZoneRules<T>(\n items: readonly T[],\n zones: readonly Zone[],\n rules: readonly ZoneRule[],\n getCenter: (item: T) => { readonly x: number; readonly y: number },\n getClassName?: (item: T) => string | undefined,\n): ZoneRuleEvalResult<T> {\n if (rules.length === 0 || zones.length === 0) {\n return { passed: items, excluded: [] }\n }\n const activeRules = rules.filter(r => r.enabled !== false)\n const includeRules = activeRules.filter(r => r.mode === 'include')\n const excludeRules = activeRules.filter(r => r.mode === 'exclude')\n const whitelistMode = includeRules.length > 0\n const zonesById = new Map(zones.map(z => [z.id, z]))\n\n const passed: T[] = []\n const excluded: T[] = []\n\n for (const item of items) {\n const center = getCenter(item)\n const className = getClassName?.(item)\n const inInclude = includeRules.some(r => ruleApplies(r, center, className, zonesById))\n const inExclude = excludeRules.some(r => ruleApplies(r, center, className, zonesById))\n if (whitelistMode) {\n if (inInclude && !inExclude) passed.push(item)\n else excluded.push(item)\n } else {\n if (inExclude) excluded.push(item)\n else passed.push(item)\n }\n }\n return { passed, excluded }\n}\n\nfunction ruleApplies(\n rule: ZoneRule,\n center: { readonly x: number; readonly y: number },\n className: string | undefined,\n zonesById: ReadonlyMap<string, Zone>,\n): boolean {\n // Class narrowing — when className is undefined (motion stage),\n // we treat the filter as matching everything. When the item has a\n // class, missing it from the filter excludes the rule.\n if (rule.classFilter && rule.classFilter.length > 0) {\n if (className !== undefined && !rule.classFilter.includes(className)) return false\n }\n for (const zoneId of rule.zoneIds) {\n const zone = zonesById.get(zoneId)\n if (!zone) continue\n if (pointInPolygon(center, zone.polygon)) return true\n }\n return false\n}\n\n/**\n * Standard ray-casting point-in-polygon. Polygon vertices are\n * normalised (0–1); the test point is too — frame-resolution-\n * agnostic. Boundary points count as inside (treats `<` as `<=` on\n * the y-edge crossing).\n */\nfunction pointInPolygon(\n point: { readonly x: number; readonly y: number },\n polygon: ReadonlyArray<{ readonly x: number; readonly y: number }>,\n): boolean {\n if (polygon.length < 3) return false\n let inside = false\n const { x, y } = point\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const a = polygon[i]!\n const b = polygon[j]!\n const intersect =\n ((a.y > y) !== (b.y > y)) &&\n (x < ((b.x - a.x) * (y - a.y)) / (b.y - a.y || Number.EPSILON) + a.x)\n if (intersect) inside = !inside\n }\n return inside\n}\n","// AUTO-GENERATED — do not edit manually.\n// Regenerate with: npx tsx scripts/generate-system-proxy.ts\n/* eslint-disable */\n\nimport type { InferProvider } from '../capabilities/capability-definition.js'\nimport type { AddonApi } from './addon-api.js'\nimport type { addonPagesCapability } from '../capabilities/addon-pages.cap.js'\nimport type { addonsCapability } from '../capabilities/addons.cap.js'\nimport type { addonSettingsCapability } from '../capabilities/addon-settings.cap.js'\nimport type { addonWidgetsCapability } from '../capabilities/addon-widgets.cap.js'\nimport type { alertsCapability } from '../capabilities/alerts.cap.js'\nimport type { audioAnalyzerCapability } from '../capabilities/audio-analyzer.cap.js'\nimport type { audioCodecCapability } from '../capabilities/audio-codec.cap.js'\nimport type { authenticationCapability } from '../capabilities/authentication.cap.js'\nimport type { backupCapability } from '../capabilities/backup.cap.js'\nimport type { decoderCapability } from '../capabilities/decoder.cap.js'\nimport type { deviceManagerCapability } from '../capabilities/device-manager.cap.js'\nimport type { deviceProviderCapability } from '../capabilities/device-provider.cap.js'\nimport type { deviceStateCapability } from '../capabilities/device-state.cap.js'\nimport type { integrationsCapability } from '../capabilities/integrations.cap.js'\nimport type { localNetworkCapability } from '../capabilities/local-network.cap.js'\nimport type { meshNetworkCapability } from '../capabilities/mesh-network.cap.js'\nimport type { meshOrchestratorCapability } from '../capabilities/mesh-orchestrator.cap.js'\nimport type { metricsProviderCapability } from '../capabilities/metrics-provider.cap.js'\nimport type { networkQualityCapability } from '../capabilities/network-quality.cap.js'\nimport type { nodesCapability } from '../capabilities/nodes.cap.js'\nimport type { notificationOutputCapability } from '../capabilities/notification-output.cap.js'\nimport type { pipelineExecutorCapability } from '../capabilities/pipeline-executor.cap.js'\nimport type { pipelineOrchestratorCapability } from '../capabilities/pipeline-orchestrator.cap.js'\nimport type { pipelineRunnerCapability } from '../capabilities/pipeline-runner.cap.js'\nimport type { platformProbeCapability } from '../capabilities/platform-probe.cap.js'\nimport type { recordingEngineCapability } from '../capabilities/recording-engine.cap.js'\nimport type { remoteAccessCapability } from '../capabilities/remote-access.cap.js'\nimport type { settingsStoreCapability } from '../capabilities/settings-store.cap.js'\nimport type { storageCapability } from '../capabilities/storage.cap.js'\nimport type { streamBrokerCapability } from '../capabilities/stream-broker.cap.js'\nimport type { systemCapability } from '../capabilities/system.cap.js'\nimport type { toastCapability } from '../capabilities/toast.cap.js'\nimport type { turnOrchestratorCapability } from '../capabilities/turn-orchestrator.cap.js'\nimport type { turnProviderCapability } from '../capabilities/turn-provider.cap.js'\nimport type { userManagementCapability } from '../capabilities/user-management.cap.js'\n\n/**\n * Cluster-wide facade over every `scope: 'system'` capability. Each entry\n * is a typed namespace exposing only the cap's non-device-bound methods —\n * device-scoped slices already surface on `DeviceProxy`.\n *\n * Consumed by the SDK's `System` class as the source of truth for\n * `system.<cap>.<method>(input)` calls.\n */\nexport interface SystemProxy {\n readonly addonPages: Pick<InferProvider<typeof addonPagesCapability>, 'listPages'>\n readonly addons: Pick<InferProvider<typeof addonsCapability>, 'list' | 'getLogs' | 'listPackages' | 'installPackage' | 'installFromWorkspace' | 'isWorkspaceAvailable' | 'listWorkspacePackages' | 'uninstallPackage' | 'reloadPackages' | 'searchAvailable' | 'listUpdates' | 'updatePackage' | 'rollbackPackage' | 'forceRefresh' | 'restartServer' | 'getVersions' | 'restartAddon' | 'retryLoad' | 'getAutoUpdateSettings' | 'setAutoUpdateSettings' | 'getAddonAutoUpdate' | 'setAddonAutoUpdate' | 'applyAutoUpdateToAll' | 'custom' | 'onAddonLogs'>\n readonly addonSettings: Pick<InferProvider<typeof addonSettingsCapability>, 'getGlobalSettings' | 'updateGlobalSettings'>\n readonly addonWidgets: Pick<InferProvider<typeof addonWidgetsCapability>, 'listWidgets'>\n readonly alerts: Pick<InferProvider<typeof alertsCapability>, 'emit' | 'update' | 'list' | 'getUnreadCount' | 'markRead' | 'markAllRead' | 'dismiss'>\n readonly audioAnalyzer: Pick<InferProvider<typeof audioAnalyzerCapability>, 'analyseChunk' | 'classify' | 'isReady' | 'dispose' | 'reprobeAudioEngine'>\n readonly audioCodec: Pick<InferProvider<typeof audioCodecCapability>, 'listSupportedCodecs' | 'canHandle' | 'createDecodeSession' | 'createEncodeSession' | 'closeSession' | 'pushEncodedFrame' | 'pullPcm' | 'pushPcm' | 'pullEncoded' | 'flushEncode' | 'listActiveSessions'>\n readonly authentication: Pick<InferProvider<typeof authenticationCapability>, 'listProviders' | 'setProviderEnabled'>\n readonly backup: Pick<InferProvider<typeof backupCapability>, 'listDestinations' | 'trigger' | 'list' | 'listLocations' | 'getEntries' | 'restore' | 'delete' | 'listArchives' | 'upsertDestinationPolicy' | 'previewSchedule'>\n readonly decoder: Pick<InferProvider<typeof decoderCapability>, 'supportsCodec' | 'getInfo' | 'createSession' | 'destroySession' | 'pushPacket' | 'openStream' | 'pullFrames' | 'updateConfig' | 'getStats' | 'listActiveSessions' | 'reprobeHwaccel'>\n readonly deviceManager: Pick<InferProvider<typeof deviceManagerCapability>, 'allocateDeviceId' | 'registerDevice' | 'removeDevice' | 'persistConfig' | 'listLocations' | 'addLocation' | 'removeLocation' | 'listPersistedByAddon' | 'listAll' | 'getChildren' | 'listWrappersForCap' | 'listBindableCapsForDeviceType' | 'discoverDevices' | 'adoptDevice' | 'getCreationSchema' | 'createDevice' | 'testCreationField'>\n readonly deviceProvider: Pick<InferProvider<typeof deviceProviderCapability>, 'start' | 'stop' | 'getStatus' | 'getDevices' | 'supportsDiscovery' | 'discoverDevices' | 'adoptDiscoveredDevice' | 'supportsManualCreation' | 'getChildCreationSchema' | 'createDevice' | 'testCreationField'>\n readonly deviceState: Pick<InferProvider<typeof deviceStateCapability>, 'getAllSnapshots'>\n readonly integrations: Pick<InferProvider<typeof integrationsCapability>, 'list' | 'get' | 'getByAddonId' | 'create' | 'update' | 'delete' | 'getSettings' | 'setSettings' | 'getAvailableTypes' | 'testConnection'>\n readonly localNetwork: Pick<InferProvider<typeof localNetworkCapability>, 'list' | 'getPreferred' | 'getConnectionEndpoints' | 'getAllowedAddresses' | 'setAllowedAddresses' | 'resetAllowlistToBestMatch'>\n readonly meshNetwork: Pick<InferProvider<typeof meshNetworkCapability>, 'getStatus' | 'join' | 'leave' | 'listPeers' | 'setPublicIngress' | 'setMeshIngress'>\n readonly meshOrchestrator: Pick<InferProvider<typeof meshOrchestratorCapability>, 'listProviders' | 'joinProvider' | 'leaveProvider'>\n readonly metricsProvider: Pick<InferProvider<typeof metricsProviderCapability>, 'collectSnapshot' | 'getCached' | 'getCurrent' | 'getDiskSpace' | 'getGpuInfo' | 'getCpuTemperature' | 'getProcessStats' | 'listAddonInstances' | 'getAddonStats' | 'listNodeProcesses' | 'killProcess'>\n readonly networkQuality: Pick<InferProvider<typeof networkQualityCapability>, 'getAllStats'>\n readonly nodes: Pick<InferProvider<typeof nodesCapability>, 'topology' | 'deployAddon' | 'undeployAddon' | 'restartAddon' | 'restartProcess' | 'restartNode' | 'shutdownNode' | 'renameNode' | 'clusterAddonStatus' | 'setProcessLogLevel' | 'executeQuery'>\n readonly notificationOutput: Pick<InferProvider<typeof notificationOutputCapability>, 'send' | 'sendTest'>\n readonly pipelineExecutor: Pick<InferProvider<typeof pipelineExecutorCapability>, 'getAvailableEngines' | 'getSelectedEngine' | 'getDefaultSteps' | 'reprobeEngine' | 'getVideoPipelineSteps' | 'setVideoPipelineSteps' | 'getSchema' | 'getGlobalSteps' | 'getGlobalPipelineConfig' | 'getOrchestratorConfigSchema' | 'listTemplates' | 'saveTemplate' | 'updateTemplate' | 'deleteTemplate' | 'getCapabilities' | 'getAddonModels' | 'downloadModel' | 'deleteModel' | 'detect' | 'cacheFrameInPool' | 'inferCached' | 'uncacheFrame' | 'getEffectiveTuning' | 'listLoadedEngines' | 'spinEngine' | 'killEngine' | 'listReferenceImages' | 'getReferenceImage' | 'getReferenceAudioFiles' | 'getReferenceAudio' | 'getAudioCapabilities' | 'runAudioTest' | 'getDetectionConfigSchema'>\n readonly pipelineOrchestrator: Pick<InferProvider<typeof pipelineOrchestratorCapability>, 'rebalance' | 'getPipelineAssignments' | 'getAgentLoad' | 'getGlobalMetrics' | 'getCapabilityBindings' | 'setCapabilityBinding' | 'getDecoderAssignments' | 'getAudioNodeLoad' | 'getAgentSettings' | 'listAgentSettings' | 'setAgentAddonDefaults' | 'removeAgentSettings' | 'listTemplates' | 'saveTemplate' | 'updateTemplate' | 'deleteTemplate'>\n readonly pipelineRunner: Pick<InferProvider<typeof pipelineRunnerCapability>, 'attachCamera' | 'reportMotion' | 'getLocalLoad' | 'getLocalMetrics' | 'getAllCameraMetrics' | 'getLocalCameras'>\n readonly platformProbe: Pick<InferProvider<typeof platformProbeCapability>, 'getCapabilities' | 'getHardware' | 'resolveInferenceConfig' | 'resolveHwAccel'>\n readonly recordingEngine: Pick<InferProvider<typeof recordingEngineCapability>, 'getStatus' | 'enable' | 'disable' | 'getConfig' | 'updateConfig' | 'getPlaylist' | 'getThumbnail' | 'getSegments' | 'getAvailability' | 'estimateStorage' | 'estimateGlobalStorage' | 'getStorageUsage' | 'setPolicy' | 'getPolicy' | 'getRetentionConfig' | 'updateRetentionConfig' | 'getMotionStats'>\n readonly remoteAccess: Pick<InferProvider<typeof remoteAccessCapability>, 'listProviders' | 'startProvider' | 'stopProvider'>\n readonly settingsStore: Pick<InferProvider<typeof settingsStoreCapability>, 'get' | 'set' | 'query' | 'insert' | 'update' | 'delete' | 'count' | 'isEmpty' | 'declareCollection'>\n readonly storage: Pick<InferProvider<typeof storageCapability>, 'resolve' | 'write' | 'read' | 'exists' | 'list' | 'delete' | 'getAvailableSpace' | 'beginUpload' | 'writeChunk' | 'finalizeUpload' | 'abortUpload' | 'beginDownload' | 'readChunk' | 'endDownload' | 'listLocations' | 'getDefaultLocation' | 'upsertLocation' | 'deleteLocation' | 'testLocation' | 'listProviders' | 'testConfig'>\n readonly streamBroker: Pick<InferProvider<typeof streamBrokerCapability>, 'listAllCameraStreams' | 'listAllProfileSlots' | 'getBrokerStats' | 'listClients' | 'killClient' | 'getStreamUrl' | 'getBroker' | 'setPreBufferDuration' | 'getPreBufferInfo' | 'getRtspPort' | 'getAllRtspEntries' | 'getRtspEntry' | 'regenerateRtspToken' | 'setRtspEnabled' | 'isRtspEnabled'>\n readonly system: Pick<InferProvider<typeof systemCapability>, 'info' | 'health' | 'featureFlags' | 'networkAddresses' | 'getRetentionConfig' | 'setRetentionConfig' | 'forceRetentionCleanup'>\n readonly toast: Pick<InferProvider<typeof toastCapability>, 'onToast'>\n readonly turnOrchestrator: Pick<InferProvider<typeof turnOrchestratorCapability>, 'listProviders' | 'getAllServers' | 'setProviderEnabled'>\n readonly turnProvider: Pick<InferProvider<typeof turnProviderCapability>, 'getTurnServers'>\n readonly userManagement: Pick<InferProvider<typeof userManagementCapability>, 'listUsers' | 'createUser' | 'updateUser' | 'deleteUser' | 'resetPassword' | 'validateCredentials' | 'listApiKeys' | 'createApiKey' | 'revokeApiKey' | 'validateApiKey' | 'createScopedToken' | 'revokeScopedToken' | 'validateScopedToken' | 'listScopedTokens'>\n}\n\n/**\n * Build a `SystemProxy` that dispatches every namespace method through\n * the existing system-cap tRPC procedures (`api.<capProp>.<method>.{query,mutate,subscribe}`).\n *\n * Pure function — no caching, no live state. The caller (typically\n * `System`) owns the `AddonApi` instance and disposes the proxy by\n * dropping the reference.\n */\nexport function createSystemProxy(api: AddonApi): SystemProxy {\n const typedApi = api as unknown as Record<string, Record<string, Record<string, (input?: unknown) => unknown>>>\n\n type Kind = 'query' | 'mutation' | 'subscription'\n\n /**\n * Invoke `api.<capProp>.<method>.{query|mutate|subscribe}(input)`.\n * Returns `any` so the caller-side per-method declaration assigns\n * cleanly into the strongly-typed `Pick<InferProvider<...>, ...>`\n * shape on the `SystemProxy` interface — the proxy's contract is\n * enforced by the interface, not the dispatch helper.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function dispatch(capProp: string, method: string, kind: Kind, input?: unknown, push?: unknown): any {\n const leaf = typedApi[capProp]?.[method]\n if (!leaf) throw new Error(`SystemProxy: api has no '${capProp}.${method}'`)\n const fn = leaf as unknown as {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n query: (i: unknown) => any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n mutate: (i: unknown) => any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n subscribe: (i: unknown, push: unknown) => any\n }\n if (kind === 'mutation') return fn.mutate(input)\n if (kind === 'subscription') return fn.subscribe(input, push)\n return fn.query(input)\n }\n\n const addonPagesInterface = {\n listPages: (input?: unknown) => dispatch('addonPages', 'listPages', 'query', input),\n }\n\n const addonsInterface = {\n list: (input?: unknown) => dispatch('addons', 'list', 'query', input),\n getLogs: (input?: unknown) => dispatch('addons', 'getLogs', 'query', input),\n listPackages: (input?: unknown) => dispatch('addons', 'listPackages', 'query', input),\n installPackage: (input?: unknown) => dispatch('addons', 'installPackage', 'mutation', input),\n installFromWorkspace: (input?: unknown) => dispatch('addons', 'installFromWorkspace', 'mutation', input),\n isWorkspaceAvailable: (input?: unknown) => dispatch('addons', 'isWorkspaceAvailable', 'query', input),\n listWorkspacePackages: (input?: unknown) => dispatch('addons', 'listWorkspacePackages', 'query', input),\n uninstallPackage: (input?: unknown) => dispatch('addons', 'uninstallPackage', 'mutation', input),\n reloadPackages: (input?: unknown) => dispatch('addons', 'reloadPackages', 'mutation', input),\n searchAvailable: (input?: unknown) => dispatch('addons', 'searchAvailable', 'query', input),\n listUpdates: (input?: unknown) => dispatch('addons', 'listUpdates', 'query', input),\n updatePackage: (input?: unknown) => dispatch('addons', 'updatePackage', 'mutation', input),\n rollbackPackage: (input?: unknown) => dispatch('addons', 'rollbackPackage', 'mutation', input),\n forceRefresh: (input?: unknown) => dispatch('addons', 'forceRefresh', 'mutation', input),\n restartServer: (input?: unknown) => dispatch('addons', 'restartServer', 'mutation', input),\n getVersions: (input?: unknown) => dispatch('addons', 'getVersions', 'query', input),\n restartAddon: (input?: unknown) => dispatch('addons', 'restartAddon', 'mutation', input),\n retryLoad: (input?: unknown) => dispatch('addons', 'retryLoad', 'mutation', input),\n getAutoUpdateSettings: (input?: unknown) => dispatch('addons', 'getAutoUpdateSettings', 'query', input),\n setAutoUpdateSettings: (input?: unknown) => dispatch('addons', 'setAutoUpdateSettings', 'mutation', input),\n getAddonAutoUpdate: (input?: unknown) => dispatch('addons', 'getAddonAutoUpdate', 'query', input),\n setAddonAutoUpdate: (input?: unknown) => dispatch('addons', 'setAddonAutoUpdate', 'mutation', input),\n applyAutoUpdateToAll: (input?: unknown) => dispatch('addons', 'applyAutoUpdateToAll', 'mutation', input),\n custom: (input?: unknown) => dispatch('addons', 'custom', 'mutation', input),\n onAddonLogs: (input?: unknown, push?: unknown) => dispatch('addons', 'onAddonLogs', 'subscription', input, push),\n }\n\n const addonSettingsInterface = {\n getGlobalSettings: (input?: unknown) => dispatch('addonSettings', 'getGlobalSettings', 'query', input),\n updateGlobalSettings: (input?: unknown) => dispatch('addonSettings', 'updateGlobalSettings', 'mutation', input),\n }\n\n const addonWidgetsInterface = {\n listWidgets: (input?: unknown) => dispatch('addonWidgets', 'listWidgets', 'query', input),\n }\n\n const alertsInterface = {\n emit: (input?: unknown) => dispatch('alerts', 'emit', 'mutation', input),\n update: (input?: unknown) => dispatch('alerts', 'update', 'mutation', input),\n list: (input?: unknown) => dispatch('alerts', 'list', 'query', input),\n getUnreadCount: (input?: unknown) => dispatch('alerts', 'getUnreadCount', 'query', input),\n markRead: (input?: unknown) => dispatch('alerts', 'markRead', 'mutation', input),\n markAllRead: (input?: unknown) => dispatch('alerts', 'markAllRead', 'mutation', input),\n dismiss: (input?: unknown) => dispatch('alerts', 'dismiss', 'mutation', input),\n }\n\n const audioAnalyzerInterface = {\n analyseChunk: (input?: unknown) => dispatch('audioAnalyzer', 'analyseChunk', 'mutation', input),\n classify: (input?: unknown) => dispatch('audioAnalyzer', 'classify', 'query', input),\n isReady: (input?: unknown) => dispatch('audioAnalyzer', 'isReady', 'query', input),\n dispose: (input?: unknown) => dispatch('audioAnalyzer', 'dispose', 'mutation', input),\n reprobeAudioEngine: (input?: unknown) => dispatch('audioAnalyzer', 'reprobeAudioEngine', 'mutation', input),\n }\n\n const audioCodecInterface = {\n listSupportedCodecs: (input?: unknown) => dispatch('audioCodec', 'listSupportedCodecs', 'query', input),\n canHandle: (input?: unknown) => dispatch('audioCodec', 'canHandle', 'query', input),\n createDecodeSession: (input?: unknown) => dispatch('audioCodec', 'createDecodeSession', 'mutation', input),\n createEncodeSession: (input?: unknown) => dispatch('audioCodec', 'createEncodeSession', 'mutation', input),\n closeSession: (input?: unknown) => dispatch('audioCodec', 'closeSession', 'mutation', input),\n pushEncodedFrame: (input?: unknown) => dispatch('audioCodec', 'pushEncodedFrame', 'mutation', input),\n pullPcm: (input?: unknown) => dispatch('audioCodec', 'pullPcm', 'query', input),\n pushPcm: (input?: unknown) => dispatch('audioCodec', 'pushPcm', 'mutation', input),\n pullEncoded: (input?: unknown) => dispatch('audioCodec', 'pullEncoded', 'query', input),\n flushEncode: (input?: unknown) => dispatch('audioCodec', 'flushEncode', 'mutation', input),\n listActiveSessions: (input?: unknown) => dispatch('audioCodec', 'listActiveSessions', 'query', input),\n }\n\n const authenticationInterface = {\n listProviders: (input?: unknown) => dispatch('authentication', 'listProviders', 'query', input),\n setProviderEnabled: (input?: unknown) => dispatch('authentication', 'setProviderEnabled', 'mutation', input),\n }\n\n const backupInterface = {\n listDestinations: (input?: unknown) => dispatch('backup', 'listDestinations', 'query', input),\n trigger: (input?: unknown) => dispatch('backup', 'trigger', 'mutation', input),\n list: (input?: unknown) => dispatch('backup', 'list', 'query', input),\n listLocations: (input?: unknown) => dispatch('backup', 'listLocations', 'query', input),\n getEntries: (input?: unknown) => dispatch('backup', 'getEntries', 'query', input),\n restore: (input?: unknown) => dispatch('backup', 'restore', 'mutation', input),\n delete: (input?: unknown) => dispatch('backup', 'delete', 'mutation', input),\n listArchives: (input?: unknown) => dispatch('backup', 'listArchives', 'query', input),\n upsertDestinationPolicy: (input?: unknown) => dispatch('backup', 'upsertDestinationPolicy', 'mutation', input),\n previewSchedule: (input?: unknown) => dispatch('backup', 'previewSchedule', 'query', input),\n }\n\n const decoderInterface = {\n supportsCodec: (input?: unknown) => dispatch('decoder', 'supportsCodec', 'query', input),\n getInfo: (input?: unknown) => dispatch('decoder', 'getInfo', 'query', input),\n createSession: (input?: unknown) => dispatch('decoder', 'createSession', 'query', input),\n destroySession: (input?: unknown) => dispatch('decoder', 'destroySession', 'query', input),\n pushPacket: (input?: unknown) => dispatch('decoder', 'pushPacket', 'query', input),\n openStream: (input?: unknown) => dispatch('decoder', 'openStream', 'query', input),\n pullFrames: (input?: unknown) => dispatch('decoder', 'pullFrames', 'query', input),\n updateConfig: (input?: unknown) => dispatch('decoder', 'updateConfig', 'query', input),\n getStats: (input?: unknown) => dispatch('decoder', 'getStats', 'query', input),\n listActiveSessions: (input?: unknown) => dispatch('decoder', 'listActiveSessions', 'query', input),\n reprobeHwaccel: (input?: unknown) => dispatch('decoder', 'reprobeHwaccel', 'mutation', input),\n }\n\n const deviceManagerInterface = {\n allocateDeviceId: (input?: unknown) => dispatch('deviceManager', 'allocateDeviceId', 'mutation', input),\n registerDevice: (input?: unknown) => dispatch('deviceManager', 'registerDevice', 'mutation', input),\n removeDevice: (input?: unknown) => dispatch('deviceManager', 'removeDevice', 'mutation', input),\n persistConfig: (input?: unknown) => dispatch('deviceManager', 'persistConfig', 'mutation', input),\n listLocations: (input?: unknown) => dispatch('deviceManager', 'listLocations', 'query', input),\n addLocation: (input?: unknown) => dispatch('deviceManager', 'addLocation', 'mutation', input),\n removeLocation: (input?: unknown) => dispatch('deviceManager', 'removeLocation', 'mutation', input),\n listPersistedByAddon: (input?: unknown) => dispatch('deviceManager', 'listPersistedByAddon', 'query', input),\n listAll: (input?: unknown) => dispatch('deviceManager', 'listAll', 'query', input),\n getChildren: (input?: unknown) => dispatch('deviceManager', 'getChildren', 'query', input),\n listWrappersForCap: (input?: unknown) => dispatch('deviceManager', 'listWrappersForCap', 'query', input),\n listBindableCapsForDeviceType: (input?: unknown) => dispatch('deviceManager', 'listBindableCapsForDeviceType', 'query', input),\n discoverDevices: (input?: unknown) => dispatch('deviceManager', 'discoverDevices', 'mutation', input),\n adoptDevice: (input?: unknown) => dispatch('deviceManager', 'adoptDevice', 'mutation', input),\n getCreationSchema: (input?: unknown) => dispatch('deviceManager', 'getCreationSchema', 'query', input),\n createDevice: (input?: unknown) => dispatch('deviceManager', 'createDevice', 'mutation', input),\n testCreationField: (input?: unknown) => dispatch('deviceManager', 'testCreationField', 'mutation', input),\n }\n\n const deviceProviderInterface = {\n start: (input?: unknown) => dispatch('deviceProvider', 'start', 'mutation', input),\n stop: (input?: unknown) => dispatch('deviceProvider', 'stop', 'mutation', input),\n getStatus: (input?: unknown) => dispatch('deviceProvider', 'getStatus', 'query', input),\n getDevices: (input?: unknown) => dispatch('deviceProvider', 'getDevices', 'query', input),\n supportsDiscovery: (input?: unknown) => dispatch('deviceProvider', 'supportsDiscovery', 'query', input),\n discoverDevices: (input?: unknown) => dispatch('deviceProvider', 'discoverDevices', 'mutation', input),\n adoptDiscoveredDevice: (input?: unknown) => dispatch('deviceProvider', 'adoptDiscoveredDevice', 'mutation', input),\n supportsManualCreation: (input?: unknown) => dispatch('deviceProvider', 'supportsManualCreation', 'query', input),\n getChildCreationSchema: (input?: unknown) => dispatch('deviceProvider', 'getChildCreationSchema', 'query', input),\n createDevice: (input?: unknown) => dispatch('deviceProvider', 'createDevice', 'mutation', input),\n testCreationField: (input?: unknown) => dispatch('deviceProvider', 'testCreationField', 'mutation', input),\n }\n\n const deviceStateInterface = {\n getAllSnapshots: (input?: unknown) => dispatch('deviceState', 'getAllSnapshots', 'query', input),\n }\n\n const integrationsInterface = {\n list: (input?: unknown) => dispatch('integrations', 'list', 'query', input),\n get: (input?: unknown) => dispatch('integrations', 'get', 'query', input),\n getByAddonId: (input?: unknown) => dispatch('integrations', 'getByAddonId', 'query', input),\n create: (input?: unknown) => dispatch('integrations', 'create', 'mutation', input),\n update: (input?: unknown) => dispatch('integrations', 'update', 'mutation', input),\n delete: (input?: unknown) => dispatch('integrations', 'delete', 'mutation', input),\n getSettings: (input?: unknown) => dispatch('integrations', 'getSettings', 'query', input),\n setSettings: (input?: unknown) => dispatch('integrations', 'setSettings', 'mutation', input),\n getAvailableTypes: (input?: unknown) => dispatch('integrations', 'getAvailableTypes', 'query', input),\n testConnection: (input?: unknown) => dispatch('integrations', 'testConnection', 'mutation', input),\n }\n\n const localNetworkInterface = {\n list: (input?: unknown) => dispatch('localNetwork', 'list', 'query', input),\n getPreferred: (input?: unknown) => dispatch('localNetwork', 'getPreferred', 'query', input),\n getConnectionEndpoints: (input?: unknown) => dispatch('localNetwork', 'getConnectionEndpoints', 'query', input),\n getAllowedAddresses: (input?: unknown) => dispatch('localNetwork', 'getAllowedAddresses', 'query', input),\n setAllowedAddresses: (input?: unknown) => dispatch('localNetwork', 'setAllowedAddresses', 'mutation', input),\n resetAllowlistToBestMatch: (input?: unknown) => dispatch('localNetwork', 'resetAllowlistToBestMatch', 'mutation', input),\n }\n\n const meshNetworkInterface = {\n getStatus: (input?: unknown) => dispatch('meshNetwork', 'getStatus', 'query', input),\n join: (input?: unknown) => dispatch('meshNetwork', 'join', 'mutation', input),\n leave: (input?: unknown) => dispatch('meshNetwork', 'leave', 'mutation', input),\n listPeers: (input?: unknown) => dispatch('meshNetwork', 'listPeers', 'query', input),\n setPublicIngress: (input?: unknown) => dispatch('meshNetwork', 'setPublicIngress', 'mutation', input),\n setMeshIngress: (input?: unknown) => dispatch('meshNetwork', 'setMeshIngress', 'mutation', input),\n }\n\n const meshOrchestratorInterface = {\n listProviders: (input?: unknown) => dispatch('meshOrchestrator', 'listProviders', 'query', input),\n joinProvider: (input?: unknown) => dispatch('meshOrchestrator', 'joinProvider', 'mutation', input),\n leaveProvider: (input?: unknown) => dispatch('meshOrchestrator', 'leaveProvider', 'mutation', input),\n }\n\n const metricsProviderInterface = {\n collectSnapshot: (input?: unknown) => dispatch('metricsProvider', 'collectSnapshot', 'query', input),\n getCached: (input?: unknown) => dispatch('metricsProvider', 'getCached', 'query', input),\n getCurrent: (input?: unknown) => dispatch('metricsProvider', 'getCurrent', 'query', input),\n getDiskSpace: (input?: unknown) => dispatch('metricsProvider', 'getDiskSpace', 'query', input),\n getGpuInfo: (input?: unknown) => dispatch('metricsProvider', 'getGpuInfo', 'query', input),\n getCpuTemperature: (input?: unknown) => dispatch('metricsProvider', 'getCpuTemperature', 'query', input),\n getProcessStats: (input?: unknown) => dispatch('metricsProvider', 'getProcessStats', 'query', input),\n listAddonInstances: (input?: unknown) => dispatch('metricsProvider', 'listAddonInstances', 'query', input),\n getAddonStats: (input?: unknown) => dispatch('metricsProvider', 'getAddonStats', 'query', input),\n listNodeProcesses: (input?: unknown) => dispatch('metricsProvider', 'listNodeProcesses', 'query', input),\n killProcess: (input?: unknown) => dispatch('metricsProvider', 'killProcess', 'mutation', input),\n }\n\n const networkQualityInterface = {\n getAllStats: (input?: unknown) => dispatch('networkQuality', 'getAllStats', 'query', input),\n }\n\n const nodesInterface = {\n topology: (input?: unknown) => dispatch('nodes', 'topology', 'query', input),\n deployAddon: (input?: unknown) => dispatch('nodes', 'deployAddon', 'mutation', input),\n undeployAddon: (input?: unknown) => dispatch('nodes', 'undeployAddon', 'mutation', input),\n restartAddon: (input?: unknown) => dispatch('nodes', 'restartAddon', 'mutation', input),\n restartProcess: (input?: unknown) => dispatch('nodes', 'restartProcess', 'mutation', input),\n restartNode: (input?: unknown) => dispatch('nodes', 'restartNode', 'mutation', input),\n shutdownNode: (input?: unknown) => dispatch('nodes', 'shutdownNode', 'mutation', input),\n renameNode: (input?: unknown) => dispatch('nodes', 'renameNode', 'mutation', input),\n clusterAddonStatus: (input?: unknown) => dispatch('nodes', 'clusterAddonStatus', 'query', input),\n setProcessLogLevel: (input?: unknown) => dispatch('nodes', 'setProcessLogLevel', 'mutation', input),\n executeQuery: (input?: unknown) => dispatch('nodes', 'executeQuery', 'mutation', input),\n }\n\n const notificationOutputInterface = {\n send: (input?: unknown) => dispatch('notificationOutput', 'send', 'mutation', input),\n sendTest: (input?: unknown) => dispatch('notificationOutput', 'sendTest', 'mutation', input),\n }\n\n const pipelineExecutorInterface = {\n getAvailableEngines: (input?: unknown) => dispatch('pipelineExecutor', 'getAvailableEngines', 'query', input),\n getSelectedEngine: (input?: unknown) => dispatch('pipelineExecutor', 'getSelectedEngine', 'query', input),\n getDefaultSteps: (input?: unknown) => dispatch('pipelineExecutor', 'getDefaultSteps', 'query', input),\n reprobeEngine: (input?: unknown) => dispatch('pipelineExecutor', 'reprobeEngine', 'mutation', input),\n getVideoPipelineSteps: (input?: unknown) => dispatch('pipelineExecutor', 'getVideoPipelineSteps', 'query', input),\n setVideoPipelineSteps: (input?: unknown) => dispatch('pipelineExecutor', 'setVideoPipelineSteps', 'mutation', input),\n getSchema: (input?: unknown) => dispatch('pipelineExecutor', 'getSchema', 'query', input),\n getGlobalSteps: (input?: unknown) => dispatch('pipelineExecutor', 'getGlobalSteps', 'query', input),\n getGlobalPipelineConfig: (input?: unknown) => dispatch('pipelineExecutor', 'getGlobalPipelineConfig', 'query', input),\n getOrchestratorConfigSchema: (input?: unknown) => dispatch('pipelineExecutor', 'getOrchestratorConfigSchema', 'query', input),\n listTemplates: (input?: unknown) => dispatch('pipelineExecutor', 'listTemplates', 'query', input),\n saveTemplate: (input?: unknown) => dispatch('pipelineExecutor', 'saveTemplate', 'mutation', input),\n updateTemplate: (input?: unknown) => dispatch('pipelineExecutor', 'updateTemplate', 'mutation', input),\n deleteTemplate: (input?: unknown) => dispatch('pipelineExecutor', 'deleteTemplate', 'mutation', input),\n getCapabilities: (input?: unknown) => dispatch('pipelineExecutor', 'getCapabilities', 'query', input),\n getAddonModels: (input?: unknown) => dispatch('pipelineExecutor', 'getAddonModels', 'query', input),\n downloadModel: (input?: unknown) => dispatch('pipelineExecutor', 'downloadModel', 'mutation', input),\n deleteModel: (input?: unknown) => dispatch('pipelineExecutor', 'deleteModel', 'mutation', input),\n detect: (input?: unknown) => dispatch('pipelineExecutor', 'detect', 'query', input),\n cacheFrameInPool: (input?: unknown) => dispatch('pipelineExecutor', 'cacheFrameInPool', 'mutation', input),\n inferCached: (input?: unknown) => dispatch('pipelineExecutor', 'inferCached', 'mutation', input),\n uncacheFrame: (input?: unknown) => dispatch('pipelineExecutor', 'uncacheFrame', 'mutation', input),\n getEffectiveTuning: (input?: unknown) => dispatch('pipelineExecutor', 'getEffectiveTuning', 'query', input),\n listLoadedEngines: (input?: unknown) => dispatch('pipelineExecutor', 'listLoadedEngines', 'query', input),\n spinEngine: (input?: unknown) => dispatch('pipelineExecutor', 'spinEngine', 'mutation', input),\n killEngine: (input?: unknown) => dispatch('pipelineExecutor', 'killEngine', 'mutation', input),\n listReferenceImages: (input?: unknown) => dispatch('pipelineExecutor', 'listReferenceImages', 'query', input),\n getReferenceImage: (input?: unknown) => dispatch('pipelineExecutor', 'getReferenceImage', 'query', input),\n getReferenceAudioFiles: (input?: unknown) => dispatch('pipelineExecutor', 'getReferenceAudioFiles', 'query', input),\n getReferenceAudio: (input?: unknown) => dispatch('pipelineExecutor', 'getReferenceAudio', 'query', input),\n getAudioCapabilities: (input?: unknown) => dispatch('pipelineExecutor', 'getAudioCapabilities', 'query', input),\n runAudioTest: (input?: unknown) => dispatch('pipelineExecutor', 'runAudioTest', 'mutation', input),\n getDetectionConfigSchema: (input?: unknown) => dispatch('pipelineExecutor', 'getDetectionConfigSchema', 'query', input),\n }\n\n const pipelineOrchestratorInterface = {\n rebalance: (input?: unknown) => dispatch('pipelineOrchestrator', 'rebalance', 'mutation', input),\n getPipelineAssignments: (input?: unknown) => dispatch('pipelineOrchestrator', 'getPipelineAssignments', 'query', input),\n getAgentLoad: (input?: unknown) => dispatch('pipelineOrchestrator', 'getAgentLoad', 'query', input),\n getGlobalMetrics: (input?: unknown) => dispatch('pipelineOrchestrator', 'getGlobalMetrics', 'query', input),\n getCapabilityBindings: (input?: unknown) => dispatch('pipelineOrchestrator', 'getCapabilityBindings', 'query', input),\n setCapabilityBinding: (input?: unknown) => dispatch('pipelineOrchestrator', 'setCapabilityBinding', 'mutation', input),\n getDecoderAssignments: (input?: unknown) => dispatch('pipelineOrchestrator', 'getDecoderAssignments', 'query', input),\n getAudioNodeLoad: (input?: unknown) => dispatch('pipelineOrchestrator', 'getAudioNodeLoad', 'query', input),\n getAgentSettings: (input?: unknown) => dispatch('pipelineOrchestrator', 'getAgentSettings', 'query', input),\n listAgentSettings: (input?: unknown) => dispatch('pipelineOrchestrator', 'listAgentSettings', 'query', input),\n setAgentAddonDefaults: (input?: unknown) => dispatch('pipelineOrchestrator', 'setAgentAddonDefaults', 'mutation', input),\n removeAgentSettings: (input?: unknown) => dispatch('pipelineOrchestrator', 'removeAgentSettings', 'mutation', input),\n listTemplates: (input?: unknown) => dispatch('pipelineOrchestrator', 'listTemplates', 'query', input),\n saveTemplate: (input?: unknown) => dispatch('pipelineOrchestrator', 'saveTemplate', 'mutation', input),\n updateTemplate: (input?: unknown) => dispatch('pipelineOrchestrator', 'updateTemplate', 'mutation', input),\n deleteTemplate: (input?: unknown) => dispatch('pipelineOrchestrator', 'deleteTemplate', 'mutation', input),\n }\n\n const pipelineRunnerInterface = {\n attachCamera: (input?: unknown) => dispatch('pipelineRunner', 'attachCamera', 'mutation', input),\n reportMotion: (input?: unknown) => dispatch('pipelineRunner', 'reportMotion', 'mutation', input),\n getLocalLoad: (input?: unknown) => dispatch('pipelineRunner', 'getLocalLoad', 'query', input),\n getLocalMetrics: (input?: unknown) => dispatch('pipelineRunner', 'getLocalMetrics', 'query', input),\n getAllCameraMetrics: (input?: unknown) => dispatch('pipelineRunner', 'getAllCameraMetrics', 'query', input),\n getLocalCameras: (input?: unknown) => dispatch('pipelineRunner', 'getLocalCameras', 'query', input),\n }\n\n const platformProbeInterface = {\n getCapabilities: (input?: unknown) => dispatch('platformProbe', 'getCapabilities', 'query', input),\n getHardware: (input?: unknown) => dispatch('platformProbe', 'getHardware', 'query', input),\n resolveInferenceConfig: (input?: unknown) => dispatch('platformProbe', 'resolveInferenceConfig', 'query', input),\n resolveHwAccel: (input?: unknown) => dispatch('platformProbe', 'resolveHwAccel', 'query', input),\n }\n\n const recordingEngineInterface = {\n getStatus: (input?: unknown) => dispatch('recordingEngine', 'getStatus', 'query', input),\n enable: (input?: unknown) => dispatch('recordingEngine', 'enable', 'mutation', input),\n disable: (input?: unknown) => dispatch('recordingEngine', 'disable', 'mutation', input),\n getConfig: (input?: unknown) => dispatch('recordingEngine', 'getConfig', 'query', input),\n updateConfig: (input?: unknown) => dispatch('recordingEngine', 'updateConfig', 'mutation', input),\n getPlaylist: (input?: unknown) => dispatch('recordingEngine', 'getPlaylist', 'query', input),\n getThumbnail: (input?: unknown) => dispatch('recordingEngine', 'getThumbnail', 'query', input),\n getSegments: (input?: unknown) => dispatch('recordingEngine', 'getSegments', 'query', input),\n getAvailability: (input?: unknown) => dispatch('recordingEngine', 'getAvailability', 'query', input),\n estimateStorage: (input?: unknown) => dispatch('recordingEngine', 'estimateStorage', 'query', input),\n estimateGlobalStorage: (input?: unknown) => dispatch('recordingEngine', 'estimateGlobalStorage', 'query', input),\n getStorageUsage: (input?: unknown) => dispatch('recordingEngine', 'getStorageUsage', 'query', input),\n setPolicy: (input?: unknown) => dispatch('recordingEngine', 'setPolicy', 'mutation', input),\n getPolicy: (input?: unknown) => dispatch('recordingEngine', 'getPolicy', 'query', input),\n getRetentionConfig: (input?: unknown) => dispatch('recordingEngine', 'getRetentionConfig', 'query', input),\n updateRetentionConfig: (input?: unknown) => dispatch('recordingEngine', 'updateRetentionConfig', 'mutation', input),\n getMotionStats: (input?: unknown) => dispatch('recordingEngine', 'getMotionStats', 'query', input),\n }\n\n const remoteAccessInterface = {\n listProviders: (input?: unknown) => dispatch('remoteAccess', 'listProviders', 'query', input),\n startProvider: (input?: unknown) => dispatch('remoteAccess', 'startProvider', 'mutation', input),\n stopProvider: (input?: unknown) => dispatch('remoteAccess', 'stopProvider', 'mutation', input),\n }\n\n const settingsStoreInterface = {\n get: (input?: unknown) => dispatch('settingsStore', 'get', 'query', input),\n set: (input?: unknown) => dispatch('settingsStore', 'set', 'mutation', input),\n query: (input?: unknown) => dispatch('settingsStore', 'query', 'query', input),\n insert: (input?: unknown) => dispatch('settingsStore', 'insert', 'mutation', input),\n update: (input?: unknown) => dispatch('settingsStore', 'update', 'mutation', input),\n delete: (input?: unknown) => dispatch('settingsStore', 'delete', 'mutation', input),\n count: (input?: unknown) => dispatch('settingsStore', 'count', 'query', input),\n isEmpty: (input?: unknown) => dispatch('settingsStore', 'isEmpty', 'query', input),\n declareCollection: (input?: unknown) => dispatch('settingsStore', 'declareCollection', 'mutation', input),\n }\n\n const storageInterface = {\n resolve: (input?: unknown) => dispatch('storage', 'resolve', 'query', input),\n write: (input?: unknown) => dispatch('storage', 'write', 'mutation', input),\n read: (input?: unknown) => dispatch('storage', 'read', 'query', input),\n exists: (input?: unknown) => dispatch('storage', 'exists', 'query', input),\n list: (input?: unknown) => dispatch('storage', 'list', 'query', input),\n delete: (input?: unknown) => dispatch('storage', 'delete', 'mutation', input),\n getAvailableSpace: (input?: unknown) => dispatch('storage', 'getAvailableSpace', 'query', input),\n beginUpload: (input?: unknown) => dispatch('storage', 'beginUpload', 'mutation', input),\n writeChunk: (input?: unknown) => dispatch('storage', 'writeChunk', 'mutation', input),\n finalizeUpload: (input?: unknown) => dispatch('storage', 'finalizeUpload', 'mutation', input),\n abortUpload: (input?: unknown) => dispatch('storage', 'abortUpload', 'mutation', input),\n beginDownload: (input?: unknown) => dispatch('storage', 'beginDownload', 'mutation', input),\n readChunk: (input?: unknown) => dispatch('storage', 'readChunk', 'query', input),\n endDownload: (input?: unknown) => dispatch('storage', 'endDownload', 'mutation', input),\n listLocations: (input?: unknown) => dispatch('storage', 'listLocations', 'query', input),\n getDefaultLocation: (input?: unknown) => dispatch('storage', 'getDefaultLocation', 'query', input),\n upsertLocation: (input?: unknown) => dispatch('storage', 'upsertLocation', 'mutation', input),\n deleteLocation: (input?: unknown) => dispatch('storage', 'deleteLocation', 'mutation', input),\n testLocation: (input?: unknown) => dispatch('storage', 'testLocation', 'query', input),\n listProviders: (input?: unknown) => dispatch('storage', 'listProviders', 'query', input),\n testConfig: (input?: unknown) => dispatch('storage', 'testConfig', 'query', input),\n }\n\n const streamBrokerInterface = {\n listAllCameraStreams: (input?: unknown) => dispatch('streamBroker', 'listAllCameraStreams', 'query', input),\n listAllProfileSlots: (input?: unknown) => dispatch('streamBroker', 'listAllProfileSlots', 'query', input),\n getBrokerStats: (input?: unknown) => dispatch('streamBroker', 'getBrokerStats', 'query', input),\n listClients: (input?: unknown) => dispatch('streamBroker', 'listClients', 'query', input),\n killClient: (input?: unknown) => dispatch('streamBroker', 'killClient', 'mutation', input),\n getStreamUrl: (input?: unknown) => dispatch('streamBroker', 'getStreamUrl', 'query', input),\n getBroker: (input?: unknown) => dispatch('streamBroker', 'getBroker', 'query', input),\n setPreBufferDuration: (input?: unknown) => dispatch('streamBroker', 'setPreBufferDuration', 'mutation', input),\n getPreBufferInfo: (input?: unknown) => dispatch('streamBroker', 'getPreBufferInfo', 'query', input),\n getRtspPort: (input?: unknown) => dispatch('streamBroker', 'getRtspPort', 'query', input),\n getAllRtspEntries: (input?: unknown) => dispatch('streamBroker', 'getAllRtspEntries', 'query', input),\n getRtspEntry: (input?: unknown) => dispatch('streamBroker', 'getRtspEntry', 'query', input),\n regenerateRtspToken: (input?: unknown) => dispatch('streamBroker', 'regenerateRtspToken', 'mutation', input),\n setRtspEnabled: (input?: unknown) => dispatch('streamBroker', 'setRtspEnabled', 'mutation', input),\n isRtspEnabled: (input?: unknown) => dispatch('streamBroker', 'isRtspEnabled', 'query', input),\n }\n\n const systemInterface = {\n info: (input?: unknown) => dispatch('system', 'info', 'query', input),\n health: (input?: unknown) => dispatch('system', 'health', 'query', input),\n featureFlags: (input?: unknown) => dispatch('system', 'featureFlags', 'query', input),\n networkAddresses: (input?: unknown) => dispatch('system', 'networkAddresses', 'query', input),\n getRetentionConfig: (input?: unknown) => dispatch('system', 'getRetentionConfig', 'query', input),\n setRetentionConfig: (input?: unknown) => dispatch('system', 'setRetentionConfig', 'mutation', input),\n forceRetentionCleanup: (input?: unknown) => dispatch('system', 'forceRetentionCleanup', 'mutation', input),\n }\n\n const toastInterface = {\n onToast: (input?: unknown, push?: unknown) => dispatch('toast', 'onToast', 'subscription', input, push),\n }\n\n const turnOrchestratorInterface = {\n listProviders: (input?: unknown) => dispatch('turnOrchestrator', 'listProviders', 'query', input),\n getAllServers: (input?: unknown) => dispatch('turnOrchestrator', 'getAllServers', 'query', input),\n setProviderEnabled: (input?: unknown) => dispatch('turnOrchestrator', 'setProviderEnabled', 'mutation', input),\n }\n\n const turnProviderInterface = {\n getTurnServers: (input?: unknown) => dispatch('turnProvider', 'getTurnServers', 'query', input),\n }\n\n const userManagementInterface = {\n listUsers: (input?: unknown) => dispatch('userManagement', 'listUsers', 'query', input),\n createUser: (input?: unknown) => dispatch('userManagement', 'createUser', 'mutation', input),\n updateUser: (input?: unknown) => dispatch('userManagement', 'updateUser', 'mutation', input),\n deleteUser: (input?: unknown) => dispatch('userManagement', 'deleteUser', 'mutation', input),\n resetPassword: (input?: unknown) => dispatch('userManagement', 'resetPassword', 'mutation', input),\n validateCredentials: (input?: unknown) => dispatch('userManagement', 'validateCredentials', 'mutation', input),\n listApiKeys: (input?: unknown) => dispatch('userManagement', 'listApiKeys', 'query', input),\n createApiKey: (input?: unknown) => dispatch('userManagement', 'createApiKey', 'mutation', input),\n revokeApiKey: (input?: unknown) => dispatch('userManagement', 'revokeApiKey', 'mutation', input),\n validateApiKey: (input?: unknown) => dispatch('userManagement', 'validateApiKey', 'mutation', input),\n createScopedToken: (input?: unknown) => dispatch('userManagement', 'createScopedToken', 'mutation', input),\n revokeScopedToken: (input?: unknown) => dispatch('userManagement', 'revokeScopedToken', 'mutation', input),\n validateScopedToken: (input?: unknown) => dispatch('userManagement', 'validateScopedToken', 'query', input),\n listScopedTokens: (input?: unknown) => dispatch('userManagement', 'listScopedTokens', 'query', input),\n }\n\n return {\n addonPages: addonPagesInterface,\n addons: addonsInterface,\n addonSettings: addonSettingsInterface,\n addonWidgets: addonWidgetsInterface,\n alerts: alertsInterface,\n audioAnalyzer: audioAnalyzerInterface,\n audioCodec: audioCodecInterface,\n authentication: authenticationInterface,\n backup: backupInterface,\n decoder: decoderInterface,\n deviceManager: deviceManagerInterface,\n deviceProvider: deviceProviderInterface,\n deviceState: deviceStateInterface,\n integrations: integrationsInterface,\n localNetwork: localNetworkInterface,\n meshNetwork: meshNetworkInterface,\n meshOrchestrator: meshOrchestratorInterface,\n metricsProvider: metricsProviderInterface,\n networkQuality: networkQualityInterface,\n nodes: nodesInterface,\n notificationOutput: notificationOutputInterface,\n pipelineExecutor: pipelineExecutorInterface,\n pipelineOrchestrator: pipelineOrchestratorInterface,\n pipelineRunner: pipelineRunnerInterface,\n platformProbe: platformProbeInterface,\n recordingEngine: recordingEngineInterface,\n remoteAccess: remoteAccessInterface,\n settingsStore: settingsStoreInterface,\n storage: storageInterface,\n streamBroker: streamBrokerInterface,\n system: systemInterface,\n toast: toastInterface,\n turnOrchestrator: turnOrchestratorInterface,\n turnProvider: turnProviderInterface,\n userManagement: userManagementInterface,\n }\n}\n","/**\n * SystemMirror — system-wide reactive view of every device, like\n * Scrypted's `systemManager.getDeviceById`. One warm-boot fetches the\n * full bindings + runtime-state snapshot + device metadata; live\n * `device.state-changed`, `capability.binding-changed`,\n * `device.registered`, `device.unregistered`, and `device.updated`\n * events keep the in-memory mirrors fresh. Subsequent\n * `getDeviceById(id)` calls are sync.\n *\n * Renamed from `SystemManager` (and its file `system-manager.ts`) when\n * the SDK introduced a top-level `System` facade. The cluster-wide\n * mirror is one of `System`'s collaborators — calling it a \"mirror\"\n * disambiguates from the new public class. The old export name is\n * still available as a deprecated alias from this file.\n *\n * Cap-agnostic by construction: the state mirror is `Map<deviceId,\n * Map<capName, slice>>` and the proxies are produced by the\n * codegen'd `createDeviceProxy` we already use everywhere — so a\n * brand-new cap with `runtimeState:` lights up here without a single\n * line of additional code.\n *\n * Two transports today, same shape:\n * - tRPC client (browser, Electron, SDK consumers).\n * - In-process AddonApi (server REPL, addons that want a global view).\n *\n * Boot:\n *\n * const sm = new SystemMirror(api)\n * await sm.init()\n *\n * const dev = sm.getDeviceById(8) // sync\n * dev?.state.battery.value?.sleeping // sync read from mirror\n * await dev?.snapshot?.getSnapshot({...}) // method dispatch via cap-router\n *\n * sm.query({ addonId: 'reolink', online: true })\n * sm.whereState('battery', s => s.percentage < 20)\n * sm.listenCap('motion', (id, slice) => …)\n * await sm.waitForState(8, 'battery', s => !s.sleeping, 30_000)\n *\n * Lifecycle: caller is responsible for `dispose()` when done — closes\n * the live event subscriptions.\n */\n\nimport type { DeviceBinding } from './device-binding.js'\nimport { createDeviceProxy, type DeviceProxy } from '../generated/device-proxy.js'\nimport type { AddonApi } from '../generated/addon-api.js'\nimport type { DeviceInfo } from '../capabilities/device-manager.cap.js'\nimport { DeviceType } from './device-type.js'\nimport { createMirrorSource, type SliceHandleApi, type SliceHandleSource } from './device-state-handle.js'\n\nconst STATE_CHANGED_CATEGORY = 'device.state-changed'\nconst BINDING_CHANGED_CATEGORY = 'capability.binding-changed'\nconst DEVICE_REGISTERED_CATEGORY = 'device.registered'\nconst DEVICE_UNREGISTERED_CATEGORY = 'device.unregistered'\nconst DEVICE_UPDATED_CATEGORY = 'device.updated'\n\n/**\n * Minimal subset of `AddonApi` the SystemMirror needs.\n */\nexport interface SystemMirrorApi extends SliceHandleApi {\n readonly deviceManager: {\n readonly getAllBindings: {\n query(input: Record<string, never>): Promise<ReadonlyArray<DeviceBinding>>\n }\n readonly listAll: {\n query(input: { addonId?: string }): Promise<ReadonlyArray<DeviceInfo>>\n }\n }\n readonly deviceState: SliceHandleApi['deviceState'] & {\n readonly getAllSnapshots: {\n query(input: Record<string, never>): Promise<Record<string, Record<string, Record<string, unknown>>>>\n }\n }\n}\n\nexport type SystemMirrorListener = (\n deviceId: number,\n capName: string,\n slice: Record<string, unknown> | undefined,\n) => void\n\nexport type DeviceCapListener = (\n deviceId: number,\n slice: Record<string, unknown> | undefined,\n) => void\n\nexport type DeviceLifecycleListener = (\n deviceId: number,\n info: DeviceInfo | null,\n) => void\n\n/**\n * Match shape — `string` is exact match, `RegExp` is regex match,\n * `{ contains }` is case-insensitive substring, `{ exact }` is the\n * verbose form of plain string. Useful for `query({ name: ... })`\n * where the same field accepts multiple match modes.\n */\nexport type StringMatch =\n | string\n | RegExp\n | { readonly exact: string }\n | { readonly contains: string }\n\n/**\n * Filter set for `query()`. All fields are optional and ANDed\n * together. Array values are ORed within a single field\n * (`addonId: ['a', 'b']` matches devices owned by either). The\n * `where` escape hatch runs LAST so the structured filters do the\n * cheap rejection first.\n */\nexport interface DeviceQueryFilters {\n /** Match by exact deviceId. Single value or array (OR'd). */\n readonly id?: number | readonly number[]\n /** Match by exact stableId. Single value or array. */\n readonly stableId?: string | readonly string[]\n /** Match by owning addonId. Single value or array. */\n readonly addonId?: string | readonly string[]\n /** Match by `DeviceType` enum value. Single value or array. */\n readonly type?: DeviceType | readonly DeviceType[]\n /** Match devices that bind ALL listed caps. Single capName or array. */\n readonly caps?: string | readonly string[]\n /** Match devices that bind ANY of the listed caps. Mutually exclusive\n * with `caps`. */\n readonly anyCap?: string | readonly string[]\n /** Match by device name. */\n readonly name?: StringMatch\n /** Match the `online` flag. */\n readonly online?: boolean\n /** Match by parent device id. Pass `null` for top-level devices. */\n readonly parentDeviceId?: number | null\n /** Match devices that expose a feature (e.g. `'BatteryOperated'`). */\n readonly feature?: string | readonly string[]\n /** Match `isCamera` flag. */\n readonly isCamera?: boolean\n /** Custom predicate. Runs last; receives both metadata and proxy. */\n readonly where?: (info: DeviceInfo, proxy: DeviceProxy) => boolean\n}\n\nexport class SystemMirror {\n /** deviceId → capName → slice (push-driven mirror). */\n private readonly stateMirror: Map<number, Map<string, Record<string, unknown>>> = new Map()\n /** deviceId → binding (warm-boot + binding-changed events). */\n private readonly bindings: Map<number, DeviceBinding> = new Map()\n /** deviceId → metadata (warm-boot + lifecycle events). */\n private readonly devices: Map<number, DeviceInfo> = new Map()\n /** Listener map for individual `(deviceId, capName)` watches —\n * shared with every `MirrorSource` we hand out. */\n private readonly handleListeners = new Map<string, Set<(slice: unknown | undefined) => void>>()\n /** Global state-change listeners registered via `listen()`. */\n private readonly globalStateListeners = new Set<SystemMirrorListener>()\n /** Per-cap state listeners registered via `listenCap(capName, …)`. */\n private readonly capListeners = new Map<string, Set<DeviceCapListener>>()\n /** Per-device state listeners registered via `listenDevice(id, …)`. */\n private readonly deviceListeners = new Map<number, Set<SystemMirrorListener>>()\n /** Lifecycle listeners. */\n private readonly addedListeners = new Set<DeviceLifecycleListener>()\n private readonly removedListeners = new Set<DeviceLifecycleListener>()\n /** waitForState pending requests — keyed by an internal counter. */\n private readonly pendingWaits = new Set<{ check: () => boolean; resolve: () => void }>()\n /** Memoised state source — every proxy shares it. */\n private readonly stateSource: SliceHandleSource\n /** Live event bridges — closed in `dispose()`. */\n private bridges: Array<{ unsubscribe: () => void }> = []\n private initialized = false\n private initPromise: Promise<void> | null = null\n\n constructor(private readonly api: SystemMirrorApi) {\n this.stateSource = createMirrorSource(this.stateMirror, this.handleListeners, this.api)\n }\n\n // ── Lifecycle ──────────────────────────────────────────────────────\n\n /**\n * Warm-boot: three round-trips (bindings + snapshots + listAll) and\n * then the live event subscriptions. Idempotent — concurrent callers\n * await the same in-flight Promise.\n *\n * Each warm-boot query is wrapped in a 15s timeout so a missing\n * endpoint or stuck broker poll surfaces as a clear error instead\n * of silently hanging the caller forever. The default is generous\n * enough for cluster-wide setups but short enough for ops to\n * notice and fix the underlying transport issue.\n */\n async init(timeoutMs: number = 15_000): Promise<void> {\n if (this.initialized) return\n if (this.initPromise) return this.initPromise\n\n this.initPromise = (async () => {\n const withTimeout = <T>(p: Promise<T>, label: string): Promise<T> => {\n if (!Number.isFinite(timeoutMs)) return p\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(\n () => reject(new Error(`SystemMirror.init: '${label}' timed out after ${timeoutMs}ms`)),\n timeoutMs,\n )\n p.then(\n (v) => { clearTimeout(timer); resolve(v) },\n (err) => { clearTimeout(timer); reject(err as Error) },\n )\n })\n }\n\n const [allBindings, allSnapshots, allDevices] = await Promise.all([\n withTimeout(this.api.deviceManager.getAllBindings.query({}), 'deviceManager.getAllBindings'),\n withTimeout(this.api.deviceState.getAllSnapshots.query({}), 'deviceState.getAllSnapshots'),\n withTimeout(this.api.deviceManager.listAll.query({}), 'deviceManager.listAll'),\n ])\n\n for (const b of allBindings) this.bindings.set(b.deviceId, b)\n\n for (const [deviceIdStr, perCap] of Object.entries(allSnapshots)) {\n const deviceId = Number(deviceIdStr)\n if (!Number.isFinite(deviceId)) continue\n const capMap = new Map<string, Record<string, unknown>>()\n for (const [capName, slice] of Object.entries(perCap)) capMap.set(capName, slice)\n this.stateMirror.set(deviceId, capMap)\n }\n\n for (const info of allDevices) this.devices.set(info.id, info)\n\n // Subscriptions are best-effort — `live.onEvent` may not be\n // wired in some environments (e.g. when the api is a partial\n // adapter). Catch errors so init still completes; the mirror\n // just stops getting live updates instead of hanging the\n // entire REPL/SDK boot.\n try {\n this.subscribeBus()\n } catch (err) {\n // Swallow — `subscribeBus` itself is safe (it checks\n // `api.live?.onEvent`), but defend against transport\n // wrappers that throw on subscribe.\n void err\n }\n this.initialized = true\n })()\n\n try {\n await this.initPromise\n } finally {\n this.initPromise = null\n }\n }\n\n /** True after `init()` resolves. */\n isReady(): boolean {\n return this.initialized\n }\n\n /** Promise that resolves once `init()` has completed. */\n async awaitReady(): Promise<void> {\n if (this.initialized) return\n if (this.initPromise) return this.initPromise\n return this.init()\n }\n\n /**\n * Tear down the event bridges + clear listener registries. Existing\n * proxy references become inert (slice reads keep working off the\n * stale mirror, but no further updates arrive).\n */\n dispose(): void {\n for (const b of this.bridges) {\n try { b.unsubscribe() } catch { /* ignore */ }\n }\n this.bridges = []\n this.handleListeners.clear()\n this.globalStateListeners.clear()\n this.capListeners.clear()\n this.deviceListeners.clear()\n this.addedListeners.clear()\n this.removedListeners.clear()\n this.pendingWaits.clear()\n this.initialized = false\n }\n\n // ── Lookup ─────────────────────────────────────────────────────────\n\n /** Sync lookup by numeric id. `null` if unknown. */\n getDeviceById(deviceId: number): DeviceProxy | null {\n const binding = this.bindings.get(deviceId)\n if (!binding) return null\n return createDeviceProxy(this.api as AddonApi, binding, { stateSource: this.stateSource })\n }\n\n /** Sync lookup by display name (exact match). `null` if unknown. */\n getDeviceByName(name: string): DeviceProxy | null {\n for (const info of this.devices.values()) {\n if (info.name === name) return this.getDeviceById(info.id)\n }\n return null\n }\n\n /** Sync lookup by stableId (the addon-scoped external id). */\n getDeviceByStableId(stableId: string): DeviceProxy | null {\n for (const info of this.devices.values()) {\n if (info.stableId === stableId) return this.getDeviceById(info.id)\n }\n return null\n }\n\n /** All devices owned by an addon. */\n getDevicesByAddon(addonId: string): readonly DeviceProxy[] {\n return this.query({ addonId })\n }\n\n /** All devices of a given `DeviceType`. */\n getDevicesByType(type: DeviceType): readonly DeviceProxy[] {\n return this.query({ type })\n }\n\n /**\n * Live metadata snapshot for a device. Same shape as\n * `deviceManager.getDevice(id)`; sync from the mirror.\n */\n getDeviceInfo(deviceId: number): DeviceInfo | null {\n return this.devices.get(deviceId) ?? null\n }\n\n /** Snapshot of every known device as a typed proxy. */\n getAllDevices(): readonly DeviceProxy[] {\n const out: DeviceProxy[] = []\n for (const id of this.bindings.keys()) {\n const proxy = this.getDeviceById(id)\n if (proxy) out.push(proxy)\n }\n return out\n }\n\n /** Filter devices by cap presence — shorthand for `query({caps: capName})`. */\n filterByCap(capName: string): readonly DeviceProxy[] {\n return this.query({ caps: capName })\n }\n\n // ── Unified query ──────────────────────────────────────────────────\n\n /**\n * Filter the fleet against a structured filter set. All fields ANDed,\n * arrays ORed within a single field. Returns proxies — chain with\n * cap-method calls or state reads as needed.\n *\n * Examples:\n *\n * sm.query({ addonId: 'reolink', online: true })\n * sm.query({ type: DeviceType.Camera, caps: ['snapshot', 'motion'] })\n * sm.query({ id: [1, 2, 3] })\n * sm.query({ name: { contains: 'sala' } })\n * sm.query({ name: /^cam-\\d+$/ })\n * sm.query({ parentDeviceId: 8 }) // accessories of cam 8\n * sm.query({ where: (info, dev) => dev.state.battery.value?.sleeping })\n */\n query(filters: DeviceQueryFilters = {}): readonly DeviceProxy[] {\n const out: DeviceProxy[] = []\n for (const [deviceId, binding] of this.bindings) {\n const info = this.devices.get(deviceId)\n // Most filters need DeviceInfo. If we don't have it, only `id` /\n // `caps` / `anyCap` filters can resolve — for everything else\n // skip the device. (This window is brief: warm-boot races\n // bindings vs metadata for a few ms.)\n if (filters.id !== undefined && !inSet(deviceId, filters.id)) continue\n if (filters.stableId !== undefined) {\n if (!info) continue\n if (!inSet(info.stableId, filters.stableId)) continue\n }\n if (filters.addonId !== undefined) {\n if (!info) continue\n if (!inSet(info.addonId, filters.addonId)) continue\n }\n if (filters.type !== undefined) {\n if (!info) continue\n if (!inSet(info.type, filters.type)) continue\n }\n if (filters.caps !== undefined) {\n const required = toArray(filters.caps)\n const bound = new Set(binding.entries.map((e) => e.capName))\n if (!required.every((c) => bound.has(c))) continue\n }\n if (filters.anyCap !== undefined) {\n const wanted = toArray(filters.anyCap)\n const bound = new Set(binding.entries.map((e) => e.capName))\n if (!wanted.some((c) => bound.has(c))) continue\n }\n if (filters.name !== undefined) {\n if (!info) continue\n if (!matchesString(info.name, filters.name)) continue\n }\n if (filters.online !== undefined) {\n if (!info) continue\n if (info.online !== filters.online) continue\n }\n if (filters.parentDeviceId !== undefined) {\n if (!info) continue\n const want = filters.parentDeviceId\n const got = info.parentDeviceId ?? null\n if (got !== want) continue\n }\n if (filters.feature !== undefined) {\n if (!info) continue\n const want = toArray(filters.feature)\n if (!want.every((f) => info.features.includes(f))) continue\n }\n if (filters.isCamera !== undefined) {\n if (!info) continue\n if (info.isCamera !== filters.isCamera) continue\n }\n const proxy = this.getDeviceById(deviceId)\n if (!proxy) continue\n if (filters.where && info) {\n if (!filters.where(info, proxy)) continue\n } else if (filters.where && !info) {\n continue\n }\n out.push(proxy)\n }\n return out\n }\n\n // ── State-driven queries ───────────────────────────────────────────\n\n /**\n * Return every proxy whose runtime-state slice for `capName` matches\n * `predicate`. Devices without the cap or without a slice are\n * skipped. The predicate receives a typed slice reference — pass\n * the typed cap (e.g. `'battery'`) and TypeScript widens to\n * `Record<string, unknown>`; cast inside the predicate body if the\n * caller knows the cap shape.\n */\n whereState<T extends Record<string, unknown> = Record<string, unknown>>(\n capName: string,\n predicate: (slice: T, deviceId: number) => boolean,\n ): readonly DeviceProxy[] {\n const out: DeviceProxy[] = []\n for (const [deviceId, perCap] of this.stateMirror) {\n const slice = perCap.get(capName) as T | undefined\n if (!slice) continue\n if (!predicate(slice, deviceId)) continue\n const proxy = this.getDeviceById(deviceId)\n if (proxy) out.push(proxy)\n }\n return out\n }\n\n /** Map every device's slice for `capName` to a derived value. Devices\n * without the cap or without a slice are skipped. */\n mapState<T extends Record<string, unknown> = Record<string, unknown>, R = unknown>(\n capName: string,\n mapper: (slice: T, deviceId: number) => R,\n ): readonly R[] {\n const out: R[] = []\n for (const [deviceId, perCap] of this.stateMirror) {\n const slice = perCap.get(capName) as T | undefined\n if (!slice) continue\n out.push(mapper(slice, deviceId))\n }\n return out\n }\n\n /** First device whose slice matches `predicate`, or null. */\n findState<T extends Record<string, unknown> = Record<string, unknown>>(\n capName: string,\n predicate: (slice: T, deviceId: number) => boolean,\n ): DeviceProxy | null {\n for (const [deviceId, perCap] of this.stateMirror) {\n const slice = perCap.get(capName) as T | undefined\n if (!slice) continue\n if (!predicate(slice, deviceId)) continue\n return this.getDeviceById(deviceId)\n }\n return null\n }\n\n /** Count devices that bind a cap. Faster than `filterByCap(...).length`. */\n countByCap(capName: string): number {\n let n = 0\n for (const binding of this.bindings.values()) {\n if (binding.entries.some((e) => e.capName === capName)) n++\n }\n return n\n }\n\n /** Count devices whose slice for `capName` matches `predicate`. */\n countByState<T extends Record<string, unknown> = Record<string, unknown>>(\n capName: string,\n predicate: (slice: T, deviceId: number) => boolean,\n ): number {\n let n = 0\n for (const [deviceId, perCap] of this.stateMirror) {\n const slice = perCap.get(capName) as T | undefined\n if (!slice) continue\n if (predicate(slice, deviceId)) n++\n }\n return n\n }\n\n // ── Listeners ──────────────────────────────────────────────────────\n\n /**\n * Global listener — fires for every `device.state-changed` event the\n * mirror absorbs.\n */\n listen(cb: SystemMirrorListener): () => void {\n this.globalStateListeners.add(cb)\n return () => { this.globalStateListeners.delete(cb) }\n }\n\n /**\n * Per-cap listener — fires only for state changes on `capName`,\n * across every device. The callback receives the deviceId so the\n * caller can route.\n */\n listenCap(capName: string, cb: DeviceCapListener): () => void {\n let set = this.capListeners.get(capName)\n if (!set) { set = new Set(); this.capListeners.set(capName, set) }\n set.add(cb)\n return () => {\n set!.delete(cb)\n if (set!.size === 0) this.capListeners.delete(capName)\n }\n }\n\n /**\n * Per-device listener — fires for every cap change on `deviceId`.\n */\n listenDevice(deviceId: number, cb: SystemMirrorListener): () => void {\n let set = this.deviceListeners.get(deviceId)\n if (!set) { set = new Set(); this.deviceListeners.set(deviceId, set) }\n set.add(cb)\n return () => {\n set!.delete(cb)\n if (set!.size === 0) this.deviceListeners.delete(deviceId)\n }\n }\n\n /** Fires when `device.registered` lands. Receives the new metadata. */\n onDeviceAdded(cb: DeviceLifecycleListener): () => void {\n this.addedListeners.add(cb)\n return () => { this.addedListeners.delete(cb) }\n }\n\n /** Fires when `device.unregistered` lands. `info` is the LAST-known\n * metadata (or null if the device was never seen). */\n onDeviceRemoved(cb: DeviceLifecycleListener): () => void {\n this.removedListeners.add(cb)\n return () => { this.removedListeners.delete(cb) }\n }\n\n // ── Wait primitives ────────────────────────────────────────────────\n\n /**\n * Resolve when `predicate` over the runtime-state slice for\n * `(deviceId, capName)` becomes true. Resolves immediately if the\n * current slice already matches. Rejects with `Error('timeout')`\n * after `timeoutMs` (default 30s; pass `Infinity` to wait forever).\n *\n * Returns the matching slice — caller can read it directly without\n * a second mirror lookup.\n */\n waitForState<T extends Record<string, unknown> = Record<string, unknown>>(\n deviceId: number,\n capName: string,\n predicate: (slice: T) => boolean,\n timeoutMs: number = 30_000,\n ): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const check = (): T | null => {\n const slice = this.stateMirror.get(deviceId)?.get(capName) as T | undefined\n if (slice && predicate(slice)) return slice\n return null\n }\n const initial = check()\n if (initial) {\n resolve(initial)\n return\n }\n\n let timer: ReturnType<typeof setTimeout> | null = null\n const off = this.listenDevice(deviceId, (_id, cap, slice) => {\n if (cap !== capName) return\n if (!slice) return\n if (predicate(slice as T)) {\n if (timer) clearTimeout(timer)\n off()\n resolve(slice as T)\n }\n })\n if (Number.isFinite(timeoutMs)) {\n timer = setTimeout(() => {\n off()\n reject(new Error(`waitForState timed out after ${timeoutMs}ms (deviceId=${deviceId}, capName=${capName})`))\n }, timeoutMs)\n }\n })\n }\n\n /**\n * Resolve when a device with `deviceId` becomes available (a\n * binding exists). Resolves immediately if already known. Rejects\n * with timeout.\n */\n waitForDevice(deviceId: number, timeoutMs: number = 30_000): Promise<DeviceProxy> {\n return new Promise<DeviceProxy>((resolve, reject) => {\n const existing = this.getDeviceById(deviceId)\n if (existing) {\n resolve(existing)\n return\n }\n let timer: ReturnType<typeof setTimeout> | null = null\n const off = this.onDeviceAdded((id) => {\n if (id !== deviceId) return\n const proxy = this.getDeviceById(id)\n if (!proxy) return\n if (timer) clearTimeout(timer)\n off()\n resolve(proxy)\n })\n if (Number.isFinite(timeoutMs)) {\n timer = setTimeout(() => {\n off()\n reject(new Error(`waitForDevice timed out after ${timeoutMs}ms (deviceId=${deviceId})`))\n }, timeoutMs)\n }\n })\n }\n\n // ── Batch actions ──────────────────────────────────────────────────\n\n /**\n * Iterate every device that binds `capName`. Awaits each callback\n * sequentially — for parallel use `invokeCap` with explicit\n * parallelism.\n */\n async forEachCap(\n capName: string,\n cb: (proxy: DeviceProxy) => void | Promise<void>,\n ): Promise<void> {\n for (const proxy of this.filterByCap(capName)) {\n await cb(proxy)\n }\n }\n\n /**\n * Invoke a cap method on every device that binds the cap. Returns\n * one result per device, success or failure isolated. Optional\n * parallelism cap — useful for \"snapshot all cameras but only 4\n * at a time so battery cams don't all wake at once\".\n *\n * Example:\n *\n * const results = await sm.invokeCap('snapshot', 'getSnapshot', {}, { parallelism: 4 })\n * const failed = results.filter(r => !r.ok)\n */\n async invokeCap<R = unknown>(\n capName: string,\n methodName: string,\n args: Record<string, unknown>,\n opts: { parallelism?: number } = {},\n ): Promise<ReadonlyArray<{ deviceId: number; ok: boolean; result?: R; error?: unknown }>> {\n const targets = this.filterByCap(capName)\n const parallelism = Math.max(1, opts.parallelism ?? targets.length)\n const out: Array<{ deviceId: number; ok: boolean; result?: R; error?: unknown }> = []\n\n for (let i = 0; i < targets.length; i += parallelism) {\n const chunk = targets.slice(i, i + parallelism)\n const settled = await Promise.allSettled(\n chunk.map(async (proxy) => {\n const cap = (proxy as unknown as Record<string, Record<string, (input: unknown) => unknown>>)[capName]\n if (!cap || typeof cap[methodName] !== 'function') {\n throw new Error(`device '${proxy.deviceId}' does not expose '${capName}.${methodName}'`)\n }\n return await cap[methodName]!(args) as R\n }),\n )\n for (let j = 0; j < settled.length; j++) {\n const proxy = chunk[j]!\n const r = settled[j]!\n if (r.status === 'fulfilled') {\n out.push({ deviceId: proxy.deviceId, ok: true, result: r.value })\n } else {\n out.push({ deviceId: proxy.deviceId, ok: false, error: r.reason })\n }\n }\n }\n\n return out\n }\n\n // ── Diagnostics ────────────────────────────────────────────────────\n\n /**\n * One-shot summary — fleet size, breakdown by cap / addon / type.\n * Designed for REPL inspection (`sm.summary()`).\n */\n summary(): {\n totalDevices: number\n online: number\n offline: number\n byCap: Record<string, number>\n byAddon: Record<string, number>\n byType: Record<string, number>\n statedDevices: number\n } {\n const byCap: Record<string, number> = {}\n const byAddon: Record<string, number> = {}\n const byType: Record<string, number> = {}\n let online = 0\n let offline = 0\n\n for (const binding of this.bindings.values()) {\n for (const entry of binding.entries) {\n byCap[entry.capName] = (byCap[entry.capName] ?? 0) + 1\n }\n }\n\n for (const info of this.devices.values()) {\n byAddon[info.addonId] = (byAddon[info.addonId] ?? 0) + 1\n byType[info.type] = (byType[info.type] ?? 0) + 1\n if (info.online) online++; else offline++\n }\n\n return {\n totalDevices: this.bindings.size,\n online,\n offline,\n byCap,\n byAddon,\n byType,\n statedDevices: this.stateMirror.size,\n }\n }\n\n /**\n * Debug-friendly dump — full state + binding + metadata for one\n * device or all devices. Cheap deep clone so caller mutations don't\n * leak into the mirror.\n */\n dump(deviceId?: number): unknown {\n const dumpOne = (id: number): unknown => {\n const info = this.devices.get(id) ?? null\n const binding = this.bindings.get(id) ?? null\n const state: Record<string, Record<string, unknown>> = {}\n const perCap = this.stateMirror.get(id)\n if (perCap) {\n for (const [cap, slice] of perCap) state[cap] = { ...slice }\n }\n return {\n deviceId: id,\n info,\n binding: binding ? { ...binding, entries: binding.entries.map((e) => ({ ...e })) } : null,\n state,\n }\n }\n\n if (deviceId !== undefined) return dumpOne(deviceId)\n\n const out: unknown[] = []\n for (const id of this.bindings.keys()) out.push(dumpOne(id))\n return out\n }\n\n /**\n * Direct read-only access to the underlying state mirror. Use\n * sparingly — `getSystemState` returns a deep copy that's safer for\n * exploratory work; this avoids the clone cost when iterating\n * thousands of slices.\n */\n getRawMirror(): ReadonlyMap<number, ReadonlyMap<string, Record<string, unknown>>> {\n return this.stateMirror\n }\n\n /**\n * Snapshot of the full state mirror — same shape as the warm-boot\n * payload. Deep-cloned; safe to mutate.\n */\n getSystemState(): Map<number, Map<string, Record<string, unknown>>> {\n const copy = new Map<number, Map<string, Record<string, unknown>>>()\n for (const [id, perCap] of this.stateMirror) {\n const dup = new Map<string, Record<string, unknown>>()\n for (const [k, v] of perCap) dup.set(k, { ...v })\n copy.set(id, dup)\n }\n return copy\n }\n\n // ── Internals ──────────────────────────────────────────────────────\n\n private subscribeBus(): void {\n if (!this.api.live?.onEvent) return\n const sub = this.api.live.onEvent\n\n this.bridges.push(\n sub.subscribe(\n { category: STATE_CHANGED_CATEGORY },\n {\n onData: (evt) => {\n const data = evt.data as { deviceId?: number; capName?: string; slice?: Record<string, unknown> } | null\n if (!data || typeof data.deviceId !== 'number' || typeof data.capName !== 'string') return\n this.applyStateUpdate(data.deviceId, data.capName, data.slice)\n },\n },\n ),\n )\n\n this.bridges.push(\n sub.subscribe(\n { category: BINDING_CHANGED_CATEGORY },\n {\n onData: (evt) => {\n const data = evt.data as { deviceId?: number; source?: { type?: string; id?: number | string } } | null\n const deviceId =\n typeof data?.deviceId === 'number'\n ? data.deviceId\n : data?.source?.type === 'device' && typeof data.source.id === 'number'\n ? data.source.id\n : null\n if (deviceId === null) return\n void this.refreshBinding(deviceId)\n },\n },\n ),\n )\n\n this.bridges.push(\n sub.subscribe(\n { category: DEVICE_REGISTERED_CATEGORY },\n {\n onData: (evt) => {\n const data = evt.data as { deviceId?: number } | null\n if (typeof data?.deviceId !== 'number') return\n void this.refreshDeviceMetadata(data.deviceId, 'added')\n },\n },\n ),\n )\n\n this.bridges.push(\n sub.subscribe(\n { category: DEVICE_UNREGISTERED_CATEGORY },\n {\n onData: (evt) => {\n const data = evt.data as { deviceId?: number } | null\n if (typeof data?.deviceId !== 'number') return\n this.applyDeviceRemoval(data.deviceId)\n },\n },\n ),\n )\n\n this.bridges.push(\n sub.subscribe(\n { category: DEVICE_UPDATED_CATEGORY },\n {\n onData: (evt) => {\n const data = evt.data as { deviceId?: number } | null\n if (typeof data?.deviceId !== 'number') return\n void this.refreshDeviceMetadata(data.deviceId, 'updated')\n },\n },\n ),\n )\n }\n\n private applyStateUpdate(\n deviceId: number,\n capName: string,\n slice: Record<string, unknown> | undefined,\n ): void {\n let perCap = this.stateMirror.get(deviceId)\n if (!perCap) {\n perCap = new Map()\n this.stateMirror.set(deviceId, perCap)\n }\n if (slice === undefined) {\n perCap.delete(capName)\n } else {\n perCap.set(capName, slice)\n }\n\n const handleKey = `${deviceId}:${capName}`\n const handleSet = this.handleListeners.get(handleKey)\n if (handleSet) {\n for (const cb of handleSet) {\n try { cb(slice) } catch { /* isolated */ }\n }\n }\n\n for (const cb of this.globalStateListeners) {\n try { cb(deviceId, capName, slice) } catch { /* isolated */ }\n }\n\n const capSet = this.capListeners.get(capName)\n if (capSet) {\n for (const cb of capSet) {\n try { cb(deviceId, slice) } catch { /* isolated */ }\n }\n }\n\n const devSet = this.deviceListeners.get(deviceId)\n if (devSet) {\n for (const cb of devSet) {\n try { cb(deviceId, capName, slice) } catch { /* isolated */ }\n }\n }\n }\n\n private applyDeviceRemoval(deviceId: number): void {\n const lastInfo = this.devices.get(deviceId) ?? null\n this.bindings.delete(deviceId)\n this.devices.delete(deviceId)\n this.stateMirror.delete(deviceId)\n for (const cb of this.removedListeners) {\n try { cb(deviceId, lastInfo) } catch { /* isolated */ }\n }\n }\n\n private async refreshBinding(deviceId: number): Promise<void> {\n try {\n const all = await this.api.deviceManager.getAllBindings.query({})\n const fresh = all.find((b) => b.deviceId === deviceId)\n if (fresh) {\n this.bindings.set(deviceId, fresh)\n } else {\n // Device was removed — emit lifecycle hook so consumers can\n // clean up. Use the same path as `device.unregistered` events.\n this.applyDeviceRemoval(deviceId)\n }\n } catch {\n // Transient failure — leave stale binding; next event retries.\n }\n }\n\n private async refreshDeviceMetadata(deviceId: number, kind: 'added' | 'updated'): Promise<void> {\n try {\n // listAll is cheap and idempotent. Single-device fetch\n // (`getDevice(id)`) would be lighter but means another method\n // on the api surface for tests; sticking with listAll keeps the\n // contract small.\n const all = await this.api.deviceManager.listAll.query({})\n const info = all.find((d) => d.id === deviceId)\n if (!info) return\n\n const wasNew = !this.devices.has(deviceId)\n this.devices.set(deviceId, info)\n\n if (kind === 'added' && wasNew) {\n // `device.registered` event ran but the bindings/state for\n // the new device may still be in flight from the worker.\n // Refresh bindings so consumers can immediately use the\n // device proxy. Lifecycle listener fires after binding lands.\n await this.refreshBinding(deviceId)\n for (const cb of this.addedListeners) {\n try { cb(deviceId, info) } catch { /* isolated */ }\n }\n }\n } catch {\n /* transient — next event retries */\n }\n }\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────\n\nfunction inSet<T>(value: T, set: T | readonly T[]): boolean {\n if (Array.isArray(set)) return (set as readonly T[]).includes(value)\n return value === set\n}\n\nfunction toArray<T>(value: T | readonly T[]): readonly T[] {\n return Array.isArray(value) ? (value as readonly T[]) : [value as T]\n}\n\nfunction matchesString(haystack: string, match: StringMatch): boolean {\n if (typeof match === 'string') return haystack === match\n if (match instanceof RegExp) return match.test(haystack)\n if ('exact' in match) return haystack === match.exact\n if ('contains' in match) return haystack.toLowerCase().includes(match.contains.toLowerCase())\n return false\n}\n\n","/**\n * Custom-action contracts — a mechanism for addons to expose system-level\n * extensibility endpoints (e.g. benchmark addon API) through a single\n * generic `api.addons.custom` tRPC endpoint.\n *\n * The contract shape mirrors `method()` from capability-definition.ts —\n * input/output Zod schemas, kind, auth — plus a `scope` discriminated union\n * (today only 'system' is runtime-supported; 'device' is typed for forward\n * compat).\n */\n\nimport type { z } from 'zod'\nimport type { DeviceType } from '../device/device-type.js'\nimport type { CapabilityMethodAuth } from './capability-definition.js'\n\n/** Scope of a custom action. Today only `system` is supported by the runtime. */\nexport type CustomActionScope =\n | { readonly kind: 'system' }\n | { readonly kind: 'device'; readonly deviceTypes?: readonly DeviceType[] }\n\nexport interface CustomActionSpec<\n TIn extends z.ZodType = z.ZodType,\n TOut extends z.ZodType = z.ZodType,\n TKind extends 'query' | 'mutation' | 'subscription' = 'query' | 'mutation' | 'subscription',\n TAuth extends CapabilityMethodAuth = CapabilityMethodAuth,\n TScope extends CustomActionScope = CustomActionScope,\n> {\n readonly input: TIn\n readonly output: TOut\n readonly kind: TKind\n readonly auth: TAuth\n readonly scope: TScope\n}\n\nexport type CustomActionsSpec = Record<string, CustomActionSpec>\n\n/**\n * Identity — preserves literal types for downstream inference.\n *\n * The constraint is `Record<string, unknown>` (not `CustomActionsSpec`) so\n * TypeScript does not widen each entry's literal `kind`/`auth` fields to\n * the broader unions declared on `CustomActionSpec`'s default generics.\n * Shape validity is enforced separately by the `customAction(...)` helper\n * whose return type is already a `CustomActionSpec<...>`.\n */\nexport function defineCustomActions<T extends Record<string, unknown>>(spec: T): T {\n return spec\n}\n\nexport interface CustomActionOptions<\n TKind extends 'query' | 'mutation' | 'subscription' = 'query',\n TAuth extends CapabilityMethodAuth = 'protected',\n> {\n readonly kind?: TKind\n readonly auth?: TAuth\n readonly scope?: CustomActionScope\n}\n\nexport function customAction<\n TIn extends z.ZodType,\n TOut extends z.ZodType,\n TKind extends 'query' | 'mutation' | 'subscription' = 'query',\n TAuth extends CapabilityMethodAuth = 'protected',\n>(\n input: TIn,\n output: TOut,\n options?: CustomActionOptions<TKind, TAuth>,\n): CustomActionSpec<TIn, TOut, TKind, TAuth, { readonly kind: 'system' }> {\n return {\n input,\n output,\n kind: (options?.kind ?? 'query') as TKind,\n auth: (options?.auth ?? 'protected') as TAuth,\n scope: (options?.scope ?? { kind: 'system' as const }) as { readonly kind: 'system' },\n }\n}\n","// AUTO-GENERATED by scripts/generate-capability-router-types.ts — DO NOT EDIT\n// Re-run after adding/modifying capability definitions.\n//\n// Generated: 2026-05-11T10:11:04.228Z\n// Capabilities: 80\n\n// ── Capability Definition Imports ────────────────────────────────────\n\nexport { accessoriesCapability } from '../capabilities/accessories.cap.js'\nexport { addonPagesCapability } from '../capabilities/addon-pages.cap.js'\nexport { addonPagesSourceCapability } from '../capabilities/addon-pages-source.cap.js'\nexport { addonRoutesCapability } from '../capabilities/addon-routes.cap.js'\nexport { addonSettingsCapability } from '../capabilities/addon-settings.cap.js'\nexport { addonWidgetsCapability } from '../capabilities/addon-widgets.cap.js'\nexport { addonWidgetsSourceCapability } from '../capabilities/addon-widgets-source.cap.js'\nexport { addonsCapability } from '../capabilities/addons.cap.js'\nexport { adminUiCapability } from '../capabilities/admin-ui.cap.js'\nexport { advancedNotifierCapability } from '../capabilities/advanced-notifier.cap.js'\nexport { alertsCapability } from '../capabilities/alerts.cap.js'\nexport { audioAnalysisCapability } from '../capabilities/audio-analysis.cap.js'\nexport { audioAnalyzerCapability } from '../capabilities/audio-analyzer.cap.js'\nexport { audioCodecCapability } from '../capabilities/audio-codec.cap.js'\nexport { audioMetricsCapability } from '../capabilities/audio-metrics.cap.js'\nexport { authProviderCapability } from '../capabilities/auth-provider.cap.js'\nexport { authenticationCapability } from '../capabilities/authentication.cap.js'\nexport { backupCapability } from '../capabilities/backup.cap.js'\nexport { batteryCapability } from '../capabilities/battery.cap.js'\nexport { brightnessCapability } from '../capabilities/brightness.cap.js'\nexport { cameraCredentialsCapability } from '../capabilities/camera-credentials.cap.js'\nexport { cameraStreamsCapability } from '../capabilities/camera-streams.cap.js'\nexport { decoderCapability } from '../capabilities/decoder.cap.js'\nexport { detectionPipelineCapability } from '../capabilities/detection-pipeline.cap.js'\nexport { deviceDiscoveryCapability } from '../capabilities/device-discovery.cap.js'\nexport { deviceManagerCapability } from '../capabilities/device-manager.cap.js'\nexport { deviceOpsCapability } from '../capabilities/device-ops.cap.js'\nexport { deviceProviderCapability } from '../capabilities/device-provider.cap.js'\nexport { deviceStateCapability } from '../capabilities/device-state.cap.js'\nexport { deviceStatusCapability } from '../capabilities/device-status.cap.js'\nexport { doorbellCapability } from '../capabilities/doorbell.cap.js'\nexport { embeddingEncoderCapability } from '../capabilities/embedding-encoder.cap.js'\nexport { eventsCapability } from '../capabilities/events.cap.js'\nexport { featureProbeCapability } from '../capabilities/feature-probe.cap.js'\nexport { integrationsCapability } from '../capabilities/integrations.cap.js'\nexport { intercomCapability } from '../capabilities/intercom.cap.js'\nexport { localNetworkCapability } from '../capabilities/local-network.cap.js'\nexport { logDestinationCapability } from '../capabilities/log-destination.cap.js'\nexport { meshNetworkCapability } from '../capabilities/mesh-network.cap.js'\nexport { meshOrchestratorCapability } from '../capabilities/mesh-orchestrator.cap.js'\nexport { metricsProviderCapability } from '../capabilities/metrics-provider.cap.js'\nexport { motionCapability } from '../capabilities/motion.cap.js'\nexport { motionDetectionCapability } from '../capabilities/motion-detection.cap.js'\nexport { motionTriggerCapability } from '../capabilities/motion-trigger.cap.js'\nexport { nativeObjectDetectionCapability } from '../capabilities/native-object-detection.cap.js'\nexport { networkAccessCapability } from '../capabilities/network-access.cap.js'\nexport { networkQualityCapability } from '../capabilities/network-quality.cap.js'\nexport { nodesCapability } from '../capabilities/nodes.cap.js'\nexport { notificationOutputCapability } from '../capabilities/notification-output.cap.js'\nexport { osdCapability } from '../capabilities/osd.cap.js'\nexport { pipelineAnalyticsCapability } from '../capabilities/pipeline-analytics.cap.js'\nexport { pipelineExecutorCapability } from '../capabilities/pipeline-executor.cap.js'\nexport { pipelineOrchestratorCapability } from '../capabilities/pipeline-orchestrator.cap.js'\nexport { pipelineRunnerCapability } from '../capabilities/pipeline-runner.cap.js'\nexport { platformProbeCapability } from '../capabilities/platform-probe.cap.js'\nexport { ptzCapability } from '../capabilities/ptz.cap.js'\nexport { ptzAutotrackCapability } from '../capabilities/ptz-autotrack.cap.js'\nexport { rebootCapability } from '../capabilities/reboot.cap.js'\nexport { recordingCapability } from '../capabilities/recording.cap.js'\nexport { recordingEngineCapability } from '../capabilities/recording-engine.cap.js'\nexport { remoteAccessCapability } from '../capabilities/remote-access.cap.js'\nexport { restreamerCapability } from '../capabilities/restreamer.cap.js'\nexport { settingsStoreCapability } from '../capabilities/settings-store.cap.js'\nexport { snapshotCapability } from '../capabilities/snapshot.cap.js'\nexport { snapshotProviderCapability } from '../capabilities/snapshot-provider.cap.js'\nexport { storageCapability } from '../capabilities/storage.cap.js'\nexport { storageProviderCapability } from '../capabilities/storage-provider.cap.js'\nexport { streamBrokerCapability } from '../capabilities/stream-broker.cap.js'\nexport { streamingEngineCapability } from '../capabilities/streaming-engine.cap.js'\nexport { switchCapability } from '../capabilities/switch.cap.js'\nexport { systemCapability } from '../capabilities/system.cap.js'\nexport { toastCapability } from '../capabilities/toast.cap.js'\nexport { turnOrchestratorCapability } from '../capabilities/turn-orchestrator.cap.js'\nexport { turnProviderCapability } from '../capabilities/turn-provider.cap.js'\nexport { userManagementCapability } from '../capabilities/user-management.cap.js'\nexport { webrtcCapability } from '../capabilities/webrtc.cap.js'\nexport { webrtcSessionCapability } from '../capabilities/webrtc-session.cap.js'\nexport { zoneAnalyticsCapability } from '../capabilities/zone-analytics.cap.js'\nexport { zoneRulesCapability } from '../capabilities/zone-rules.cap.js'\nexport { zonesCapability } from '../capabilities/zones.cap.js'\n\n// ── Capability Names (for registry key constants) ────────────────────\n\nexport const CAPABILITY_NAMES = {\n accessories: 'accessories' as const,\n addonPages: 'addon-pages' as const,\n addonPagesSource: 'addon-pages-source' as const,\n addonRoutes: 'addon-routes' as const,\n addonSettings: 'addon-settings' as const,\n addonWidgets: 'addon-widgets' as const,\n addonWidgetsSource: 'addon-widgets-source' as const,\n addons: 'addons' as const,\n adminUi: 'admin-ui' as const,\n advancedNotifier: 'advanced-notifier' as const,\n alerts: 'alerts' as const,\n audioAnalysis: 'audio-analysis' as const,\n audioAnalyzer: 'audio-analyzer' as const,\n audioCodec: 'audio-codec' as const,\n audioMetrics: 'audio-metrics' as const,\n authProvider: 'auth-provider' as const,\n authentication: 'authentication' as const,\n backup: 'backup' as const,\n battery: 'battery' as const,\n brightness: 'brightness' as const,\n cameraCredentials: 'camera-credentials' as const,\n cameraStreams: 'camera-streams' as const,\n decoder: 'decoder' as const,\n detectionPipeline: 'detection-pipeline' as const,\n deviceDiscovery: 'device-discovery' as const,\n deviceManager: 'device-manager' as const,\n deviceOps: 'device-ops' as const,\n deviceProvider: 'device-provider' as const,\n deviceState: 'device-state' as const,\n deviceStatus: 'device-status' as const,\n doorbell: 'doorbell' as const,\n embeddingEncoder: 'embedding-encoder' as const,\n events: 'events' as const,\n featureProbe: 'feature-probe' as const,\n integrations: 'integrations' as const,\n intercom: 'intercom' as const,\n localNetwork: 'local-network' as const,\n logDestination: 'log-destination' as const,\n meshNetwork: 'mesh-network' as const,\n meshOrchestrator: 'mesh-orchestrator' as const,\n metricsProvider: 'metrics-provider' as const,\n motion: 'motion' as const,\n motionDetection: 'motion-detection' as const,\n motionTrigger: 'motion-trigger' as const,\n nativeObjectDetection: 'native-object-detection' as const,\n networkAccess: 'network-access' as const,\n networkQuality: 'network-quality' as const,\n nodes: 'nodes' as const,\n notificationOutput: 'notification-output' as const,\n osd: 'osd' as const,\n pipelineAnalytics: 'pipeline-analytics' as const,\n pipelineExecutor: 'pipeline-executor' as const,\n pipelineOrchestrator: 'pipeline-orchestrator' as const,\n pipelineRunner: 'pipeline-runner' as const,\n platformProbe: 'platform-probe' as const,\n ptz: 'ptz' as const,\n ptzAutotrack: 'ptz-autotrack' as const,\n reboot: 'reboot' as const,\n recording: 'recording' as const,\n recordingEngine: 'recording-engine' as const,\n remoteAccess: 'remote-access' as const,\n restreamer: 'restreamer' as const,\n settingsStore: 'settings-store' as const,\n snapshot: 'snapshot' as const,\n snapshotProvider: 'snapshot-provider' as const,\n storage: 'storage' as const,\n storageProvider: 'storage-provider' as const,\n streamBroker: 'stream-broker' as const,\n streamingEngine: 'streaming-engine' as const,\n switch: 'switch' as const,\n system: 'system' as const,\n toast: 'toast' as const,\n turnOrchestrator: 'turn-orchestrator' as const,\n turnProvider: 'turn-provider' as const,\n userManagement: 'user-management' as const,\n webrtc: 'webrtc' as const,\n webrtcSession: 'webrtc-session' as const,\n zoneAnalytics: 'zone-analytics' as const,\n zoneRules: 'zone-rules' as const,\n zones: 'zones' as const,\n} as const\n\n/** All known capability names. */\nexport type CapabilityName = typeof CAPABILITY_NAMES[keyof typeof CAPABILITY_NAMES]\n\n/** Router key → capability name mapping for auto-mount. */\nexport const CAPABILITY_ROUTER_KEYS: ReadonlyArray<{ readonly key: string; readonly name: string }> = [\n { key: 'accessories', name: 'accessories' },\n { key: 'addonPages', name: 'addon-pages' },\n { key: 'addonPagesSource', name: 'addon-pages-source' },\n { key: 'addonRoutes', name: 'addon-routes' },\n { key: 'addonSettings', name: 'addon-settings' },\n { key: 'addonWidgets', name: 'addon-widgets' },\n { key: 'addonWidgetsSource', name: 'addon-widgets-source' },\n { key: 'addons', name: 'addons' },\n { key: 'adminUi', name: 'admin-ui' },\n { key: 'advancedNotifier', name: 'advanced-notifier' },\n { key: 'alerts', name: 'alerts' },\n { key: 'audioAnalysis', name: 'audio-analysis' },\n { key: 'audioAnalyzer', name: 'audio-analyzer' },\n { key: 'audioCodec', name: 'audio-codec' },\n { key: 'audioMetrics', name: 'audio-metrics' },\n { key: 'authProvider', name: 'auth-provider' },\n { key: 'authentication', name: 'authentication' },\n { key: 'backup', name: 'backup' },\n { key: 'battery', name: 'battery' },\n { key: 'brightness', name: 'brightness' },\n { key: 'cameraCredentials', name: 'camera-credentials' },\n { key: 'cameraStreams', name: 'camera-streams' },\n { key: 'decoder', name: 'decoder' },\n { key: 'detectionPipeline', name: 'detection-pipeline' },\n { key: 'deviceDiscovery', name: 'device-discovery' },\n { key: 'deviceManager', name: 'device-manager' },\n { key: 'deviceOps', name: 'device-ops' },\n { key: 'deviceProvider', name: 'device-provider' },\n { key: 'deviceState', name: 'device-state' },\n { key: 'deviceStatus', name: 'device-status' },\n { key: 'doorbell', name: 'doorbell' },\n { key: 'embeddingEncoder', name: 'embedding-encoder' },\n { key: 'events', name: 'events' },\n { key: 'featureProbe', name: 'feature-probe' },\n { key: 'integrations', name: 'integrations' },\n { key: 'intercom', name: 'intercom' },\n { key: 'localNetwork', name: 'local-network' },\n { key: 'logDestination', name: 'log-destination' },\n { key: 'meshNetwork', name: 'mesh-network' },\n { key: 'meshOrchestrator', name: 'mesh-orchestrator' },\n { key: 'metricsProvider', name: 'metrics-provider' },\n { key: 'motion', name: 'motion' },\n { key: 'motionDetection', name: 'motion-detection' },\n { key: 'motionTrigger', name: 'motion-trigger' },\n { key: 'nativeObjectDetection', name: 'native-object-detection' },\n { key: 'networkAccess', name: 'network-access' },\n { key: 'networkQuality', name: 'network-quality' },\n { key: 'nodes', name: 'nodes' },\n { key: 'notificationOutput', name: 'notification-output' },\n { key: 'osd', name: 'osd' },\n { key: 'pipelineAnalytics', name: 'pipeline-analytics' },\n { key: 'pipelineExecutor', name: 'pipeline-executor' },\n { key: 'pipelineOrchestrator', name: 'pipeline-orchestrator' },\n { key: 'pipelineRunner', name: 'pipeline-runner' },\n { key: 'platformProbe', name: 'platform-probe' },\n { key: 'ptz', name: 'ptz' },\n { key: 'ptzAutotrack', name: 'ptz-autotrack' },\n { key: 'reboot', name: 'reboot' },\n { key: 'recording', name: 'recording' },\n { key: 'recordingEngine', name: 'recording-engine' },\n { key: 'remoteAccess', name: 'remote-access' },\n { key: 'restreamer', name: 'restreamer' },\n { key: 'settingsStore', name: 'settings-store' },\n { key: 'snapshot', name: 'snapshot' },\n { key: 'snapshotProvider', name: 'snapshot-provider' },\n { key: 'storage', name: 'storage' },\n { key: 'storageProvider', name: 'storage-provider' },\n { key: 'streamBroker', name: 'stream-broker' },\n { key: 'streamingEngine', name: 'streaming-engine' },\n { key: 'switch', name: 'switch' },\n { key: 'system', name: 'system' },\n { key: 'toast', name: 'toast' },\n { key: 'turnOrchestrator', name: 'turn-orchestrator' },\n { key: 'turnProvider', name: 'turn-provider' },\n { key: 'userManagement', name: 'user-management' },\n { key: 'webrtc', name: 'webrtc' },\n { key: 'webrtcSession', name: 'webrtc-session' },\n { key: 'zoneAnalytics', name: 'zone-analytics' },\n { key: 'zoneRules', name: 'zone-rules' },\n { key: 'zones', name: 'zones' },\n]\n// ── Typed Router Map (for AppRouter) ─────────────────────────────────\n//\n// Import CapabilityTRPCRouter from the server to type the map.\n// This type is consumed by trpc.router.ts for typed spread.\n\n/**\n * Map of {name} → TRouter for typed AppRouter spread.\n * Generic TRouter defaults to unknown — the server layer resolves it\n * to the generated capability router type.\n */\nexport interface CapabilityRouterMap<TRouter = unknown> {\n readonly accessories: TRouter\n readonly addonPages: TRouter\n readonly addonPagesSource: TRouter\n readonly addonRoutes: TRouter\n readonly addonSettings: TRouter\n readonly addonWidgets: TRouter\n readonly addonWidgetsSource: TRouter\n readonly addons: TRouter\n readonly adminUi: TRouter\n readonly advancedNotifier: TRouter\n readonly alerts: TRouter\n readonly audioAnalysis: TRouter\n readonly audioAnalyzer: TRouter\n readonly audioCodec: TRouter\n readonly audioMetrics: TRouter\n readonly authProvider: TRouter\n readonly authentication: TRouter\n readonly backup: TRouter\n readonly battery: TRouter\n readonly brightness: TRouter\n readonly cameraCredentials: TRouter\n readonly cameraStreams: TRouter\n readonly decoder: TRouter\n readonly detectionPipeline: TRouter\n readonly deviceDiscovery: TRouter\n readonly deviceManager: TRouter\n readonly deviceOps: TRouter\n readonly deviceProvider: TRouter\n readonly deviceState: TRouter\n readonly deviceStatus: TRouter\n readonly doorbell: TRouter\n readonly embeddingEncoder: TRouter\n readonly events: TRouter\n readonly featureProbe: TRouter\n readonly integrations: TRouter\n readonly intercom: TRouter\n readonly localNetwork: TRouter\n readonly logDestination: TRouter\n readonly meshNetwork: TRouter\n readonly meshOrchestrator: TRouter\n readonly metricsProvider: TRouter\n readonly motion: TRouter\n readonly motionDetection: TRouter\n readonly motionTrigger: TRouter\n readonly nativeObjectDetection: TRouter\n readonly networkAccess: TRouter\n readonly networkQuality: TRouter\n readonly nodes: TRouter\n readonly notificationOutput: TRouter\n readonly osd: TRouter\n readonly pipelineAnalytics: TRouter\n readonly pipelineExecutor: TRouter\n readonly pipelineOrchestrator: TRouter\n readonly pipelineRunner: TRouter\n readonly platformProbe: TRouter\n readonly ptz: TRouter\n readonly ptzAutotrack: TRouter\n readonly reboot: TRouter\n readonly recording: TRouter\n readonly recordingEngine: TRouter\n readonly remoteAccess: TRouter\n readonly restreamer: TRouter\n readonly settingsStore: TRouter\n readonly snapshot: TRouter\n readonly snapshotProvider: TRouter\n readonly storage: TRouter\n readonly storageProvider: TRouter\n readonly streamBroker: TRouter\n readonly streamingEngine: TRouter\n readonly switch: TRouter\n readonly system: TRouter\n readonly toast: TRouter\n readonly turnOrchestrator: TRouter\n readonly turnProvider: TRouter\n readonly userManagement: TRouter\n readonly webrtc: TRouter\n readonly webrtcSession: TRouter\n readonly zoneAnalytics: TRouter\n readonly zoneRules: TRouter\n readonly zones: TRouter\n}\n\n// ── Singleton / Collection split (derived from cap.mode) ─────────────\n\n/** Capability names whose mode is `singleton` (65 caps). */\nexport const SINGLETON_CAPABILITY_NAMES = [\n 'accessories',\n 'addon-pages',\n 'addon-settings',\n 'addon-widgets',\n 'addons',\n 'admin-ui',\n 'advanced-notifier',\n 'alerts',\n 'audio-analysis',\n 'audio-analyzer',\n 'audio-codec',\n 'audio-metrics',\n 'authentication',\n 'backup',\n 'battery',\n 'brightness',\n 'camera-credentials',\n 'camera-streams',\n 'decoder',\n 'detection-pipeline',\n 'device-discovery',\n 'device-manager',\n 'device-ops',\n 'device-state',\n 'device-status',\n 'doorbell',\n 'events',\n 'feature-probe',\n 'integrations',\n 'intercom',\n 'local-network',\n 'mesh-orchestrator',\n 'metrics-provider',\n 'motion',\n 'motion-detection',\n 'motion-trigger',\n 'native-object-detection',\n 'network-quality',\n 'nodes',\n 'osd',\n 'pipeline-analytics',\n 'pipeline-executor',\n 'pipeline-orchestrator',\n 'pipeline-runner',\n 'platform-probe',\n 'ptz',\n 'ptz-autotrack',\n 'reboot',\n 'recording',\n 'recording-engine',\n 'remote-access',\n 'settings-store',\n 'snapshot',\n 'storage',\n 'stream-broker',\n 'streaming-engine',\n 'switch',\n 'system',\n 'toast',\n 'turn-orchestrator',\n 'user-management',\n 'webrtc-session',\n 'zone-analytics',\n 'zone-rules',\n 'zones',\n] as const\n\n/** Union of singleton capability names (literal string union). */\nexport type SingletonCapabilityName = typeof SINGLETON_CAPABILITY_NAMES[number]\n\n/** Capability names whose mode is `collection` (15 caps). */\nexport const COLLECTION_CAPABILITY_NAMES = [\n 'addon-pages-source',\n 'addon-routes',\n 'addon-widgets-source',\n 'auth-provider',\n 'device-provider',\n 'embedding-encoder',\n 'log-destination',\n 'mesh-network',\n 'network-access',\n 'notification-output',\n 'restreamer',\n 'snapshot-provider',\n 'storage-provider',\n 'turn-provider',\n 'webrtc',\n] as const\n\n/** Union of collection capability names (literal string union). */\nexport type CollectionCapabilityName = typeof COLLECTION_CAPABILITY_NAMES[number]\n\n/** Capability mode lookup at runtime — mirrors the `.cap.ts` definitions. */\nexport const CAPABILITY_MODE: Readonly<Record<string, 'singleton' | 'collection'>> = {\n 'accessories': 'singleton',\n 'addon-pages': 'singleton',\n 'addon-pages-source': 'collection',\n 'addon-routes': 'collection',\n 'addon-settings': 'singleton',\n 'addon-widgets': 'singleton',\n 'addon-widgets-source': 'collection',\n 'addons': 'singleton',\n 'admin-ui': 'singleton',\n 'advanced-notifier': 'singleton',\n 'alerts': 'singleton',\n 'audio-analysis': 'singleton',\n 'audio-analyzer': 'singleton',\n 'audio-codec': 'singleton',\n 'audio-metrics': 'singleton',\n 'auth-provider': 'collection',\n 'authentication': 'singleton',\n 'backup': 'singleton',\n 'battery': 'singleton',\n 'brightness': 'singleton',\n 'camera-credentials': 'singleton',\n 'camera-streams': 'singleton',\n 'decoder': 'singleton',\n 'detection-pipeline': 'singleton',\n 'device-discovery': 'singleton',\n 'device-manager': 'singleton',\n 'device-ops': 'singleton',\n 'device-provider': 'collection',\n 'device-state': 'singleton',\n 'device-status': 'singleton',\n 'doorbell': 'singleton',\n 'embedding-encoder': 'collection',\n 'events': 'singleton',\n 'feature-probe': 'singleton',\n 'integrations': 'singleton',\n 'intercom': 'singleton',\n 'local-network': 'singleton',\n 'log-destination': 'collection',\n 'mesh-network': 'collection',\n 'mesh-orchestrator': 'singleton',\n 'metrics-provider': 'singleton',\n 'motion': 'singleton',\n 'motion-detection': 'singleton',\n 'motion-trigger': 'singleton',\n 'native-object-detection': 'singleton',\n 'network-access': 'collection',\n 'network-quality': 'singleton',\n 'nodes': 'singleton',\n 'notification-output': 'collection',\n 'osd': 'singleton',\n 'pipeline-analytics': 'singleton',\n 'pipeline-executor': 'singleton',\n 'pipeline-orchestrator': 'singleton',\n 'pipeline-runner': 'singleton',\n 'platform-probe': 'singleton',\n 'ptz': 'singleton',\n 'ptz-autotrack': 'singleton',\n 'reboot': 'singleton',\n 'recording': 'singleton',\n 'recording-engine': 'singleton',\n 'remote-access': 'singleton',\n 'restreamer': 'collection',\n 'settings-store': 'singleton',\n 'snapshot': 'singleton',\n 'snapshot-provider': 'collection',\n 'storage': 'singleton',\n 'storage-provider': 'collection',\n 'stream-broker': 'singleton',\n 'streaming-engine': 'singleton',\n 'switch': 'singleton',\n 'system': 'singleton',\n 'toast': 'singleton',\n 'turn-orchestrator': 'singleton',\n 'turn-provider': 'collection',\n 'user-management': 'singleton',\n 'webrtc': 'collection',\n 'webrtc-session': 'singleton',\n 'zone-analytics': 'singleton',\n 'zone-rules': 'singleton',\n 'zones': 'singleton',\n}\n\n// ── All Capability Definitions (for boot-time declaration) ───────────\n\nimport type { CapabilityDefinition } from '../capabilities/capability-definition.js'\nimport { accessoriesCapability as _accessoriesCapability } from '../capabilities/accessories.cap.js'\nimport { addonPagesCapability as _addonPagesCapability } from '../capabilities/addon-pages.cap.js'\nimport { addonPagesSourceCapability as _addonPagesSourceCapability } from '../capabilities/addon-pages-source.cap.js'\nimport { addonRoutesCapability as _addonRoutesCapability } from '../capabilities/addon-routes.cap.js'\nimport { addonSettingsCapability as _addonSettingsCapability } from '../capabilities/addon-settings.cap.js'\nimport { addonWidgetsCapability as _addonWidgetsCapability } from '../capabilities/addon-widgets.cap.js'\nimport { addonWidgetsSourceCapability as _addonWidgetsSourceCapability } from '../capabilities/addon-widgets-source.cap.js'\nimport { addonsCapability as _addonsCapability } from '../capabilities/addons.cap.js'\nimport { adminUiCapability as _adminUiCapability } from '../capabilities/admin-ui.cap.js'\nimport { advancedNotifierCapability as _advancedNotifierCapability } from '../capabilities/advanced-notifier.cap.js'\nimport { alertsCapability as _alertsCapability } from '../capabilities/alerts.cap.js'\nimport { audioAnalysisCapability as _audioAnalysisCapability } from '../capabilities/audio-analysis.cap.js'\nimport { audioAnalyzerCapability as _audioAnalyzerCapability } from '../capabilities/audio-analyzer.cap.js'\nimport { audioCodecCapability as _audioCodecCapability } from '../capabilities/audio-codec.cap.js'\nimport { audioMetricsCapability as _audioMetricsCapability } from '../capabilities/audio-metrics.cap.js'\nimport { authProviderCapability as _authProviderCapability } from '../capabilities/auth-provider.cap.js'\nimport { authenticationCapability as _authenticationCapability } from '../capabilities/authentication.cap.js'\nimport { backupCapability as _backupCapability } from '../capabilities/backup.cap.js'\nimport { batteryCapability as _batteryCapability } from '../capabilities/battery.cap.js'\nimport { brightnessCapability as _brightnessCapability } from '../capabilities/brightness.cap.js'\nimport { cameraCredentialsCapability as _cameraCredentialsCapability } from '../capabilities/camera-credentials.cap.js'\nimport { cameraStreamsCapability as _cameraStreamsCapability } from '../capabilities/camera-streams.cap.js'\nimport { decoderCapability as _decoderCapability } from '../capabilities/decoder.cap.js'\nimport { detectionPipelineCapability as _detectionPipelineCapability } from '../capabilities/detection-pipeline.cap.js'\nimport { deviceDiscoveryCapability as _deviceDiscoveryCapability } from '../capabilities/device-discovery.cap.js'\nimport { deviceManagerCapability as _deviceManagerCapability } from '../capabilities/device-manager.cap.js'\nimport { deviceOpsCapability as _deviceOpsCapability } from '../capabilities/device-ops.cap.js'\nimport { deviceProviderCapability as _deviceProviderCapability } from '../capabilities/device-provider.cap.js'\nimport { deviceStateCapability as _deviceStateCapability } from '../capabilities/device-state.cap.js'\nimport { deviceStatusCapability as _deviceStatusCapability } from '../capabilities/device-status.cap.js'\nimport { doorbellCapability as _doorbellCapability } from '../capabilities/doorbell.cap.js'\nimport { embeddingEncoderCapability as _embeddingEncoderCapability } from '../capabilities/embedding-encoder.cap.js'\nimport { eventsCapability as _eventsCapability } from '../capabilities/events.cap.js'\nimport { featureProbeCapability as _featureProbeCapability } from '../capabilities/feature-probe.cap.js'\nimport { integrationsCapability as _integrationsCapability } from '../capabilities/integrations.cap.js'\nimport { intercomCapability as _intercomCapability } from '../capabilities/intercom.cap.js'\nimport { localNetworkCapability as _localNetworkCapability } from '../capabilities/local-network.cap.js'\nimport { logDestinationCapability as _logDestinationCapability } from '../capabilities/log-destination.cap.js'\nimport { meshNetworkCapability as _meshNetworkCapability } from '../capabilities/mesh-network.cap.js'\nimport { meshOrchestratorCapability as _meshOrchestratorCapability } from '../capabilities/mesh-orchestrator.cap.js'\nimport { metricsProviderCapability as _metricsProviderCapability } from '../capabilities/metrics-provider.cap.js'\nimport { motionCapability as _motionCapability } from '../capabilities/motion.cap.js'\nimport { motionDetectionCapability as _motionDetectionCapability } from '../capabilities/motion-detection.cap.js'\nimport { motionTriggerCapability as _motionTriggerCapability } from '../capabilities/motion-trigger.cap.js'\nimport { nativeObjectDetectionCapability as _nativeObjectDetectionCapability } from '../capabilities/native-object-detection.cap.js'\nimport { networkAccessCapability as _networkAccessCapability } from '../capabilities/network-access.cap.js'\nimport { networkQualityCapability as _networkQualityCapability } from '../capabilities/network-quality.cap.js'\nimport { nodesCapability as _nodesCapability } from '../capabilities/nodes.cap.js'\nimport { notificationOutputCapability as _notificationOutputCapability } from '../capabilities/notification-output.cap.js'\nimport { osdCapability as _osdCapability } from '../capabilities/osd.cap.js'\nimport { pipelineAnalyticsCapability as _pipelineAnalyticsCapability } from '../capabilities/pipeline-analytics.cap.js'\nimport { pipelineExecutorCapability as _pipelineExecutorCapability } from '../capabilities/pipeline-executor.cap.js'\nimport { pipelineOrchestratorCapability as _pipelineOrchestratorCapability } from '../capabilities/pipeline-orchestrator.cap.js'\nimport { pipelineRunnerCapability as _pipelineRunnerCapability } from '../capabilities/pipeline-runner.cap.js'\nimport { platformProbeCapability as _platformProbeCapability } from '../capabilities/platform-probe.cap.js'\nimport { ptzCapability as _ptzCapability } from '../capabilities/ptz.cap.js'\nimport { ptzAutotrackCapability as _ptzAutotrackCapability } from '../capabilities/ptz-autotrack.cap.js'\nimport { rebootCapability as _rebootCapability } from '../capabilities/reboot.cap.js'\nimport { recordingCapability as _recordingCapability } from '../capabilities/recording.cap.js'\nimport { recordingEngineCapability as _recordingEngineCapability } from '../capabilities/recording-engine.cap.js'\nimport { remoteAccessCapability as _remoteAccessCapability } from '../capabilities/remote-access.cap.js'\nimport { restreamerCapability as _restreamerCapability } from '../capabilities/restreamer.cap.js'\nimport { settingsStoreCapability as _settingsStoreCapability } from '../capabilities/settings-store.cap.js'\nimport { snapshotCapability as _snapshotCapability } from '../capabilities/snapshot.cap.js'\nimport { snapshotProviderCapability as _snapshotProviderCapability } from '../capabilities/snapshot-provider.cap.js'\nimport { storageCapability as _storageCapability } from '../capabilities/storage.cap.js'\nimport { storageProviderCapability as _storageProviderCapability } from '../capabilities/storage-provider.cap.js'\nimport { streamBrokerCapability as _streamBrokerCapability } from '../capabilities/stream-broker.cap.js'\nimport { streamingEngineCapability as _streamingEngineCapability } from '../capabilities/streaming-engine.cap.js'\nimport { switchCapability as _switchCapability } from '../capabilities/switch.cap.js'\nimport { systemCapability as _systemCapability } from '../capabilities/system.cap.js'\nimport { toastCapability as _toastCapability } from '../capabilities/toast.cap.js'\nimport { turnOrchestratorCapability as _turnOrchestratorCapability } from '../capabilities/turn-orchestrator.cap.js'\nimport { turnProviderCapability as _turnProviderCapability } from '../capabilities/turn-provider.cap.js'\nimport { userManagementCapability as _userManagementCapability } from '../capabilities/user-management.cap.js'\nimport { webrtcCapability as _webrtcCapability } from '../capabilities/webrtc.cap.js'\nimport { webrtcSessionCapability as _webrtcSessionCapability } from '../capabilities/webrtc-session.cap.js'\nimport { zoneAnalyticsCapability as _zoneAnalyticsCapability } from '../capabilities/zone-analytics.cap.js'\nimport { zoneRulesCapability as _zoneRulesCapability } from '../capabilities/zone-rules.cap.js'\nimport { zonesCapability as _zonesCapability } from '../capabilities/zones.cap.js'\n\n/**\n * Every CapabilityDefinition shipped by `@camstack/types`. The hub\n * iterates this array at boot to declare each cap on the registry\n * before addons (in-process or via the Moleculer bridge) attempt\n * `registerProvider`. Adding a new cap means dropping a `*.cap.ts`\n * file in `packages/types/src/capabilities/` and re-running\n * `npx tsx scripts/generate-capability-router-types.ts` — no manual\n * edit to `main.ts` required.\n */\nexport const ALL_CAPABILITY_DEFINITIONS: readonly CapabilityDefinition[] = [\n _accessoriesCapability as CapabilityDefinition,\n _addonPagesCapability as CapabilityDefinition,\n _addonPagesSourceCapability as CapabilityDefinition,\n _addonRoutesCapability as CapabilityDefinition,\n _addonSettingsCapability as CapabilityDefinition,\n _addonWidgetsCapability as CapabilityDefinition,\n _addonWidgetsSourceCapability as CapabilityDefinition,\n _addonsCapability as CapabilityDefinition,\n _adminUiCapability as CapabilityDefinition,\n _advancedNotifierCapability as CapabilityDefinition,\n _alertsCapability as CapabilityDefinition,\n _audioAnalysisCapability as CapabilityDefinition,\n _audioAnalyzerCapability as CapabilityDefinition,\n _audioCodecCapability as CapabilityDefinition,\n _audioMetricsCapability as CapabilityDefinition,\n _authProviderCapability as CapabilityDefinition,\n _authenticationCapability as CapabilityDefinition,\n _backupCapability as CapabilityDefinition,\n _batteryCapability as CapabilityDefinition,\n _brightnessCapability as CapabilityDefinition,\n _cameraCredentialsCapability as CapabilityDefinition,\n _cameraStreamsCapability as CapabilityDefinition,\n _decoderCapability as CapabilityDefinition,\n _detectionPipelineCapability as CapabilityDefinition,\n _deviceDiscoveryCapability as CapabilityDefinition,\n _deviceManagerCapability as CapabilityDefinition,\n _deviceOpsCapability as CapabilityDefinition,\n _deviceProviderCapability as CapabilityDefinition,\n _deviceStateCapability as CapabilityDefinition,\n _deviceStatusCapability as CapabilityDefinition,\n _doorbellCapability as CapabilityDefinition,\n _embeddingEncoderCapability as CapabilityDefinition,\n _eventsCapability as CapabilityDefinition,\n _featureProbeCapability as CapabilityDefinition,\n _integrationsCapability as CapabilityDefinition,\n _intercomCapability as CapabilityDefinition,\n _localNetworkCapability as CapabilityDefinition,\n _logDestinationCapability as CapabilityDefinition,\n _meshNetworkCapability as CapabilityDefinition,\n _meshOrchestratorCapability as CapabilityDefinition,\n _metricsProviderCapability as CapabilityDefinition,\n _motionCapability as CapabilityDefinition,\n _motionDetectionCapability as CapabilityDefinition,\n _motionTriggerCapability as CapabilityDefinition,\n _nativeObjectDetectionCapability as CapabilityDefinition,\n _networkAccessCapability as CapabilityDefinition,\n _networkQualityCapability as CapabilityDefinition,\n _nodesCapability as CapabilityDefinition,\n _notificationOutputCapability as CapabilityDefinition,\n _osdCapability as CapabilityDefinition,\n _pipelineAnalyticsCapability as CapabilityDefinition,\n _pipelineExecutorCapability as CapabilityDefinition,\n _pipelineOrchestratorCapability as CapabilityDefinition,\n _pipelineRunnerCapability as CapabilityDefinition,\n _platformProbeCapability as CapabilityDefinition,\n _ptzCapability as CapabilityDefinition,\n _ptzAutotrackCapability as CapabilityDefinition,\n _rebootCapability as CapabilityDefinition,\n _recordingCapability as CapabilityDefinition,\n _recordingEngineCapability as CapabilityDefinition,\n _remoteAccessCapability as CapabilityDefinition,\n _restreamerCapability as CapabilityDefinition,\n _settingsStoreCapability as CapabilityDefinition,\n _snapshotCapability as CapabilityDefinition,\n _snapshotProviderCapability as CapabilityDefinition,\n _storageCapability as CapabilityDefinition,\n _storageProviderCapability as CapabilityDefinition,\n _streamBrokerCapability as CapabilityDefinition,\n _streamingEngineCapability as CapabilityDefinition,\n _switchCapability as CapabilityDefinition,\n _systemCapability as CapabilityDefinition,\n _toastCapability as CapabilityDefinition,\n _turnOrchestratorCapability as CapabilityDefinition,\n _turnProviderCapability as CapabilityDefinition,\n _userManagementCapability as CapabilityDefinition,\n _webrtcCapability as CapabilityDefinition,\n _webrtcSessionCapability as CapabilityDefinition,\n _zoneAnalyticsCapability as CapabilityDefinition,\n _zoneRulesCapability as CapabilityDefinition,\n _zonesCapability as CapabilityDefinition,\n]\n\n","/* AUTO-GENERATED by scripts/generate-cap-status-types.ts. DO NOT EDIT. */\n/* eslint-disable */\n\nimport type { z } from 'zod'\n\nimport { AccessoriesStatusSchema } from '../capabilities/accessories.cap.js'\nimport { BatteryStatusSchema } from '../capabilities/battery.cap.js'\nimport { BrightnessStatusSchema } from '../capabilities/brightness.cap.js'\nimport { CameraCredentialsStatusSchema } from '../capabilities/camera-credentials.cap.js'\nimport { DeviceDiscoveryStatusSchema } from '../capabilities/device-discovery.cap.js'\nimport { deviceStatusCapability } from '../capabilities/device-status.cap.js'\nimport { DoorbellStatusSchema } from '../capabilities/doorbell.cap.js'\nimport { FeatureProbeStatusSchema } from '../capabilities/feature-probe.cap.js'\nimport { IntercomStatusSchema } from '../capabilities/intercom.cap.js'\nimport { MotionStatusSchema } from '../capabilities/motion.cap.js'\nimport { MotionTriggerStatusSchema } from '../capabilities/motion-trigger.cap.js'\nimport { NativeObjectDetectionStatusSchema } from '../capabilities/native-object-detection.cap.js'\nimport { OsdStatusSchema } from '../capabilities/osd.cap.js'\nimport { ptzCapability } from '../capabilities/ptz.cap.js'\nimport { PtzAutotrackStatusSchema } from '../capabilities/ptz-autotrack.cap.js'\nimport { SnapshotStatusSchema } from '../capabilities/snapshot.cap.js'\nimport { SwitchStatusSchema } from '../capabilities/switch.cap.js'\n\n/**\n * Lookup from cap name (literal) → the TypeScript type of that\n * capability's `status.schema`. Populated at codegen time from every\n * `*.cap.ts` file that declares a `status` block.\n */\nexport type CapStatusTypeMap = {\n readonly 'accessories': z.infer<typeof AccessoriesStatusSchema>\n readonly 'battery': z.infer<typeof BatteryStatusSchema>\n readonly 'brightness': z.infer<typeof BrightnessStatusSchema>\n readonly 'camera-credentials': z.infer<typeof CameraCredentialsStatusSchema>\n readonly 'device-discovery': z.infer<typeof DeviceDiscoveryStatusSchema>\n readonly 'device-status': z.infer<(typeof deviceStatusCapability)['status']['schema']>\n readonly 'doorbell': z.infer<typeof DoorbellStatusSchema>\n readonly 'feature-probe': z.infer<typeof FeatureProbeStatusSchema>\n readonly 'intercom': z.infer<typeof IntercomStatusSchema>\n readonly 'motion': z.infer<typeof MotionStatusSchema>\n readonly 'motion-trigger': z.infer<typeof MotionTriggerStatusSchema>\n readonly 'native-object-detection': z.infer<typeof NativeObjectDetectionStatusSchema>\n readonly 'osd': z.infer<typeof OsdStatusSchema>\n readonly 'ptz': z.infer<(typeof ptzCapability)['status']['schema']>\n readonly 'ptz-autotrack': z.infer<typeof PtzAutotrackStatusSchema>\n readonly 'snapshot': z.infer<typeof SnapshotStatusSchema>\n readonly 'switch': z.infer<typeof SwitchStatusSchema>\n}\n\n/** Union of every cap name that has a typed status block. */\nexport type CapNameWithStatus = keyof CapStatusTypeMap\n\n/**\n * Runtime list of cap names with status. Used by the settings\n * aggregator to enumerate caps whose `status` should be polled +\n * streamed via `subscribeDeviceStatusAggregate`.\n */\nexport const CAP_NAMES_WITH_STATUS = [\n 'accessories',\n 'battery',\n 'brightness',\n 'camera-credentials',\n 'device-discovery',\n 'device-status',\n 'doorbell',\n 'feature-probe',\n 'intercom',\n 'motion',\n 'motion-trigger',\n 'native-object-detection',\n 'osd',\n 'ptz',\n 'ptz-autotrack',\n 'snapshot',\n 'switch',\n] as const satisfies readonly CapNameWithStatus[]\n","/**\n * Strip the `userinfo` (`user:password@`) component from any URL we\n * surface in logs or telemetry. Camera credentials live inside RTSP /\n * RTMP / HTTP URLs by convention; emitting them verbatim leaks\n * plaintext secrets into log files, support transcripts, and shared\n * diagnostics. Returns the original string when the input is not a\n * parseable URL — a log helper must never throw.\n */\nexport function maskUrlCredentials(rawUrl: string): string {\n try {\n const u = new URL(rawUrl)\n if (!u.username && !u.password) return rawUrl\n u.username = ''\n u.password = ''\n return u.toString()\n } catch {\n return rawUrl\n }\n}\n","/**\n * Fixed-capacity ring buffer. When full, push() overwrites the oldest entry.\n * drain() returns up to maxCount items in FIFO order and removes them.\n */\nexport class RingBuffer<T> {\n private readonly items: Array<T | undefined>\n private head = 0\n private tail = 0\n private count = 0\n\n constructor(private readonly capacity: number) {\n this.items = Array.from<T | undefined>({ length: capacity })\n }\n\n get size(): number { return this.count }\n\n push(item: T): void {\n this.items[this.tail] = item\n this.tail = (this.tail + 1) % this.capacity\n if (this.count < this.capacity) {\n this.count++\n } else {\n this.head = (this.head + 1) % this.capacity\n }\n }\n\n drain(maxCount: number): T[] {\n const result: T[] = []\n const n = Math.min(maxCount, this.count)\n for (let i = 0; i < n; i++) {\n result.push(this.items[this.head]!)\n this.items[this.head] = undefined\n this.head = (this.head + 1) % this.capacity\n }\n this.count -= n\n return result\n }\n}\n","import type { z } from 'zod'\nimport type { CustomActionsSpec } from '../capabilities/custom-actions.js'\nimport type { AddonApi } from '../generated/addon-api.js'\n\n/**\n * Bind an addon's custom-action catalog to its tRPC surface, returning a\n * typed object with one method per action. Each method:\n * - Dispatches via `api.addons.custom.mutate({ addonId, action, input })`\n * - Inputs are typed as `z.infer<spec.input>`\n * - Outputs are typed as `z.infer<spec.output>`\n *\n * Example:\n * import { benchmarkActions } from '@camstack/addon-benchmark'\n * const benchmark = bindAddonActions(ctx.api, 'benchmark', benchmarkActions)\n * const { runId } = await benchmark.runBenchmark({ iterations: 100, target: 'cam-01' })\n */\nexport function bindAddonActions<T extends CustomActionsSpec>(\n api: AddonApi,\n addonId: string,\n catalog: T,\n): { [K in keyof T]: (input: z.infer<T[K]['input']>) => Promise<z.infer<T[K]['output']>> } {\n const out: Record<string, (input: unknown) => Promise<unknown>> = {}\n for (const action of Object.keys(catalog)) {\n out[action] = (input: unknown) => {\n const dispatcher = (\n api as unknown as {\n addons: {\n custom: {\n mutate: (args: { addonId: string; action: string; input: unknown }) => Promise<unknown>\n }\n }\n }\n ).addons.custom\n return dispatcher.mutate({ addonId, action, input })\n }\n }\n return out as never\n}\n"],"names":["EventCategory","hydrateSchema","streams","EventSourceType","errMsg","audioMetricsCapability","batteryCapability","brightnessCapability","cameraStreamsCapability","deviceDiscoveryCapability","deviceStatusCapability","doorbellCapability","featureProbeCapability","motionCapability","motionTriggerCapability","ptzAutotrackCapability","switchCapability","zoneAnalyticsCapability","zoneRulesCapability","zonesCapability","deviceProviderCapability","z","field","withTimeout","_accessoriesCapability","_addonPagesCapability","_addonPagesSourceCapability","_addonRoutesCapability","_addonSettingsCapability","_addonWidgetsCapability","_addonWidgetsSourceCapability","_addonsCapability","_adminUiCapability","_advancedNotifierCapability","_alertsCapability","_audioAnalysisCapability","_audioAnalyzerCapability","_audioCodecCapability","_audioMetricsCapability","_authProviderCapability","_authenticationCapability","_backupCapability","_batteryCapability","_brightnessCapability","_cameraCredentialsCapability","_cameraStreamsCapability","_decoderCapability","_detectionPipelineCapability","_deviceDiscoveryCapability","_deviceManagerCapability","_deviceOpsCapability","_deviceProviderCapability","_deviceStateCapability","_deviceStatusCapability","_doorbellCapability","_embeddingEncoderCapability","_eventsCapability","_featureProbeCapability","_integrationsCapability","_intercomCapability","_localNetworkCapability","_logDestinationCapability","_meshNetworkCapability","_meshOrchestratorCapability","_metricsProviderCapability","_motionCapability","_motionDetectionCapability","_motionTriggerCapability","_nativeObjectDetectionCapability","_networkAccessCapability","_networkQualityCapability","_nodesCapability","_notificationOutputCapability","_osdCapability","_pipelineAnalyticsCapability","_pipelineExecutorCapability","_pipelineOrchestratorCapability","_pipelineRunnerCapability","_platformProbeCapability","_ptzCapability","_ptzAutotrackCapability","_rebootCapability","_recordingCapability","_recordingEngineCapability","_remoteAccessCapability","_restreamerCapability","_settingsStoreCapability","_snapshotCapability","_snapshotProviderCapability","_storageCapability","_storageProviderCapability","_streamBrokerCapability","_streamingEngineCapability","_switchCapability","_systemCapability","_toastCapability","_turnOrchestratorCapability","_turnProviderCapability","_userManagementCapability","_webrtcCapability","_webrtcSessionCapability","_zoneAnalyticsCapability","_zoneRulesCapability","_zonesCapability"],"mappings":"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"}
|