@camstack/addon-export-hap 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.
@@ -5018,6 +5018,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5018
5018
  */
5019
5019
  EventCategory["PipelineEngineMetricsSnapshot"] = "pipeline.engine-metrics-snapshot";
5020
5020
  /**
5021
+ * Per-node detection-engine runtime-provisioning transition. Emitted by
5022
+ * the detection-pipeline provider on every state change of its lazy
5023
+ * engine-provisioning machine (idle → installing → verifying → ready,
5024
+ * or → failed with a `nextRetryAt`). Payload is the
5025
+ * `EngineProvisioningState` snapshot; `event.source.nodeId` carries the
5026
+ * node. The Pipeline page subscribes to drive a live "installing
5027
+ * OpenVINO… / ready" indicator per node without polling
5028
+ * `pipelineExecutor.getEngineProvisioning`. Telemetry-grade (D8): the UI
5029
+ * also reads the cap snapshot on mount / reconnect. Phase 2.
5030
+ */
5031
+ EventCategory["PipelineEngineProvisioning"] = "pipeline.engine-provisioning";
5032
+ /**
5021
5033
  * Cluster topology snapshot. Carries the same payload returned by
5022
5034
  * `nodes.topology` (every reachable node + addons + processes).
5023
5035
  * Emitted by the hub on any agent / addon lifecycle change
@@ -5167,14 +5179,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5167
5179
  EventCategory["DeviceSleeping"] = "device.sleeping";
5168
5180
  EventCategory["RetentionCleanup"] = "retention.cleanup";
5169
5181
  /**
5170
- * Progress snapshot emitted by `BulkUpdateCoordinator` on every state
5171
- * transition (item status change, phase change, completion, cancel).
5172
- * Payload is `BulkUpdateState`. Admin UI subscribes via `useLiveEvent`
5173
- * to drive the sticky `BulkUpdateBanner` and per-row `AddonRowBadge`.
5174
- *
5175
- * Spec: docs/superpowers/specs/2026-05-21-addons-bulk-update-progress-design.md
5182
+ * Legacy bulk-update progress snapshot (payload `BulkUpdateState`). No longer
5183
+ * emitted F3 removed the coordinator that produced it; "Update all" now runs
5184
+ * as one lifecycle engine job (`AddonsJobProgress`/`AddonsJobLog`). Retained
5185
+ * (with `BulkUpdateState`) only to avoid regenerating the event maps; removed
5186
+ * in F4 once live bulk progress is re-implemented over the engine events.
5176
5187
  */
5177
5188
  EventCategory["AddonsBulkUpdateProgress"] = "addons.bulk-update-progress";
5189
+ EventCategory["AddonsJobProgress"] = "addons.job-progress";
5190
+ EventCategory["AddonsJobLog"] = "addons.job-log";
5178
5191
  /**
5179
5192
  * A container's child visibility toggled (hidden/shown). Emitted by the
5180
5193
  * `accessories` cap when a child device is hidden or revealed.
@@ -9235,6 +9248,24 @@ var DetectorOutputSchema = object({
9235
9248
  inferenceMs: number(),
9236
9249
  modelId: string()
9237
9250
  });
9251
+ var EngineProvisioningSchema = object({
9252
+ runtimeId: _enum([
9253
+ "onnx",
9254
+ "openvino",
9255
+ "coreml"
9256
+ ]).nullable(),
9257
+ device: string().nullable(),
9258
+ state: _enum([
9259
+ "idle",
9260
+ "installing",
9261
+ "verifying",
9262
+ "ready",
9263
+ "failed"
9264
+ ]),
9265
+ progress: number().optional(),
9266
+ error: string().optional(),
9267
+ nextRetryAt: number().optional()
9268
+ });
9238
9269
  var PipelineStepInputSchema = lazy(() => object({
9239
9270
  addonId: string(),
9240
9271
  modelId: string(),
@@ -9303,7 +9334,7 @@ var PipelineRunResultBridge = custom();
9303
9334
  method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
9304
9335
  kind: "mutation",
9305
9336
  auth: "admin"
9306
- }), method(_void(), record(string(), object({
9337
+ }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
9307
9338
  modelId: string(),
9308
9339
  settings: record(string(), unknown()).readonly()
9309
9340
  }))), method(object({ steps: record(string(), object({
@@ -12915,7 +12946,10 @@ var AgentAddonConfigSchema = object({
12915
12946
  modelId: string(),
12916
12947
  settings: record(string(), unknown()).readonly()
12917
12948
  });
12918
- var AgentPipelineSettingsSchema = object({ addonDefaults: record(string(), AgentAddonConfigSchema).readonly() });
12949
+ var AgentPipelineSettingsSchema = object({
12950
+ addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
12951
+ maxCameras: number().int().nonnegative().nullable().default(null)
12952
+ });
12919
12953
  var CameraPipelineForAgentSchema = object({
12920
12954
  steps: array(PipelineStepInputSchema).readonly(),
12921
12955
  audio: object({
@@ -13017,6 +13051,133 @@ var GlobalMetricsSchema = object({
13017
13051
  * capability providers.
13018
13052
  */
13019
13053
  var CapabilityBindingsSchema = record(string(), string());
13054
+ /** Source block — always present; derives from the stream catalog. */
13055
+ var CameraSourceStatusSchema = object({ streams: array(object({
13056
+ camStreamId: string(),
13057
+ codec: string(),
13058
+ width: number(),
13059
+ height: number(),
13060
+ fps: number(),
13061
+ kind: string()
13062
+ })).readonly() });
13063
+ /** Assignment block — always present (orchestrator-local, no remote call). */
13064
+ var CameraAssignmentStatusSchema = object({
13065
+ detectionNodeId: string().nullable(),
13066
+ decoderNodeId: string().nullable(),
13067
+ audioNodeId: string().nullable(),
13068
+ pinned: object({
13069
+ detection: boolean(),
13070
+ decoder: boolean(),
13071
+ audio: boolean()
13072
+ }),
13073
+ reasons: object({
13074
+ detection: string().optional(),
13075
+ decoder: string().optional(),
13076
+ audio: string().optional()
13077
+ })
13078
+ });
13079
+ /** Broker block — null when the broker stage is unreachable or inactive. */
13080
+ var CameraBrokerStatusSchema = object({
13081
+ profiles: array(object({
13082
+ profile: string(),
13083
+ status: string(),
13084
+ codec: string(),
13085
+ width: number(),
13086
+ height: number(),
13087
+ subscribers: number(),
13088
+ inFps: number(),
13089
+ outFps: number()
13090
+ })).readonly(),
13091
+ webrtcSessions: number(),
13092
+ rtspRestream: boolean()
13093
+ });
13094
+ /** Shared-memory ring statistics within the decoder block. */
13095
+ var CameraDecoderShmSchema = object({
13096
+ framesWritten: number(),
13097
+ getFrameHits: number(),
13098
+ getFrameMisses: number(),
13099
+ budgetMb: number()
13100
+ });
13101
+ /** Decoder block — null when the decoder stage is unreachable or inactive. */
13102
+ var CameraDecoderStatusSchema = object({
13103
+ nodeId: string(),
13104
+ formats: array(string()).readonly(),
13105
+ sessionCount: number(),
13106
+ shm: CameraDecoderShmSchema
13107
+ });
13108
+ /** Motion block — null when motion detection is not active for this device. */
13109
+ var CameraMotionStatusSchema = object({
13110
+ enabled: boolean(),
13111
+ fps: number()
13112
+ });
13113
+ /** Detection provisioning sub-block. */
13114
+ var CameraDetectionProvisioningSchema = object({
13115
+ state: _enum([
13116
+ "idle",
13117
+ "installing",
13118
+ "verifying",
13119
+ "ready",
13120
+ "failed"
13121
+ ]),
13122
+ error: string().optional()
13123
+ });
13124
+ /** Detection phase — derived from the runner's engine phase. */
13125
+ var CameraDetectionPhaseSchema = _enum([
13126
+ "idle",
13127
+ "watching",
13128
+ "active"
13129
+ ]);
13130
+ /** Detection block — null when no detection node is assigned or reachable. */
13131
+ var CameraDetectionStatusSchema = object({
13132
+ nodeId: string(),
13133
+ engine: object({
13134
+ backend: string(),
13135
+ device: string()
13136
+ }),
13137
+ phase: CameraDetectionPhaseSchema,
13138
+ configuredFps: number(),
13139
+ actualFps: number(),
13140
+ queueDepth: number(),
13141
+ avgInferenceMs: number(),
13142
+ provisioning: CameraDetectionProvisioningSchema
13143
+ });
13144
+ /** Audio block — null when no audio node is assigned or reachable. */
13145
+ var CameraAudioStatusSchema = object({
13146
+ nodeId: string(),
13147
+ enabled: boolean()
13148
+ });
13149
+ /** Recording block — null when no recording cap is active for this device. */
13150
+ var CameraRecordingStatusSchema = object({
13151
+ mode: _enum([
13152
+ "off",
13153
+ "continuous",
13154
+ "events"
13155
+ ]),
13156
+ active: boolean(),
13157
+ storageBytes: number()
13158
+ });
13159
+ /**
13160
+ * Aggregated per-camera pipeline status — server-composed, single call.
13161
+ *
13162
+ * The `assignment` and `source` blocks are always present.
13163
+ * Every other block is `null` when the stage is inactive or unreachable
13164
+ * during the bounded parallel fan-out in the orchestrator implementation.
13165
+ *
13166
+ * See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
13167
+ */
13168
+ var CameraStatusSchema = object({
13169
+ deviceId: number(),
13170
+ assignment: CameraAssignmentStatusSchema,
13171
+ source: CameraSourceStatusSchema,
13172
+ broker: CameraBrokerStatusSchema.nullable(),
13173
+ decoder: CameraDecoderStatusSchema.nullable(),
13174
+ motion: CameraMotionStatusSchema.nullable(),
13175
+ detection: CameraDetectionStatusSchema.nullable(),
13176
+ audio: CameraAudioStatusSchema.nullable(),
13177
+ recording: CameraRecordingStatusSchema.nullable(),
13178
+ /** Unix timestamp (ms) when this snapshot was composed server-side. */
13179
+ fetchedAt: number()
13180
+ });
13020
13181
  method(object({
13021
13182
  deviceId: number(),
13022
13183
  agentNodeId: string()
@@ -13084,6 +13245,12 @@ method(object({
13084
13245
  }), {
13085
13246
  kind: "mutation",
13086
13247
  auth: "admin"
13248
+ }), method(object({
13249
+ agentNodeId: string(),
13250
+ maxCameras: number().int().nonnegative().nullable()
13251
+ }), object({ success: literal(true) }), {
13252
+ kind: "mutation",
13253
+ auth: "admin"
13087
13254
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
13088
13255
  deviceId: number(),
13089
13256
  addonId: string(),
@@ -13109,7 +13276,7 @@ method(object({
13109
13276
  }), method(object({
13110
13277
  deviceId: number(),
13111
13278
  agentNodeId: string().optional()
13112
- }), CameraPipelineConfigSchema), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13279
+ }), CameraPipelineConfigSchema), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13113
13280
  name: string(),
13114
13281
  description: string().optional(),
13115
13282
  config: CameraPipelineConfigSchema
@@ -16073,6 +16240,69 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
16073
16240
  kind: "mutation",
16074
16241
  auth: "admin"
16075
16242
  });
16243
+ var jobKindSchema = _enum([
16244
+ "install",
16245
+ "update",
16246
+ "uninstall",
16247
+ "restart"
16248
+ ]);
16249
+ var taskPhaseSchema = _enum([
16250
+ "queued",
16251
+ "fetching",
16252
+ "staged",
16253
+ "validating",
16254
+ "applying",
16255
+ "restarting",
16256
+ "applied",
16257
+ "done",
16258
+ "failed",
16259
+ "skipped"
16260
+ ]);
16261
+ var taskTargetSchema = _enum(["framework", "addon"]);
16262
+ var taskLogEntrySchema = object({
16263
+ tsMs: number(),
16264
+ nodeId: string(),
16265
+ packageName: string(),
16266
+ phase: taskPhaseSchema,
16267
+ message: string()
16268
+ });
16269
+ var lifecycleTaskSchema = object({
16270
+ taskId: string(),
16271
+ nodeId: string(),
16272
+ packageName: string(),
16273
+ fromVersion: string().nullable(),
16274
+ toVersion: string(),
16275
+ target: taskTargetSchema,
16276
+ phase: taskPhaseSchema,
16277
+ stagedPath: string().nullable(),
16278
+ attempts: number(),
16279
+ steps: array(taskLogEntrySchema),
16280
+ error: string().nullable(),
16281
+ startedAtMs: number().nullable(),
16282
+ finishedAtMs: number().nullable()
16283
+ });
16284
+ var lifecycleJobStateSchema = _enum([
16285
+ "running",
16286
+ "completed",
16287
+ "failed",
16288
+ "partially-failed",
16289
+ "cancelled"
16290
+ ]);
16291
+ var lifecycleJobScopeSchema = _enum([
16292
+ "single",
16293
+ "bulk",
16294
+ "cluster"
16295
+ ]);
16296
+ var lifecycleJobSchema = object({
16297
+ jobId: string(),
16298
+ kind: jobKindSchema,
16299
+ createdAtMs: number(),
16300
+ createdBy: string(),
16301
+ scope: lifecycleJobScopeSchema,
16302
+ tasks: array(lifecycleTaskSchema),
16303
+ state: lifecycleJobStateSchema,
16304
+ schemaVersion: literal(1)
16305
+ });
16076
16306
  /**
16077
16307
  * addons — system-scoped singleton capability for addon package
16078
16308
  * management (install, update, configure, restart) and per-addon log
@@ -16255,7 +16485,7 @@ var BulkUpdatePhaseSchema = _enum([
16255
16485
  "restarting",
16256
16486
  "finalizing"
16257
16487
  ]);
16258
- var BulkUpdateStateSchema = object({
16488
+ object({
16259
16489
  id: string(),
16260
16490
  nodeId: string(),
16261
16491
  startedAtMs: number(),
@@ -16358,20 +16588,7 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
16358
16588
  }), UpdateFrameworkPackageResultSchema, {
16359
16589
  kind: "mutation",
16360
16590
  auth: "admin"
16361
- }), method(object({
16362
- nodeId: string(),
16363
- items: array(object({
16364
- name: string(),
16365
- version: string(),
16366
- isSystem: boolean()
16367
- })).readonly()
16368
- }), object({ id: string() }), {
16369
- kind: "mutation",
16370
- auth: "admin"
16371
- }), method(object({ id: string() }), BulkUpdateStateSchema.nullable(), { auth: "admin" }), method(object({ id: string() }), object({ cancelled: boolean() }), {
16372
- kind: "mutation",
16373
- auth: "admin"
16374
- }), method(object({ nodeId: string().optional() }), array(BulkUpdateStateSchema).readonly(), { auth: "admin" }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
16591
+ }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
16375
16592
  kind: "mutation",
16376
16593
  auth: "admin"
16377
16594
  }), method(object({ packageName: string() }), object({ success: literal(true) }), {
@@ -16393,6 +16610,24 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
16393
16610
  kind: "mutation",
16394
16611
  auth: "admin"
16395
16612
  }), method(CustomActionInputSchema, unknown(), { kind: "mutation" }), method(object({
16613
+ kind: _enum([
16614
+ "install",
16615
+ "update",
16616
+ "uninstall",
16617
+ "restart"
16618
+ ]),
16619
+ targets: array(object({
16620
+ name: string().min(1),
16621
+ version: string().min(1)
16622
+ })).min(1),
16623
+ nodeIds: array(string()).optional()
16624
+ }), object({ jobId: string() }), {
16625
+ kind: "mutation",
16626
+ auth: "admin"
16627
+ }), method(object({ jobId: string() }), lifecycleJobSchema.nullable(), { auth: "admin" }), method(object({ activeOnly: boolean().optional() }), array(lifecycleJobSchema), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
16628
+ kind: "mutation",
16629
+ auth: "admin"
16630
+ }), method(object({
16396
16631
  addonId: string(),
16397
16632
  level: LogLevelSchema$1.optional()
16398
16633
  }), LogStreamEntrySchema, { kind: "subscription" });
@@ -16433,7 +16668,7 @@ Object.freeze({
16433
16668
  addonId: null,
16434
16669
  access: "create"
16435
16670
  },
16436
- "addons.cancelBulkUpdate": {
16671
+ "addons.cancelJob": {
16437
16672
  capName: "addons",
16438
16673
  capScope: "system",
16439
16674
  addonId: null,
@@ -16463,7 +16698,7 @@ Object.freeze({
16463
16698
  addonId: null,
16464
16699
  access: "view"
16465
16700
  },
16466
- "addons.getBulkUpdateState": {
16701
+ "addons.getJob": {
16467
16702
  capName: "addons",
16468
16703
  capScope: "system",
16469
16704
  addonId: null,
@@ -16511,19 +16746,19 @@ Object.freeze({
16511
16746
  addonId: null,
16512
16747
  access: "view"
16513
16748
  },
16514
- "addons.listActiveBulkUpdates": {
16749
+ "addons.listCapabilityProviders": {
16515
16750
  capName: "addons",
16516
16751
  capScope: "system",
16517
16752
  addonId: null,
16518
16753
  access: "view"
16519
16754
  },
16520
- "addons.listCapabilityProviders": {
16755
+ "addons.listFrameworkPackages": {
16521
16756
  capName: "addons",
16522
16757
  capScope: "system",
16523
16758
  addonId: null,
16524
16759
  access: "view"
16525
16760
  },
16526
- "addons.listFrameworkPackages": {
16761
+ "addons.listJobs": {
16527
16762
  capName: "addons",
16528
16763
  capScope: "system",
16529
16764
  addonId: null,
@@ -16607,7 +16842,7 @@ Object.freeze({
16607
16842
  addonId: null,
16608
16843
  access: "create"
16609
16844
  },
16610
- "addons.startBulkUpdate": {
16845
+ "addons.startJob": {
16611
16846
  capName: "addons",
16612
16847
  capScope: "system",
16613
16848
  addonId: null,
@@ -18833,6 +19068,12 @@ Object.freeze({
18833
19068
  addonId: null,
18834
19069
  access: "view"
18835
19070
  },
19071
+ "pipelineExecutor.getEngineProvisioning": {
19072
+ capName: "pipeline-executor",
19073
+ capScope: "system",
19074
+ addonId: null,
19075
+ access: "view"
19076
+ },
18836
19077
  "pipelineExecutor.getGlobalPipelineConfig": {
18837
19078
  capName: "pipeline-executor",
18838
19079
  capScope: "system",
@@ -19037,6 +19278,18 @@ Object.freeze({
19037
19278
  addonId: null,
19038
19279
  access: "view"
19039
19280
  },
19281
+ "pipelineOrchestrator.getCameraStatus": {
19282
+ capName: "pipeline-orchestrator",
19283
+ capScope: "system",
19284
+ addonId: null,
19285
+ access: "view"
19286
+ },
19287
+ "pipelineOrchestrator.getCameraStatuses": {
19288
+ capName: "pipeline-orchestrator",
19289
+ capScope: "system",
19290
+ addonId: null,
19291
+ access: "view"
19292
+ },
19040
19293
  "pipelineOrchestrator.getCameraStepOverrides": {
19041
19294
  capName: "pipeline-orchestrator",
19042
19295
  capScope: "system",
@@ -19121,6 +19374,12 @@ Object.freeze({
19121
19374
  addonId: null,
19122
19375
  access: "create"
19123
19376
  },
19377
+ "pipelineOrchestrator.setAgentMaxCameras": {
19378
+ capName: "pipeline-orchestrator",
19379
+ capScope: "system",
19380
+ addonId: null,
19381
+ access: "create"
19382
+ },
19124
19383
  "pipelineOrchestrator.setCameraPipelineForAgent": {
19125
19384
  capName: "pipeline-orchestrator",
19126
19385
  capScope: "system",
@@ -20594,6 +20853,32 @@ Object.freeze({
20594
20853
  "network-access": "ingress",
20595
20854
  "smtp-provider": "email"
20596
20855
  });
20856
+ var frameworkSwapPackageSchema = object({
20857
+ name: string(),
20858
+ stagedPath: string(),
20859
+ backupPath: string(),
20860
+ toVersion: string(),
20861
+ fromVersion: string().nullable()
20862
+ });
20863
+ object({
20864
+ jobId: string(),
20865
+ taskId: string(),
20866
+ packages: array(frameworkSwapPackageSchema),
20867
+ requestedAtMs: number(),
20868
+ schemaVersion: literal(1)
20869
+ });
20870
+ object({
20871
+ jobId: string(),
20872
+ taskId: string(),
20873
+ backups: array(object({
20874
+ name: string(),
20875
+ backupPath: string(),
20876
+ livePath: string()
20877
+ })),
20878
+ appliedAtMs: number(),
20879
+ bootAttempts: number(),
20880
+ schemaVersion: literal(1)
20881
+ });
20597
20882
  /**
20598
20883
  * Deterministic SHA-256 hash of an arbitrary serialisable value. The
20599
20884
  * canonical form sorts object keys alphabetically at every depth so two
@@ -4993,6 +4993,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
4993
4993
  */
4994
4994
  EventCategory["PipelineEngineMetricsSnapshot"] = "pipeline.engine-metrics-snapshot";
4995
4995
  /**
4996
+ * Per-node detection-engine runtime-provisioning transition. Emitted by
4997
+ * the detection-pipeline provider on every state change of its lazy
4998
+ * engine-provisioning machine (idle → installing → verifying → ready,
4999
+ * or → failed with a `nextRetryAt`). Payload is the
5000
+ * `EngineProvisioningState` snapshot; `event.source.nodeId` carries the
5001
+ * node. The Pipeline page subscribes to drive a live "installing
5002
+ * OpenVINO… / ready" indicator per node without polling
5003
+ * `pipelineExecutor.getEngineProvisioning`. Telemetry-grade (D8): the UI
5004
+ * also reads the cap snapshot on mount / reconnect. Phase 2.
5005
+ */
5006
+ EventCategory["PipelineEngineProvisioning"] = "pipeline.engine-provisioning";
5007
+ /**
4996
5008
  * Cluster topology snapshot. Carries the same payload returned by
4997
5009
  * `nodes.topology` (every reachable node + addons + processes).
4998
5010
  * Emitted by the hub on any agent / addon lifecycle change
@@ -5142,14 +5154,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5142
5154
  EventCategory["DeviceSleeping"] = "device.sleeping";
5143
5155
  EventCategory["RetentionCleanup"] = "retention.cleanup";
5144
5156
  /**
5145
- * Progress snapshot emitted by `BulkUpdateCoordinator` on every state
5146
- * transition (item status change, phase change, completion, cancel).
5147
- * Payload is `BulkUpdateState`. Admin UI subscribes via `useLiveEvent`
5148
- * to drive the sticky `BulkUpdateBanner` and per-row `AddonRowBadge`.
5149
- *
5150
- * Spec: docs/superpowers/specs/2026-05-21-addons-bulk-update-progress-design.md
5157
+ * Legacy bulk-update progress snapshot (payload `BulkUpdateState`). No longer
5158
+ * emitted F3 removed the coordinator that produced it; "Update all" now runs
5159
+ * as one lifecycle engine job (`AddonsJobProgress`/`AddonsJobLog`). Retained
5160
+ * (with `BulkUpdateState`) only to avoid regenerating the event maps; removed
5161
+ * in F4 once live bulk progress is re-implemented over the engine events.
5151
5162
  */
5152
5163
  EventCategory["AddonsBulkUpdateProgress"] = "addons.bulk-update-progress";
5164
+ EventCategory["AddonsJobProgress"] = "addons.job-progress";
5165
+ EventCategory["AddonsJobLog"] = "addons.job-log";
5153
5166
  /**
5154
5167
  * A container's child visibility toggled (hidden/shown). Emitted by the
5155
5168
  * `accessories` cap when a child device is hidden or revealed.
@@ -9210,6 +9223,24 @@ var DetectorOutputSchema = object({
9210
9223
  inferenceMs: number(),
9211
9224
  modelId: string()
9212
9225
  });
9226
+ var EngineProvisioningSchema = object({
9227
+ runtimeId: _enum([
9228
+ "onnx",
9229
+ "openvino",
9230
+ "coreml"
9231
+ ]).nullable(),
9232
+ device: string().nullable(),
9233
+ state: _enum([
9234
+ "idle",
9235
+ "installing",
9236
+ "verifying",
9237
+ "ready",
9238
+ "failed"
9239
+ ]),
9240
+ progress: number().optional(),
9241
+ error: string().optional(),
9242
+ nextRetryAt: number().optional()
9243
+ });
9213
9244
  var PipelineStepInputSchema = lazy(() => object({
9214
9245
  addonId: string(),
9215
9246
  modelId: string(),
@@ -9278,7 +9309,7 @@ var PipelineRunResultBridge = custom();
9278
9309
  method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
9279
9310
  kind: "mutation",
9280
9311
  auth: "admin"
9281
- }), method(_void(), record(string(), object({
9312
+ }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
9282
9313
  modelId: string(),
9283
9314
  settings: record(string(), unknown()).readonly()
9284
9315
  }))), method(object({ steps: record(string(), object({
@@ -12890,7 +12921,10 @@ var AgentAddonConfigSchema = object({
12890
12921
  modelId: string(),
12891
12922
  settings: record(string(), unknown()).readonly()
12892
12923
  });
12893
- var AgentPipelineSettingsSchema = object({ addonDefaults: record(string(), AgentAddonConfigSchema).readonly() });
12924
+ var AgentPipelineSettingsSchema = object({
12925
+ addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
12926
+ maxCameras: number().int().nonnegative().nullable().default(null)
12927
+ });
12894
12928
  var CameraPipelineForAgentSchema = object({
12895
12929
  steps: array(PipelineStepInputSchema).readonly(),
12896
12930
  audio: object({
@@ -12992,6 +13026,133 @@ var GlobalMetricsSchema = object({
12992
13026
  * capability providers.
12993
13027
  */
12994
13028
  var CapabilityBindingsSchema = record(string(), string());
13029
+ /** Source block — always present; derives from the stream catalog. */
13030
+ var CameraSourceStatusSchema = object({ streams: array(object({
13031
+ camStreamId: string(),
13032
+ codec: string(),
13033
+ width: number(),
13034
+ height: number(),
13035
+ fps: number(),
13036
+ kind: string()
13037
+ })).readonly() });
13038
+ /** Assignment block — always present (orchestrator-local, no remote call). */
13039
+ var CameraAssignmentStatusSchema = object({
13040
+ detectionNodeId: string().nullable(),
13041
+ decoderNodeId: string().nullable(),
13042
+ audioNodeId: string().nullable(),
13043
+ pinned: object({
13044
+ detection: boolean(),
13045
+ decoder: boolean(),
13046
+ audio: boolean()
13047
+ }),
13048
+ reasons: object({
13049
+ detection: string().optional(),
13050
+ decoder: string().optional(),
13051
+ audio: string().optional()
13052
+ })
13053
+ });
13054
+ /** Broker block — null when the broker stage is unreachable or inactive. */
13055
+ var CameraBrokerStatusSchema = object({
13056
+ profiles: array(object({
13057
+ profile: string(),
13058
+ status: string(),
13059
+ codec: string(),
13060
+ width: number(),
13061
+ height: number(),
13062
+ subscribers: number(),
13063
+ inFps: number(),
13064
+ outFps: number()
13065
+ })).readonly(),
13066
+ webrtcSessions: number(),
13067
+ rtspRestream: boolean()
13068
+ });
13069
+ /** Shared-memory ring statistics within the decoder block. */
13070
+ var CameraDecoderShmSchema = object({
13071
+ framesWritten: number(),
13072
+ getFrameHits: number(),
13073
+ getFrameMisses: number(),
13074
+ budgetMb: number()
13075
+ });
13076
+ /** Decoder block — null when the decoder stage is unreachable or inactive. */
13077
+ var CameraDecoderStatusSchema = object({
13078
+ nodeId: string(),
13079
+ formats: array(string()).readonly(),
13080
+ sessionCount: number(),
13081
+ shm: CameraDecoderShmSchema
13082
+ });
13083
+ /** Motion block — null when motion detection is not active for this device. */
13084
+ var CameraMotionStatusSchema = object({
13085
+ enabled: boolean(),
13086
+ fps: number()
13087
+ });
13088
+ /** Detection provisioning sub-block. */
13089
+ var CameraDetectionProvisioningSchema = object({
13090
+ state: _enum([
13091
+ "idle",
13092
+ "installing",
13093
+ "verifying",
13094
+ "ready",
13095
+ "failed"
13096
+ ]),
13097
+ error: string().optional()
13098
+ });
13099
+ /** Detection phase — derived from the runner's engine phase. */
13100
+ var CameraDetectionPhaseSchema = _enum([
13101
+ "idle",
13102
+ "watching",
13103
+ "active"
13104
+ ]);
13105
+ /** Detection block — null when no detection node is assigned or reachable. */
13106
+ var CameraDetectionStatusSchema = object({
13107
+ nodeId: string(),
13108
+ engine: object({
13109
+ backend: string(),
13110
+ device: string()
13111
+ }),
13112
+ phase: CameraDetectionPhaseSchema,
13113
+ configuredFps: number(),
13114
+ actualFps: number(),
13115
+ queueDepth: number(),
13116
+ avgInferenceMs: number(),
13117
+ provisioning: CameraDetectionProvisioningSchema
13118
+ });
13119
+ /** Audio block — null when no audio node is assigned or reachable. */
13120
+ var CameraAudioStatusSchema = object({
13121
+ nodeId: string(),
13122
+ enabled: boolean()
13123
+ });
13124
+ /** Recording block — null when no recording cap is active for this device. */
13125
+ var CameraRecordingStatusSchema = object({
13126
+ mode: _enum([
13127
+ "off",
13128
+ "continuous",
13129
+ "events"
13130
+ ]),
13131
+ active: boolean(),
13132
+ storageBytes: number()
13133
+ });
13134
+ /**
13135
+ * Aggregated per-camera pipeline status — server-composed, single call.
13136
+ *
13137
+ * The `assignment` and `source` blocks are always present.
13138
+ * Every other block is `null` when the stage is inactive or unreachable
13139
+ * during the bounded parallel fan-out in the orchestrator implementation.
13140
+ *
13141
+ * See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
13142
+ */
13143
+ var CameraStatusSchema = object({
13144
+ deviceId: number(),
13145
+ assignment: CameraAssignmentStatusSchema,
13146
+ source: CameraSourceStatusSchema,
13147
+ broker: CameraBrokerStatusSchema.nullable(),
13148
+ decoder: CameraDecoderStatusSchema.nullable(),
13149
+ motion: CameraMotionStatusSchema.nullable(),
13150
+ detection: CameraDetectionStatusSchema.nullable(),
13151
+ audio: CameraAudioStatusSchema.nullable(),
13152
+ recording: CameraRecordingStatusSchema.nullable(),
13153
+ /** Unix timestamp (ms) when this snapshot was composed server-side. */
13154
+ fetchedAt: number()
13155
+ });
12995
13156
  method(object({
12996
13157
  deviceId: number(),
12997
13158
  agentNodeId: string()
@@ -13059,6 +13220,12 @@ method(object({
13059
13220
  }), {
13060
13221
  kind: "mutation",
13061
13222
  auth: "admin"
13223
+ }), method(object({
13224
+ agentNodeId: string(),
13225
+ maxCameras: number().int().nonnegative().nullable()
13226
+ }), object({ success: literal(true) }), {
13227
+ kind: "mutation",
13228
+ auth: "admin"
13062
13229
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
13063
13230
  deviceId: number(),
13064
13231
  addonId: string(),
@@ -13084,7 +13251,7 @@ method(object({
13084
13251
  }), method(object({
13085
13252
  deviceId: number(),
13086
13253
  agentNodeId: string().optional()
13087
- }), CameraPipelineConfigSchema), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13254
+ }), CameraPipelineConfigSchema), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13088
13255
  name: string(),
13089
13256
  description: string().optional(),
13090
13257
  config: CameraPipelineConfigSchema
@@ -16048,6 +16215,69 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
16048
16215
  kind: "mutation",
16049
16216
  auth: "admin"
16050
16217
  });
16218
+ var jobKindSchema = _enum([
16219
+ "install",
16220
+ "update",
16221
+ "uninstall",
16222
+ "restart"
16223
+ ]);
16224
+ var taskPhaseSchema = _enum([
16225
+ "queued",
16226
+ "fetching",
16227
+ "staged",
16228
+ "validating",
16229
+ "applying",
16230
+ "restarting",
16231
+ "applied",
16232
+ "done",
16233
+ "failed",
16234
+ "skipped"
16235
+ ]);
16236
+ var taskTargetSchema = _enum(["framework", "addon"]);
16237
+ var taskLogEntrySchema = object({
16238
+ tsMs: number(),
16239
+ nodeId: string(),
16240
+ packageName: string(),
16241
+ phase: taskPhaseSchema,
16242
+ message: string()
16243
+ });
16244
+ var lifecycleTaskSchema = object({
16245
+ taskId: string(),
16246
+ nodeId: string(),
16247
+ packageName: string(),
16248
+ fromVersion: string().nullable(),
16249
+ toVersion: string(),
16250
+ target: taskTargetSchema,
16251
+ phase: taskPhaseSchema,
16252
+ stagedPath: string().nullable(),
16253
+ attempts: number(),
16254
+ steps: array(taskLogEntrySchema),
16255
+ error: string().nullable(),
16256
+ startedAtMs: number().nullable(),
16257
+ finishedAtMs: number().nullable()
16258
+ });
16259
+ var lifecycleJobStateSchema = _enum([
16260
+ "running",
16261
+ "completed",
16262
+ "failed",
16263
+ "partially-failed",
16264
+ "cancelled"
16265
+ ]);
16266
+ var lifecycleJobScopeSchema = _enum([
16267
+ "single",
16268
+ "bulk",
16269
+ "cluster"
16270
+ ]);
16271
+ var lifecycleJobSchema = object({
16272
+ jobId: string(),
16273
+ kind: jobKindSchema,
16274
+ createdAtMs: number(),
16275
+ createdBy: string(),
16276
+ scope: lifecycleJobScopeSchema,
16277
+ tasks: array(lifecycleTaskSchema),
16278
+ state: lifecycleJobStateSchema,
16279
+ schemaVersion: literal(1)
16280
+ });
16051
16281
  /**
16052
16282
  * addons — system-scoped singleton capability for addon package
16053
16283
  * management (install, update, configure, restart) and per-addon log
@@ -16230,7 +16460,7 @@ var BulkUpdatePhaseSchema = _enum([
16230
16460
  "restarting",
16231
16461
  "finalizing"
16232
16462
  ]);
16233
- var BulkUpdateStateSchema = object({
16463
+ object({
16234
16464
  id: string(),
16235
16465
  nodeId: string(),
16236
16466
  startedAtMs: number(),
@@ -16333,20 +16563,7 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
16333
16563
  }), UpdateFrameworkPackageResultSchema, {
16334
16564
  kind: "mutation",
16335
16565
  auth: "admin"
16336
- }), method(object({
16337
- nodeId: string(),
16338
- items: array(object({
16339
- name: string(),
16340
- version: string(),
16341
- isSystem: boolean()
16342
- })).readonly()
16343
- }), object({ id: string() }), {
16344
- kind: "mutation",
16345
- auth: "admin"
16346
- }), method(object({ id: string() }), BulkUpdateStateSchema.nullable(), { auth: "admin" }), method(object({ id: string() }), object({ cancelled: boolean() }), {
16347
- kind: "mutation",
16348
- auth: "admin"
16349
- }), method(object({ nodeId: string().optional() }), array(BulkUpdateStateSchema).readonly(), { auth: "admin" }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
16566
+ }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
16350
16567
  kind: "mutation",
16351
16568
  auth: "admin"
16352
16569
  }), method(object({ packageName: string() }), object({ success: literal(true) }), {
@@ -16368,6 +16585,24 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
16368
16585
  kind: "mutation",
16369
16586
  auth: "admin"
16370
16587
  }), method(CustomActionInputSchema, unknown(), { kind: "mutation" }), method(object({
16588
+ kind: _enum([
16589
+ "install",
16590
+ "update",
16591
+ "uninstall",
16592
+ "restart"
16593
+ ]),
16594
+ targets: array(object({
16595
+ name: string().min(1),
16596
+ version: string().min(1)
16597
+ })).min(1),
16598
+ nodeIds: array(string()).optional()
16599
+ }), object({ jobId: string() }), {
16600
+ kind: "mutation",
16601
+ auth: "admin"
16602
+ }), method(object({ jobId: string() }), lifecycleJobSchema.nullable(), { auth: "admin" }), method(object({ activeOnly: boolean().optional() }), array(lifecycleJobSchema), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
16603
+ kind: "mutation",
16604
+ auth: "admin"
16605
+ }), method(object({
16371
16606
  addonId: string(),
16372
16607
  level: LogLevelSchema$1.optional()
16373
16608
  }), LogStreamEntrySchema, { kind: "subscription" });
@@ -16408,7 +16643,7 @@ Object.freeze({
16408
16643
  addonId: null,
16409
16644
  access: "create"
16410
16645
  },
16411
- "addons.cancelBulkUpdate": {
16646
+ "addons.cancelJob": {
16412
16647
  capName: "addons",
16413
16648
  capScope: "system",
16414
16649
  addonId: null,
@@ -16438,7 +16673,7 @@ Object.freeze({
16438
16673
  addonId: null,
16439
16674
  access: "view"
16440
16675
  },
16441
- "addons.getBulkUpdateState": {
16676
+ "addons.getJob": {
16442
16677
  capName: "addons",
16443
16678
  capScope: "system",
16444
16679
  addonId: null,
@@ -16486,19 +16721,19 @@ Object.freeze({
16486
16721
  addonId: null,
16487
16722
  access: "view"
16488
16723
  },
16489
- "addons.listActiveBulkUpdates": {
16724
+ "addons.listCapabilityProviders": {
16490
16725
  capName: "addons",
16491
16726
  capScope: "system",
16492
16727
  addonId: null,
16493
16728
  access: "view"
16494
16729
  },
16495
- "addons.listCapabilityProviders": {
16730
+ "addons.listFrameworkPackages": {
16496
16731
  capName: "addons",
16497
16732
  capScope: "system",
16498
16733
  addonId: null,
16499
16734
  access: "view"
16500
16735
  },
16501
- "addons.listFrameworkPackages": {
16736
+ "addons.listJobs": {
16502
16737
  capName: "addons",
16503
16738
  capScope: "system",
16504
16739
  addonId: null,
@@ -16582,7 +16817,7 @@ Object.freeze({
16582
16817
  addonId: null,
16583
16818
  access: "create"
16584
16819
  },
16585
- "addons.startBulkUpdate": {
16820
+ "addons.startJob": {
16586
16821
  capName: "addons",
16587
16822
  capScope: "system",
16588
16823
  addonId: null,
@@ -18808,6 +19043,12 @@ Object.freeze({
18808
19043
  addonId: null,
18809
19044
  access: "view"
18810
19045
  },
19046
+ "pipelineExecutor.getEngineProvisioning": {
19047
+ capName: "pipeline-executor",
19048
+ capScope: "system",
19049
+ addonId: null,
19050
+ access: "view"
19051
+ },
18811
19052
  "pipelineExecutor.getGlobalPipelineConfig": {
18812
19053
  capName: "pipeline-executor",
18813
19054
  capScope: "system",
@@ -19012,6 +19253,18 @@ Object.freeze({
19012
19253
  addonId: null,
19013
19254
  access: "view"
19014
19255
  },
19256
+ "pipelineOrchestrator.getCameraStatus": {
19257
+ capName: "pipeline-orchestrator",
19258
+ capScope: "system",
19259
+ addonId: null,
19260
+ access: "view"
19261
+ },
19262
+ "pipelineOrchestrator.getCameraStatuses": {
19263
+ capName: "pipeline-orchestrator",
19264
+ capScope: "system",
19265
+ addonId: null,
19266
+ access: "view"
19267
+ },
19015
19268
  "pipelineOrchestrator.getCameraStepOverrides": {
19016
19269
  capName: "pipeline-orchestrator",
19017
19270
  capScope: "system",
@@ -19096,6 +19349,12 @@ Object.freeze({
19096
19349
  addonId: null,
19097
19350
  access: "create"
19098
19351
  },
19352
+ "pipelineOrchestrator.setAgentMaxCameras": {
19353
+ capName: "pipeline-orchestrator",
19354
+ capScope: "system",
19355
+ addonId: null,
19356
+ access: "create"
19357
+ },
19099
19358
  "pipelineOrchestrator.setCameraPipelineForAgent": {
19100
19359
  capName: "pipeline-orchestrator",
19101
19360
  capScope: "system",
@@ -20569,6 +20828,32 @@ Object.freeze({
20569
20828
  "network-access": "ingress",
20570
20829
  "smtp-provider": "email"
20571
20830
  });
20831
+ var frameworkSwapPackageSchema = object({
20832
+ name: string(),
20833
+ stagedPath: string(),
20834
+ backupPath: string(),
20835
+ toVersion: string(),
20836
+ fromVersion: string().nullable()
20837
+ });
20838
+ object({
20839
+ jobId: string(),
20840
+ taskId: string(),
20841
+ packages: array(frameworkSwapPackageSchema),
20842
+ requestedAtMs: number(),
20843
+ schemaVersion: literal(1)
20844
+ });
20845
+ object({
20846
+ jobId: string(),
20847
+ taskId: string(),
20848
+ backups: array(object({
20849
+ name: string(),
20850
+ backupPath: string(),
20851
+ livePath: string()
20852
+ })),
20853
+ appliedAtMs: number(),
20854
+ bootAttempts: number(),
20855
+ schemaVersion: literal(1)
20856
+ });
20572
20857
  /**
20573
20858
  * Deterministic SHA-256 hash of an arbitrary serialisable value. The
20574
20859
  * canonical form sorts object keys alphabetically at every depth so two
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-hap",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "HomeKit (HAP) bridge exporter for CamStack devices. Publishes a bridged accessory per exposed device — MotionSensor in this MVP; Camera/Doorbell/Switch/Light follow.",
5
5
  "keywords": [
6
6
  "camstack",