@camstack/addon-provider-onvif 1.1.30 → 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.
Files changed (3) hide show
  1. package/dist/addon.js +193 -103
  2. package/dist/addon.mjs +193 -103
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -7083,6 +7083,17 @@ var ModelCatalogEntrySchema = object({
7083
7083
  "imagenet",
7084
7084
  "none"
7085
7085
  ]).optional(),
7086
+ /**
7087
+ * The model already applies softmax IN-GRAPH — its raw output is a
7088
+ * probability distribution, not logits. When set, the `softmax`
7089
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7090
+ * probability vector collapses it toward uniform (top-1 score craters far
7091
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7092
+ * the output is raw logits and the postprocessor applies softmax (the normal
7093
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7094
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7095
+ */
7096
+ outputProbabilities: boolean().optional(),
7086
7097
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7087
7098
  /**
7088
7099
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -11266,10 +11277,7 @@ var ConfigUISchemaNullableBridge = custom();
11266
11277
  var InferenceCapabilitiesBridge = custom();
11267
11278
  var ModelAvailabilityListBridge = custom();
11268
11279
  var PipelineRunResultBridge = custom();
11269
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
11270
- kind: "mutation",
11271
- auth: "admin"
11272
- }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
11280
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
11273
11281
  modelId: string(),
11274
11282
  settings: record(string(), unknown()).readonly()
11275
11283
  }))), method(object({ steps: record(string(), object({
@@ -11329,13 +11337,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
11329
11337
  * (inputClasses ≠ null) are skipped and served per-track via
11330
11338
  * pipelineRunner.runDetailSubtree (two-plane design).
11331
11339
  */
11332
- plane: _enum(["full", "frame"]).optional()
11340
+ plane: _enum(["full", "frame"]).optional(),
11341
+ /**
11342
+ * Inference-device selector (Phase 2 multi-device). Format
11343
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
11344
+ * Omitted ⇒ the runner's default device (current single-engine
11345
+ * behaviour). Selects WHICH device pool of the node runs the call.
11346
+ */
11347
+ deviceKey: string().optional()
11333
11348
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
11334
11349
  engine: PipelineEngineChoiceSchema.optional(),
11335
11350
  steps: array(PipelineStepInputSchema).min(1),
11336
11351
  frames: array(FrameInputSchema).min(1).max(255),
11337
11352
  deviceId: number().optional(),
11338
- sessionId: string().optional()
11353
+ sessionId: string().optional(),
11354
+ /**
11355
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
11356
+ * the batch to the Python pool's bench preprocess cache
11357
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
11358
+ * preprocessed ONCE and every later inference is a pure-inference cache
11359
+ * hit — the sustained-throughput run measures inference, not
11360
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
11361
+ * full preprocess every call, correct). Fresh per sustained run;
11362
+ * released via `uncacheFrame`.
11363
+ */
11364
+ frameId: number().int().nonnegative().optional(),
11365
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
11366
+ deviceKey: string().optional()
11339
11367
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
11340
11368
  data: _instanceof(Uint8Array),
11341
11369
  width: number().int().positive(),
@@ -11367,8 +11395,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
11367
11395
  * - `runtime` — main camera-serving engine (no idle TTL).
11368
11396
  * - `warm-override` — benchmark/test override held in the warm
11369
11397
  * cache; auto-disposed after the idle TTL.
11398
+ * - `device-pool` — a concurrent per-device pool (Phase 2
11399
+ * multi-device, keyed by `deviceKey`) resolved
11400
+ * via `resolveDeviceFactory`. Runs alongside the
11401
+ * `runtime` engine on a DIFFERENT accelerator
11402
+ * (NPU / iGPU / Coral) — this is how the
11403
+ * Engines tab shows all pools running at once.
11370
11404
  */
11371
- kind: _enum(["runtime", "warm-override"]),
11405
+ kind: _enum([
11406
+ "runtime",
11407
+ "warm-override",
11408
+ "device-pool"
11409
+ ]),
11372
11410
  /** Native pid of the underlying Python pool (null when no pool). */
11373
11411
  poolPid: number().nullable(),
11374
11412
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -11710,7 +11748,14 @@ var RunnerCameraConfigSchema = object({
11710
11748
  * camera's detect node differs from its source-owner (P2d, gated by the
11711
11749
  * `remoteSourcingNodes` rollout setting).
11712
11750
  */
11713
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
11751
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
11752
+ /**
11753
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
11754
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
11755
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
11756
+ * this only selects WHICH device pool of that node runs the session.
11757
+ */
11758
+ deviceKey: string().optional()
11714
11759
  });
11715
11760
  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;
11716
11761
  /**
@@ -11731,6 +11776,19 @@ var RunnerLocalLoadSchema = object({
11731
11776
  avgInferenceTimeMs: number(),
11732
11777
  /** Total queue depth across motion + detection queues. */
11733
11778
  queueDepthTotal: number(),
11779
+ /**
11780
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
11781
+ * this runner currently has attached cameras on, so the orchestrator's second
11782
+ * `balance()` pass (over a node's devices) weights on real per-pool session
11783
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
11784
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
11785
+ */
11786
+ devices: array(object({
11787
+ deviceKey: string(),
11788
+ backend: string(),
11789
+ attachedCameras: number(),
11790
+ queueDepthTotal: number()
11791
+ })).default([]),
11734
11792
  /** Hardware capability flags reported by this node. */
11735
11793
  hardware: object({
11736
11794
  hasGpu: boolean(),
@@ -13500,6 +13558,8 @@ var BaseDeviceProvider = class extends BaseAddon {
13500
13558
  return toDeviceSummary(device, this.addonId);
13501
13559
  }
13502
13560
  };
13561
+ 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;
13562
+ new Set(Object.values(DeviceType));
13503
13563
  /**
13504
13564
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
13505
13565
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -17169,13 +17229,11 @@ var PipelineTemplateSchema = object({
17169
17229
  createdAt: string(),
17170
17230
  updatedAt: string()
17171
17231
  });
17172
- var AgentAddonConfigSchema = object({
17173
- enabled: boolean(),
17232
+ var DeviceStepConfigSchema = object({
17174
17233
  modelId: string().optional(),
17175
- settings: record(string(), unknown()).readonly()
17234
+ settings: record(string(), unknown()).optional()
17176
17235
  });
17177
17236
  var AgentPipelineSettingsSchema = object({
17178
- addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
17179
17237
  maxCameras: number().int().nonnegative().nullable().default(null),
17180
17238
  /** Per-node detection weight (relative share for the quota balancer). */
17181
17239
  detectWeight: number().positive().optional(),
@@ -17199,7 +17257,22 @@ var AgentPipelineSettingsSchema = object({
17199
17257
  * it already uses to reach the hub). Set this only when the auto-detected
17200
17258
  * address is wrong (multi-homed host, NAT, custom interface).
17201
17259
  */
17202
- reachableHost: string().optional()
17260
+ reachableHost: string().optional(),
17261
+ /**
17262
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
17263
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
17264
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
17265
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
17266
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
17267
+ * the default model/settings for every camera landing on that accelerator;
17268
+ * a stepId absent ⇒ the step uses that device's format default.
17269
+ */
17270
+ inferenceDevices: record(string(), object({
17271
+ enabled: boolean(),
17272
+ weight: number().positive().optional(),
17273
+ maxSessions: number().int().positive().optional(),
17274
+ steps: record(string(), DeviceStepConfigSchema).optional()
17275
+ })).optional()
17203
17276
  });
17204
17277
  var CameraPipelineForAgentSchema = object({
17205
17278
  steps: array(PipelineStepInputSchema).readonly(),
@@ -17209,14 +17282,13 @@ var CameraPipelineForAgentSchema = object({
17209
17282
  }).nullable()
17210
17283
  });
17211
17284
  var CameraStepOverridePatchSchema = object({
17212
- enabled: boolean().optional(),
17213
17285
  modelId: string().optional(),
17214
17286
  settings: record(string(), unknown()).readonly().optional()
17215
17287
  });
17216
17288
  var CameraPipelineSettingsSchema = object({
17217
17289
  pinnedAgentNodeId: string().optional(),
17218
17290
  stepToggles: record(string(), boolean()).optional(),
17219
- stepOverridesByAgent: record(string(), record(string(), CameraStepOverridePatchSchema)).optional(),
17291
+ stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
17220
17292
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
17221
17293
  });
17222
17294
  /**
@@ -17430,6 +17502,44 @@ var CameraStatusSchema = object({
17430
17502
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
17431
17503
  fetchedAt: number()
17432
17504
  });
17505
+ var NodeInferenceDeviceSchema = object({
17506
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
17507
+ key: string(),
17508
+ backend: string(),
17509
+ device: string(),
17510
+ format: _enum(MODEL_FORMATS),
17511
+ /** Whether the node's live probe reports the device as usable right now. */
17512
+ available: boolean(),
17513
+ /**
17514
+ * Whether this device participates in dispatch. AUTO default (spec C2):
17515
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
17516
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
17517
+ * not a balanced target). An explicit stored value always wins; a stored-only
17518
+ * (unavailable) key keeps its stored value.
17519
+ */
17520
+ enabled: boolean(),
17521
+ /** Relative balancer weight for the enabled device (default 1). */
17522
+ weight: number(),
17523
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
17524
+ maxSessions: number().nullable(),
17525
+ /** Object-detection model the executor defaults to for this deviceKey. */
17526
+ defaultModelId: string(),
17527
+ /**
17528
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
17529
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
17530
+ * Absent/empty ⇒ no base (every step uses its device format default). The
17531
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
17532
+ * available per format; this is the stored selection that becomes the
17533
+ * default for EVERY camera landing on this accelerator.
17534
+ */
17535
+ steps: record(string(), DeviceStepConfigSchema).optional()
17536
+ });
17537
+ var NodeInferenceDevicesSchema = object({
17538
+ nodeId: string(),
17539
+ /** False when the node's platform-probe was unreachable (no live device set). */
17540
+ reachable: boolean(),
17541
+ devices: array(NodeInferenceDeviceSchema).readonly()
17542
+ });
17433
17543
  method(object({
17434
17544
  deviceId: number(),
17435
17545
  agentNodeId: string()
@@ -17439,7 +17549,13 @@ method(object({
17439
17549
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
17440
17550
  kind: "mutation",
17441
17551
  auth: "admin"
17442
- }), method(_void(), object({ migrated: number() }), {
17552
+ }), method(object({
17553
+ deviceId: number(),
17554
+ deviceKey: string()
17555
+ }), object({ success: literal(true) }), {
17556
+ kind: "mutation",
17557
+ auth: "admin"
17558
+ }), method(object({ deviceId: number() }), object({ deviceKey: string().nullable() })), method(_void(), object({ migrated: number() }), {
17443
17559
  kind: "mutation",
17444
17560
  auth: "admin"
17445
17561
  }), 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({
@@ -17473,13 +17589,7 @@ method(object({
17473
17589
  }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
17474
17590
  nodeId: string(),
17475
17591
  settings: AgentPipelineSettingsSchema
17476
- })).readonly()), method(object({
17477
- agentNodeId: string(),
17478
- defaults: record(string(), AgentAddonConfigSchema)
17479
- }), object({ success: literal(true) }), {
17480
- kind: "mutation",
17481
- auth: "admin"
17482
- }), method(object({ agentNodeId: string() }), object({
17592
+ })).readonly()), method(object({ agentNodeId: string() }), object({
17483
17593
  success: boolean(),
17484
17594
  removed: boolean()
17485
17595
  }), {
@@ -17511,7 +17621,18 @@ method(object({
17511
17621
  }), object({ success: literal(true) }), {
17512
17622
  kind: "mutation",
17513
17623
  auth: "admin"
17514
- }), method(object({ agentNodeId: string() }), object({
17624
+ }), method(object({
17625
+ agentNodeId: string(),
17626
+ inferenceDevices: record(string(), object({
17627
+ enabled: boolean(),
17628
+ weight: number().positive().optional(),
17629
+ maxSessions: number().int().positive().optional(),
17630
+ steps: record(string(), DeviceStepConfigSchema).optional()
17631
+ }))
17632
+ }), object({ success: literal(true) }), {
17633
+ kind: "mutation",
17634
+ auth: "admin"
17635
+ }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string() }), object({
17515
17636
  success: literal(true),
17516
17637
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
17517
17638
  effectiveModelId: string().nullable(),
@@ -17527,9 +17648,10 @@ method(object({
17527
17648
  }), object({ success: literal(true) }), {
17528
17649
  kind: "mutation",
17529
17650
  auth: "admin"
17530
- }), method(object({ deviceId: number() }), record(string(), record(string(), CameraStepOverridePatchSchema)).nullable()), method(object({
17651
+ }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
17531
17652
  deviceId: number(),
17532
17653
  agentNodeId: string(),
17654
+ deviceKey: string(),
17533
17655
  addonId: string(),
17534
17656
  patch: CameraStepOverridePatchSchema.nullable()
17535
17657
  }), object({ success: literal(true) }), {
@@ -17566,14 +17688,13 @@ method(object({
17566
17688
  });
17567
17689
  /**
17568
17690
  * server-management — per-NODE singleton capability for a node's ROOT
17569
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
17570
- * agents).
17691
+ * package lifecycle (runtime-updatable node packages).
17571
17692
  *
17572
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
17573
- * on agents) carries the whole software stack in its npm dep tree, so ONE
17574
- * version describes the node. Updates install into
17575
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
17576
- * starter (probation boot + auto-rollback to N-1).
17693
+ * Every node role runs the SAME root package (`@camstack/server`), which
17694
+ * carries the whole software stack in its npm dep tree, so ONE version
17695
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
17696
+ * on restart via the baked starter (single-copy in-place swap — no probation,
17697
+ * no auto-rollback).
17577
17698
  *
17578
17699
  * Providers:
17579
17700
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -17681,7 +17802,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
17681
17802
  /** Explicit target version; omitted = latest from the registry. */
17682
17803
  version: string().optional() }), ServerUpdateActionResultSchema, {
17683
17804
  kind: "mutation",
17684
- auth: "admin"
17805
+ auth: "admin",
17806
+ timeoutMs: 16 * 6e4
17685
17807
  }), method(_void(), ServerUpdateActionResultSchema, {
17686
17808
  kind: "mutation",
17687
17809
  auth: "admin"
@@ -18776,22 +18898,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
18776
18898
  var RestartAddonResultSchema = unknown();
18777
18899
  var InstallPackageResultSchema = unknown();
18778
18900
  var ReloadPackagesResultSchema = unknown();
18779
- /**
18780
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
18781
- * server restarts so the admin UI can react to the `restartingAt`
18782
- * timestamp (shows reconnect overlay). The transition from
18783
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
18784
- * `system.restart-completed` event after the new process boots.
18785
- *
18786
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
18787
- */
18788
- var UpdateFrameworkPackageResultSchema = object({
18789
- packageName: string(),
18790
- fromVersion: string(),
18791
- toVersion: string(),
18792
- /** Ms-epoch the server scheduled its self-restart. */
18793
- restartingAt: number()
18794
- });
18795
18901
  var BulkUpdateItemStatusSchema = _enum([
18796
18902
  "queued",
18797
18903
  "updating",
@@ -18919,13 +19025,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
18919
19025
  }), object({ success: literal(true) }), {
18920
19026
  kind: "mutation",
18921
19027
  auth: "admin"
18922
- }), method(object({
18923
- packageName: string().min(1),
18924
- version: string().optional(),
18925
- deferRestart: boolean().optional()
18926
- }), UpdateFrameworkPackageResultSchema, {
18927
- kind: "mutation",
18928
- auth: "admin"
18929
19028
  }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
18930
19029
  kind: "mutation",
18931
19030
  auth: "admin"
@@ -19791,10 +19890,10 @@ var TopologyCategorySchema = object({
19791
19890
  addons: array(TopologyCategoryAddonSchema).readonly()
19792
19891
  });
19793
19892
  /**
19794
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
19795
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
19796
- * version visibility for the Server management surface. Nullable: offline
19797
- * rows and pre-phase-2 nodes report none.
19893
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
19894
+ * root package for every node role) as reported by its `registerNode`
19895
+ * manifest — version visibility for the Server management surface. Nullable:
19896
+ * offline rows and nodes that never reported one.
19798
19897
  */
19799
19898
  var TopologyRootPackageSchema = object({
19800
19899
  name: string(),
@@ -20182,17 +20281,28 @@ var PlatformScoreSchema = object({
20182
20281
  format: _enum([
20183
20282
  "onnx",
20184
20283
  "coreml",
20185
- "openvino"
20284
+ "openvino",
20285
+ "tflite"
20186
20286
  ]),
20187
20287
  score: number(),
20188
20288
  reason: string(),
20189
20289
  available: boolean()
20190
20290
  });
20291
+ var InferenceDeviceDescriptorSchema = object({
20292
+ key: string(),
20293
+ backend: string(),
20294
+ device: string(),
20295
+ format: ModelFormatSchema,
20296
+ runtime: literal("python"),
20297
+ score: number(),
20298
+ available: boolean()
20299
+ });
20191
20300
  var PlatformCapabilitiesSchema = object({
20192
20301
  hardware: HardwareInfoSchema,
20193
20302
  scores: array(PlatformScoreSchema).readonly(),
20194
20303
  bestScore: PlatformScoreSchema,
20195
- pythonPath: string().nullable()
20304
+ pythonPath: string().nullable(),
20305
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
20196
20306
  });
20197
20307
  var ModelRequirementSchema = object({
20198
20308
  modelId: string(),
@@ -21113,12 +21223,6 @@ Object.freeze({
21113
21223
  addonId: null,
21114
21224
  access: "delete"
21115
21225
  },
21116
- "addons.updateFrameworkPackage": {
21117
- capName: "addons",
21118
- capScope: "system",
21119
- addonId: null,
21120
- access: "create"
21121
- },
21122
21226
  "addons.updatePackage": {
21123
21227
  capName: "addons",
21124
21228
  capScope: "system",
@@ -23891,12 +23995,6 @@ Object.freeze({
23891
23995
  addonId: null,
23892
23996
  access: "view"
23893
23997
  },
23894
- "pipelineExecutor.reprobeEngine": {
23895
- capName: "pipeline-executor",
23896
- capScope: "system",
23897
- addonId: null,
23898
- access: "create"
23899
- },
23900
23998
  "pipelineExecutor.runAudioTest": {
23901
23999
  capName: "pipeline-executor",
23902
24000
  capScope: "system",
@@ -24047,6 +24145,12 @@ Object.freeze({
24047
24145
  addonId: null,
24048
24146
  access: "view"
24049
24147
  },
24148
+ "pipelineOrchestrator.getNodeInferenceDevices": {
24149
+ capName: "pipeline-orchestrator",
24150
+ capScope: "system",
24151
+ addonId: null,
24152
+ access: "view"
24153
+ },
24050
24154
  "pipelineOrchestrator.getPipelineAssignment": {
24051
24155
  capName: "pipeline-orchestrator",
24052
24156
  capScope: "system",
@@ -24059,6 +24163,12 @@ Object.freeze({
24059
24163
  addonId: null,
24060
24164
  access: "view"
24061
24165
  },
24166
+ "pipelineOrchestrator.getPipelineDevicePin": {
24167
+ capName: "pipeline-orchestrator",
24168
+ capScope: "system",
24169
+ addonId: null,
24170
+ access: "view"
24171
+ },
24062
24172
  "pipelineOrchestrator.listAgentSettings": {
24063
24173
  capName: "pipeline-orchestrator",
24064
24174
  capScope: "system",
@@ -24101,19 +24211,19 @@ Object.freeze({
24101
24211
  addonId: null,
24102
24212
  access: "create"
24103
24213
  },
24104
- "pipelineOrchestrator.setAgentAddonDefaults": {
24214
+ "pipelineOrchestrator.setAgentCapabilities": {
24105
24215
  capName: "pipeline-orchestrator",
24106
24216
  capScope: "system",
24107
24217
  addonId: null,
24108
24218
  access: "create"
24109
24219
  },
24110
- "pipelineOrchestrator.setAgentCapabilities": {
24220
+ "pipelineOrchestrator.setAgentDetectWeight": {
24111
24221
  capName: "pipeline-orchestrator",
24112
24222
  capScope: "system",
24113
24223
  addonId: null,
24114
24224
  access: "create"
24115
24225
  },
24116
- "pipelineOrchestrator.setAgentDetectWeight": {
24226
+ "pipelineOrchestrator.setAgentInferenceDevices": {
24117
24227
  capName: "pipeline-orchestrator",
24118
24228
  capScope: "system",
24119
24229
  addonId: null,
@@ -24155,6 +24265,12 @@ Object.freeze({
24155
24265
  addonId: null,
24156
24266
  access: "create"
24157
24267
  },
24268
+ "pipelineOrchestrator.setPipelineDevicePin": {
24269
+ capName: "pipeline-orchestrator",
24270
+ capScope: "system",
24271
+ addonId: null,
24272
+ access: "create"
24273
+ },
24158
24274
  "pipelineOrchestrator.unassignAudio": {
24159
24275
  capName: "pipeline-orchestrator",
24160
24276
  capScope: "system",
@@ -25707,32 +25823,6 @@ Object.freeze({
25707
25823
  "network-access": "ingress",
25708
25824
  "smtp-provider": "email"
25709
25825
  });
25710
- var frameworkSwapPackageSchema = object({
25711
- name: string(),
25712
- stagedPath: string(),
25713
- backupPath: string(),
25714
- toVersion: string(),
25715
- fromVersion: string().nullable()
25716
- });
25717
- object({
25718
- jobId: string(),
25719
- taskId: string(),
25720
- packages: array(frameworkSwapPackageSchema),
25721
- requestedAtMs: number(),
25722
- schemaVersion: literal(1)
25723
- });
25724
- object({
25725
- jobId: string(),
25726
- taskId: string(),
25727
- backups: array(object({
25728
- name: string(),
25729
- backupPath: string(),
25730
- livePath: string()
25731
- })),
25732
- appliedAtMs: number(),
25733
- bootAttempts: number(),
25734
- schemaVersion: literal(1)
25735
- });
25736
25826
  //#endregion
25737
25827
  //#region src/onvif-camera.ts
25738
25828
  var onvifCameraSchema = object({
package/dist/addon.mjs CHANGED
@@ -7084,6 +7084,17 @@ var ModelCatalogEntrySchema = object({
7084
7084
  "imagenet",
7085
7085
  "none"
7086
7086
  ]).optional(),
7087
+ /**
7088
+ * The model already applies softmax IN-GRAPH — its raw output is a
7089
+ * probability distribution, not logits. When set, the `softmax`
7090
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7091
+ * probability vector collapses it toward uniform (top-1 score craters far
7092
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7093
+ * the output is raw logits and the postprocessor applies softmax (the normal
7094
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7095
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7096
+ */
7097
+ outputProbabilities: boolean().optional(),
7087
7098
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7088
7099
  /**
7089
7100
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -11267,10 +11278,7 @@ var ConfigUISchemaNullableBridge = custom();
11267
11278
  var InferenceCapabilitiesBridge = custom();
11268
11279
  var ModelAvailabilityListBridge = custom();
11269
11280
  var PipelineRunResultBridge = custom();
11270
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
11271
- kind: "mutation",
11272
- auth: "admin"
11273
- }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
11281
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
11274
11282
  modelId: string(),
11275
11283
  settings: record(string(), unknown()).readonly()
11276
11284
  }))), method(object({ steps: record(string(), object({
@@ -11330,13 +11338,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
11330
11338
  * (inputClasses ≠ null) are skipped and served per-track via
11331
11339
  * pipelineRunner.runDetailSubtree (two-plane design).
11332
11340
  */
11333
- plane: _enum(["full", "frame"]).optional()
11341
+ plane: _enum(["full", "frame"]).optional(),
11342
+ /**
11343
+ * Inference-device selector (Phase 2 multi-device). Format
11344
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
11345
+ * Omitted ⇒ the runner's default device (current single-engine
11346
+ * behaviour). Selects WHICH device pool of the node runs the call.
11347
+ */
11348
+ deviceKey: string().optional()
11334
11349
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
11335
11350
  engine: PipelineEngineChoiceSchema.optional(),
11336
11351
  steps: array(PipelineStepInputSchema).min(1),
11337
11352
  frames: array(FrameInputSchema).min(1).max(255),
11338
11353
  deviceId: number().optional(),
11339
- sessionId: string().optional()
11354
+ sessionId: string().optional(),
11355
+ /**
11356
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
11357
+ * the batch to the Python pool's bench preprocess cache
11358
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
11359
+ * preprocessed ONCE and every later inference is a pure-inference cache
11360
+ * hit — the sustained-throughput run measures inference, not
11361
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
11362
+ * full preprocess every call, correct). Fresh per sustained run;
11363
+ * released via `uncacheFrame`.
11364
+ */
11365
+ frameId: number().int().nonnegative().optional(),
11366
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
11367
+ deviceKey: string().optional()
11340
11368
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
11341
11369
  data: _instanceof(Uint8Array),
11342
11370
  width: number().int().positive(),
@@ -11368,8 +11396,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
11368
11396
  * - `runtime` — main camera-serving engine (no idle TTL).
11369
11397
  * - `warm-override` — benchmark/test override held in the warm
11370
11398
  * cache; auto-disposed after the idle TTL.
11399
+ * - `device-pool` — a concurrent per-device pool (Phase 2
11400
+ * multi-device, keyed by `deviceKey`) resolved
11401
+ * via `resolveDeviceFactory`. Runs alongside the
11402
+ * `runtime` engine on a DIFFERENT accelerator
11403
+ * (NPU / iGPU / Coral) — this is how the
11404
+ * Engines tab shows all pools running at once.
11371
11405
  */
11372
- kind: _enum(["runtime", "warm-override"]),
11406
+ kind: _enum([
11407
+ "runtime",
11408
+ "warm-override",
11409
+ "device-pool"
11410
+ ]),
11373
11411
  /** Native pid of the underlying Python pool (null when no pool). */
11374
11412
  poolPid: number().nullable(),
11375
11413
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -11711,7 +11749,14 @@ var RunnerCameraConfigSchema = object({
11711
11749
  * camera's detect node differs from its source-owner (P2d, gated by the
11712
11750
  * `remoteSourcingNodes` rollout setting).
11713
11751
  */
11714
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
11752
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
11753
+ /**
11754
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
11755
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
11756
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
11757
+ * this only selects WHICH device pool of that node runs the session.
11758
+ */
11759
+ deviceKey: string().optional()
11715
11760
  });
11716
11761
  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;
11717
11762
  /**
@@ -11732,6 +11777,19 @@ var RunnerLocalLoadSchema = object({
11732
11777
  avgInferenceTimeMs: number(),
11733
11778
  /** Total queue depth across motion + detection queues. */
11734
11779
  queueDepthTotal: number(),
11780
+ /**
11781
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
11782
+ * this runner currently has attached cameras on, so the orchestrator's second
11783
+ * `balance()` pass (over a node's devices) weights on real per-pool session
11784
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
11785
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
11786
+ */
11787
+ devices: array(object({
11788
+ deviceKey: string(),
11789
+ backend: string(),
11790
+ attachedCameras: number(),
11791
+ queueDepthTotal: number()
11792
+ })).default([]),
11735
11793
  /** Hardware capability flags reported by this node. */
11736
11794
  hardware: object({
11737
11795
  hasGpu: boolean(),
@@ -13501,6 +13559,8 @@ var BaseDeviceProvider = class extends BaseAddon {
13501
13559
  return toDeviceSummary(device, this.addonId);
13502
13560
  }
13503
13561
  };
13562
+ 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;
13563
+ new Set(Object.values(DeviceType));
13504
13564
  /**
13505
13565
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
13506
13566
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -17170,13 +17230,11 @@ var PipelineTemplateSchema = object({
17170
17230
  createdAt: string(),
17171
17231
  updatedAt: string()
17172
17232
  });
17173
- var AgentAddonConfigSchema = object({
17174
- enabled: boolean(),
17233
+ var DeviceStepConfigSchema = object({
17175
17234
  modelId: string().optional(),
17176
- settings: record(string(), unknown()).readonly()
17235
+ settings: record(string(), unknown()).optional()
17177
17236
  });
17178
17237
  var AgentPipelineSettingsSchema = object({
17179
- addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
17180
17238
  maxCameras: number().int().nonnegative().nullable().default(null),
17181
17239
  /** Per-node detection weight (relative share for the quota balancer). */
17182
17240
  detectWeight: number().positive().optional(),
@@ -17200,7 +17258,22 @@ var AgentPipelineSettingsSchema = object({
17200
17258
  * it already uses to reach the hub). Set this only when the auto-detected
17201
17259
  * address is wrong (multi-homed host, NAT, custom interface).
17202
17260
  */
17203
- reachableHost: string().optional()
17261
+ reachableHost: string().optional(),
17262
+ /**
17263
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
17264
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
17265
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
17266
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
17267
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
17268
+ * the default model/settings for every camera landing on that accelerator;
17269
+ * a stepId absent ⇒ the step uses that device's format default.
17270
+ */
17271
+ inferenceDevices: record(string(), object({
17272
+ enabled: boolean(),
17273
+ weight: number().positive().optional(),
17274
+ maxSessions: number().int().positive().optional(),
17275
+ steps: record(string(), DeviceStepConfigSchema).optional()
17276
+ })).optional()
17204
17277
  });
17205
17278
  var CameraPipelineForAgentSchema = object({
17206
17279
  steps: array(PipelineStepInputSchema).readonly(),
@@ -17210,14 +17283,13 @@ var CameraPipelineForAgentSchema = object({
17210
17283
  }).nullable()
17211
17284
  });
17212
17285
  var CameraStepOverridePatchSchema = object({
17213
- enabled: boolean().optional(),
17214
17286
  modelId: string().optional(),
17215
17287
  settings: record(string(), unknown()).readonly().optional()
17216
17288
  });
17217
17289
  var CameraPipelineSettingsSchema = object({
17218
17290
  pinnedAgentNodeId: string().optional(),
17219
17291
  stepToggles: record(string(), boolean()).optional(),
17220
- stepOverridesByAgent: record(string(), record(string(), CameraStepOverridePatchSchema)).optional(),
17292
+ stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
17221
17293
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
17222
17294
  });
17223
17295
  /**
@@ -17431,6 +17503,44 @@ var CameraStatusSchema = object({
17431
17503
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
17432
17504
  fetchedAt: number()
17433
17505
  });
17506
+ var NodeInferenceDeviceSchema = object({
17507
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
17508
+ key: string(),
17509
+ backend: string(),
17510
+ device: string(),
17511
+ format: _enum(MODEL_FORMATS),
17512
+ /** Whether the node's live probe reports the device as usable right now. */
17513
+ available: boolean(),
17514
+ /**
17515
+ * Whether this device participates in dispatch. AUTO default (spec C2):
17516
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
17517
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
17518
+ * not a balanced target). An explicit stored value always wins; a stored-only
17519
+ * (unavailable) key keeps its stored value.
17520
+ */
17521
+ enabled: boolean(),
17522
+ /** Relative balancer weight for the enabled device (default 1). */
17523
+ weight: number(),
17524
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
17525
+ maxSessions: number().nullable(),
17526
+ /** Object-detection model the executor defaults to for this deviceKey. */
17527
+ defaultModelId: string(),
17528
+ /**
17529
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
17530
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
17531
+ * Absent/empty ⇒ no base (every step uses its device format default). The
17532
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
17533
+ * available per format; this is the stored selection that becomes the
17534
+ * default for EVERY camera landing on this accelerator.
17535
+ */
17536
+ steps: record(string(), DeviceStepConfigSchema).optional()
17537
+ });
17538
+ var NodeInferenceDevicesSchema = object({
17539
+ nodeId: string(),
17540
+ /** False when the node's platform-probe was unreachable (no live device set). */
17541
+ reachable: boolean(),
17542
+ devices: array(NodeInferenceDeviceSchema).readonly()
17543
+ });
17434
17544
  method(object({
17435
17545
  deviceId: number(),
17436
17546
  agentNodeId: string()
@@ -17440,7 +17550,13 @@ method(object({
17440
17550
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
17441
17551
  kind: "mutation",
17442
17552
  auth: "admin"
17443
- }), method(_void(), object({ migrated: number() }), {
17553
+ }), method(object({
17554
+ deviceId: number(),
17555
+ deviceKey: string()
17556
+ }), object({ success: literal(true) }), {
17557
+ kind: "mutation",
17558
+ auth: "admin"
17559
+ }), method(object({ deviceId: number() }), object({ deviceKey: string().nullable() })), method(_void(), object({ migrated: number() }), {
17444
17560
  kind: "mutation",
17445
17561
  auth: "admin"
17446
17562
  }), 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({
@@ -17474,13 +17590,7 @@ method(object({
17474
17590
  }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
17475
17591
  nodeId: string(),
17476
17592
  settings: AgentPipelineSettingsSchema
17477
- })).readonly()), method(object({
17478
- agentNodeId: string(),
17479
- defaults: record(string(), AgentAddonConfigSchema)
17480
- }), object({ success: literal(true) }), {
17481
- kind: "mutation",
17482
- auth: "admin"
17483
- }), method(object({ agentNodeId: string() }), object({
17593
+ })).readonly()), method(object({ agentNodeId: string() }), object({
17484
17594
  success: boolean(),
17485
17595
  removed: boolean()
17486
17596
  }), {
@@ -17512,7 +17622,18 @@ method(object({
17512
17622
  }), object({ success: literal(true) }), {
17513
17623
  kind: "mutation",
17514
17624
  auth: "admin"
17515
- }), method(object({ agentNodeId: string() }), object({
17625
+ }), method(object({
17626
+ agentNodeId: string(),
17627
+ inferenceDevices: record(string(), object({
17628
+ enabled: boolean(),
17629
+ weight: number().positive().optional(),
17630
+ maxSessions: number().int().positive().optional(),
17631
+ steps: record(string(), DeviceStepConfigSchema).optional()
17632
+ }))
17633
+ }), object({ success: literal(true) }), {
17634
+ kind: "mutation",
17635
+ auth: "admin"
17636
+ }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string() }), object({
17516
17637
  success: literal(true),
17517
17638
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
17518
17639
  effectiveModelId: string().nullable(),
@@ -17528,9 +17649,10 @@ method(object({
17528
17649
  }), object({ success: literal(true) }), {
17529
17650
  kind: "mutation",
17530
17651
  auth: "admin"
17531
- }), method(object({ deviceId: number() }), record(string(), record(string(), CameraStepOverridePatchSchema)).nullable()), method(object({
17652
+ }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
17532
17653
  deviceId: number(),
17533
17654
  agentNodeId: string(),
17655
+ deviceKey: string(),
17534
17656
  addonId: string(),
17535
17657
  patch: CameraStepOverridePatchSchema.nullable()
17536
17658
  }), object({ success: literal(true) }), {
@@ -17567,14 +17689,13 @@ method(object({
17567
17689
  });
17568
17690
  /**
17569
17691
  * server-management — per-NODE singleton capability for a node's ROOT
17570
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
17571
- * agents).
17692
+ * package lifecycle (runtime-updatable node packages).
17572
17693
  *
17573
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
17574
- * on agents) carries the whole software stack in its npm dep tree, so ONE
17575
- * version describes the node. Updates install into
17576
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
17577
- * starter (probation boot + auto-rollback to N-1).
17694
+ * Every node role runs the SAME root package (`@camstack/server`), which
17695
+ * carries the whole software stack in its npm dep tree, so ONE version
17696
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
17697
+ * on restart via the baked starter (single-copy in-place swap — no probation,
17698
+ * no auto-rollback).
17578
17699
  *
17579
17700
  * Providers:
17580
17701
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -17682,7 +17803,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
17682
17803
  /** Explicit target version; omitted = latest from the registry. */
17683
17804
  version: string().optional() }), ServerUpdateActionResultSchema, {
17684
17805
  kind: "mutation",
17685
- auth: "admin"
17806
+ auth: "admin",
17807
+ timeoutMs: 16 * 6e4
17686
17808
  }), method(_void(), ServerUpdateActionResultSchema, {
17687
17809
  kind: "mutation",
17688
17810
  auth: "admin"
@@ -18777,22 +18899,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
18777
18899
  var RestartAddonResultSchema = unknown();
18778
18900
  var InstallPackageResultSchema = unknown();
18779
18901
  var ReloadPackagesResultSchema = unknown();
18780
- /**
18781
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
18782
- * server restarts so the admin UI can react to the `restartingAt`
18783
- * timestamp (shows reconnect overlay). The transition from
18784
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
18785
- * `system.restart-completed` event after the new process boots.
18786
- *
18787
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
18788
- */
18789
- var UpdateFrameworkPackageResultSchema = object({
18790
- packageName: string(),
18791
- fromVersion: string(),
18792
- toVersion: string(),
18793
- /** Ms-epoch the server scheduled its self-restart. */
18794
- restartingAt: number()
18795
- });
18796
18902
  var BulkUpdateItemStatusSchema = _enum([
18797
18903
  "queued",
18798
18904
  "updating",
@@ -18920,13 +19026,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
18920
19026
  }), object({ success: literal(true) }), {
18921
19027
  kind: "mutation",
18922
19028
  auth: "admin"
18923
- }), method(object({
18924
- packageName: string().min(1),
18925
- version: string().optional(),
18926
- deferRestart: boolean().optional()
18927
- }), UpdateFrameworkPackageResultSchema, {
18928
- kind: "mutation",
18929
- auth: "admin"
18930
19029
  }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
18931
19030
  kind: "mutation",
18932
19031
  auth: "admin"
@@ -19792,10 +19891,10 @@ var TopologyCategorySchema = object({
19792
19891
  addons: array(TopologyCategoryAddonSchema).readonly()
19793
19892
  });
19794
19893
  /**
19795
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
19796
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
19797
- * version visibility for the Server management surface. Nullable: offline
19798
- * rows and pre-phase-2 nodes report none.
19894
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
19895
+ * root package for every node role) as reported by its `registerNode`
19896
+ * manifest — version visibility for the Server management surface. Nullable:
19897
+ * offline rows and nodes that never reported one.
19799
19898
  */
19800
19899
  var TopologyRootPackageSchema = object({
19801
19900
  name: string(),
@@ -20183,17 +20282,28 @@ var PlatformScoreSchema = object({
20183
20282
  format: _enum([
20184
20283
  "onnx",
20185
20284
  "coreml",
20186
- "openvino"
20285
+ "openvino",
20286
+ "tflite"
20187
20287
  ]),
20188
20288
  score: number(),
20189
20289
  reason: string(),
20190
20290
  available: boolean()
20191
20291
  });
20292
+ var InferenceDeviceDescriptorSchema = object({
20293
+ key: string(),
20294
+ backend: string(),
20295
+ device: string(),
20296
+ format: ModelFormatSchema,
20297
+ runtime: literal("python"),
20298
+ score: number(),
20299
+ available: boolean()
20300
+ });
20192
20301
  var PlatformCapabilitiesSchema = object({
20193
20302
  hardware: HardwareInfoSchema,
20194
20303
  scores: array(PlatformScoreSchema).readonly(),
20195
20304
  bestScore: PlatformScoreSchema,
20196
- pythonPath: string().nullable()
20305
+ pythonPath: string().nullable(),
20306
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
20197
20307
  });
20198
20308
  var ModelRequirementSchema = object({
20199
20309
  modelId: string(),
@@ -21114,12 +21224,6 @@ Object.freeze({
21114
21224
  addonId: null,
21115
21225
  access: "delete"
21116
21226
  },
21117
- "addons.updateFrameworkPackage": {
21118
- capName: "addons",
21119
- capScope: "system",
21120
- addonId: null,
21121
- access: "create"
21122
- },
21123
21227
  "addons.updatePackage": {
21124
21228
  capName: "addons",
21125
21229
  capScope: "system",
@@ -23892,12 +23996,6 @@ Object.freeze({
23892
23996
  addonId: null,
23893
23997
  access: "view"
23894
23998
  },
23895
- "pipelineExecutor.reprobeEngine": {
23896
- capName: "pipeline-executor",
23897
- capScope: "system",
23898
- addonId: null,
23899
- access: "create"
23900
- },
23901
23999
  "pipelineExecutor.runAudioTest": {
23902
24000
  capName: "pipeline-executor",
23903
24001
  capScope: "system",
@@ -24048,6 +24146,12 @@ Object.freeze({
24048
24146
  addonId: null,
24049
24147
  access: "view"
24050
24148
  },
24149
+ "pipelineOrchestrator.getNodeInferenceDevices": {
24150
+ capName: "pipeline-orchestrator",
24151
+ capScope: "system",
24152
+ addonId: null,
24153
+ access: "view"
24154
+ },
24051
24155
  "pipelineOrchestrator.getPipelineAssignment": {
24052
24156
  capName: "pipeline-orchestrator",
24053
24157
  capScope: "system",
@@ -24060,6 +24164,12 @@ Object.freeze({
24060
24164
  addonId: null,
24061
24165
  access: "view"
24062
24166
  },
24167
+ "pipelineOrchestrator.getPipelineDevicePin": {
24168
+ capName: "pipeline-orchestrator",
24169
+ capScope: "system",
24170
+ addonId: null,
24171
+ access: "view"
24172
+ },
24063
24173
  "pipelineOrchestrator.listAgentSettings": {
24064
24174
  capName: "pipeline-orchestrator",
24065
24175
  capScope: "system",
@@ -24102,19 +24212,19 @@ Object.freeze({
24102
24212
  addonId: null,
24103
24213
  access: "create"
24104
24214
  },
24105
- "pipelineOrchestrator.setAgentAddonDefaults": {
24215
+ "pipelineOrchestrator.setAgentCapabilities": {
24106
24216
  capName: "pipeline-orchestrator",
24107
24217
  capScope: "system",
24108
24218
  addonId: null,
24109
24219
  access: "create"
24110
24220
  },
24111
- "pipelineOrchestrator.setAgentCapabilities": {
24221
+ "pipelineOrchestrator.setAgentDetectWeight": {
24112
24222
  capName: "pipeline-orchestrator",
24113
24223
  capScope: "system",
24114
24224
  addonId: null,
24115
24225
  access: "create"
24116
24226
  },
24117
- "pipelineOrchestrator.setAgentDetectWeight": {
24227
+ "pipelineOrchestrator.setAgentInferenceDevices": {
24118
24228
  capName: "pipeline-orchestrator",
24119
24229
  capScope: "system",
24120
24230
  addonId: null,
@@ -24156,6 +24266,12 @@ Object.freeze({
24156
24266
  addonId: null,
24157
24267
  access: "create"
24158
24268
  },
24269
+ "pipelineOrchestrator.setPipelineDevicePin": {
24270
+ capName: "pipeline-orchestrator",
24271
+ capScope: "system",
24272
+ addonId: null,
24273
+ access: "create"
24274
+ },
24159
24275
  "pipelineOrchestrator.unassignAudio": {
24160
24276
  capName: "pipeline-orchestrator",
24161
24277
  capScope: "system",
@@ -25708,32 +25824,6 @@ Object.freeze({
25708
25824
  "network-access": "ingress",
25709
25825
  "smtp-provider": "email"
25710
25826
  });
25711
- var frameworkSwapPackageSchema = object({
25712
- name: string(),
25713
- stagedPath: string(),
25714
- backupPath: string(),
25715
- toVersion: string(),
25716
- fromVersion: string().nullable()
25717
- });
25718
- object({
25719
- jobId: string(),
25720
- taskId: string(),
25721
- packages: array(frameworkSwapPackageSchema),
25722
- requestedAtMs: number(),
25723
- schemaVersion: literal(1)
25724
- });
25725
- object({
25726
- jobId: string(),
25727
- taskId: string(),
25728
- backups: array(object({
25729
- name: string(),
25730
- backupPath: string(),
25731
- livePath: string()
25732
- })),
25733
- appliedAtMs: number(),
25734
- bootAttempts: number(),
25735
- schemaVersion: literal(1)
25736
- });
25737
25827
  //#endregion
25738
25828
  //#region src/onvif-camera.ts
25739
25829
  var onvifCameraSchema = object({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-onvif",
3
- "version": "1.1.30",
3
+ "version": "1.2.0",
4
4
  "description": "ONVIF camera device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",