@camstack/addon-provider-homeassistant 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/addon.js +315 -30
  2. package/dist/addon.mjs +315 -30
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -4983,6 +4983,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
4983
4983
  */
4984
4984
  EventCategory["PipelineEngineMetricsSnapshot"] = "pipeline.engine-metrics-snapshot";
4985
4985
  /**
4986
+ * Per-node detection-engine runtime-provisioning transition. Emitted by
4987
+ * the detection-pipeline provider on every state change of its lazy
4988
+ * engine-provisioning machine (idle → installing → verifying → ready,
4989
+ * or → failed with a `nextRetryAt`). Payload is the
4990
+ * `EngineProvisioningState` snapshot; `event.source.nodeId` carries the
4991
+ * node. The Pipeline page subscribes to drive a live "installing
4992
+ * OpenVINO… / ready" indicator per node without polling
4993
+ * `pipelineExecutor.getEngineProvisioning`. Telemetry-grade (D8): the UI
4994
+ * also reads the cap snapshot on mount / reconnect. Phase 2.
4995
+ */
4996
+ EventCategory["PipelineEngineProvisioning"] = "pipeline.engine-provisioning";
4997
+ /**
4986
4998
  * Cluster topology snapshot. Carries the same payload returned by
4987
4999
  * `nodes.topology` (every reachable node + addons + processes).
4988
5000
  * Emitted by the hub on any agent / addon lifecycle change
@@ -5132,14 +5144,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5132
5144
  EventCategory["DeviceSleeping"] = "device.sleeping";
5133
5145
  EventCategory["RetentionCleanup"] = "retention.cleanup";
5134
5146
  /**
5135
- * Progress snapshot emitted by `BulkUpdateCoordinator` on every state
5136
- * transition (item status change, phase change, completion, cancel).
5137
- * Payload is `BulkUpdateState`. Admin UI subscribes via `useLiveEvent`
5138
- * to drive the sticky `BulkUpdateBanner` and per-row `AddonRowBadge`.
5139
- *
5140
- * Spec: docs/superpowers/specs/2026-05-21-addons-bulk-update-progress-design.md
5147
+ * Legacy bulk-update progress snapshot (payload `BulkUpdateState`). No longer
5148
+ * emitted F3 removed the coordinator that produced it; "Update all" now runs
5149
+ * as one lifecycle engine job (`AddonsJobProgress`/`AddonsJobLog`). Retained
5150
+ * (with `BulkUpdateState`) only to avoid regenerating the event maps; removed
5151
+ * in F4 once live bulk progress is re-implemented over the engine events.
5141
5152
  */
5142
5153
  EventCategory["AddonsBulkUpdateProgress"] = "addons.bulk-update-progress";
5154
+ EventCategory["AddonsJobProgress"] = "addons.job-progress";
5155
+ EventCategory["AddonsJobLog"] = "addons.job-log";
5143
5156
  /**
5144
5157
  * A container's child visibility toggled (hidden/shown). Emitted by the
5145
5158
  * `accessories` cap when a child device is hidden or revealed.
@@ -10400,6 +10413,24 @@ var DetectorOutputSchema = object({
10400
10413
  inferenceMs: number(),
10401
10414
  modelId: string()
10402
10415
  });
10416
+ var EngineProvisioningSchema = object({
10417
+ runtimeId: _enum([
10418
+ "onnx",
10419
+ "openvino",
10420
+ "coreml"
10421
+ ]).nullable(),
10422
+ device: string().nullable(),
10423
+ state: _enum([
10424
+ "idle",
10425
+ "installing",
10426
+ "verifying",
10427
+ "ready",
10428
+ "failed"
10429
+ ]),
10430
+ progress: number().optional(),
10431
+ error: string().optional(),
10432
+ nextRetryAt: number().optional()
10433
+ });
10403
10434
  var PipelineStepInputSchema = lazy(() => object({
10404
10435
  addonId: string(),
10405
10436
  modelId: string(),
@@ -10468,7 +10499,7 @@ var PipelineRunResultBridge = custom();
10468
10499
  method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
10469
10500
  kind: "mutation",
10470
10501
  auth: "admin"
10471
- }), method(_void(), record(string(), object({
10502
+ }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
10472
10503
  modelId: string(),
10473
10504
  settings: record(string(), unknown()).readonly()
10474
10505
  }))), method(object({ steps: record(string(), object({
@@ -15690,7 +15721,10 @@ var AgentAddonConfigSchema = object({
15690
15721
  modelId: string(),
15691
15722
  settings: record(string(), unknown()).readonly()
15692
15723
  });
15693
- var AgentPipelineSettingsSchema = object({ addonDefaults: record(string(), AgentAddonConfigSchema).readonly() });
15724
+ var AgentPipelineSettingsSchema = object({
15725
+ addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
15726
+ maxCameras: number().int().nonnegative().nullable().default(null)
15727
+ });
15694
15728
  var CameraPipelineForAgentSchema = object({
15695
15729
  steps: array(PipelineStepInputSchema).readonly(),
15696
15730
  audio: object({
@@ -15792,6 +15826,133 @@ var GlobalMetricsSchema = object({
15792
15826
  * capability providers.
15793
15827
  */
15794
15828
  var CapabilityBindingsSchema = record(string(), string());
15829
+ /** Source block — always present; derives from the stream catalog. */
15830
+ var CameraSourceStatusSchema = object({ streams: array(object({
15831
+ camStreamId: string(),
15832
+ codec: string(),
15833
+ width: number(),
15834
+ height: number(),
15835
+ fps: number(),
15836
+ kind: string()
15837
+ })).readonly() });
15838
+ /** Assignment block — always present (orchestrator-local, no remote call). */
15839
+ var CameraAssignmentStatusSchema = object({
15840
+ detectionNodeId: string().nullable(),
15841
+ decoderNodeId: string().nullable(),
15842
+ audioNodeId: string().nullable(),
15843
+ pinned: object({
15844
+ detection: boolean(),
15845
+ decoder: boolean(),
15846
+ audio: boolean()
15847
+ }),
15848
+ reasons: object({
15849
+ detection: string().optional(),
15850
+ decoder: string().optional(),
15851
+ audio: string().optional()
15852
+ })
15853
+ });
15854
+ /** Broker block — null when the broker stage is unreachable or inactive. */
15855
+ var CameraBrokerStatusSchema = object({
15856
+ profiles: array(object({
15857
+ profile: string(),
15858
+ status: string(),
15859
+ codec: string(),
15860
+ width: number(),
15861
+ height: number(),
15862
+ subscribers: number(),
15863
+ inFps: number(),
15864
+ outFps: number()
15865
+ })).readonly(),
15866
+ webrtcSessions: number(),
15867
+ rtspRestream: boolean()
15868
+ });
15869
+ /** Shared-memory ring statistics within the decoder block. */
15870
+ var CameraDecoderShmSchema = object({
15871
+ framesWritten: number(),
15872
+ getFrameHits: number(),
15873
+ getFrameMisses: number(),
15874
+ budgetMb: number()
15875
+ });
15876
+ /** Decoder block — null when the decoder stage is unreachable or inactive. */
15877
+ var CameraDecoderStatusSchema = object({
15878
+ nodeId: string(),
15879
+ formats: array(string()).readonly(),
15880
+ sessionCount: number(),
15881
+ shm: CameraDecoderShmSchema
15882
+ });
15883
+ /** Motion block — null when motion detection is not active for this device. */
15884
+ var CameraMotionStatusSchema = object({
15885
+ enabled: boolean(),
15886
+ fps: number()
15887
+ });
15888
+ /** Detection provisioning sub-block. */
15889
+ var CameraDetectionProvisioningSchema = object({
15890
+ state: _enum([
15891
+ "idle",
15892
+ "installing",
15893
+ "verifying",
15894
+ "ready",
15895
+ "failed"
15896
+ ]),
15897
+ error: string().optional()
15898
+ });
15899
+ /** Detection phase — derived from the runner's engine phase. */
15900
+ var CameraDetectionPhaseSchema = _enum([
15901
+ "idle",
15902
+ "watching",
15903
+ "active"
15904
+ ]);
15905
+ /** Detection block — null when no detection node is assigned or reachable. */
15906
+ var CameraDetectionStatusSchema = object({
15907
+ nodeId: string(),
15908
+ engine: object({
15909
+ backend: string(),
15910
+ device: string()
15911
+ }),
15912
+ phase: CameraDetectionPhaseSchema,
15913
+ configuredFps: number(),
15914
+ actualFps: number(),
15915
+ queueDepth: number(),
15916
+ avgInferenceMs: number(),
15917
+ provisioning: CameraDetectionProvisioningSchema
15918
+ });
15919
+ /** Audio block — null when no audio node is assigned or reachable. */
15920
+ var CameraAudioStatusSchema = object({
15921
+ nodeId: string(),
15922
+ enabled: boolean()
15923
+ });
15924
+ /** Recording block — null when no recording cap is active for this device. */
15925
+ var CameraRecordingStatusSchema = object({
15926
+ mode: _enum([
15927
+ "off",
15928
+ "continuous",
15929
+ "events"
15930
+ ]),
15931
+ active: boolean(),
15932
+ storageBytes: number()
15933
+ });
15934
+ /**
15935
+ * Aggregated per-camera pipeline status — server-composed, single call.
15936
+ *
15937
+ * The `assignment` and `source` blocks are always present.
15938
+ * Every other block is `null` when the stage is inactive or unreachable
15939
+ * during the bounded parallel fan-out in the orchestrator implementation.
15940
+ *
15941
+ * See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
15942
+ */
15943
+ var CameraStatusSchema = object({
15944
+ deviceId: number(),
15945
+ assignment: CameraAssignmentStatusSchema,
15946
+ source: CameraSourceStatusSchema,
15947
+ broker: CameraBrokerStatusSchema.nullable(),
15948
+ decoder: CameraDecoderStatusSchema.nullable(),
15949
+ motion: CameraMotionStatusSchema.nullable(),
15950
+ detection: CameraDetectionStatusSchema.nullable(),
15951
+ audio: CameraAudioStatusSchema.nullable(),
15952
+ recording: CameraRecordingStatusSchema.nullable(),
15953
+ /** Unix timestamp (ms) when this snapshot was composed server-side. */
15954
+ fetchedAt: number()
15955
+ });
15795
15956
  method(object({
15796
15957
  deviceId: number(),
15797
15958
  agentNodeId: string()
@@ -15859,6 +16020,12 @@ method(object({
15859
16020
  }), {
15860
16021
  kind: "mutation",
15861
16022
  auth: "admin"
16023
+ }), method(object({
16024
+ agentNodeId: string(),
16025
+ maxCameras: number().int().nonnegative().nullable()
16026
+ }), object({ success: literal(true) }), {
16027
+ kind: "mutation",
16028
+ auth: "admin"
15862
16029
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
15863
16030
  deviceId: number(),
15864
16031
  addonId: string(),
@@ -15884,7 +16051,7 @@ method(object({
15884
16051
  }), method(object({
15885
16052
  deviceId: number(),
15886
16053
  agentNodeId: string().optional()
15887
- }), CameraPipelineConfigSchema), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
16054
+ }), CameraPipelineConfigSchema), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
15888
16055
  name: string(),
15889
16056
  description: string().optional(),
15890
16057
  config: CameraPipelineConfigSchema
@@ -18937,6 +19104,69 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
18937
19104
  kind: "mutation",
18938
19105
  auth: "admin"
18939
19106
  });
19107
+ var jobKindSchema = _enum([
19108
+ "install",
19109
+ "update",
19110
+ "uninstall",
19111
+ "restart"
19112
+ ]);
19113
+ var taskPhaseSchema = _enum([
19114
+ "queued",
19115
+ "fetching",
19116
+ "staged",
19117
+ "validating",
19118
+ "applying",
19119
+ "restarting",
19120
+ "applied",
19121
+ "done",
19122
+ "failed",
19123
+ "skipped"
19124
+ ]);
19125
+ var taskTargetSchema = _enum(["framework", "addon"]);
19126
+ var taskLogEntrySchema = object({
19127
+ tsMs: number(),
19128
+ nodeId: string(),
19129
+ packageName: string(),
19130
+ phase: taskPhaseSchema,
19131
+ message: string()
19132
+ });
19133
+ var lifecycleTaskSchema = object({
19134
+ taskId: string(),
19135
+ nodeId: string(),
19136
+ packageName: string(),
19137
+ fromVersion: string().nullable(),
19138
+ toVersion: string(),
19139
+ target: taskTargetSchema,
19140
+ phase: taskPhaseSchema,
19141
+ stagedPath: string().nullable(),
19142
+ attempts: number(),
19143
+ steps: array(taskLogEntrySchema),
19144
+ error: string().nullable(),
19145
+ startedAtMs: number().nullable(),
19146
+ finishedAtMs: number().nullable()
19147
+ });
19148
+ var lifecycleJobStateSchema = _enum([
19149
+ "running",
19150
+ "completed",
19151
+ "failed",
19152
+ "partially-failed",
19153
+ "cancelled"
19154
+ ]);
19155
+ var lifecycleJobScopeSchema = _enum([
19156
+ "single",
19157
+ "bulk",
19158
+ "cluster"
19159
+ ]);
19160
+ var lifecycleJobSchema = object({
19161
+ jobId: string(),
19162
+ kind: jobKindSchema,
19163
+ createdAtMs: number(),
19164
+ createdBy: string(),
19165
+ scope: lifecycleJobScopeSchema,
19166
+ tasks: array(lifecycleTaskSchema),
19167
+ state: lifecycleJobStateSchema,
19168
+ schemaVersion: literal(1)
19169
+ });
18940
19170
  /**
18941
19171
  * addons — system-scoped singleton capability for addon package
18942
19172
  * management (install, update, configure, restart) and per-addon log
@@ -19119,7 +19349,7 @@ var BulkUpdatePhaseSchema = _enum([
19119
19349
  "restarting",
19120
19350
  "finalizing"
19121
19351
  ]);
19122
- var BulkUpdateStateSchema = object({
19352
+ object({
19123
19353
  id: string(),
19124
19354
  nodeId: string(),
19125
19355
  startedAtMs: number(),
@@ -19222,20 +19452,7 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
19222
19452
  }), UpdateFrameworkPackageResultSchema, {
19223
19453
  kind: "mutation",
19224
19454
  auth: "admin"
19225
- }), method(object({
19226
- nodeId: string(),
19227
- items: array(object({
19228
- name: string(),
19229
- version: string(),
19230
- isSystem: boolean()
19231
- })).readonly()
19232
- }), object({ id: string() }), {
19233
- kind: "mutation",
19234
- auth: "admin"
19235
- }), method(object({ id: string() }), BulkUpdateStateSchema.nullable(), { auth: "admin" }), method(object({ id: string() }), object({ cancelled: boolean() }), {
19236
- kind: "mutation",
19237
- auth: "admin"
19238
- }), method(object({ nodeId: string().optional() }), array(BulkUpdateStateSchema).readonly(), { auth: "admin" }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
19455
+ }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
19239
19456
  kind: "mutation",
19240
19457
  auth: "admin"
19241
19458
  }), method(object({ packageName: string() }), object({ success: literal(true) }), {
@@ -19257,6 +19474,24 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
19257
19474
  kind: "mutation",
19258
19475
  auth: "admin"
19259
19476
  }), method(CustomActionInputSchema, unknown(), { kind: "mutation" }), method(object({
19477
+ kind: _enum([
19478
+ "install",
19479
+ "update",
19480
+ "uninstall",
19481
+ "restart"
19482
+ ]),
19483
+ targets: array(object({
19484
+ name: string().min(1),
19485
+ version: string().min(1)
19486
+ })).min(1),
19487
+ nodeIds: array(string()).optional()
19488
+ }), object({ jobId: string() }), {
19489
+ kind: "mutation",
19490
+ auth: "admin"
19491
+ }), method(object({ jobId: string() }), lifecycleJobSchema.nullable(), { auth: "admin" }), method(object({ activeOnly: boolean().optional() }), array(lifecycleJobSchema), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
19492
+ kind: "mutation",
19493
+ auth: "admin"
19494
+ }), method(object({
19260
19495
  addonId: string(),
19261
19496
  level: LogLevelSchema$1.optional()
19262
19497
  }), LogStreamEntrySchema, { kind: "subscription" });
@@ -19297,7 +19532,7 @@ Object.freeze({
19297
19532
  addonId: null,
19298
19533
  access: "create"
19299
19534
  },
19300
- "addons.cancelBulkUpdate": {
19535
+ "addons.cancelJob": {
19301
19536
  capName: "addons",
19302
19537
  capScope: "system",
19303
19538
  addonId: null,
@@ -19327,7 +19562,7 @@ Object.freeze({
19327
19562
  addonId: null,
19328
19563
  access: "view"
19329
19564
  },
19330
- "addons.getBulkUpdateState": {
19565
+ "addons.getJob": {
19331
19566
  capName: "addons",
19332
19567
  capScope: "system",
19333
19568
  addonId: null,
@@ -19375,19 +19610,19 @@ Object.freeze({
19375
19610
  addonId: null,
19376
19611
  access: "view"
19377
19612
  },
19378
- "addons.listActiveBulkUpdates": {
19613
+ "addons.listCapabilityProviders": {
19379
19614
  capName: "addons",
19380
19615
  capScope: "system",
19381
19616
  addonId: null,
19382
19617
  access: "view"
19383
19618
  },
19384
- "addons.listCapabilityProviders": {
19619
+ "addons.listFrameworkPackages": {
19385
19620
  capName: "addons",
19386
19621
  capScope: "system",
19387
19622
  addonId: null,
19388
19623
  access: "view"
19389
19624
  },
19390
- "addons.listFrameworkPackages": {
19625
+ "addons.listJobs": {
19391
19626
  capName: "addons",
19392
19627
  capScope: "system",
19393
19628
  addonId: null,
@@ -19471,7 +19706,7 @@ Object.freeze({
19471
19706
  addonId: null,
19472
19707
  access: "create"
19473
19708
  },
19474
- "addons.startBulkUpdate": {
19709
+ "addons.startJob": {
19475
19710
  capName: "addons",
19476
19711
  capScope: "system",
19477
19712
  addonId: null,
@@ -21697,6 +21932,12 @@ Object.freeze({
21697
21932
  addonId: null,
21698
21933
  access: "view"
21699
21934
  },
21935
+ "pipelineExecutor.getEngineProvisioning": {
21936
+ capName: "pipeline-executor",
21937
+ capScope: "system",
21938
+ addonId: null,
21939
+ access: "view"
21940
+ },
21700
21941
  "pipelineExecutor.getGlobalPipelineConfig": {
21701
21942
  capName: "pipeline-executor",
21702
21943
  capScope: "system",
@@ -21901,6 +22142,18 @@ Object.freeze({
21901
22142
  addonId: null,
21902
22143
  access: "view"
21903
22144
  },
22145
+ "pipelineOrchestrator.getCameraStatus": {
22146
+ capName: "pipeline-orchestrator",
22147
+ capScope: "system",
22148
+ addonId: null,
22149
+ access: "view"
22150
+ },
22151
+ "pipelineOrchestrator.getCameraStatuses": {
22152
+ capName: "pipeline-orchestrator",
22153
+ capScope: "system",
22154
+ addonId: null,
22155
+ access: "view"
22156
+ },
21904
22157
  "pipelineOrchestrator.getCameraStepOverrides": {
21905
22158
  capName: "pipeline-orchestrator",
21906
22159
  capScope: "system",
@@ -21985,6 +22238,12 @@ Object.freeze({
21985
22238
  addonId: null,
21986
22239
  access: "create"
21987
22240
  },
22241
+ "pipelineOrchestrator.setAgentMaxCameras": {
22242
+ capName: "pipeline-orchestrator",
22243
+ capScope: "system",
22244
+ addonId: null,
22245
+ access: "create"
22246
+ },
21988
22247
  "pipelineOrchestrator.setCameraPipelineForAgent": {
21989
22248
  capName: "pipeline-orchestrator",
21990
22249
  capScope: "system",
@@ -23458,6 +23717,32 @@ Object.freeze({
23458
23717
  "network-access": "ingress",
23459
23718
  "smtp-provider": "email"
23460
23719
  });
23720
+ var frameworkSwapPackageSchema = object({
23721
+ name: string(),
23722
+ stagedPath: string(),
23723
+ backupPath: string(),
23724
+ toVersion: string(),
23725
+ fromVersion: string().nullable()
23726
+ });
23727
+ object({
23728
+ jobId: string(),
23729
+ taskId: string(),
23730
+ packages: array(frameworkSwapPackageSchema),
23731
+ requestedAtMs: number(),
23732
+ schemaVersion: literal(1)
23733
+ });
23734
+ object({
23735
+ jobId: string(),
23736
+ taskId: string(),
23737
+ backups: array(object({
23738
+ name: string(),
23739
+ backupPath: string(),
23740
+ livePath: string()
23741
+ })),
23742
+ appliedAtMs: number(),
23743
+ bootAttempts: number(),
23744
+ schemaVersion: literal(1)
23745
+ });
23461
23746
  /**
23462
23747
  * Pure fuzzy matcher for adoption location import. Normalized
23463
23748
  * case-insensitive Levenshtein similarity, used to reuse an existing
package/dist/addon.mjs CHANGED
@@ -4982,6 +4982,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
4982
4982
  */
4983
4983
  EventCategory["PipelineEngineMetricsSnapshot"] = "pipeline.engine-metrics-snapshot";
4984
4984
  /**
4985
+ * Per-node detection-engine runtime-provisioning transition. Emitted by
4986
+ * the detection-pipeline provider on every state change of its lazy
4987
+ * engine-provisioning machine (idle → installing → verifying → ready,
4988
+ * or → failed with a `nextRetryAt`). Payload is the
4989
+ * `EngineProvisioningState` snapshot; `event.source.nodeId` carries the
4990
+ * node. The Pipeline page subscribes to drive a live "installing
4991
+ * OpenVINO… / ready" indicator per node without polling
4992
+ * `pipelineExecutor.getEngineProvisioning`. Telemetry-grade (D8): the UI
4993
+ * also reads the cap snapshot on mount / reconnect. Phase 2.
4994
+ */
4995
+ EventCategory["PipelineEngineProvisioning"] = "pipeline.engine-provisioning";
4996
+ /**
4985
4997
  * Cluster topology snapshot. Carries the same payload returned by
4986
4998
  * `nodes.topology` (every reachable node + addons + processes).
4987
4999
  * Emitted by the hub on any agent / addon lifecycle change
@@ -5131,14 +5143,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5131
5143
  EventCategory["DeviceSleeping"] = "device.sleeping";
5132
5144
  EventCategory["RetentionCleanup"] = "retention.cleanup";
5133
5145
  /**
5134
- * Progress snapshot emitted by `BulkUpdateCoordinator` on every state
5135
- * transition (item status change, phase change, completion, cancel).
5136
- * Payload is `BulkUpdateState`. Admin UI subscribes via `useLiveEvent`
5137
- * to drive the sticky `BulkUpdateBanner` and per-row `AddonRowBadge`.
5138
- *
5139
- * Spec: docs/superpowers/specs/2026-05-21-addons-bulk-update-progress-design.md
5146
+ * Legacy bulk-update progress snapshot (payload `BulkUpdateState`). No longer
5147
+ * emitted F3 removed the coordinator that produced it; "Update all" now runs
5148
+ * as one lifecycle engine job (`AddonsJobProgress`/`AddonsJobLog`). Retained
5149
+ * (with `BulkUpdateState`) only to avoid regenerating the event maps; removed
5150
+ * in F4 once live bulk progress is re-implemented over the engine events.
5140
5151
  */
5141
5152
  EventCategory["AddonsBulkUpdateProgress"] = "addons.bulk-update-progress";
5153
+ EventCategory["AddonsJobProgress"] = "addons.job-progress";
5154
+ EventCategory["AddonsJobLog"] = "addons.job-log";
5142
5155
  /**
5143
5156
  * A container's child visibility toggled (hidden/shown). Emitted by the
5144
5157
  * `accessories` cap when a child device is hidden or revealed.
@@ -10399,6 +10412,24 @@ var DetectorOutputSchema = object({
10399
10412
  inferenceMs: number(),
10400
10413
  modelId: string()
10401
10414
  });
10415
+ var EngineProvisioningSchema = object({
10416
+ runtimeId: _enum([
10417
+ "onnx",
10418
+ "openvino",
10419
+ "coreml"
10420
+ ]).nullable(),
10421
+ device: string().nullable(),
10422
+ state: _enum([
10423
+ "idle",
10424
+ "installing",
10425
+ "verifying",
10426
+ "ready",
10427
+ "failed"
10428
+ ]),
10429
+ progress: number().optional(),
10430
+ error: string().optional(),
10431
+ nextRetryAt: number().optional()
10432
+ });
10402
10433
  var PipelineStepInputSchema = lazy(() => object({
10403
10434
  addonId: string(),
10404
10435
  modelId: string(),
@@ -10467,7 +10498,7 @@ var PipelineRunResultBridge = custom();
10467
10498
  method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
10468
10499
  kind: "mutation",
10469
10500
  auth: "admin"
10470
- }), method(_void(), record(string(), object({
10501
+ }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
10471
10502
  modelId: string(),
10472
10503
  settings: record(string(), unknown()).readonly()
10473
10504
  }))), method(object({ steps: record(string(), object({
@@ -15689,7 +15720,10 @@ var AgentAddonConfigSchema = object({
15689
15720
  modelId: string(),
15690
15721
  settings: record(string(), unknown()).readonly()
15691
15722
  });
15692
- var AgentPipelineSettingsSchema = object({ addonDefaults: record(string(), AgentAddonConfigSchema).readonly() });
15723
+ var AgentPipelineSettingsSchema = object({
15724
+ addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
15725
+ maxCameras: number().int().nonnegative().nullable().default(null)
15726
+ });
15693
15727
  var CameraPipelineForAgentSchema = object({
15694
15728
  steps: array(PipelineStepInputSchema).readonly(),
15695
15729
  audio: object({
@@ -15791,6 +15825,133 @@ var GlobalMetricsSchema = object({
15791
15825
  * capability providers.
15792
15826
  */
15793
15827
  var CapabilityBindingsSchema = record(string(), string());
15828
+ /** Source block — always present; derives from the stream catalog. */
15829
+ var CameraSourceStatusSchema = object({ streams: array(object({
15830
+ camStreamId: string(),
15831
+ codec: string(),
15832
+ width: number(),
15833
+ height: number(),
15834
+ fps: number(),
15835
+ kind: string()
15836
+ })).readonly() });
15837
+ /** Assignment block — always present (orchestrator-local, no remote call). */
15838
+ var CameraAssignmentStatusSchema = object({
15839
+ detectionNodeId: string().nullable(),
15840
+ decoderNodeId: string().nullable(),
15841
+ audioNodeId: string().nullable(),
15842
+ pinned: object({
15843
+ detection: boolean(),
15844
+ decoder: boolean(),
15845
+ audio: boolean()
15846
+ }),
15847
+ reasons: object({
15848
+ detection: string().optional(),
15849
+ decoder: string().optional(),
15850
+ audio: string().optional()
15851
+ })
15852
+ });
15853
+ /** Broker block — null when the broker stage is unreachable or inactive. */
15854
+ var CameraBrokerStatusSchema = object({
15855
+ profiles: array(object({
15856
+ profile: string(),
15857
+ status: string(),
15858
+ codec: string(),
15859
+ width: number(),
15860
+ height: number(),
15861
+ subscribers: number(),
15862
+ inFps: number(),
15863
+ outFps: number()
15864
+ })).readonly(),
15865
+ webrtcSessions: number(),
15866
+ rtspRestream: boolean()
15867
+ });
15868
+ /** Shared-memory ring statistics within the decoder block. */
15869
+ var CameraDecoderShmSchema = object({
15870
+ framesWritten: number(),
15871
+ getFrameHits: number(),
15872
+ getFrameMisses: number(),
15873
+ budgetMb: number()
15874
+ });
15875
+ /** Decoder block — null when the decoder stage is unreachable or inactive. */
15876
+ var CameraDecoderStatusSchema = object({
15877
+ nodeId: string(),
15878
+ formats: array(string()).readonly(),
15879
+ sessionCount: number(),
15880
+ shm: CameraDecoderShmSchema
15881
+ });
15882
+ /** Motion block — null when motion detection is not active for this device. */
15883
+ var CameraMotionStatusSchema = object({
15884
+ enabled: boolean(),
15885
+ fps: number()
15886
+ });
15887
+ /** Detection provisioning sub-block. */
15888
+ var CameraDetectionProvisioningSchema = object({
15889
+ state: _enum([
15890
+ "idle",
15891
+ "installing",
15892
+ "verifying",
15893
+ "ready",
15894
+ "failed"
15895
+ ]),
15896
+ error: string().optional()
15897
+ });
15898
+ /** Detection phase — derived from the runner's engine phase. */
15899
+ var CameraDetectionPhaseSchema = _enum([
15900
+ "idle",
15901
+ "watching",
15902
+ "active"
15903
+ ]);
15904
+ /** Detection block — null when no detection node is assigned or reachable. */
15905
+ var CameraDetectionStatusSchema = object({
15906
+ nodeId: string(),
15907
+ engine: object({
15908
+ backend: string(),
15909
+ device: string()
15910
+ }),
15911
+ phase: CameraDetectionPhaseSchema,
15912
+ configuredFps: number(),
15913
+ actualFps: number(),
15914
+ queueDepth: number(),
15915
+ avgInferenceMs: number(),
15916
+ provisioning: CameraDetectionProvisioningSchema
15917
+ });
15918
+ /** Audio block — null when no audio node is assigned or reachable. */
15919
+ var CameraAudioStatusSchema = object({
15920
+ nodeId: string(),
15921
+ enabled: boolean()
15922
+ });
15923
+ /** Recording block — null when no recording cap is active for this device. */
15924
+ var CameraRecordingStatusSchema = object({
15925
+ mode: _enum([
15926
+ "off",
15927
+ "continuous",
15928
+ "events"
15929
+ ]),
15930
+ active: boolean(),
15931
+ storageBytes: number()
15932
+ });
15933
+ /**
15934
+ * Aggregated per-camera pipeline status — server-composed, single call.
15935
+ *
15936
+ * The `assignment` and `source` blocks are always present.
15937
+ * Every other block is `null` when the stage is inactive or unreachable
15938
+ * during the bounded parallel fan-out in the orchestrator implementation.
15939
+ *
15940
+ * See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
15941
+ */
15942
+ var CameraStatusSchema = object({
15943
+ deviceId: number(),
15944
+ assignment: CameraAssignmentStatusSchema,
15945
+ source: CameraSourceStatusSchema,
15946
+ broker: CameraBrokerStatusSchema.nullable(),
15947
+ decoder: CameraDecoderStatusSchema.nullable(),
15948
+ motion: CameraMotionStatusSchema.nullable(),
15949
+ detection: CameraDetectionStatusSchema.nullable(),
15950
+ audio: CameraAudioStatusSchema.nullable(),
15951
+ recording: CameraRecordingStatusSchema.nullable(),
15952
+ /** Unix timestamp (ms) when this snapshot was composed server-side. */
15953
+ fetchedAt: number()
15954
+ });
15794
15955
  method(object({
15795
15956
  deviceId: number(),
15796
15957
  agentNodeId: string()
@@ -15858,6 +16019,12 @@ method(object({
15858
16019
  }), {
15859
16020
  kind: "mutation",
15860
16021
  auth: "admin"
16022
+ }), method(object({
16023
+ agentNodeId: string(),
16024
+ maxCameras: number().int().nonnegative().nullable()
16025
+ }), object({ success: literal(true) }), {
16026
+ kind: "mutation",
16027
+ auth: "admin"
15861
16028
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
15862
16029
  deviceId: number(),
15863
16030
  addonId: string(),
@@ -15883,7 +16050,7 @@ method(object({
15883
16050
  }), method(object({
15884
16051
  deviceId: number(),
15885
16052
  agentNodeId: string().optional()
15886
- }), CameraPipelineConfigSchema), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
16053
+ }), CameraPipelineConfigSchema), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
15887
16054
  name: string(),
15888
16055
  description: string().optional(),
15889
16056
  config: CameraPipelineConfigSchema
@@ -18936,6 +19103,69 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
18936
19103
  kind: "mutation",
18937
19104
  auth: "admin"
18938
19105
  });
19106
+ var jobKindSchema = _enum([
19107
+ "install",
19108
+ "update",
19109
+ "uninstall",
19110
+ "restart"
19111
+ ]);
19112
+ var taskPhaseSchema = _enum([
19113
+ "queued",
19114
+ "fetching",
19115
+ "staged",
19116
+ "validating",
19117
+ "applying",
19118
+ "restarting",
19119
+ "applied",
19120
+ "done",
19121
+ "failed",
19122
+ "skipped"
19123
+ ]);
19124
+ var taskTargetSchema = _enum(["framework", "addon"]);
19125
+ var taskLogEntrySchema = object({
19126
+ tsMs: number(),
19127
+ nodeId: string(),
19128
+ packageName: string(),
19129
+ phase: taskPhaseSchema,
19130
+ message: string()
19131
+ });
19132
+ var lifecycleTaskSchema = object({
19133
+ taskId: string(),
19134
+ nodeId: string(),
19135
+ packageName: string(),
19136
+ fromVersion: string().nullable(),
19137
+ toVersion: string(),
19138
+ target: taskTargetSchema,
19139
+ phase: taskPhaseSchema,
19140
+ stagedPath: string().nullable(),
19141
+ attempts: number(),
19142
+ steps: array(taskLogEntrySchema),
19143
+ error: string().nullable(),
19144
+ startedAtMs: number().nullable(),
19145
+ finishedAtMs: number().nullable()
19146
+ });
19147
+ var lifecycleJobStateSchema = _enum([
19148
+ "running",
19149
+ "completed",
19150
+ "failed",
19151
+ "partially-failed",
19152
+ "cancelled"
19153
+ ]);
19154
+ var lifecycleJobScopeSchema = _enum([
19155
+ "single",
19156
+ "bulk",
19157
+ "cluster"
19158
+ ]);
19159
+ var lifecycleJobSchema = object({
19160
+ jobId: string(),
19161
+ kind: jobKindSchema,
19162
+ createdAtMs: number(),
19163
+ createdBy: string(),
19164
+ scope: lifecycleJobScopeSchema,
19165
+ tasks: array(lifecycleTaskSchema),
19166
+ state: lifecycleJobStateSchema,
19167
+ schemaVersion: literal(1)
19168
+ });
18939
19169
  /**
18940
19170
  * addons — system-scoped singleton capability for addon package
18941
19171
  * management (install, update, configure, restart) and per-addon log
@@ -19118,7 +19348,7 @@ var BulkUpdatePhaseSchema = _enum([
19118
19348
  "restarting",
19119
19349
  "finalizing"
19120
19350
  ]);
19121
- var BulkUpdateStateSchema = object({
19351
+ object({
19122
19352
  id: string(),
19123
19353
  nodeId: string(),
19124
19354
  startedAtMs: number(),
@@ -19221,20 +19451,7 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
19221
19451
  }), UpdateFrameworkPackageResultSchema, {
19222
19452
  kind: "mutation",
19223
19453
  auth: "admin"
19224
- }), method(object({
19225
- nodeId: string(),
19226
- items: array(object({
19227
- name: string(),
19228
- version: string(),
19229
- isSystem: boolean()
19230
- })).readonly()
19231
- }), object({ id: string() }), {
19232
- kind: "mutation",
19233
- auth: "admin"
19234
- }), method(object({ id: string() }), BulkUpdateStateSchema.nullable(), { auth: "admin" }), method(object({ id: string() }), object({ cancelled: boolean() }), {
19235
- kind: "mutation",
19236
- auth: "admin"
19237
- }), method(object({ nodeId: string().optional() }), array(BulkUpdateStateSchema).readonly(), { auth: "admin" }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
19454
+ }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
19238
19455
  kind: "mutation",
19239
19456
  auth: "admin"
19240
19457
  }), method(object({ packageName: string() }), object({ success: literal(true) }), {
@@ -19256,6 +19473,24 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
19256
19473
  kind: "mutation",
19257
19474
  auth: "admin"
19258
19475
  }), method(CustomActionInputSchema, unknown(), { kind: "mutation" }), method(object({
19476
+ kind: _enum([
19477
+ "install",
19478
+ "update",
19479
+ "uninstall",
19480
+ "restart"
19481
+ ]),
19482
+ targets: array(object({
19483
+ name: string().min(1),
19484
+ version: string().min(1)
19485
+ })).min(1),
19486
+ nodeIds: array(string()).optional()
19487
+ }), object({ jobId: string() }), {
19488
+ kind: "mutation",
19489
+ auth: "admin"
19490
+ }), method(object({ jobId: string() }), lifecycleJobSchema.nullable(), { auth: "admin" }), method(object({ activeOnly: boolean().optional() }), array(lifecycleJobSchema), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
19491
+ kind: "mutation",
19492
+ auth: "admin"
19493
+ }), method(object({
19259
19494
  addonId: string(),
19260
19495
  level: LogLevelSchema$1.optional()
19261
19496
  }), LogStreamEntrySchema, { kind: "subscription" });
@@ -19296,7 +19531,7 @@ Object.freeze({
19296
19531
  addonId: null,
19297
19532
  access: "create"
19298
19533
  },
19299
- "addons.cancelBulkUpdate": {
19534
+ "addons.cancelJob": {
19300
19535
  capName: "addons",
19301
19536
  capScope: "system",
19302
19537
  addonId: null,
@@ -19326,7 +19561,7 @@ Object.freeze({
19326
19561
  addonId: null,
19327
19562
  access: "view"
19328
19563
  },
19329
- "addons.getBulkUpdateState": {
19564
+ "addons.getJob": {
19330
19565
  capName: "addons",
19331
19566
  capScope: "system",
19332
19567
  addonId: null,
@@ -19374,19 +19609,19 @@ Object.freeze({
19374
19609
  addonId: null,
19375
19610
  access: "view"
19376
19611
  },
19377
- "addons.listActiveBulkUpdates": {
19612
+ "addons.listCapabilityProviders": {
19378
19613
  capName: "addons",
19379
19614
  capScope: "system",
19380
19615
  addonId: null,
19381
19616
  access: "view"
19382
19617
  },
19383
- "addons.listCapabilityProviders": {
19618
+ "addons.listFrameworkPackages": {
19384
19619
  capName: "addons",
19385
19620
  capScope: "system",
19386
19621
  addonId: null,
19387
19622
  access: "view"
19388
19623
  },
19389
- "addons.listFrameworkPackages": {
19624
+ "addons.listJobs": {
19390
19625
  capName: "addons",
19391
19626
  capScope: "system",
19392
19627
  addonId: null,
@@ -19470,7 +19705,7 @@ Object.freeze({
19470
19705
  addonId: null,
19471
19706
  access: "create"
19472
19707
  },
19473
- "addons.startBulkUpdate": {
19708
+ "addons.startJob": {
19474
19709
  capName: "addons",
19475
19710
  capScope: "system",
19476
19711
  addonId: null,
@@ -21696,6 +21931,12 @@ Object.freeze({
21696
21931
  addonId: null,
21697
21932
  access: "view"
21698
21933
  },
21934
+ "pipelineExecutor.getEngineProvisioning": {
21935
+ capName: "pipeline-executor",
21936
+ capScope: "system",
21937
+ addonId: null,
21938
+ access: "view"
21939
+ },
21699
21940
  "pipelineExecutor.getGlobalPipelineConfig": {
21700
21941
  capName: "pipeline-executor",
21701
21942
  capScope: "system",
@@ -21900,6 +22141,18 @@ Object.freeze({
21900
22141
  addonId: null,
21901
22142
  access: "view"
21902
22143
  },
22144
+ "pipelineOrchestrator.getCameraStatus": {
22145
+ capName: "pipeline-orchestrator",
22146
+ capScope: "system",
22147
+ addonId: null,
22148
+ access: "view"
22149
+ },
22150
+ "pipelineOrchestrator.getCameraStatuses": {
22151
+ capName: "pipeline-orchestrator",
22152
+ capScope: "system",
22153
+ addonId: null,
22154
+ access: "view"
22155
+ },
21903
22156
  "pipelineOrchestrator.getCameraStepOverrides": {
21904
22157
  capName: "pipeline-orchestrator",
21905
22158
  capScope: "system",
@@ -21984,6 +22237,12 @@ Object.freeze({
21984
22237
  addonId: null,
21985
22238
  access: "create"
21986
22239
  },
22240
+ "pipelineOrchestrator.setAgentMaxCameras": {
22241
+ capName: "pipeline-orchestrator",
22242
+ capScope: "system",
22243
+ addonId: null,
22244
+ access: "create"
22245
+ },
21987
22246
  "pipelineOrchestrator.setCameraPipelineForAgent": {
21988
22247
  capName: "pipeline-orchestrator",
21989
22248
  capScope: "system",
@@ -23457,6 +23716,32 @@ Object.freeze({
23457
23716
  "network-access": "ingress",
23458
23717
  "smtp-provider": "email"
23459
23718
  });
23719
+ var frameworkSwapPackageSchema = object({
23720
+ name: string(),
23721
+ stagedPath: string(),
23722
+ backupPath: string(),
23723
+ toVersion: string(),
23724
+ fromVersion: string().nullable()
23725
+ });
23726
+ object({
23727
+ jobId: string(),
23728
+ taskId: string(),
23729
+ packages: array(frameworkSwapPackageSchema),
23730
+ requestedAtMs: number(),
23731
+ schemaVersion: literal(1)
23732
+ });
23733
+ object({
23734
+ jobId: string(),
23735
+ taskId: string(),
23736
+ backups: array(object({
23737
+ name: string(),
23738
+ backupPath: string(),
23739
+ livePath: string()
23740
+ })),
23741
+ appliedAtMs: number(),
23742
+ bootAttempts: number(),
23743
+ schemaVersion: literal(1)
23744
+ });
23460
23745
  /**
23461
23746
  * Pure fuzzy matcher for adoption location import. Normalized
23462
23747
  * case-insensitive Levenshtein similarity, used to reuse an existing
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-homeassistant",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Home Assistant device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",