@camstack/addon-provider-homematic 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
@@ -5005,6 +5005,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5005
5005
  */
5006
5006
  EventCategory["PipelineEngineMetricsSnapshot"] = "pipeline.engine-metrics-snapshot";
5007
5007
  /**
5008
+ * Per-node detection-engine runtime-provisioning transition. Emitted by
5009
+ * the detection-pipeline provider on every state change of its lazy
5010
+ * engine-provisioning machine (idle → installing → verifying → ready,
5011
+ * or → failed with a `nextRetryAt`). Payload is the
5012
+ * `EngineProvisioningState` snapshot; `event.source.nodeId` carries the
5013
+ * node. The Pipeline page subscribes to drive a live "installing
5014
+ * OpenVINO… / ready" indicator per node without polling
5015
+ * `pipelineExecutor.getEngineProvisioning`. Telemetry-grade (D8): the UI
5016
+ * also reads the cap snapshot on mount / reconnect. Phase 2.
5017
+ */
5018
+ EventCategory["PipelineEngineProvisioning"] = "pipeline.engine-provisioning";
5019
+ /**
5008
5020
  * Cluster topology snapshot. Carries the same payload returned by
5009
5021
  * `nodes.topology` (every reachable node + addons + processes).
5010
5022
  * Emitted by the hub on any agent / addon lifecycle change
@@ -5154,14 +5166,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5154
5166
  EventCategory["DeviceSleeping"] = "device.sleeping";
5155
5167
  EventCategory["RetentionCleanup"] = "retention.cleanup";
5156
5168
  /**
5157
- * Progress snapshot emitted by `BulkUpdateCoordinator` on every state
5158
- * transition (item status change, phase change, completion, cancel).
5159
- * Payload is `BulkUpdateState`. Admin UI subscribes via `useLiveEvent`
5160
- * to drive the sticky `BulkUpdateBanner` and per-row `AddonRowBadge`.
5161
- *
5162
- * Spec: docs/superpowers/specs/2026-05-21-addons-bulk-update-progress-design.md
5169
+ * Legacy bulk-update progress snapshot (payload `BulkUpdateState`). No longer
5170
+ * emitted F3 removed the coordinator that produced it; "Update all" now runs
5171
+ * as one lifecycle engine job (`AddonsJobProgress`/`AddonsJobLog`). Retained
5172
+ * (with `BulkUpdateState`) only to avoid regenerating the event maps; removed
5173
+ * in F4 once live bulk progress is re-implemented over the engine events.
5163
5174
  */
5164
5175
  EventCategory["AddonsBulkUpdateProgress"] = "addons.bulk-update-progress";
5176
+ EventCategory["AddonsJobProgress"] = "addons.job-progress";
5177
+ EventCategory["AddonsJobLog"] = "addons.job-log";
5165
5178
  /**
5166
5179
  * A container's child visibility toggled (hidden/shown). Emitted by the
5167
5180
  * `accessories` cap when a child device is hidden or revealed.
@@ -10377,6 +10390,24 @@ var DetectorOutputSchema = object({
10377
10390
  inferenceMs: number(),
10378
10391
  modelId: string()
10379
10392
  });
10393
+ var EngineProvisioningSchema = object({
10394
+ runtimeId: _enum([
10395
+ "onnx",
10396
+ "openvino",
10397
+ "coreml"
10398
+ ]).nullable(),
10399
+ device: string().nullable(),
10400
+ state: _enum([
10401
+ "idle",
10402
+ "installing",
10403
+ "verifying",
10404
+ "ready",
10405
+ "failed"
10406
+ ]),
10407
+ progress: number().optional(),
10408
+ error: string().optional(),
10409
+ nextRetryAt: number().optional()
10410
+ });
10380
10411
  var PipelineStepInputSchema = lazy(() => object({
10381
10412
  addonId: string(),
10382
10413
  modelId: string(),
@@ -10445,7 +10476,7 @@ var PipelineRunResultBridge = custom();
10445
10476
  method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
10446
10477
  kind: "mutation",
10447
10478
  auth: "admin"
10448
- }), method(_void(), record(string(), object({
10479
+ }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
10449
10480
  modelId: string(),
10450
10481
  settings: record(string(), unknown()).readonly()
10451
10482
  }))), method(object({ steps: record(string(), object({
@@ -15667,7 +15698,10 @@ var AgentAddonConfigSchema = object({
15667
15698
  modelId: string(),
15668
15699
  settings: record(string(), unknown()).readonly()
15669
15700
  });
15670
- var AgentPipelineSettingsSchema = object({ addonDefaults: record(string(), AgentAddonConfigSchema).readonly() });
15701
+ var AgentPipelineSettingsSchema = object({
15702
+ addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
15703
+ maxCameras: number().int().nonnegative().nullable().default(null)
15704
+ });
15671
15705
  var CameraPipelineForAgentSchema = object({
15672
15706
  steps: array(PipelineStepInputSchema).readonly(),
15673
15707
  audio: object({
@@ -15769,6 +15803,133 @@ var GlobalMetricsSchema = object({
15769
15803
  * capability providers.
15770
15804
  */
15771
15805
  var CapabilityBindingsSchema = record(string(), string());
15806
+ /** Source block — always present; derives from the stream catalog. */
15807
+ var CameraSourceStatusSchema = object({ streams: array(object({
15808
+ camStreamId: string(),
15809
+ codec: string(),
15810
+ width: number(),
15811
+ height: number(),
15812
+ fps: number(),
15813
+ kind: string()
15814
+ })).readonly() });
15815
+ /** Assignment block — always present (orchestrator-local, no remote call). */
15816
+ var CameraAssignmentStatusSchema = object({
15817
+ detectionNodeId: string().nullable(),
15818
+ decoderNodeId: string().nullable(),
15819
+ audioNodeId: string().nullable(),
15820
+ pinned: object({
15821
+ detection: boolean(),
15822
+ decoder: boolean(),
15823
+ audio: boolean()
15824
+ }),
15825
+ reasons: object({
15826
+ detection: string().optional(),
15827
+ decoder: string().optional(),
15828
+ audio: string().optional()
15829
+ })
15830
+ });
15831
+ /** Broker block — null when the broker stage is unreachable or inactive. */
15832
+ var CameraBrokerStatusSchema = object({
15833
+ profiles: array(object({
15834
+ profile: string(),
15835
+ status: string(),
15836
+ codec: string(),
15837
+ width: number(),
15838
+ height: number(),
15839
+ subscribers: number(),
15840
+ inFps: number(),
15841
+ outFps: number()
15842
+ })).readonly(),
15843
+ webrtcSessions: number(),
15844
+ rtspRestream: boolean()
15845
+ });
15846
+ /** Shared-memory ring statistics within the decoder block. */
15847
+ var CameraDecoderShmSchema = object({
15848
+ framesWritten: number(),
15849
+ getFrameHits: number(),
15850
+ getFrameMisses: number(),
15851
+ budgetMb: number()
15852
+ });
15853
+ /** Decoder block — null when the decoder stage is unreachable or inactive. */
15854
+ var CameraDecoderStatusSchema = object({
15855
+ nodeId: string(),
15856
+ formats: array(string()).readonly(),
15857
+ sessionCount: number(),
15858
+ shm: CameraDecoderShmSchema
15859
+ });
15860
+ /** Motion block — null when motion detection is not active for this device. */
15861
+ var CameraMotionStatusSchema = object({
15862
+ enabled: boolean(),
15863
+ fps: number()
15864
+ });
15865
+ /** Detection provisioning sub-block. */
15866
+ var CameraDetectionProvisioningSchema = object({
15867
+ state: _enum([
15868
+ "idle",
15869
+ "installing",
15870
+ "verifying",
15871
+ "ready",
15872
+ "failed"
15873
+ ]),
15874
+ error: string().optional()
15875
+ });
15876
+ /** Detection phase — derived from the runner's engine phase. */
15877
+ var CameraDetectionPhaseSchema = _enum([
15878
+ "idle",
15879
+ "watching",
15880
+ "active"
15881
+ ]);
15882
+ /** Detection block — null when no detection node is assigned or reachable. */
15883
+ var CameraDetectionStatusSchema = object({
15884
+ nodeId: string(),
15885
+ engine: object({
15886
+ backend: string(),
15887
+ device: string()
15888
+ }),
15889
+ phase: CameraDetectionPhaseSchema,
15890
+ configuredFps: number(),
15891
+ actualFps: number(),
15892
+ queueDepth: number(),
15893
+ avgInferenceMs: number(),
15894
+ provisioning: CameraDetectionProvisioningSchema
15895
+ });
15896
+ /** Audio block — null when no audio node is assigned or reachable. */
15897
+ var CameraAudioStatusSchema = object({
15898
+ nodeId: string(),
15899
+ enabled: boolean()
15900
+ });
15901
+ /** Recording block — null when no recording cap is active for this device. */
15902
+ var CameraRecordingStatusSchema = object({
15903
+ mode: _enum([
15904
+ "off",
15905
+ "continuous",
15906
+ "events"
15907
+ ]),
15908
+ active: boolean(),
15909
+ storageBytes: number()
15910
+ });
15911
+ /**
15912
+ * Aggregated per-camera pipeline status — server-composed, single call.
15913
+ *
15914
+ * The `assignment` and `source` blocks are always present.
15915
+ * Every other block is `null` when the stage is inactive or unreachable
15916
+ * during the bounded parallel fan-out in the orchestrator implementation.
15917
+ *
15918
+ * See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
15919
+ */
15920
+ var CameraStatusSchema = object({
15921
+ deviceId: number(),
15922
+ assignment: CameraAssignmentStatusSchema,
15923
+ source: CameraSourceStatusSchema,
15924
+ broker: CameraBrokerStatusSchema.nullable(),
15925
+ decoder: CameraDecoderStatusSchema.nullable(),
15926
+ motion: CameraMotionStatusSchema.nullable(),
15927
+ detection: CameraDetectionStatusSchema.nullable(),
15928
+ audio: CameraAudioStatusSchema.nullable(),
15929
+ recording: CameraRecordingStatusSchema.nullable(),
15930
+ /** Unix timestamp (ms) when this snapshot was composed server-side. */
15931
+ fetchedAt: number()
15932
+ });
15772
15933
  method(object({
15773
15934
  deviceId: number(),
15774
15935
  agentNodeId: string()
@@ -15836,6 +15997,12 @@ method(object({
15836
15997
  }), {
15837
15998
  kind: "mutation",
15838
15999
  auth: "admin"
16000
+ }), method(object({
16001
+ agentNodeId: string(),
16002
+ maxCameras: number().int().nonnegative().nullable()
16003
+ }), object({ success: literal(true) }), {
16004
+ kind: "mutation",
16005
+ auth: "admin"
15839
16006
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
15840
16007
  deviceId: number(),
15841
16008
  addonId: string(),
@@ -15861,7 +16028,7 @@ method(object({
15861
16028
  }), method(object({
15862
16029
  deviceId: number(),
15863
16030
  agentNodeId: string().optional()
15864
- }), CameraPipelineConfigSchema), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
16031
+ }), CameraPipelineConfigSchema), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
15865
16032
  name: string(),
15866
16033
  description: string().optional(),
15867
16034
  config: CameraPipelineConfigSchema
@@ -18825,6 +18992,69 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
18825
18992
  kind: "mutation",
18826
18993
  auth: "admin"
18827
18994
  });
18995
+ var jobKindSchema = _enum([
18996
+ "install",
18997
+ "update",
18998
+ "uninstall",
18999
+ "restart"
19000
+ ]);
19001
+ var taskPhaseSchema = _enum([
19002
+ "queued",
19003
+ "fetching",
19004
+ "staged",
19005
+ "validating",
19006
+ "applying",
19007
+ "restarting",
19008
+ "applied",
19009
+ "done",
19010
+ "failed",
19011
+ "skipped"
19012
+ ]);
19013
+ var taskTargetSchema = _enum(["framework", "addon"]);
19014
+ var taskLogEntrySchema = object({
19015
+ tsMs: number(),
19016
+ nodeId: string(),
19017
+ packageName: string(),
19018
+ phase: taskPhaseSchema,
19019
+ message: string()
19020
+ });
19021
+ var lifecycleTaskSchema = object({
19022
+ taskId: string(),
19023
+ nodeId: string(),
19024
+ packageName: string(),
19025
+ fromVersion: string().nullable(),
19026
+ toVersion: string(),
19027
+ target: taskTargetSchema,
19028
+ phase: taskPhaseSchema,
19029
+ stagedPath: string().nullable(),
19030
+ attempts: number(),
19031
+ steps: array(taskLogEntrySchema),
19032
+ error: string().nullable(),
19033
+ startedAtMs: number().nullable(),
19034
+ finishedAtMs: number().nullable()
19035
+ });
19036
+ var lifecycleJobStateSchema = _enum([
19037
+ "running",
19038
+ "completed",
19039
+ "failed",
19040
+ "partially-failed",
19041
+ "cancelled"
19042
+ ]);
19043
+ var lifecycleJobScopeSchema = _enum([
19044
+ "single",
19045
+ "bulk",
19046
+ "cluster"
19047
+ ]);
19048
+ var lifecycleJobSchema = object({
19049
+ jobId: string(),
19050
+ kind: jobKindSchema,
19051
+ createdAtMs: number(),
19052
+ createdBy: string(),
19053
+ scope: lifecycleJobScopeSchema,
19054
+ tasks: array(lifecycleTaskSchema),
19055
+ state: lifecycleJobStateSchema,
19056
+ schemaVersion: literal(1)
19057
+ });
18828
19058
  /**
18829
19059
  * addons — system-scoped singleton capability for addon package
18830
19060
  * management (install, update, configure, restart) and per-addon log
@@ -19007,7 +19237,7 @@ var BulkUpdatePhaseSchema = _enum([
19007
19237
  "restarting",
19008
19238
  "finalizing"
19009
19239
  ]);
19010
- var BulkUpdateStateSchema = object({
19240
+ object({
19011
19241
  id: string(),
19012
19242
  nodeId: string(),
19013
19243
  startedAtMs: number(),
@@ -19110,20 +19340,7 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
19110
19340
  }), UpdateFrameworkPackageResultSchema, {
19111
19341
  kind: "mutation",
19112
19342
  auth: "admin"
19113
- }), method(object({
19114
- nodeId: string(),
19115
- items: array(object({
19116
- name: string(),
19117
- version: string(),
19118
- isSystem: boolean()
19119
- })).readonly()
19120
- }), object({ id: string() }), {
19121
- kind: "mutation",
19122
- auth: "admin"
19123
- }), method(object({ id: string() }), BulkUpdateStateSchema.nullable(), { auth: "admin" }), method(object({ id: string() }), object({ cancelled: boolean() }), {
19124
- kind: "mutation",
19125
- auth: "admin"
19126
- }), method(object({ nodeId: string().optional() }), array(BulkUpdateStateSchema).readonly(), { auth: "admin" }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
19343
+ }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
19127
19344
  kind: "mutation",
19128
19345
  auth: "admin"
19129
19346
  }), method(object({ packageName: string() }), object({ success: literal(true) }), {
@@ -19145,6 +19362,24 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
19145
19362
  kind: "mutation",
19146
19363
  auth: "admin"
19147
19364
  }), method(CustomActionInputSchema, unknown(), { kind: "mutation" }), method(object({
19365
+ kind: _enum([
19366
+ "install",
19367
+ "update",
19368
+ "uninstall",
19369
+ "restart"
19370
+ ]),
19371
+ targets: array(object({
19372
+ name: string().min(1),
19373
+ version: string().min(1)
19374
+ })).min(1),
19375
+ nodeIds: array(string()).optional()
19376
+ }), object({ jobId: string() }), {
19377
+ kind: "mutation",
19378
+ auth: "admin"
19379
+ }), method(object({ jobId: string() }), lifecycleJobSchema.nullable(), { auth: "admin" }), method(object({ activeOnly: boolean().optional() }), array(lifecycleJobSchema), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
19380
+ kind: "mutation",
19381
+ auth: "admin"
19382
+ }), method(object({
19148
19383
  addonId: string(),
19149
19384
  level: LogLevelSchema$1.optional()
19150
19385
  }), LogStreamEntrySchema, { kind: "subscription" });
@@ -19185,7 +19420,7 @@ Object.freeze({
19185
19420
  addonId: null,
19186
19421
  access: "create"
19187
19422
  },
19188
- "addons.cancelBulkUpdate": {
19423
+ "addons.cancelJob": {
19189
19424
  capName: "addons",
19190
19425
  capScope: "system",
19191
19426
  addonId: null,
@@ -19215,7 +19450,7 @@ Object.freeze({
19215
19450
  addonId: null,
19216
19451
  access: "view"
19217
19452
  },
19218
- "addons.getBulkUpdateState": {
19453
+ "addons.getJob": {
19219
19454
  capName: "addons",
19220
19455
  capScope: "system",
19221
19456
  addonId: null,
@@ -19263,19 +19498,19 @@ Object.freeze({
19263
19498
  addonId: null,
19264
19499
  access: "view"
19265
19500
  },
19266
- "addons.listActiveBulkUpdates": {
19501
+ "addons.listCapabilityProviders": {
19267
19502
  capName: "addons",
19268
19503
  capScope: "system",
19269
19504
  addonId: null,
19270
19505
  access: "view"
19271
19506
  },
19272
- "addons.listCapabilityProviders": {
19507
+ "addons.listFrameworkPackages": {
19273
19508
  capName: "addons",
19274
19509
  capScope: "system",
19275
19510
  addonId: null,
19276
19511
  access: "view"
19277
19512
  },
19278
- "addons.listFrameworkPackages": {
19513
+ "addons.listJobs": {
19279
19514
  capName: "addons",
19280
19515
  capScope: "system",
19281
19516
  addonId: null,
@@ -19359,7 +19594,7 @@ Object.freeze({
19359
19594
  addonId: null,
19360
19595
  access: "create"
19361
19596
  },
19362
- "addons.startBulkUpdate": {
19597
+ "addons.startJob": {
19363
19598
  capName: "addons",
19364
19599
  capScope: "system",
19365
19600
  addonId: null,
@@ -21585,6 +21820,12 @@ Object.freeze({
21585
21820
  addonId: null,
21586
21821
  access: "view"
21587
21822
  },
21823
+ "pipelineExecutor.getEngineProvisioning": {
21824
+ capName: "pipeline-executor",
21825
+ capScope: "system",
21826
+ addonId: null,
21827
+ access: "view"
21828
+ },
21588
21829
  "pipelineExecutor.getGlobalPipelineConfig": {
21589
21830
  capName: "pipeline-executor",
21590
21831
  capScope: "system",
@@ -21789,6 +22030,18 @@ Object.freeze({
21789
22030
  addonId: null,
21790
22031
  access: "view"
21791
22032
  },
22033
+ "pipelineOrchestrator.getCameraStatus": {
22034
+ capName: "pipeline-orchestrator",
22035
+ capScope: "system",
22036
+ addonId: null,
22037
+ access: "view"
22038
+ },
22039
+ "pipelineOrchestrator.getCameraStatuses": {
22040
+ capName: "pipeline-orchestrator",
22041
+ capScope: "system",
22042
+ addonId: null,
22043
+ access: "view"
22044
+ },
21792
22045
  "pipelineOrchestrator.getCameraStepOverrides": {
21793
22046
  capName: "pipeline-orchestrator",
21794
22047
  capScope: "system",
@@ -21873,6 +22126,12 @@ Object.freeze({
21873
22126
  addonId: null,
21874
22127
  access: "create"
21875
22128
  },
22129
+ "pipelineOrchestrator.setAgentMaxCameras": {
22130
+ capName: "pipeline-orchestrator",
22131
+ capScope: "system",
22132
+ addonId: null,
22133
+ access: "create"
22134
+ },
21876
22135
  "pipelineOrchestrator.setCameraPipelineForAgent": {
21877
22136
  capName: "pipeline-orchestrator",
21878
22137
  capScope: "system",
@@ -23346,6 +23605,32 @@ Object.freeze({
23346
23605
  "network-access": "ingress",
23347
23606
  "smtp-provider": "email"
23348
23607
  });
23608
+ var frameworkSwapPackageSchema = object({
23609
+ name: string(),
23610
+ stagedPath: string(),
23611
+ backupPath: string(),
23612
+ toVersion: string(),
23613
+ fromVersion: string().nullable()
23614
+ });
23615
+ object({
23616
+ jobId: string(),
23617
+ taskId: string(),
23618
+ packages: array(frameworkSwapPackageSchema),
23619
+ requestedAtMs: number(),
23620
+ schemaVersion: literal(1)
23621
+ });
23622
+ object({
23623
+ jobId: string(),
23624
+ taskId: string(),
23625
+ backups: array(object({
23626
+ name: string(),
23627
+ backupPath: string(),
23628
+ livePath: string()
23629
+ })),
23630
+ appliedAtMs: number(),
23631
+ bootAttempts: number(),
23632
+ schemaVersion: literal(1)
23633
+ });
23349
23634
  /**
23350
23635
  * Pure fuzzy matcher for adoption location import. Normalized
23351
23636
  * case-insensitive Levenshtein similarity, used to reuse an existing
package/dist/addon.mjs CHANGED
@@ -5006,6 +5006,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5006
5006
  */
5007
5007
  EventCategory["PipelineEngineMetricsSnapshot"] = "pipeline.engine-metrics-snapshot";
5008
5008
  /**
5009
+ * Per-node detection-engine runtime-provisioning transition. Emitted by
5010
+ * the detection-pipeline provider on every state change of its lazy
5011
+ * engine-provisioning machine (idle → installing → verifying → ready,
5012
+ * or → failed with a `nextRetryAt`). Payload is the
5013
+ * `EngineProvisioningState` snapshot; `event.source.nodeId` carries the
5014
+ * node. The Pipeline page subscribes to drive a live "installing
5015
+ * OpenVINO… / ready" indicator per node without polling
5016
+ * `pipelineExecutor.getEngineProvisioning`. Telemetry-grade (D8): the UI
5017
+ * also reads the cap snapshot on mount / reconnect. Phase 2.
5018
+ */
5019
+ EventCategory["PipelineEngineProvisioning"] = "pipeline.engine-provisioning";
5020
+ /**
5009
5021
  * Cluster topology snapshot. Carries the same payload returned by
5010
5022
  * `nodes.topology` (every reachable node + addons + processes).
5011
5023
  * Emitted by the hub on any agent / addon lifecycle change
@@ -5155,14 +5167,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5155
5167
  EventCategory["DeviceSleeping"] = "device.sleeping";
5156
5168
  EventCategory["RetentionCleanup"] = "retention.cleanup";
5157
5169
  /**
5158
- * Progress snapshot emitted by `BulkUpdateCoordinator` on every state
5159
- * transition (item status change, phase change, completion, cancel).
5160
- * Payload is `BulkUpdateState`. Admin UI subscribes via `useLiveEvent`
5161
- * to drive the sticky `BulkUpdateBanner` and per-row `AddonRowBadge`.
5162
- *
5163
- * Spec: docs/superpowers/specs/2026-05-21-addons-bulk-update-progress-design.md
5170
+ * Legacy bulk-update progress snapshot (payload `BulkUpdateState`). No longer
5171
+ * emitted F3 removed the coordinator that produced it; "Update all" now runs
5172
+ * as one lifecycle engine job (`AddonsJobProgress`/`AddonsJobLog`). Retained
5173
+ * (with `BulkUpdateState`) only to avoid regenerating the event maps; removed
5174
+ * in F4 once live bulk progress is re-implemented over the engine events.
5164
5175
  */
5165
5176
  EventCategory["AddonsBulkUpdateProgress"] = "addons.bulk-update-progress";
5177
+ EventCategory["AddonsJobProgress"] = "addons.job-progress";
5178
+ EventCategory["AddonsJobLog"] = "addons.job-log";
5166
5179
  /**
5167
5180
  * A container's child visibility toggled (hidden/shown). Emitted by the
5168
5181
  * `accessories` cap when a child device is hidden or revealed.
@@ -10378,6 +10391,24 @@ var DetectorOutputSchema = object({
10378
10391
  inferenceMs: number(),
10379
10392
  modelId: string()
10380
10393
  });
10394
+ var EngineProvisioningSchema = object({
10395
+ runtimeId: _enum([
10396
+ "onnx",
10397
+ "openvino",
10398
+ "coreml"
10399
+ ]).nullable(),
10400
+ device: string().nullable(),
10401
+ state: _enum([
10402
+ "idle",
10403
+ "installing",
10404
+ "verifying",
10405
+ "ready",
10406
+ "failed"
10407
+ ]),
10408
+ progress: number().optional(),
10409
+ error: string().optional(),
10410
+ nextRetryAt: number().optional()
10411
+ });
10381
10412
  var PipelineStepInputSchema = lazy(() => object({
10382
10413
  addonId: string(),
10383
10414
  modelId: string(),
@@ -10446,7 +10477,7 @@ var PipelineRunResultBridge = custom();
10446
10477
  method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
10447
10478
  kind: "mutation",
10448
10479
  auth: "admin"
10449
- }), method(_void(), record(string(), object({
10480
+ }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
10450
10481
  modelId: string(),
10451
10482
  settings: record(string(), unknown()).readonly()
10452
10483
  }))), method(object({ steps: record(string(), object({
@@ -15668,7 +15699,10 @@ var AgentAddonConfigSchema = object({
15668
15699
  modelId: string(),
15669
15700
  settings: record(string(), unknown()).readonly()
15670
15701
  });
15671
- var AgentPipelineSettingsSchema = object({ addonDefaults: record(string(), AgentAddonConfigSchema).readonly() });
15702
+ var AgentPipelineSettingsSchema = object({
15703
+ addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
15704
+ maxCameras: number().int().nonnegative().nullable().default(null)
15705
+ });
15672
15706
  var CameraPipelineForAgentSchema = object({
15673
15707
  steps: array(PipelineStepInputSchema).readonly(),
15674
15708
  audio: object({
@@ -15770,6 +15804,133 @@ var GlobalMetricsSchema = object({
15770
15804
  * capability providers.
15771
15805
  */
15772
15806
  var CapabilityBindingsSchema = record(string(), string());
15807
+ /** Source block — always present; derives from the stream catalog. */
15808
+ var CameraSourceStatusSchema = object({ streams: array(object({
15809
+ camStreamId: string(),
15810
+ codec: string(),
15811
+ width: number(),
15812
+ height: number(),
15813
+ fps: number(),
15814
+ kind: string()
15815
+ })).readonly() });
15816
+ /** Assignment block — always present (orchestrator-local, no remote call). */
15817
+ var CameraAssignmentStatusSchema = object({
15818
+ detectionNodeId: string().nullable(),
15819
+ decoderNodeId: string().nullable(),
15820
+ audioNodeId: string().nullable(),
15821
+ pinned: object({
15822
+ detection: boolean(),
15823
+ decoder: boolean(),
15824
+ audio: boolean()
15825
+ }),
15826
+ reasons: object({
15827
+ detection: string().optional(),
15828
+ decoder: string().optional(),
15829
+ audio: string().optional()
15830
+ })
15831
+ });
15832
+ /** Broker block — null when the broker stage is unreachable or inactive. */
15833
+ var CameraBrokerStatusSchema = object({
15834
+ profiles: array(object({
15835
+ profile: string(),
15836
+ status: string(),
15837
+ codec: string(),
15838
+ width: number(),
15839
+ height: number(),
15840
+ subscribers: number(),
15841
+ inFps: number(),
15842
+ outFps: number()
15843
+ })).readonly(),
15844
+ webrtcSessions: number(),
15845
+ rtspRestream: boolean()
15846
+ });
15847
+ /** Shared-memory ring statistics within the decoder block. */
15848
+ var CameraDecoderShmSchema = object({
15849
+ framesWritten: number(),
15850
+ getFrameHits: number(),
15851
+ getFrameMisses: number(),
15852
+ budgetMb: number()
15853
+ });
15854
+ /** Decoder block — null when the decoder stage is unreachable or inactive. */
15855
+ var CameraDecoderStatusSchema = object({
15856
+ nodeId: string(),
15857
+ formats: array(string()).readonly(),
15858
+ sessionCount: number(),
15859
+ shm: CameraDecoderShmSchema
15860
+ });
15861
+ /** Motion block — null when motion detection is not active for this device. */
15862
+ var CameraMotionStatusSchema = object({
15863
+ enabled: boolean(),
15864
+ fps: number()
15865
+ });
15866
+ /** Detection provisioning sub-block. */
15867
+ var CameraDetectionProvisioningSchema = object({
15868
+ state: _enum([
15869
+ "idle",
15870
+ "installing",
15871
+ "verifying",
15872
+ "ready",
15873
+ "failed"
15874
+ ]),
15875
+ error: string().optional()
15876
+ });
15877
+ /** Detection phase — derived from the runner's engine phase. */
15878
+ var CameraDetectionPhaseSchema = _enum([
15879
+ "idle",
15880
+ "watching",
15881
+ "active"
15882
+ ]);
15883
+ /** Detection block — null when no detection node is assigned or reachable. */
15884
+ var CameraDetectionStatusSchema = object({
15885
+ nodeId: string(),
15886
+ engine: object({
15887
+ backend: string(),
15888
+ device: string()
15889
+ }),
15890
+ phase: CameraDetectionPhaseSchema,
15891
+ configuredFps: number(),
15892
+ actualFps: number(),
15893
+ queueDepth: number(),
15894
+ avgInferenceMs: number(),
15895
+ provisioning: CameraDetectionProvisioningSchema
15896
+ });
15897
+ /** Audio block — null when no audio node is assigned or reachable. */
15898
+ var CameraAudioStatusSchema = object({
15899
+ nodeId: string(),
15900
+ enabled: boolean()
15901
+ });
15902
+ /** Recording block — null when no recording cap is active for this device. */
15903
+ var CameraRecordingStatusSchema = object({
15904
+ mode: _enum([
15905
+ "off",
15906
+ "continuous",
15907
+ "events"
15908
+ ]),
15909
+ active: boolean(),
15910
+ storageBytes: number()
15911
+ });
15912
+ /**
15913
+ * Aggregated per-camera pipeline status — server-composed, single call.
15914
+ *
15915
+ * The `assignment` and `source` blocks are always present.
15916
+ * Every other block is `null` when the stage is inactive or unreachable
15917
+ * during the bounded parallel fan-out in the orchestrator implementation.
15918
+ *
15919
+ * See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
15920
+ */
15921
+ var CameraStatusSchema = object({
15922
+ deviceId: number(),
15923
+ assignment: CameraAssignmentStatusSchema,
15924
+ source: CameraSourceStatusSchema,
15925
+ broker: CameraBrokerStatusSchema.nullable(),
15926
+ decoder: CameraDecoderStatusSchema.nullable(),
15927
+ motion: CameraMotionStatusSchema.nullable(),
15928
+ detection: CameraDetectionStatusSchema.nullable(),
15929
+ audio: CameraAudioStatusSchema.nullable(),
15930
+ recording: CameraRecordingStatusSchema.nullable(),
15931
+ /** Unix timestamp (ms) when this snapshot was composed server-side. */
15932
+ fetchedAt: number()
15933
+ });
15773
15934
  method(object({
15774
15935
  deviceId: number(),
15775
15936
  agentNodeId: string()
@@ -15837,6 +15998,12 @@ method(object({
15837
15998
  }), {
15838
15999
  kind: "mutation",
15839
16000
  auth: "admin"
16001
+ }), method(object({
16002
+ agentNodeId: string(),
16003
+ maxCameras: number().int().nonnegative().nullable()
16004
+ }), object({ success: literal(true) }), {
16005
+ kind: "mutation",
16006
+ auth: "admin"
15840
16007
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
15841
16008
  deviceId: number(),
15842
16009
  addonId: string(),
@@ -15862,7 +16029,7 @@ method(object({
15862
16029
  }), method(object({
15863
16030
  deviceId: number(),
15864
16031
  agentNodeId: string().optional()
15865
- }), CameraPipelineConfigSchema), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
16032
+ }), CameraPipelineConfigSchema), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
15866
16033
  name: string(),
15867
16034
  description: string().optional(),
15868
16035
  config: CameraPipelineConfigSchema
@@ -18826,6 +18993,69 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
18826
18993
  kind: "mutation",
18827
18994
  auth: "admin"
18828
18995
  });
18996
+ var jobKindSchema = _enum([
18997
+ "install",
18998
+ "update",
18999
+ "uninstall",
19000
+ "restart"
19001
+ ]);
19002
+ var taskPhaseSchema = _enum([
19003
+ "queued",
19004
+ "fetching",
19005
+ "staged",
19006
+ "validating",
19007
+ "applying",
19008
+ "restarting",
19009
+ "applied",
19010
+ "done",
19011
+ "failed",
19012
+ "skipped"
19013
+ ]);
19014
+ var taskTargetSchema = _enum(["framework", "addon"]);
19015
+ var taskLogEntrySchema = object({
19016
+ tsMs: number(),
19017
+ nodeId: string(),
19018
+ packageName: string(),
19019
+ phase: taskPhaseSchema,
19020
+ message: string()
19021
+ });
19022
+ var lifecycleTaskSchema = object({
19023
+ taskId: string(),
19024
+ nodeId: string(),
19025
+ packageName: string(),
19026
+ fromVersion: string().nullable(),
19027
+ toVersion: string(),
19028
+ target: taskTargetSchema,
19029
+ phase: taskPhaseSchema,
19030
+ stagedPath: string().nullable(),
19031
+ attempts: number(),
19032
+ steps: array(taskLogEntrySchema),
19033
+ error: string().nullable(),
19034
+ startedAtMs: number().nullable(),
19035
+ finishedAtMs: number().nullable()
19036
+ });
19037
+ var lifecycleJobStateSchema = _enum([
19038
+ "running",
19039
+ "completed",
19040
+ "failed",
19041
+ "partially-failed",
19042
+ "cancelled"
19043
+ ]);
19044
+ var lifecycleJobScopeSchema = _enum([
19045
+ "single",
19046
+ "bulk",
19047
+ "cluster"
19048
+ ]);
19049
+ var lifecycleJobSchema = object({
19050
+ jobId: string(),
19051
+ kind: jobKindSchema,
19052
+ createdAtMs: number(),
19053
+ createdBy: string(),
19054
+ scope: lifecycleJobScopeSchema,
19055
+ tasks: array(lifecycleTaskSchema),
19056
+ state: lifecycleJobStateSchema,
19057
+ schemaVersion: literal(1)
19058
+ });
18829
19059
  /**
18830
19060
  * addons — system-scoped singleton capability for addon package
18831
19061
  * management (install, update, configure, restart) and per-addon log
@@ -19008,7 +19238,7 @@ var BulkUpdatePhaseSchema = _enum([
19008
19238
  "restarting",
19009
19239
  "finalizing"
19010
19240
  ]);
19011
- var BulkUpdateStateSchema = object({
19241
+ object({
19012
19242
  id: string(),
19013
19243
  nodeId: string(),
19014
19244
  startedAtMs: number(),
@@ -19111,20 +19341,7 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
19111
19341
  }), UpdateFrameworkPackageResultSchema, {
19112
19342
  kind: "mutation",
19113
19343
  auth: "admin"
19114
- }), method(object({
19115
- nodeId: string(),
19116
- items: array(object({
19117
- name: string(),
19118
- version: string(),
19119
- isSystem: boolean()
19120
- })).readonly()
19121
- }), object({ id: string() }), {
19122
- kind: "mutation",
19123
- auth: "admin"
19124
- }), method(object({ id: string() }), BulkUpdateStateSchema.nullable(), { auth: "admin" }), method(object({ id: string() }), object({ cancelled: boolean() }), {
19125
- kind: "mutation",
19126
- auth: "admin"
19127
- }), method(object({ nodeId: string().optional() }), array(BulkUpdateStateSchema).readonly(), { auth: "admin" }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
19344
+ }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
19128
19345
  kind: "mutation",
19129
19346
  auth: "admin"
19130
19347
  }), method(object({ packageName: string() }), object({ success: literal(true) }), {
@@ -19146,6 +19363,24 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
19146
19363
  kind: "mutation",
19147
19364
  auth: "admin"
19148
19365
  }), method(CustomActionInputSchema, unknown(), { kind: "mutation" }), method(object({
19366
+ kind: _enum([
19367
+ "install",
19368
+ "update",
19369
+ "uninstall",
19370
+ "restart"
19371
+ ]),
19372
+ targets: array(object({
19373
+ name: string().min(1),
19374
+ version: string().min(1)
19375
+ })).min(1),
19376
+ nodeIds: array(string()).optional()
19377
+ }), object({ jobId: string() }), {
19378
+ kind: "mutation",
19379
+ auth: "admin"
19380
+ }), method(object({ jobId: string() }), lifecycleJobSchema.nullable(), { auth: "admin" }), method(object({ activeOnly: boolean().optional() }), array(lifecycleJobSchema), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
19381
+ kind: "mutation",
19382
+ auth: "admin"
19383
+ }), method(object({
19149
19384
  addonId: string(),
19150
19385
  level: LogLevelSchema$1.optional()
19151
19386
  }), LogStreamEntrySchema, { kind: "subscription" });
@@ -19186,7 +19421,7 @@ Object.freeze({
19186
19421
  addonId: null,
19187
19422
  access: "create"
19188
19423
  },
19189
- "addons.cancelBulkUpdate": {
19424
+ "addons.cancelJob": {
19190
19425
  capName: "addons",
19191
19426
  capScope: "system",
19192
19427
  addonId: null,
@@ -19216,7 +19451,7 @@ Object.freeze({
19216
19451
  addonId: null,
19217
19452
  access: "view"
19218
19453
  },
19219
- "addons.getBulkUpdateState": {
19454
+ "addons.getJob": {
19220
19455
  capName: "addons",
19221
19456
  capScope: "system",
19222
19457
  addonId: null,
@@ -19264,19 +19499,19 @@ Object.freeze({
19264
19499
  addonId: null,
19265
19500
  access: "view"
19266
19501
  },
19267
- "addons.listActiveBulkUpdates": {
19502
+ "addons.listCapabilityProviders": {
19268
19503
  capName: "addons",
19269
19504
  capScope: "system",
19270
19505
  addonId: null,
19271
19506
  access: "view"
19272
19507
  },
19273
- "addons.listCapabilityProviders": {
19508
+ "addons.listFrameworkPackages": {
19274
19509
  capName: "addons",
19275
19510
  capScope: "system",
19276
19511
  addonId: null,
19277
19512
  access: "view"
19278
19513
  },
19279
- "addons.listFrameworkPackages": {
19514
+ "addons.listJobs": {
19280
19515
  capName: "addons",
19281
19516
  capScope: "system",
19282
19517
  addonId: null,
@@ -19360,7 +19595,7 @@ Object.freeze({
19360
19595
  addonId: null,
19361
19596
  access: "create"
19362
19597
  },
19363
- "addons.startBulkUpdate": {
19598
+ "addons.startJob": {
19364
19599
  capName: "addons",
19365
19600
  capScope: "system",
19366
19601
  addonId: null,
@@ -21586,6 +21821,12 @@ Object.freeze({
21586
21821
  addonId: null,
21587
21822
  access: "view"
21588
21823
  },
21824
+ "pipelineExecutor.getEngineProvisioning": {
21825
+ capName: "pipeline-executor",
21826
+ capScope: "system",
21827
+ addonId: null,
21828
+ access: "view"
21829
+ },
21589
21830
  "pipelineExecutor.getGlobalPipelineConfig": {
21590
21831
  capName: "pipeline-executor",
21591
21832
  capScope: "system",
@@ -21790,6 +22031,18 @@ Object.freeze({
21790
22031
  addonId: null,
21791
22032
  access: "view"
21792
22033
  },
22034
+ "pipelineOrchestrator.getCameraStatus": {
22035
+ capName: "pipeline-orchestrator",
22036
+ capScope: "system",
22037
+ addonId: null,
22038
+ access: "view"
22039
+ },
22040
+ "pipelineOrchestrator.getCameraStatuses": {
22041
+ capName: "pipeline-orchestrator",
22042
+ capScope: "system",
22043
+ addonId: null,
22044
+ access: "view"
22045
+ },
21793
22046
  "pipelineOrchestrator.getCameraStepOverrides": {
21794
22047
  capName: "pipeline-orchestrator",
21795
22048
  capScope: "system",
@@ -21874,6 +22127,12 @@ Object.freeze({
21874
22127
  addonId: null,
21875
22128
  access: "create"
21876
22129
  },
22130
+ "pipelineOrchestrator.setAgentMaxCameras": {
22131
+ capName: "pipeline-orchestrator",
22132
+ capScope: "system",
22133
+ addonId: null,
22134
+ access: "create"
22135
+ },
21877
22136
  "pipelineOrchestrator.setCameraPipelineForAgent": {
21878
22137
  capName: "pipeline-orchestrator",
21879
22138
  capScope: "system",
@@ -23347,6 +23606,32 @@ Object.freeze({
23347
23606
  "network-access": "ingress",
23348
23607
  "smtp-provider": "email"
23349
23608
  });
23609
+ var frameworkSwapPackageSchema = object({
23610
+ name: string(),
23611
+ stagedPath: string(),
23612
+ backupPath: string(),
23613
+ toVersion: string(),
23614
+ fromVersion: string().nullable()
23615
+ });
23616
+ object({
23617
+ jobId: string(),
23618
+ taskId: string(),
23619
+ packages: array(frameworkSwapPackageSchema),
23620
+ requestedAtMs: number(),
23621
+ schemaVersion: literal(1)
23622
+ });
23623
+ object({
23624
+ jobId: string(),
23625
+ taskId: string(),
23626
+ backups: array(object({
23627
+ name: string(),
23628
+ backupPath: string(),
23629
+ livePath: string()
23630
+ })),
23631
+ appliedAtMs: number(),
23632
+ bootAttempts: number(),
23633
+ schemaVersion: literal(1)
23634
+ });
23350
23635
  /**
23351
23636
  * Pure fuzzy matcher for adoption location import. Normalized
23352
23637
  * 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-homematic",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Homematic / HomematicIP (CCU3 / RaspberryMatic) device-provider addon for CamStack — wraps the nodehomematic library",
5
5
  "keywords": [
6
6
  "camstack",