@camstack/addon-export-alexa 1.1.27 → 1.2.0

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.
@@ -7118,6 +7118,17 @@ var ModelCatalogEntrySchema = object({
7118
7118
  "imagenet",
7119
7119
  "none"
7120
7120
  ]).optional(),
7121
+ /**
7122
+ * The model already applies softmax IN-GRAPH — its raw output is a
7123
+ * probability distribution, not logits. When set, the `softmax`
7124
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7125
+ * probability vector collapses it toward uniform (top-1 score craters far
7126
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7127
+ * the output is raw logits and the postprocessor applies softmax (the normal
7128
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7129
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7130
+ */
7131
+ outputProbabilities: boolean().optional(),
7121
7132
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7122
7133
  /**
7123
7134
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -11302,10 +11313,7 @@ var ConfigUISchemaNullableBridge = custom();
11302
11313
  var InferenceCapabilitiesBridge = custom();
11303
11314
  var ModelAvailabilityListBridge = custom();
11304
11315
  var PipelineRunResultBridge = custom();
11305
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
11306
- kind: "mutation",
11307
- auth: "admin"
11308
- }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
11316
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
11309
11317
  modelId: string(),
11310
11318
  settings: record(string(), unknown()).readonly()
11311
11319
  }))), method(object({ steps: record(string(), object({
@@ -11365,13 +11373,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
11365
11373
  * (inputClasses ≠ null) are skipped and served per-track via
11366
11374
  * pipelineRunner.runDetailSubtree (two-plane design).
11367
11375
  */
11368
- plane: _enum(["full", "frame"]).optional()
11376
+ plane: _enum(["full", "frame"]).optional(),
11377
+ /**
11378
+ * Inference-device selector (Phase 2 multi-device). Format
11379
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
11380
+ * Omitted ⇒ the runner's default device (current single-engine
11381
+ * behaviour). Selects WHICH device pool of the node runs the call.
11382
+ */
11383
+ deviceKey: string().optional()
11369
11384
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
11370
11385
  engine: PipelineEngineChoiceSchema.optional(),
11371
11386
  steps: array(PipelineStepInputSchema).min(1),
11372
11387
  frames: array(FrameInputSchema).min(1).max(255),
11373
11388
  deviceId: number().optional(),
11374
- sessionId: string().optional()
11389
+ sessionId: string().optional(),
11390
+ /**
11391
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
11392
+ * the batch to the Python pool's bench preprocess cache
11393
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
11394
+ * preprocessed ONCE and every later inference is a pure-inference cache
11395
+ * hit — the sustained-throughput run measures inference, not
11396
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
11397
+ * full preprocess every call, correct). Fresh per sustained run;
11398
+ * released via `uncacheFrame`.
11399
+ */
11400
+ frameId: number().int().nonnegative().optional(),
11401
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
11402
+ deviceKey: string().optional()
11375
11403
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
11376
11404
  data: _instanceof(Uint8Array),
11377
11405
  width: number().int().positive(),
@@ -11403,8 +11431,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
11403
11431
  * - `runtime` — main camera-serving engine (no idle TTL).
11404
11432
  * - `warm-override` — benchmark/test override held in the warm
11405
11433
  * cache; auto-disposed after the idle TTL.
11434
+ * - `device-pool` — a concurrent per-device pool (Phase 2
11435
+ * multi-device, keyed by `deviceKey`) resolved
11436
+ * via `resolveDeviceFactory`. Runs alongside the
11437
+ * `runtime` engine on a DIFFERENT accelerator
11438
+ * (NPU / iGPU / Coral) — this is how the
11439
+ * Engines tab shows all pools running at once.
11406
11440
  */
11407
- kind: _enum(["runtime", "warm-override"]),
11441
+ kind: _enum([
11442
+ "runtime",
11443
+ "warm-override",
11444
+ "device-pool"
11445
+ ]),
11408
11446
  /** Native pid of the underlying Python pool (null when no pool). */
11409
11447
  poolPid: number().nullable(),
11410
11448
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -11746,7 +11784,14 @@ var RunnerCameraConfigSchema = object({
11746
11784
  * camera's detect node differs from its source-owner (P2d, gated by the
11747
11785
  * `remoteSourcingNodes` rollout setting).
11748
11786
  */
11749
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
11787
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
11788
+ /**
11789
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
11790
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
11791
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
11792
+ * this only selects WHICH device pool of that node runs the session.
11793
+ */
11794
+ deviceKey: string().optional()
11750
11795
  });
11751
11796
  motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
11752
11797
  /**
@@ -11767,6 +11812,19 @@ var RunnerLocalLoadSchema = object({
11767
11812
  avgInferenceTimeMs: number(),
11768
11813
  /** Total queue depth across motion + detection queues. */
11769
11814
  queueDepthTotal: number(),
11815
+ /**
11816
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
11817
+ * this runner currently has attached cameras on, so the orchestrator's second
11818
+ * `balance()` pass (over a node's devices) weights on real per-pool session
11819
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
11820
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
11821
+ */
11822
+ devices: array(object({
11823
+ deviceKey: string(),
11824
+ backend: string(),
11825
+ attachedCameras: number(),
11826
+ queueDepthTotal: number()
11827
+ })).default([]),
11770
11828
  /** Hardware capability flags reported by this node. */
11771
11829
  hardware: object({
11772
11830
  hasGpu: boolean(),
@@ -13242,6 +13300,8 @@ method(_void(), _void(), { kind: "mutation" }), method(_void(), _void(), { kind:
13242
13300
  kind: "mutation",
13243
13301
  auth: "admin"
13244
13302
  });
13303
+ DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder;
13304
+ new Set(Object.values(DeviceType));
13245
13305
  /**
13246
13306
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
13247
13307
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -16982,13 +17042,11 @@ var PipelineTemplateSchema = object({
16982
17042
  createdAt: string(),
16983
17043
  updatedAt: string()
16984
17044
  });
16985
- var AgentAddonConfigSchema = object({
16986
- enabled: boolean(),
17045
+ var DeviceStepConfigSchema = object({
16987
17046
  modelId: string().optional(),
16988
- settings: record(string(), unknown()).readonly()
17047
+ settings: record(string(), unknown()).optional()
16989
17048
  });
16990
17049
  var AgentPipelineSettingsSchema = object({
16991
- addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
16992
17050
  maxCameras: number().int().nonnegative().nullable().default(null),
16993
17051
  /** Per-node detection weight (relative share for the quota balancer). */
16994
17052
  detectWeight: number().positive().optional(),
@@ -17012,7 +17070,22 @@ var AgentPipelineSettingsSchema = object({
17012
17070
  * it already uses to reach the hub). Set this only when the auto-detected
17013
17071
  * address is wrong (multi-homed host, NAT, custom interface).
17014
17072
  */
17015
- reachableHost: string().optional()
17073
+ reachableHost: string().optional(),
17074
+ /**
17075
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
17076
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
17077
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
17078
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
17079
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
17080
+ * the default model/settings for every camera landing on that accelerator;
17081
+ * a stepId absent ⇒ the step uses that device's format default.
17082
+ */
17083
+ inferenceDevices: record(string(), object({
17084
+ enabled: boolean(),
17085
+ weight: number().positive().optional(),
17086
+ maxSessions: number().int().positive().optional(),
17087
+ steps: record(string(), DeviceStepConfigSchema).optional()
17088
+ })).optional()
17016
17089
  });
17017
17090
  var CameraPipelineForAgentSchema = object({
17018
17091
  steps: array(PipelineStepInputSchema).readonly(),
@@ -17022,14 +17095,13 @@ var CameraPipelineForAgentSchema = object({
17022
17095
  }).nullable()
17023
17096
  });
17024
17097
  var CameraStepOverridePatchSchema = object({
17025
- enabled: boolean().optional(),
17026
17098
  modelId: string().optional(),
17027
17099
  settings: record(string(), unknown()).readonly().optional()
17028
17100
  });
17029
17101
  var CameraPipelineSettingsSchema = object({
17030
17102
  pinnedAgentNodeId: string().optional(),
17031
17103
  stepToggles: record(string(), boolean()).optional(),
17032
- stepOverridesByAgent: record(string(), record(string(), CameraStepOverridePatchSchema)).optional(),
17104
+ stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
17033
17105
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
17034
17106
  });
17035
17107
  /**
@@ -17243,6 +17315,44 @@ var CameraStatusSchema = object({
17243
17315
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
17244
17316
  fetchedAt: number()
17245
17317
  });
17318
+ var NodeInferenceDeviceSchema = object({
17319
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
17320
+ key: string(),
17321
+ backend: string(),
17322
+ device: string(),
17323
+ format: _enum(MODEL_FORMATS),
17324
+ /** Whether the node's live probe reports the device as usable right now. */
17325
+ available: boolean(),
17326
+ /**
17327
+ * Whether this device participates in dispatch. AUTO default (spec C2):
17328
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
17329
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
17330
+ * not a balanced target). An explicit stored value always wins; a stored-only
17331
+ * (unavailable) key keeps its stored value.
17332
+ */
17333
+ enabled: boolean(),
17334
+ /** Relative balancer weight for the enabled device (default 1). */
17335
+ weight: number(),
17336
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
17337
+ maxSessions: number().nullable(),
17338
+ /** Object-detection model the executor defaults to for this deviceKey. */
17339
+ defaultModelId: string(),
17340
+ /**
17341
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
17342
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
17343
+ * Absent/empty ⇒ no base (every step uses its device format default). The
17344
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
17345
+ * available per format; this is the stored selection that becomes the
17346
+ * default for EVERY camera landing on this accelerator.
17347
+ */
17348
+ steps: record(string(), DeviceStepConfigSchema).optional()
17349
+ });
17350
+ var NodeInferenceDevicesSchema = object({
17351
+ nodeId: string(),
17352
+ /** False when the node's platform-probe was unreachable (no live device set). */
17353
+ reachable: boolean(),
17354
+ devices: array(NodeInferenceDeviceSchema).readonly()
17355
+ });
17246
17356
  method(object({
17247
17357
  deviceId: number(),
17248
17358
  agentNodeId: string()
@@ -17252,7 +17362,13 @@ method(object({
17252
17362
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
17253
17363
  kind: "mutation",
17254
17364
  auth: "admin"
17255
- }), method(_void(), object({ migrated: number() }), {
17365
+ }), method(object({
17366
+ deviceId: number(),
17367
+ deviceKey: string()
17368
+ }), object({ success: literal(true) }), {
17369
+ kind: "mutation",
17370
+ auth: "admin"
17371
+ }), method(object({ deviceId: number() }), object({ deviceKey: string().nullable() })), method(_void(), object({ migrated: number() }), {
17256
17372
  kind: "mutation",
17257
17373
  auth: "admin"
17258
17374
  }), method(_void(), array(PipelineAssignmentSchema).readonly()), method(object({ deviceId: number() }), PipelineAssignmentSchema.nullable()), method(_void(), array(AgentLoadSummarySchema).readonly()), method(_void(), GlobalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(object({ nodeId: string() }), CapabilityBindingsSchema), method(object({
@@ -17286,13 +17402,7 @@ method(object({
17286
17402
  }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
17287
17403
  nodeId: string(),
17288
17404
  settings: AgentPipelineSettingsSchema
17289
- })).readonly()), method(object({
17290
- agentNodeId: string(),
17291
- defaults: record(string(), AgentAddonConfigSchema)
17292
- }), object({ success: literal(true) }), {
17293
- kind: "mutation",
17294
- auth: "admin"
17295
- }), method(object({ agentNodeId: string() }), object({
17405
+ })).readonly()), method(object({ agentNodeId: string() }), object({
17296
17406
  success: boolean(),
17297
17407
  removed: boolean()
17298
17408
  }), {
@@ -17324,7 +17434,18 @@ method(object({
17324
17434
  }), object({ success: literal(true) }), {
17325
17435
  kind: "mutation",
17326
17436
  auth: "admin"
17327
- }), method(object({ agentNodeId: string() }), object({
17437
+ }), method(object({
17438
+ agentNodeId: string(),
17439
+ inferenceDevices: record(string(), object({
17440
+ enabled: boolean(),
17441
+ weight: number().positive().optional(),
17442
+ maxSessions: number().int().positive().optional(),
17443
+ steps: record(string(), DeviceStepConfigSchema).optional()
17444
+ }))
17445
+ }), object({ success: literal(true) }), {
17446
+ kind: "mutation",
17447
+ auth: "admin"
17448
+ }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string() }), object({
17328
17449
  success: literal(true),
17329
17450
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
17330
17451
  effectiveModelId: string().nullable(),
@@ -17340,9 +17461,10 @@ method(object({
17340
17461
  }), object({ success: literal(true) }), {
17341
17462
  kind: "mutation",
17342
17463
  auth: "admin"
17343
- }), method(object({ deviceId: number() }), record(string(), record(string(), CameraStepOverridePatchSchema)).nullable()), method(object({
17464
+ }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
17344
17465
  deviceId: number(),
17345
17466
  agentNodeId: string(),
17467
+ deviceKey: string(),
17346
17468
  addonId: string(),
17347
17469
  patch: CameraStepOverridePatchSchema.nullable()
17348
17470
  }), object({ success: literal(true) }), {
@@ -17379,14 +17501,13 @@ method(object({
17379
17501
  });
17380
17502
  /**
17381
17503
  * server-management — per-NODE singleton capability for a node's ROOT
17382
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
17383
- * agents).
17504
+ * package lifecycle (runtime-updatable node packages).
17384
17505
  *
17385
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
17386
- * on agents) carries the whole software stack in its npm dep tree, so ONE
17387
- * version describes the node. Updates install into
17388
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
17389
- * starter (probation boot + auto-rollback to N-1).
17506
+ * Every node role runs the SAME root package (`@camstack/server`), which
17507
+ * carries the whole software stack in its npm dep tree, so ONE version
17508
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
17509
+ * on restart via the baked starter (single-copy in-place swap — no probation,
17510
+ * no auto-rollback).
17390
17511
  *
17391
17512
  * Providers:
17392
17513
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -17494,7 +17615,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
17494
17615
  /** Explicit target version; omitted = latest from the registry. */
17495
17616
  version: string().optional() }), ServerUpdateActionResultSchema, {
17496
17617
  kind: "mutation",
17497
- auth: "admin"
17618
+ auth: "admin",
17619
+ timeoutMs: 16 * 6e4
17498
17620
  }), method(_void(), ServerUpdateActionResultSchema, {
17499
17621
  kind: "mutation",
17500
17622
  auth: "admin"
@@ -18538,22 +18660,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
18538
18660
  var RestartAddonResultSchema = unknown();
18539
18661
  var InstallPackageResultSchema = unknown();
18540
18662
  var ReloadPackagesResultSchema = unknown();
18541
- /**
18542
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
18543
- * server restarts so the admin UI can react to the `restartingAt`
18544
- * timestamp (shows reconnect overlay). The transition from
18545
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
18546
- * `system.restart-completed` event after the new process boots.
18547
- *
18548
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
18549
- */
18550
- var UpdateFrameworkPackageResultSchema = object({
18551
- packageName: string(),
18552
- fromVersion: string(),
18553
- toVersion: string(),
18554
- /** Ms-epoch the server scheduled its self-restart. */
18555
- restartingAt: number()
18556
- });
18557
18663
  var BulkUpdateItemStatusSchema = _enum([
18558
18664
  "queued",
18559
18665
  "updating",
@@ -18681,13 +18787,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
18681
18787
  }), object({ success: literal(true) }), {
18682
18788
  kind: "mutation",
18683
18789
  auth: "admin"
18684
- }), method(object({
18685
- packageName: string().min(1),
18686
- version: string().optional(),
18687
- deferRestart: boolean().optional()
18688
- }), UpdateFrameworkPackageResultSchema, {
18689
- kind: "mutation",
18690
- auth: "admin"
18691
18790
  }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
18692
18791
  kind: "mutation",
18693
18792
  auth: "admin"
@@ -19553,10 +19652,10 @@ var TopologyCategorySchema = object({
19553
19652
  addons: array(TopologyCategoryAddonSchema).readonly()
19554
19653
  });
19555
19654
  /**
19556
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
19557
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
19558
- * version visibility for the Server management surface. Nullable: offline
19559
- * rows and pre-phase-2 nodes report none.
19655
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
19656
+ * root package for every node role) as reported by its `registerNode`
19657
+ * manifest — version visibility for the Server management surface. Nullable:
19658
+ * offline rows and nodes that never reported one.
19560
19659
  */
19561
19660
  var TopologyRootPackageSchema = object({
19562
19661
  name: string(),
@@ -19944,17 +20043,28 @@ var PlatformScoreSchema = object({
19944
20043
  format: _enum([
19945
20044
  "onnx",
19946
20045
  "coreml",
19947
- "openvino"
20046
+ "openvino",
20047
+ "tflite"
19948
20048
  ]),
19949
20049
  score: number(),
19950
20050
  reason: string(),
19951
20051
  available: boolean()
19952
20052
  });
20053
+ var InferenceDeviceDescriptorSchema = object({
20054
+ key: string(),
20055
+ backend: string(),
20056
+ device: string(),
20057
+ format: ModelFormatSchema,
20058
+ runtime: literal("python"),
20059
+ score: number(),
20060
+ available: boolean()
20061
+ });
19953
20062
  var PlatformCapabilitiesSchema = object({
19954
20063
  hardware: HardwareInfoSchema,
19955
20064
  scores: array(PlatformScoreSchema).readonly(),
19956
20065
  bestScore: PlatformScoreSchema,
19957
- pythonPath: string().nullable()
20066
+ pythonPath: string().nullable(),
20067
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
19958
20068
  });
19959
20069
  var ModelRequirementSchema = object({
19960
20070
  modelId: string(),
@@ -20833,12 +20943,6 @@ Object.freeze({
20833
20943
  addonId: null,
20834
20944
  access: "delete"
20835
20945
  },
20836
- "addons.updateFrameworkPackage": {
20837
- capName: "addons",
20838
- capScope: "system",
20839
- addonId: null,
20840
- access: "create"
20841
- },
20842
20946
  "addons.updatePackage": {
20843
20947
  capName: "addons",
20844
20948
  capScope: "system",
@@ -23611,12 +23715,6 @@ Object.freeze({
23611
23715
  addonId: null,
23612
23716
  access: "view"
23613
23717
  },
23614
- "pipelineExecutor.reprobeEngine": {
23615
- capName: "pipeline-executor",
23616
- capScope: "system",
23617
- addonId: null,
23618
- access: "create"
23619
- },
23620
23718
  "pipelineExecutor.runAudioTest": {
23621
23719
  capName: "pipeline-executor",
23622
23720
  capScope: "system",
@@ -23767,6 +23865,12 @@ Object.freeze({
23767
23865
  addonId: null,
23768
23866
  access: "view"
23769
23867
  },
23868
+ "pipelineOrchestrator.getNodeInferenceDevices": {
23869
+ capName: "pipeline-orchestrator",
23870
+ capScope: "system",
23871
+ addonId: null,
23872
+ access: "view"
23873
+ },
23770
23874
  "pipelineOrchestrator.getPipelineAssignment": {
23771
23875
  capName: "pipeline-orchestrator",
23772
23876
  capScope: "system",
@@ -23779,6 +23883,12 @@ Object.freeze({
23779
23883
  addonId: null,
23780
23884
  access: "view"
23781
23885
  },
23886
+ "pipelineOrchestrator.getPipelineDevicePin": {
23887
+ capName: "pipeline-orchestrator",
23888
+ capScope: "system",
23889
+ addonId: null,
23890
+ access: "view"
23891
+ },
23782
23892
  "pipelineOrchestrator.listAgentSettings": {
23783
23893
  capName: "pipeline-orchestrator",
23784
23894
  capScope: "system",
@@ -23821,19 +23931,19 @@ Object.freeze({
23821
23931
  addonId: null,
23822
23932
  access: "create"
23823
23933
  },
23824
- "pipelineOrchestrator.setAgentAddonDefaults": {
23934
+ "pipelineOrchestrator.setAgentCapabilities": {
23825
23935
  capName: "pipeline-orchestrator",
23826
23936
  capScope: "system",
23827
23937
  addonId: null,
23828
23938
  access: "create"
23829
23939
  },
23830
- "pipelineOrchestrator.setAgentCapabilities": {
23940
+ "pipelineOrchestrator.setAgentDetectWeight": {
23831
23941
  capName: "pipeline-orchestrator",
23832
23942
  capScope: "system",
23833
23943
  addonId: null,
23834
23944
  access: "create"
23835
23945
  },
23836
- "pipelineOrchestrator.setAgentDetectWeight": {
23946
+ "pipelineOrchestrator.setAgentInferenceDevices": {
23837
23947
  capName: "pipeline-orchestrator",
23838
23948
  capScope: "system",
23839
23949
  addonId: null,
@@ -23875,6 +23985,12 @@ Object.freeze({
23875
23985
  addonId: null,
23876
23986
  access: "create"
23877
23987
  },
23988
+ "pipelineOrchestrator.setPipelineDevicePin": {
23989
+ capName: "pipeline-orchestrator",
23990
+ capScope: "system",
23991
+ addonId: null,
23992
+ access: "create"
23993
+ },
23878
23994
  "pipelineOrchestrator.unassignAudio": {
23879
23995
  capName: "pipeline-orchestrator",
23880
23996
  capScope: "system",
@@ -25427,32 +25543,6 @@ Object.freeze({
25427
25543
  "network-access": "ingress",
25428
25544
  "smtp-provider": "email"
25429
25545
  });
25430
- var frameworkSwapPackageSchema = object({
25431
- name: string(),
25432
- stagedPath: string(),
25433
- backupPath: string(),
25434
- toVersion: string(),
25435
- fromVersion: string().nullable()
25436
- });
25437
- object({
25438
- jobId: string(),
25439
- taskId: string(),
25440
- packages: array(frameworkSwapPackageSchema),
25441
- requestedAtMs: number(),
25442
- schemaVersion: literal(1)
25443
- });
25444
- object({
25445
- jobId: string(),
25446
- taskId: string(),
25447
- backups: array(object({
25448
- name: string(),
25449
- backupPath: string(),
25450
- livePath: string()
25451
- })),
25452
- appliedAtMs: number(),
25453
- bootAttempts: number(),
25454
- schemaVersion: literal(1)
25455
- });
25456
25546
  //#endregion
25457
25547
  //#region src/custom-actions.ts
25458
25548
  /**
@@ -7092,6 +7092,17 @@ var ModelCatalogEntrySchema = object({
7092
7092
  "imagenet",
7093
7093
  "none"
7094
7094
  ]).optional(),
7095
+ /**
7096
+ * The model already applies softmax IN-GRAPH — its raw output is a
7097
+ * probability distribution, not logits. When set, the `softmax`
7098
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7099
+ * probability vector collapses it toward uniform (top-1 score craters far
7100
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7101
+ * the output is raw logits and the postprocessor applies softmax (the normal
7102
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7103
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7104
+ */
7105
+ outputProbabilities: boolean().optional(),
7095
7106
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7096
7107
  /**
7097
7108
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -11276,10 +11287,7 @@ var ConfigUISchemaNullableBridge = custom();
11276
11287
  var InferenceCapabilitiesBridge = custom();
11277
11288
  var ModelAvailabilityListBridge = custom();
11278
11289
  var PipelineRunResultBridge = custom();
11279
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
11280
- kind: "mutation",
11281
- auth: "admin"
11282
- }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
11290
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
11283
11291
  modelId: string(),
11284
11292
  settings: record(string(), unknown()).readonly()
11285
11293
  }))), method(object({ steps: record(string(), object({
@@ -11339,13 +11347,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
11339
11347
  * (inputClasses ≠ null) are skipped and served per-track via
11340
11348
  * pipelineRunner.runDetailSubtree (two-plane design).
11341
11349
  */
11342
- plane: _enum(["full", "frame"]).optional()
11350
+ plane: _enum(["full", "frame"]).optional(),
11351
+ /**
11352
+ * Inference-device selector (Phase 2 multi-device). Format
11353
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
11354
+ * Omitted ⇒ the runner's default device (current single-engine
11355
+ * behaviour). Selects WHICH device pool of the node runs the call.
11356
+ */
11357
+ deviceKey: string().optional()
11343
11358
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
11344
11359
  engine: PipelineEngineChoiceSchema.optional(),
11345
11360
  steps: array(PipelineStepInputSchema).min(1),
11346
11361
  frames: array(FrameInputSchema).min(1).max(255),
11347
11362
  deviceId: number().optional(),
11348
- sessionId: string().optional()
11363
+ sessionId: string().optional(),
11364
+ /**
11365
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
11366
+ * the batch to the Python pool's bench preprocess cache
11367
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
11368
+ * preprocessed ONCE and every later inference is a pure-inference cache
11369
+ * hit — the sustained-throughput run measures inference, not
11370
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
11371
+ * full preprocess every call, correct). Fresh per sustained run;
11372
+ * released via `uncacheFrame`.
11373
+ */
11374
+ frameId: number().int().nonnegative().optional(),
11375
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
11376
+ deviceKey: string().optional()
11349
11377
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
11350
11378
  data: _instanceof(Uint8Array),
11351
11379
  width: number().int().positive(),
@@ -11377,8 +11405,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
11377
11405
  * - `runtime` — main camera-serving engine (no idle TTL).
11378
11406
  * - `warm-override` — benchmark/test override held in the warm
11379
11407
  * cache; auto-disposed after the idle TTL.
11408
+ * - `device-pool` — a concurrent per-device pool (Phase 2
11409
+ * multi-device, keyed by `deviceKey`) resolved
11410
+ * via `resolveDeviceFactory`. Runs alongside the
11411
+ * `runtime` engine on a DIFFERENT accelerator
11412
+ * (NPU / iGPU / Coral) — this is how the
11413
+ * Engines tab shows all pools running at once.
11380
11414
  */
11381
- kind: _enum(["runtime", "warm-override"]),
11415
+ kind: _enum([
11416
+ "runtime",
11417
+ "warm-override",
11418
+ "device-pool"
11419
+ ]),
11382
11420
  /** Native pid of the underlying Python pool (null when no pool). */
11383
11421
  poolPid: number().nullable(),
11384
11422
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -11720,7 +11758,14 @@ var RunnerCameraConfigSchema = object({
11720
11758
  * camera's detect node differs from its source-owner (P2d, gated by the
11721
11759
  * `remoteSourcingNodes` rollout setting).
11722
11760
  */
11723
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
11761
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
11762
+ /**
11763
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
11764
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
11765
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
11766
+ * this only selects WHICH device pool of that node runs the session.
11767
+ */
11768
+ deviceKey: string().optional()
11724
11769
  });
11725
11770
  motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
11726
11771
  /**
@@ -11741,6 +11786,19 @@ var RunnerLocalLoadSchema = object({
11741
11786
  avgInferenceTimeMs: number(),
11742
11787
  /** Total queue depth across motion + detection queues. */
11743
11788
  queueDepthTotal: number(),
11789
+ /**
11790
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
11791
+ * this runner currently has attached cameras on, so the orchestrator's second
11792
+ * `balance()` pass (over a node's devices) weights on real per-pool session
11793
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
11794
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
11795
+ */
11796
+ devices: array(object({
11797
+ deviceKey: string(),
11798
+ backend: string(),
11799
+ attachedCameras: number(),
11800
+ queueDepthTotal: number()
11801
+ })).default([]),
11744
11802
  /** Hardware capability flags reported by this node. */
11745
11803
  hardware: object({
11746
11804
  hasGpu: boolean(),
@@ -13216,6 +13274,8 @@ method(_void(), _void(), { kind: "mutation" }), method(_void(), _void(), { kind:
13216
13274
  kind: "mutation",
13217
13275
  auth: "admin"
13218
13276
  });
13277
+ DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder;
13278
+ new Set(Object.values(DeviceType));
13219
13279
  /**
13220
13280
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
13221
13281
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -16956,13 +17016,11 @@ var PipelineTemplateSchema = object({
16956
17016
  createdAt: string(),
16957
17017
  updatedAt: string()
16958
17018
  });
16959
- var AgentAddonConfigSchema = object({
16960
- enabled: boolean(),
17019
+ var DeviceStepConfigSchema = object({
16961
17020
  modelId: string().optional(),
16962
- settings: record(string(), unknown()).readonly()
17021
+ settings: record(string(), unknown()).optional()
16963
17022
  });
16964
17023
  var AgentPipelineSettingsSchema = object({
16965
- addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
16966
17024
  maxCameras: number().int().nonnegative().nullable().default(null),
16967
17025
  /** Per-node detection weight (relative share for the quota balancer). */
16968
17026
  detectWeight: number().positive().optional(),
@@ -16986,7 +17044,22 @@ var AgentPipelineSettingsSchema = object({
16986
17044
  * it already uses to reach the hub). Set this only when the auto-detected
16987
17045
  * address is wrong (multi-homed host, NAT, custom interface).
16988
17046
  */
16989
- reachableHost: string().optional()
17047
+ reachableHost: string().optional(),
17048
+ /**
17049
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
17050
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
17051
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
17052
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
17053
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
17054
+ * the default model/settings for every camera landing on that accelerator;
17055
+ * a stepId absent ⇒ the step uses that device's format default.
17056
+ */
17057
+ inferenceDevices: record(string(), object({
17058
+ enabled: boolean(),
17059
+ weight: number().positive().optional(),
17060
+ maxSessions: number().int().positive().optional(),
17061
+ steps: record(string(), DeviceStepConfigSchema).optional()
17062
+ })).optional()
16990
17063
  });
16991
17064
  var CameraPipelineForAgentSchema = object({
16992
17065
  steps: array(PipelineStepInputSchema).readonly(),
@@ -16996,14 +17069,13 @@ var CameraPipelineForAgentSchema = object({
16996
17069
  }).nullable()
16997
17070
  });
16998
17071
  var CameraStepOverridePatchSchema = object({
16999
- enabled: boolean().optional(),
17000
17072
  modelId: string().optional(),
17001
17073
  settings: record(string(), unknown()).readonly().optional()
17002
17074
  });
17003
17075
  var CameraPipelineSettingsSchema = object({
17004
17076
  pinnedAgentNodeId: string().optional(),
17005
17077
  stepToggles: record(string(), boolean()).optional(),
17006
- stepOverridesByAgent: record(string(), record(string(), CameraStepOverridePatchSchema)).optional(),
17078
+ stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
17007
17079
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
17008
17080
  });
17009
17081
  /**
@@ -17217,6 +17289,44 @@ var CameraStatusSchema = object({
17217
17289
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
17218
17290
  fetchedAt: number()
17219
17291
  });
17292
+ var NodeInferenceDeviceSchema = object({
17293
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
17294
+ key: string(),
17295
+ backend: string(),
17296
+ device: string(),
17297
+ format: _enum(MODEL_FORMATS),
17298
+ /** Whether the node's live probe reports the device as usable right now. */
17299
+ available: boolean(),
17300
+ /**
17301
+ * Whether this device participates in dispatch. AUTO default (spec C2):
17302
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
17303
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
17304
+ * not a balanced target). An explicit stored value always wins; a stored-only
17305
+ * (unavailable) key keeps its stored value.
17306
+ */
17307
+ enabled: boolean(),
17308
+ /** Relative balancer weight for the enabled device (default 1). */
17309
+ weight: number(),
17310
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
17311
+ maxSessions: number().nullable(),
17312
+ /** Object-detection model the executor defaults to for this deviceKey. */
17313
+ defaultModelId: string(),
17314
+ /**
17315
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
17316
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
17317
+ * Absent/empty ⇒ no base (every step uses its device format default). The
17318
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
17319
+ * available per format; this is the stored selection that becomes the
17320
+ * default for EVERY camera landing on this accelerator.
17321
+ */
17322
+ steps: record(string(), DeviceStepConfigSchema).optional()
17323
+ });
17324
+ var NodeInferenceDevicesSchema = object({
17325
+ nodeId: string(),
17326
+ /** False when the node's platform-probe was unreachable (no live device set). */
17327
+ reachable: boolean(),
17328
+ devices: array(NodeInferenceDeviceSchema).readonly()
17329
+ });
17220
17330
  method(object({
17221
17331
  deviceId: number(),
17222
17332
  agentNodeId: string()
@@ -17226,7 +17336,13 @@ method(object({
17226
17336
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
17227
17337
  kind: "mutation",
17228
17338
  auth: "admin"
17229
- }), method(_void(), object({ migrated: number() }), {
17339
+ }), method(object({
17340
+ deviceId: number(),
17341
+ deviceKey: string()
17342
+ }), object({ success: literal(true) }), {
17343
+ kind: "mutation",
17344
+ auth: "admin"
17345
+ }), method(object({ deviceId: number() }), object({ deviceKey: string().nullable() })), method(_void(), object({ migrated: number() }), {
17230
17346
  kind: "mutation",
17231
17347
  auth: "admin"
17232
17348
  }), method(_void(), array(PipelineAssignmentSchema).readonly()), method(object({ deviceId: number() }), PipelineAssignmentSchema.nullable()), method(_void(), array(AgentLoadSummarySchema).readonly()), method(_void(), GlobalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(object({ nodeId: string() }), CapabilityBindingsSchema), method(object({
@@ -17260,13 +17376,7 @@ method(object({
17260
17376
  }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
17261
17377
  nodeId: string(),
17262
17378
  settings: AgentPipelineSettingsSchema
17263
- })).readonly()), method(object({
17264
- agentNodeId: string(),
17265
- defaults: record(string(), AgentAddonConfigSchema)
17266
- }), object({ success: literal(true) }), {
17267
- kind: "mutation",
17268
- auth: "admin"
17269
- }), method(object({ agentNodeId: string() }), object({
17379
+ })).readonly()), method(object({ agentNodeId: string() }), object({
17270
17380
  success: boolean(),
17271
17381
  removed: boolean()
17272
17382
  }), {
@@ -17298,7 +17408,18 @@ method(object({
17298
17408
  }), object({ success: literal(true) }), {
17299
17409
  kind: "mutation",
17300
17410
  auth: "admin"
17301
- }), method(object({ agentNodeId: string() }), object({
17411
+ }), method(object({
17412
+ agentNodeId: string(),
17413
+ inferenceDevices: record(string(), object({
17414
+ enabled: boolean(),
17415
+ weight: number().positive().optional(),
17416
+ maxSessions: number().int().positive().optional(),
17417
+ steps: record(string(), DeviceStepConfigSchema).optional()
17418
+ }))
17419
+ }), object({ success: literal(true) }), {
17420
+ kind: "mutation",
17421
+ auth: "admin"
17422
+ }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string() }), object({
17302
17423
  success: literal(true),
17303
17424
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
17304
17425
  effectiveModelId: string().nullable(),
@@ -17314,9 +17435,10 @@ method(object({
17314
17435
  }), object({ success: literal(true) }), {
17315
17436
  kind: "mutation",
17316
17437
  auth: "admin"
17317
- }), method(object({ deviceId: number() }), record(string(), record(string(), CameraStepOverridePatchSchema)).nullable()), method(object({
17438
+ }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
17318
17439
  deviceId: number(),
17319
17440
  agentNodeId: string(),
17441
+ deviceKey: string(),
17320
17442
  addonId: string(),
17321
17443
  patch: CameraStepOverridePatchSchema.nullable()
17322
17444
  }), object({ success: literal(true) }), {
@@ -17353,14 +17475,13 @@ method(object({
17353
17475
  });
17354
17476
  /**
17355
17477
  * server-management — per-NODE singleton capability for a node's ROOT
17356
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
17357
- * agents).
17478
+ * package lifecycle (runtime-updatable node packages).
17358
17479
  *
17359
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
17360
- * on agents) carries the whole software stack in its npm dep tree, so ONE
17361
- * version describes the node. Updates install into
17362
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
17363
- * starter (probation boot + auto-rollback to N-1).
17480
+ * Every node role runs the SAME root package (`@camstack/server`), which
17481
+ * carries the whole software stack in its npm dep tree, so ONE version
17482
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
17483
+ * on restart via the baked starter (single-copy in-place swap — no probation,
17484
+ * no auto-rollback).
17364
17485
  *
17365
17486
  * Providers:
17366
17487
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -17468,7 +17589,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
17468
17589
  /** Explicit target version; omitted = latest from the registry. */
17469
17590
  version: string().optional() }), ServerUpdateActionResultSchema, {
17470
17591
  kind: "mutation",
17471
- auth: "admin"
17592
+ auth: "admin",
17593
+ timeoutMs: 16 * 6e4
17472
17594
  }), method(_void(), ServerUpdateActionResultSchema, {
17473
17595
  kind: "mutation",
17474
17596
  auth: "admin"
@@ -18512,22 +18634,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
18512
18634
  var RestartAddonResultSchema = unknown();
18513
18635
  var InstallPackageResultSchema = unknown();
18514
18636
  var ReloadPackagesResultSchema = unknown();
18515
- /**
18516
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
18517
- * server restarts so the admin UI can react to the `restartingAt`
18518
- * timestamp (shows reconnect overlay). The transition from
18519
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
18520
- * `system.restart-completed` event after the new process boots.
18521
- *
18522
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
18523
- */
18524
- var UpdateFrameworkPackageResultSchema = object({
18525
- packageName: string(),
18526
- fromVersion: string(),
18527
- toVersion: string(),
18528
- /** Ms-epoch the server scheduled its self-restart. */
18529
- restartingAt: number()
18530
- });
18531
18637
  var BulkUpdateItemStatusSchema = _enum([
18532
18638
  "queued",
18533
18639
  "updating",
@@ -18655,13 +18761,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
18655
18761
  }), object({ success: literal(true) }), {
18656
18762
  kind: "mutation",
18657
18763
  auth: "admin"
18658
- }), method(object({
18659
- packageName: string().min(1),
18660
- version: string().optional(),
18661
- deferRestart: boolean().optional()
18662
- }), UpdateFrameworkPackageResultSchema, {
18663
- kind: "mutation",
18664
- auth: "admin"
18665
18764
  }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
18666
18765
  kind: "mutation",
18667
18766
  auth: "admin"
@@ -19527,10 +19626,10 @@ var TopologyCategorySchema = object({
19527
19626
  addons: array(TopologyCategoryAddonSchema).readonly()
19528
19627
  });
19529
19628
  /**
19530
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
19531
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
19532
- * version visibility for the Server management surface. Nullable: offline
19533
- * rows and pre-phase-2 nodes report none.
19629
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
19630
+ * root package for every node role) as reported by its `registerNode`
19631
+ * manifest — version visibility for the Server management surface. Nullable:
19632
+ * offline rows and nodes that never reported one.
19534
19633
  */
19535
19634
  var TopologyRootPackageSchema = object({
19536
19635
  name: string(),
@@ -19918,17 +20017,28 @@ var PlatformScoreSchema = object({
19918
20017
  format: _enum([
19919
20018
  "onnx",
19920
20019
  "coreml",
19921
- "openvino"
20020
+ "openvino",
20021
+ "tflite"
19922
20022
  ]),
19923
20023
  score: number(),
19924
20024
  reason: string(),
19925
20025
  available: boolean()
19926
20026
  });
20027
+ var InferenceDeviceDescriptorSchema = object({
20028
+ key: string(),
20029
+ backend: string(),
20030
+ device: string(),
20031
+ format: ModelFormatSchema,
20032
+ runtime: literal("python"),
20033
+ score: number(),
20034
+ available: boolean()
20035
+ });
19927
20036
  var PlatformCapabilitiesSchema = object({
19928
20037
  hardware: HardwareInfoSchema,
19929
20038
  scores: array(PlatformScoreSchema).readonly(),
19930
20039
  bestScore: PlatformScoreSchema,
19931
- pythonPath: string().nullable()
20040
+ pythonPath: string().nullable(),
20041
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
19932
20042
  });
19933
20043
  var ModelRequirementSchema = object({
19934
20044
  modelId: string(),
@@ -20807,12 +20917,6 @@ Object.freeze({
20807
20917
  addonId: null,
20808
20918
  access: "delete"
20809
20919
  },
20810
- "addons.updateFrameworkPackage": {
20811
- capName: "addons",
20812
- capScope: "system",
20813
- addonId: null,
20814
- access: "create"
20815
- },
20816
20920
  "addons.updatePackage": {
20817
20921
  capName: "addons",
20818
20922
  capScope: "system",
@@ -23585,12 +23689,6 @@ Object.freeze({
23585
23689
  addonId: null,
23586
23690
  access: "view"
23587
23691
  },
23588
- "pipelineExecutor.reprobeEngine": {
23589
- capName: "pipeline-executor",
23590
- capScope: "system",
23591
- addonId: null,
23592
- access: "create"
23593
- },
23594
23692
  "pipelineExecutor.runAudioTest": {
23595
23693
  capName: "pipeline-executor",
23596
23694
  capScope: "system",
@@ -23741,6 +23839,12 @@ Object.freeze({
23741
23839
  addonId: null,
23742
23840
  access: "view"
23743
23841
  },
23842
+ "pipelineOrchestrator.getNodeInferenceDevices": {
23843
+ capName: "pipeline-orchestrator",
23844
+ capScope: "system",
23845
+ addonId: null,
23846
+ access: "view"
23847
+ },
23744
23848
  "pipelineOrchestrator.getPipelineAssignment": {
23745
23849
  capName: "pipeline-orchestrator",
23746
23850
  capScope: "system",
@@ -23753,6 +23857,12 @@ Object.freeze({
23753
23857
  addonId: null,
23754
23858
  access: "view"
23755
23859
  },
23860
+ "pipelineOrchestrator.getPipelineDevicePin": {
23861
+ capName: "pipeline-orchestrator",
23862
+ capScope: "system",
23863
+ addonId: null,
23864
+ access: "view"
23865
+ },
23756
23866
  "pipelineOrchestrator.listAgentSettings": {
23757
23867
  capName: "pipeline-orchestrator",
23758
23868
  capScope: "system",
@@ -23795,19 +23905,19 @@ Object.freeze({
23795
23905
  addonId: null,
23796
23906
  access: "create"
23797
23907
  },
23798
- "pipelineOrchestrator.setAgentAddonDefaults": {
23908
+ "pipelineOrchestrator.setAgentCapabilities": {
23799
23909
  capName: "pipeline-orchestrator",
23800
23910
  capScope: "system",
23801
23911
  addonId: null,
23802
23912
  access: "create"
23803
23913
  },
23804
- "pipelineOrchestrator.setAgentCapabilities": {
23914
+ "pipelineOrchestrator.setAgentDetectWeight": {
23805
23915
  capName: "pipeline-orchestrator",
23806
23916
  capScope: "system",
23807
23917
  addonId: null,
23808
23918
  access: "create"
23809
23919
  },
23810
- "pipelineOrchestrator.setAgentDetectWeight": {
23920
+ "pipelineOrchestrator.setAgentInferenceDevices": {
23811
23921
  capName: "pipeline-orchestrator",
23812
23922
  capScope: "system",
23813
23923
  addonId: null,
@@ -23849,6 +23959,12 @@ Object.freeze({
23849
23959
  addonId: null,
23850
23960
  access: "create"
23851
23961
  },
23962
+ "pipelineOrchestrator.setPipelineDevicePin": {
23963
+ capName: "pipeline-orchestrator",
23964
+ capScope: "system",
23965
+ addonId: null,
23966
+ access: "create"
23967
+ },
23852
23968
  "pipelineOrchestrator.unassignAudio": {
23853
23969
  capName: "pipeline-orchestrator",
23854
23970
  capScope: "system",
@@ -25401,32 +25517,6 @@ Object.freeze({
25401
25517
  "network-access": "ingress",
25402
25518
  "smtp-provider": "email"
25403
25519
  });
25404
- var frameworkSwapPackageSchema = object({
25405
- name: string(),
25406
- stagedPath: string(),
25407
- backupPath: string(),
25408
- toVersion: string(),
25409
- fromVersion: string().nullable()
25410
- });
25411
- object({
25412
- jobId: string(),
25413
- taskId: string(),
25414
- packages: array(frameworkSwapPackageSchema),
25415
- requestedAtMs: number(),
25416
- schemaVersion: literal(1)
25417
- });
25418
- object({
25419
- jobId: string(),
25420
- taskId: string(),
25421
- backups: array(object({
25422
- name: string(),
25423
- backupPath: string(),
25424
- livePath: string()
25425
- })),
25426
- appliedAtMs: number(),
25427
- bootAttempts: number(),
25428
- schemaVersion: literal(1)
25429
- });
25430
25520
  //#endregion
25431
25521
  //#region src/custom-actions.ts
25432
25522
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-alexa",
3
- "version": "1.1.27",
3
+ "version": "1.2.0",
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",