@camstack/addon-export-alexa 1.0.4 → 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.
@@ -5009,6 +5009,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5009
5009
  */
5010
5010
  EventCategory["PipelineEngineMetricsSnapshot"] = "pipeline.engine-metrics-snapshot";
5011
5011
  /**
5012
+ * Per-node detection-engine runtime-provisioning transition. Emitted by
5013
+ * the detection-pipeline provider on every state change of its lazy
5014
+ * engine-provisioning machine (idle → installing → verifying → ready,
5015
+ * or → failed with a `nextRetryAt`). Payload is the
5016
+ * `EngineProvisioningState` snapshot; `event.source.nodeId` carries the
5017
+ * node. The Pipeline page subscribes to drive a live "installing
5018
+ * OpenVINO… / ready" indicator per node without polling
5019
+ * `pipelineExecutor.getEngineProvisioning`. Telemetry-grade (D8): the UI
5020
+ * also reads the cap snapshot on mount / reconnect. Phase 2.
5021
+ */
5022
+ EventCategory["PipelineEngineProvisioning"] = "pipeline.engine-provisioning";
5023
+ /**
5012
5024
  * Cluster topology snapshot. Carries the same payload returned by
5013
5025
  * `nodes.topology` (every reachable node + addons + processes).
5014
5026
  * Emitted by the hub on any agent / addon lifecycle change
@@ -9365,6 +9377,24 @@ var DetectorOutputSchema = object({
9365
9377
  inferenceMs: number(),
9366
9378
  modelId: string()
9367
9379
  });
9380
+ var EngineProvisioningSchema = object({
9381
+ runtimeId: _enum([
9382
+ "onnx",
9383
+ "openvino",
9384
+ "coreml"
9385
+ ]).nullable(),
9386
+ device: string().nullable(),
9387
+ state: _enum([
9388
+ "idle",
9389
+ "installing",
9390
+ "verifying",
9391
+ "ready",
9392
+ "failed"
9393
+ ]),
9394
+ progress: number().optional(),
9395
+ error: string().optional(),
9396
+ nextRetryAt: number().optional()
9397
+ });
9368
9398
  var PipelineStepInputSchema = lazy(() => object({
9369
9399
  addonId: string(),
9370
9400
  modelId: string(),
@@ -9433,7 +9463,7 @@ var PipelineRunResultBridge = custom();
9433
9463
  method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
9434
9464
  kind: "mutation",
9435
9465
  auth: "admin"
9436
- }), method(_void(), record(string(), object({
9466
+ }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
9437
9467
  modelId: string(),
9438
9468
  settings: record(string(), unknown()).readonly()
9439
9469
  }))), method(object({ steps: record(string(), object({
@@ -13089,7 +13119,10 @@ var AgentAddonConfigSchema = object({
13089
13119
  modelId: string(),
13090
13120
  settings: record(string(), unknown()).readonly()
13091
13121
  });
13092
- var AgentPipelineSettingsSchema = object({ addonDefaults: record(string(), AgentAddonConfigSchema).readonly() });
13122
+ var AgentPipelineSettingsSchema = object({
13123
+ addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
13124
+ maxCameras: number().int().nonnegative().nullable().default(null)
13125
+ });
13093
13126
  var CameraPipelineForAgentSchema = object({
13094
13127
  steps: array(PipelineStepInputSchema).readonly(),
13095
13128
  audio: object({
@@ -13191,6 +13224,133 @@ var GlobalMetricsSchema = object({
13191
13224
  * capability providers.
13192
13225
  */
13193
13226
  var CapabilityBindingsSchema = record(string(), string());
13227
+ /** Source block — always present; derives from the stream catalog. */
13228
+ var CameraSourceStatusSchema = object({ streams: array(object({
13229
+ camStreamId: string(),
13230
+ codec: string(),
13231
+ width: number(),
13232
+ height: number(),
13233
+ fps: number(),
13234
+ kind: string()
13235
+ })).readonly() });
13236
+ /** Assignment block — always present (orchestrator-local, no remote call). */
13237
+ var CameraAssignmentStatusSchema = object({
13238
+ detectionNodeId: string().nullable(),
13239
+ decoderNodeId: string().nullable(),
13240
+ audioNodeId: string().nullable(),
13241
+ pinned: object({
13242
+ detection: boolean(),
13243
+ decoder: boolean(),
13244
+ audio: boolean()
13245
+ }),
13246
+ reasons: object({
13247
+ detection: string().optional(),
13248
+ decoder: string().optional(),
13249
+ audio: string().optional()
13250
+ })
13251
+ });
13252
+ /** Broker block — null when the broker stage is unreachable or inactive. */
13253
+ var CameraBrokerStatusSchema = object({
13254
+ profiles: array(object({
13255
+ profile: string(),
13256
+ status: string(),
13257
+ codec: string(),
13258
+ width: number(),
13259
+ height: number(),
13260
+ subscribers: number(),
13261
+ inFps: number(),
13262
+ outFps: number()
13263
+ })).readonly(),
13264
+ webrtcSessions: number(),
13265
+ rtspRestream: boolean()
13266
+ });
13267
+ /** Shared-memory ring statistics within the decoder block. */
13268
+ var CameraDecoderShmSchema = object({
13269
+ framesWritten: number(),
13270
+ getFrameHits: number(),
13271
+ getFrameMisses: number(),
13272
+ budgetMb: number()
13273
+ });
13274
+ /** Decoder block — null when the decoder stage is unreachable or inactive. */
13275
+ var CameraDecoderStatusSchema = object({
13276
+ nodeId: string(),
13277
+ formats: array(string()).readonly(),
13278
+ sessionCount: number(),
13279
+ shm: CameraDecoderShmSchema
13280
+ });
13281
+ /** Motion block — null when motion detection is not active for this device. */
13282
+ var CameraMotionStatusSchema = object({
13283
+ enabled: boolean(),
13284
+ fps: number()
13285
+ });
13286
+ /** Detection provisioning sub-block. */
13287
+ var CameraDetectionProvisioningSchema = object({
13288
+ state: _enum([
13289
+ "idle",
13290
+ "installing",
13291
+ "verifying",
13292
+ "ready",
13293
+ "failed"
13294
+ ]),
13295
+ error: string().optional()
13296
+ });
13297
+ /** Detection phase — derived from the runner's engine phase. */
13298
+ var CameraDetectionPhaseSchema = _enum([
13299
+ "idle",
13300
+ "watching",
13301
+ "active"
13302
+ ]);
13303
+ /** Detection block — null when no detection node is assigned or reachable. */
13304
+ var CameraDetectionStatusSchema = object({
13305
+ nodeId: string(),
13306
+ engine: object({
13307
+ backend: string(),
13308
+ device: string()
13309
+ }),
13310
+ phase: CameraDetectionPhaseSchema,
13311
+ configuredFps: number(),
13312
+ actualFps: number(),
13313
+ queueDepth: number(),
13314
+ avgInferenceMs: number(),
13315
+ provisioning: CameraDetectionProvisioningSchema
13316
+ });
13317
+ /** Audio block — null when no audio node is assigned or reachable. */
13318
+ var CameraAudioStatusSchema = object({
13319
+ nodeId: string(),
13320
+ enabled: boolean()
13321
+ });
13322
+ /** Recording block — null when no recording cap is active for this device. */
13323
+ var CameraRecordingStatusSchema = object({
13324
+ mode: _enum([
13325
+ "off",
13326
+ "continuous",
13327
+ "events"
13328
+ ]),
13329
+ active: boolean(),
13330
+ storageBytes: number()
13331
+ });
13332
+ /**
13333
+ * Aggregated per-camera pipeline status — server-composed, single call.
13334
+ *
13335
+ * The `assignment` and `source` blocks are always present.
13336
+ * Every other block is `null` when the stage is inactive or unreachable
13337
+ * during the bounded parallel fan-out in the orchestrator implementation.
13338
+ *
13339
+ * See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
13340
+ */
13341
+ var CameraStatusSchema = object({
13342
+ deviceId: number(),
13343
+ assignment: CameraAssignmentStatusSchema,
13344
+ source: CameraSourceStatusSchema,
13345
+ broker: CameraBrokerStatusSchema.nullable(),
13346
+ decoder: CameraDecoderStatusSchema.nullable(),
13347
+ motion: CameraMotionStatusSchema.nullable(),
13348
+ detection: CameraDetectionStatusSchema.nullable(),
13349
+ audio: CameraAudioStatusSchema.nullable(),
13350
+ recording: CameraRecordingStatusSchema.nullable(),
13351
+ /** Unix timestamp (ms) when this snapshot was composed server-side. */
13352
+ fetchedAt: number()
13353
+ });
13194
13354
  method(object({
13195
13355
  deviceId: number(),
13196
13356
  agentNodeId: string()
@@ -13258,6 +13418,12 @@ method(object({
13258
13418
  }), {
13259
13419
  kind: "mutation",
13260
13420
  auth: "admin"
13421
+ }), method(object({
13422
+ agentNodeId: string(),
13423
+ maxCameras: number().int().nonnegative().nullable()
13424
+ }), object({ success: literal(true) }), {
13425
+ kind: "mutation",
13426
+ auth: "admin"
13261
13427
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
13262
13428
  deviceId: number(),
13263
13429
  addonId: string(),
@@ -13283,7 +13449,7 @@ method(object({
13283
13449
  }), method(object({
13284
13450
  deviceId: number(),
13285
13451
  agentNodeId: string().optional()
13286
- }), CameraPipelineConfigSchema), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13452
+ }), CameraPipelineConfigSchema), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13287
13453
  name: string(),
13288
13454
  description: string().optional(),
13289
13455
  config: CameraPipelineConfigSchema
@@ -19075,6 +19241,12 @@ Object.freeze({
19075
19241
  addonId: null,
19076
19242
  access: "view"
19077
19243
  },
19244
+ "pipelineExecutor.getEngineProvisioning": {
19245
+ capName: "pipeline-executor",
19246
+ capScope: "system",
19247
+ addonId: null,
19248
+ access: "view"
19249
+ },
19078
19250
  "pipelineExecutor.getGlobalPipelineConfig": {
19079
19251
  capName: "pipeline-executor",
19080
19252
  capScope: "system",
@@ -19279,6 +19451,18 @@ Object.freeze({
19279
19451
  addonId: null,
19280
19452
  access: "view"
19281
19453
  },
19454
+ "pipelineOrchestrator.getCameraStatus": {
19455
+ capName: "pipeline-orchestrator",
19456
+ capScope: "system",
19457
+ addonId: null,
19458
+ access: "view"
19459
+ },
19460
+ "pipelineOrchestrator.getCameraStatuses": {
19461
+ capName: "pipeline-orchestrator",
19462
+ capScope: "system",
19463
+ addonId: null,
19464
+ access: "view"
19465
+ },
19282
19466
  "pipelineOrchestrator.getCameraStepOverrides": {
19283
19467
  capName: "pipeline-orchestrator",
19284
19468
  capScope: "system",
@@ -19363,6 +19547,12 @@ Object.freeze({
19363
19547
  addonId: null,
19364
19548
  access: "create"
19365
19549
  },
19550
+ "pipelineOrchestrator.setAgentMaxCameras": {
19551
+ capName: "pipeline-orchestrator",
19552
+ capScope: "system",
19553
+ addonId: null,
19554
+ access: "create"
19555
+ },
19366
19556
  "pipelineOrchestrator.setCameraPipelineForAgent": {
19367
19557
  capName: "pipeline-orchestrator",
19368
19558
  capScope: "system",
@@ -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
@@ -9339,6 +9351,24 @@ var DetectorOutputSchema = object({
9339
9351
  inferenceMs: number(),
9340
9352
  modelId: string()
9341
9353
  });
9354
+ var EngineProvisioningSchema = object({
9355
+ runtimeId: _enum([
9356
+ "onnx",
9357
+ "openvino",
9358
+ "coreml"
9359
+ ]).nullable(),
9360
+ device: string().nullable(),
9361
+ state: _enum([
9362
+ "idle",
9363
+ "installing",
9364
+ "verifying",
9365
+ "ready",
9366
+ "failed"
9367
+ ]),
9368
+ progress: number().optional(),
9369
+ error: string().optional(),
9370
+ nextRetryAt: number().optional()
9371
+ });
9342
9372
  var PipelineStepInputSchema = lazy(() => object({
9343
9373
  addonId: string(),
9344
9374
  modelId: string(),
@@ -9407,7 +9437,7 @@ var PipelineRunResultBridge = custom();
9407
9437
  method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
9408
9438
  kind: "mutation",
9409
9439
  auth: "admin"
9410
- }), method(_void(), record(string(), object({
9440
+ }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
9411
9441
  modelId: string(),
9412
9442
  settings: record(string(), unknown()).readonly()
9413
9443
  }))), method(object({ steps: record(string(), object({
@@ -13063,7 +13093,10 @@ var AgentAddonConfigSchema = object({
13063
13093
  modelId: string(),
13064
13094
  settings: record(string(), unknown()).readonly()
13065
13095
  });
13066
- var AgentPipelineSettingsSchema = object({ addonDefaults: record(string(), AgentAddonConfigSchema).readonly() });
13096
+ var AgentPipelineSettingsSchema = object({
13097
+ addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
13098
+ maxCameras: number().int().nonnegative().nullable().default(null)
13099
+ });
13067
13100
  var CameraPipelineForAgentSchema = object({
13068
13101
  steps: array(PipelineStepInputSchema).readonly(),
13069
13102
  audio: object({
@@ -13165,6 +13198,133 @@ var GlobalMetricsSchema = object({
13165
13198
  * capability providers.
13166
13199
  */
13167
13200
  var CapabilityBindingsSchema = record(string(), string());
13201
+ /** Source block — always present; derives from the stream catalog. */
13202
+ var CameraSourceStatusSchema = object({ streams: array(object({
13203
+ camStreamId: string(),
13204
+ codec: string(),
13205
+ width: number(),
13206
+ height: number(),
13207
+ fps: number(),
13208
+ kind: string()
13209
+ })).readonly() });
13210
+ /** Assignment block — always present (orchestrator-local, no remote call). */
13211
+ var CameraAssignmentStatusSchema = object({
13212
+ detectionNodeId: string().nullable(),
13213
+ decoderNodeId: string().nullable(),
13214
+ audioNodeId: string().nullable(),
13215
+ pinned: object({
13216
+ detection: boolean(),
13217
+ decoder: boolean(),
13218
+ audio: boolean()
13219
+ }),
13220
+ reasons: object({
13221
+ detection: string().optional(),
13222
+ decoder: string().optional(),
13223
+ audio: string().optional()
13224
+ })
13225
+ });
13226
+ /** Broker block — null when the broker stage is unreachable or inactive. */
13227
+ var CameraBrokerStatusSchema = object({
13228
+ profiles: array(object({
13229
+ profile: string(),
13230
+ status: string(),
13231
+ codec: string(),
13232
+ width: number(),
13233
+ height: number(),
13234
+ subscribers: number(),
13235
+ inFps: number(),
13236
+ outFps: number()
13237
+ })).readonly(),
13238
+ webrtcSessions: number(),
13239
+ rtspRestream: boolean()
13240
+ });
13241
+ /** Shared-memory ring statistics within the decoder block. */
13242
+ var CameraDecoderShmSchema = object({
13243
+ framesWritten: number(),
13244
+ getFrameHits: number(),
13245
+ getFrameMisses: number(),
13246
+ budgetMb: number()
13247
+ });
13248
+ /** Decoder block — null when the decoder stage is unreachable or inactive. */
13249
+ var CameraDecoderStatusSchema = object({
13250
+ nodeId: string(),
13251
+ formats: array(string()).readonly(),
13252
+ sessionCount: number(),
13253
+ shm: CameraDecoderShmSchema
13254
+ });
13255
+ /** Motion block — null when motion detection is not active for this device. */
13256
+ var CameraMotionStatusSchema = object({
13257
+ enabled: boolean(),
13258
+ fps: number()
13259
+ });
13260
+ /** Detection provisioning sub-block. */
13261
+ var CameraDetectionProvisioningSchema = object({
13262
+ state: _enum([
13263
+ "idle",
13264
+ "installing",
13265
+ "verifying",
13266
+ "ready",
13267
+ "failed"
13268
+ ]),
13269
+ error: string().optional()
13270
+ });
13271
+ /** Detection phase — derived from the runner's engine phase. */
13272
+ var CameraDetectionPhaseSchema = _enum([
13273
+ "idle",
13274
+ "watching",
13275
+ "active"
13276
+ ]);
13277
+ /** Detection block — null when no detection node is assigned or reachable. */
13278
+ var CameraDetectionStatusSchema = object({
13279
+ nodeId: string(),
13280
+ engine: object({
13281
+ backend: string(),
13282
+ device: string()
13283
+ }),
13284
+ phase: CameraDetectionPhaseSchema,
13285
+ configuredFps: number(),
13286
+ actualFps: number(),
13287
+ queueDepth: number(),
13288
+ avgInferenceMs: number(),
13289
+ provisioning: CameraDetectionProvisioningSchema
13290
+ });
13291
+ /** Audio block — null when no audio node is assigned or reachable. */
13292
+ var CameraAudioStatusSchema = object({
13293
+ nodeId: string(),
13294
+ enabled: boolean()
13295
+ });
13296
+ /** Recording block — null when no recording cap is active for this device. */
13297
+ var CameraRecordingStatusSchema = object({
13298
+ mode: _enum([
13299
+ "off",
13300
+ "continuous",
13301
+ "events"
13302
+ ]),
13303
+ active: boolean(),
13304
+ storageBytes: number()
13305
+ });
13306
+ /**
13307
+ * Aggregated per-camera pipeline status — server-composed, single call.
13308
+ *
13309
+ * The `assignment` and `source` blocks are always present.
13310
+ * Every other block is `null` when the stage is inactive or unreachable
13311
+ * during the bounded parallel fan-out in the orchestrator implementation.
13312
+ *
13313
+ * See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
13314
+ */
13315
+ var CameraStatusSchema = object({
13316
+ deviceId: number(),
13317
+ assignment: CameraAssignmentStatusSchema,
13318
+ source: CameraSourceStatusSchema,
13319
+ broker: CameraBrokerStatusSchema.nullable(),
13320
+ decoder: CameraDecoderStatusSchema.nullable(),
13321
+ motion: CameraMotionStatusSchema.nullable(),
13322
+ detection: CameraDetectionStatusSchema.nullable(),
13323
+ audio: CameraAudioStatusSchema.nullable(),
13324
+ recording: CameraRecordingStatusSchema.nullable(),
13325
+ /** Unix timestamp (ms) when this snapshot was composed server-side. */
13326
+ fetchedAt: number()
13327
+ });
13168
13328
  method(object({
13169
13329
  deviceId: number(),
13170
13330
  agentNodeId: string()
@@ -13232,6 +13392,12 @@ method(object({
13232
13392
  }), {
13233
13393
  kind: "mutation",
13234
13394
  auth: "admin"
13395
+ }), method(object({
13396
+ agentNodeId: string(),
13397
+ maxCameras: number().int().nonnegative().nullable()
13398
+ }), object({ success: literal(true) }), {
13399
+ kind: "mutation",
13400
+ auth: "admin"
13235
13401
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
13236
13402
  deviceId: number(),
13237
13403
  addonId: string(),
@@ -13257,7 +13423,7 @@ method(object({
13257
13423
  }), method(object({
13258
13424
  deviceId: number(),
13259
13425
  agentNodeId: string().optional()
13260
- }), CameraPipelineConfigSchema), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13426
+ }), CameraPipelineConfigSchema), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13261
13427
  name: string(),
13262
13428
  description: string().optional(),
13263
13429
  config: CameraPipelineConfigSchema
@@ -19049,6 +19215,12 @@ Object.freeze({
19049
19215
  addonId: null,
19050
19216
  access: "view"
19051
19217
  },
19218
+ "pipelineExecutor.getEngineProvisioning": {
19219
+ capName: "pipeline-executor",
19220
+ capScope: "system",
19221
+ addonId: null,
19222
+ access: "view"
19223
+ },
19052
19224
  "pipelineExecutor.getGlobalPipelineConfig": {
19053
19225
  capName: "pipeline-executor",
19054
19226
  capScope: "system",
@@ -19253,6 +19425,18 @@ Object.freeze({
19253
19425
  addonId: null,
19254
19426
  access: "view"
19255
19427
  },
19428
+ "pipelineOrchestrator.getCameraStatus": {
19429
+ capName: "pipeline-orchestrator",
19430
+ capScope: "system",
19431
+ addonId: null,
19432
+ access: "view"
19433
+ },
19434
+ "pipelineOrchestrator.getCameraStatuses": {
19435
+ capName: "pipeline-orchestrator",
19436
+ capScope: "system",
19437
+ addonId: null,
19438
+ access: "view"
19439
+ },
19256
19440
  "pipelineOrchestrator.getCameraStepOverrides": {
19257
19441
  capName: "pipeline-orchestrator",
19258
19442
  capScope: "system",
@@ -19337,6 +19521,12 @@ Object.freeze({
19337
19521
  addonId: null,
19338
19522
  access: "create"
19339
19523
  },
19524
+ "pipelineOrchestrator.setAgentMaxCameras": {
19525
+ capName: "pipeline-orchestrator",
19526
+ capScope: "system",
19527
+ addonId: null,
19528
+ access: "create"
19529
+ },
19340
19530
  "pipelineOrchestrator.setCameraPipelineForAgent": {
19341
19531
  capName: "pipeline-orchestrator",
19342
19532
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-alexa",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Alexa Smart Home Skill export — hub-side OAuth provider + directive handler. The companion AWS Lambda forwards Alexa directives to this addon's /addon/export-alexa/directive endpoint.",
5
5
  "keywords": [
6
6
  "camstack",