@camstack/addon-static-turn 1.1.28 → 1.2.1

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.
@@ -7068,6 +7068,17 @@ var ModelCatalogEntrySchema = object({
7068
7068
  "imagenet",
7069
7069
  "none"
7070
7070
  ]).optional(),
7071
+ /**
7072
+ * The model already applies softmax IN-GRAPH — its raw output is a
7073
+ * probability distribution, not logits. When set, the `softmax`
7074
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7075
+ * probability vector collapses it toward uniform (top-1 score craters far
7076
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7077
+ * the output is raw logits and the postprocessor applies softmax (the normal
7078
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7079
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7080
+ */
7081
+ outputProbabilities: boolean().optional(),
7071
7082
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7072
7083
  /**
7073
7084
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -11081,10 +11092,7 @@ var ConfigUISchemaNullableBridge = custom();
11081
11092
  var InferenceCapabilitiesBridge = custom();
11082
11093
  var ModelAvailabilityListBridge = custom();
11083
11094
  var PipelineRunResultBridge = custom();
11084
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
11085
- kind: "mutation",
11086
- auth: "admin"
11087
- }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
11095
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
11088
11096
  modelId: string(),
11089
11097
  settings: record(string(), unknown()).readonly()
11090
11098
  }))), method(object({ steps: record(string(), object({
@@ -11144,13 +11152,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
11144
11152
  * (inputClasses ≠ null) are skipped and served per-track via
11145
11153
  * pipelineRunner.runDetailSubtree (two-plane design).
11146
11154
  */
11147
- plane: _enum(["full", "frame"]).optional()
11155
+ plane: _enum(["full", "frame"]).optional(),
11156
+ /**
11157
+ * Inference-device selector (Phase 2 multi-device). Format
11158
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
11159
+ * Omitted ⇒ the runner's default device (current single-engine
11160
+ * behaviour). Selects WHICH device pool of the node runs the call.
11161
+ */
11162
+ deviceKey: string().optional()
11148
11163
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
11149
11164
  engine: PipelineEngineChoiceSchema.optional(),
11150
11165
  steps: array(PipelineStepInputSchema).min(1),
11151
11166
  frames: array(FrameInputSchema).min(1).max(255),
11152
11167
  deviceId: number().optional(),
11153
- sessionId: string().optional()
11168
+ sessionId: string().optional(),
11169
+ /**
11170
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
11171
+ * the batch to the Python pool's bench preprocess cache
11172
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
11173
+ * preprocessed ONCE and every later inference is a pure-inference cache
11174
+ * hit — the sustained-throughput run measures inference, not
11175
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
11176
+ * full preprocess every call, correct). Fresh per sustained run;
11177
+ * released via `uncacheFrame`.
11178
+ */
11179
+ frameId: number().int().nonnegative().optional(),
11180
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
11181
+ deviceKey: string().optional()
11154
11182
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
11155
11183
  data: _instanceof(Uint8Array),
11156
11184
  width: number().int().positive(),
@@ -11182,8 +11210,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
11182
11210
  * - `runtime` — main camera-serving engine (no idle TTL).
11183
11211
  * - `warm-override` — benchmark/test override held in the warm
11184
11212
  * cache; auto-disposed after the idle TTL.
11213
+ * - `device-pool` — a concurrent per-device pool (Phase 2
11214
+ * multi-device, keyed by `deviceKey`) resolved
11215
+ * via `resolveDeviceFactory`. Runs alongside the
11216
+ * `runtime` engine on a DIFFERENT accelerator
11217
+ * (NPU / iGPU / Coral) — this is how the
11218
+ * Engines tab shows all pools running at once.
11185
11219
  */
11186
- kind: _enum(["runtime", "warm-override"]),
11220
+ kind: _enum([
11221
+ "runtime",
11222
+ "warm-override",
11223
+ "device-pool"
11224
+ ]),
11187
11225
  /** Native pid of the underlying Python pool (null when no pool). */
11188
11226
  poolPid: number().nullable(),
11189
11227
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -11285,7 +11323,21 @@ var NativeCropResultSchema = object({
11285
11323
  /** Packed rgb (24-bit) pixels of the crop. */
11286
11324
  bytes: _instanceof(Uint8Array),
11287
11325
  width: number().int().positive(),
11288
- height: number().int().positive()
11326
+ height: number().int().positive(),
11327
+ /**
11328
+ * Which source served this crop, so a quality-sensitive consumer (the native
11329
+ * `keyFrame`) can reject a degraded fallback:
11330
+ * - `native` — cut from the decode worker's retained NATIVE surface (the
11331
+ * quality path).
11332
+ * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
11333
+ * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
11334
+ * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
11335
+ *
11336
+ * OPTIONAL: a pre-tier runner (version skew) omits it — an ABSENT `tier` MUST be
11337
+ * treated as `native` (accepted) by every consumer so mixed-version clusters
11338
+ * keep the pre-tier behaviour. An ROI miss returns `null` (no tier at all).
11339
+ */
11340
+ tier: _enum(["native", "ram-fullframe"]).optional()
11289
11341
  });
11290
11342
  /** Parent detection context passed to `runDetailSubtree` — the crop's
11291
11343
  * originating detection, in FRAME-space coordinates. Reuses
@@ -11525,7 +11577,14 @@ var RunnerCameraConfigSchema = object({
11525
11577
  * camera's detect node differs from its source-owner (P2d, gated by the
11526
11578
  * `remoteSourcingNodes` rollout setting).
11527
11579
  */
11528
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
11580
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
11581
+ /**
11582
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
11583
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
11584
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
11585
+ * this only selects WHICH device pool of that node runs the session.
11586
+ */
11587
+ deviceKey: string().optional()
11529
11588
  });
11530
11589
  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;
11531
11590
  /**
@@ -11546,6 +11605,19 @@ var RunnerLocalLoadSchema = object({
11546
11605
  avgInferenceTimeMs: number(),
11547
11606
  /** Total queue depth across motion + detection queues. */
11548
11607
  queueDepthTotal: number(),
11608
+ /**
11609
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
11610
+ * this runner currently has attached cameras on, so the orchestrator's second
11611
+ * `balance()` pass (over a node's devices) weights on real per-pool session
11612
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
11613
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
11614
+ */
11615
+ devices: array(object({
11616
+ deviceKey: string(),
11617
+ backend: string(),
11618
+ attachedCameras: number(),
11619
+ queueDepthTotal: number()
11620
+ })).default([]),
11549
11621
  /** Hardware capability flags reported by this node. */
11550
11622
  hardware: object({
11551
11623
  hasGpu: boolean(),
@@ -13021,6 +13093,8 @@ method(_void(), _void(), { kind: "mutation" }), method(_void(), _void(), { kind:
13021
13093
  kind: "mutation",
13022
13094
  auth: "admin"
13023
13095
  });
13096
+ 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;
13097
+ new Set(Object.values(DeviceType));
13024
13098
  /**
13025
13099
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
13026
13100
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -14594,7 +14668,8 @@ var LinkedDeviceSchema = object({
14594
14668
  deviceId: number(),
14595
14669
  name: string(),
14596
14670
  location: string().nullable(),
14597
- features: array(string())
14671
+ features: array(string()),
14672
+ producesTrackedEvents: boolean().optional()
14598
14673
  });
14599
14674
  var SavedDeviceRowSchema = object({
14600
14675
  /** Numeric id reserved at allocateDeviceId time. */
@@ -16224,6 +16299,7 @@ var TrackSchema = object({
16224
16299
  deviceId: number(),
16225
16300
  className: string(),
16226
16301
  label: string().optional(),
16302
+ producingDeviceName: string().optional(),
16227
16303
  /** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
16228
16304
  source: TrackSourceSchema.optional(),
16229
16305
  firstSeen: number(),
@@ -16361,7 +16437,8 @@ var MediaFileKindEnum = _enum([
16361
16437
  "fullFrameBoxed",
16362
16438
  "faceCrop",
16363
16439
  "plateCrop",
16364
- "keyFrame"
16440
+ "keyFrame",
16441
+ "keyFrameSmall"
16365
16442
  ]);
16366
16443
  var MediaFileSchema = object({
16367
16444
  key: string(),
@@ -16690,13 +16767,11 @@ var PipelineTemplateSchema = object({
16690
16767
  createdAt: string(),
16691
16768
  updatedAt: string()
16692
16769
  });
16693
- var AgentAddonConfigSchema = object({
16694
- enabled: boolean(),
16770
+ var DeviceStepConfigSchema = object({
16695
16771
  modelId: string().optional(),
16696
- settings: record(string(), unknown()).readonly()
16772
+ settings: record(string(), unknown()).optional()
16697
16773
  });
16698
16774
  var AgentPipelineSettingsSchema = object({
16699
- addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
16700
16775
  maxCameras: number().int().nonnegative().nullable().default(null),
16701
16776
  /** Per-node detection weight (relative share for the quota balancer). */
16702
16777
  detectWeight: number().positive().optional(),
@@ -16720,7 +16795,22 @@ var AgentPipelineSettingsSchema = object({
16720
16795
  * it already uses to reach the hub). Set this only when the auto-detected
16721
16796
  * address is wrong (multi-homed host, NAT, custom interface).
16722
16797
  */
16723
- reachableHost: string().optional()
16798
+ reachableHost: string().optional(),
16799
+ /**
16800
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
16801
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
16802
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
16803
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
16804
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
16805
+ * the default model/settings for every camera landing on that accelerator;
16806
+ * a stepId absent ⇒ the step uses that device's format default.
16807
+ */
16808
+ inferenceDevices: record(string(), object({
16809
+ enabled: boolean(),
16810
+ weight: number().positive().optional(),
16811
+ maxSessions: number().int().positive().optional(),
16812
+ steps: record(string(), DeviceStepConfigSchema).optional()
16813
+ })).optional()
16724
16814
  });
16725
16815
  var CameraPipelineForAgentSchema = object({
16726
16816
  steps: array(PipelineStepInputSchema).readonly(),
@@ -16730,14 +16820,13 @@ var CameraPipelineForAgentSchema = object({
16730
16820
  }).nullable()
16731
16821
  });
16732
16822
  var CameraStepOverridePatchSchema = object({
16733
- enabled: boolean().optional(),
16734
16823
  modelId: string().optional(),
16735
16824
  settings: record(string(), unknown()).readonly().optional()
16736
16825
  });
16737
16826
  var CameraPipelineSettingsSchema = object({
16738
16827
  pinnedAgentNodeId: string().optional(),
16739
16828
  stepToggles: record(string(), boolean()).optional(),
16740
- stepOverridesByAgent: record(string(), record(string(), CameraStepOverridePatchSchema)).optional(),
16829
+ stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
16741
16830
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
16742
16831
  });
16743
16832
  /**
@@ -16951,6 +17040,44 @@ var CameraStatusSchema = object({
16951
17040
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
16952
17041
  fetchedAt: number()
16953
17042
  });
17043
+ var NodeInferenceDeviceSchema = object({
17044
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
17045
+ key: string(),
17046
+ backend: string(),
17047
+ device: string(),
17048
+ format: _enum(MODEL_FORMATS),
17049
+ /** Whether the node's live probe reports the device as usable right now. */
17050
+ available: boolean(),
17051
+ /**
17052
+ * Whether this device participates in dispatch. AUTO default (spec C2):
17053
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
17054
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
17055
+ * not a balanced target). An explicit stored value always wins; a stored-only
17056
+ * (unavailable) key keeps its stored value.
17057
+ */
17058
+ enabled: boolean(),
17059
+ /** Relative balancer weight for the enabled device (default 1). */
17060
+ weight: number(),
17061
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
17062
+ maxSessions: number().nullable(),
17063
+ /** Object-detection model the executor defaults to for this deviceKey. */
17064
+ defaultModelId: string(),
17065
+ /**
17066
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
17067
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
17068
+ * Absent/empty ⇒ no base (every step uses its device format default). The
17069
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
17070
+ * available per format; this is the stored selection that becomes the
17071
+ * default for EVERY camera landing on this accelerator.
17072
+ */
17073
+ steps: record(string(), DeviceStepConfigSchema).optional()
17074
+ });
17075
+ var NodeInferenceDevicesSchema = object({
17076
+ nodeId: string(),
17077
+ /** False when the node's platform-probe was unreachable (no live device set). */
17078
+ reachable: boolean(),
17079
+ devices: array(NodeInferenceDeviceSchema).readonly()
17080
+ });
16954
17081
  method(object({
16955
17082
  deviceId: number(),
16956
17083
  agentNodeId: string()
@@ -16960,7 +17087,13 @@ method(object({
16960
17087
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
16961
17088
  kind: "mutation",
16962
17089
  auth: "admin"
16963
- }), method(_void(), object({ migrated: number() }), {
17090
+ }), method(object({
17091
+ deviceId: number(),
17092
+ deviceKey: string()
17093
+ }), object({ success: literal(true) }), {
17094
+ kind: "mutation",
17095
+ auth: "admin"
17096
+ }), method(object({ deviceId: number() }), object({ deviceKey: string().nullable() })), method(_void(), object({ migrated: number() }), {
16964
17097
  kind: "mutation",
16965
17098
  auth: "admin"
16966
17099
  }), 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({
@@ -16994,13 +17127,7 @@ method(object({
16994
17127
  }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
16995
17128
  nodeId: string(),
16996
17129
  settings: AgentPipelineSettingsSchema
16997
- })).readonly()), method(object({
16998
- agentNodeId: string(),
16999
- defaults: record(string(), AgentAddonConfigSchema)
17000
- }), object({ success: literal(true) }), {
17001
- kind: "mutation",
17002
- auth: "admin"
17003
- }), method(object({ agentNodeId: string() }), object({
17130
+ })).readonly()), method(object({ agentNodeId: string() }), object({
17004
17131
  success: boolean(),
17005
17132
  removed: boolean()
17006
17133
  }), {
@@ -17032,7 +17159,18 @@ method(object({
17032
17159
  }), object({ success: literal(true) }), {
17033
17160
  kind: "mutation",
17034
17161
  auth: "admin"
17035
- }), method(object({ agentNodeId: string() }), object({
17162
+ }), method(object({
17163
+ agentNodeId: string(),
17164
+ inferenceDevices: record(string(), object({
17165
+ enabled: boolean(),
17166
+ weight: number().positive().optional(),
17167
+ maxSessions: number().int().positive().optional(),
17168
+ steps: record(string(), DeviceStepConfigSchema).optional()
17169
+ }))
17170
+ }), object({ success: literal(true) }), {
17171
+ kind: "mutation",
17172
+ auth: "admin"
17173
+ }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string() }), object({
17036
17174
  success: literal(true),
17037
17175
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
17038
17176
  effectiveModelId: string().nullable(),
@@ -17048,9 +17186,10 @@ method(object({
17048
17186
  }), object({ success: literal(true) }), {
17049
17187
  kind: "mutation",
17050
17188
  auth: "admin"
17051
- }), method(object({ deviceId: number() }), record(string(), record(string(), CameraStepOverridePatchSchema)).nullable()), method(object({
17189
+ }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
17052
17190
  deviceId: number(),
17053
17191
  agentNodeId: string(),
17192
+ deviceKey: string(),
17054
17193
  addonId: string(),
17055
17194
  patch: CameraStepOverridePatchSchema.nullable()
17056
17195
  }), object({ success: literal(true) }), {
@@ -17087,14 +17226,13 @@ method(object({
17087
17226
  });
17088
17227
  /**
17089
17228
  * server-management — per-NODE singleton capability for a node's ROOT
17090
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
17091
- * agents).
17229
+ * package lifecycle (runtime-updatable node packages).
17092
17230
  *
17093
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
17094
- * on agents) carries the whole software stack in its npm dep tree, so ONE
17095
- * version describes the node. Updates install into
17096
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
17097
- * starter (probation boot + auto-rollback to N-1).
17231
+ * Every node role runs the SAME root package (`@camstack/server`), which
17232
+ * carries the whole software stack in its npm dep tree, so ONE version
17233
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
17234
+ * on restart via the baked starter (single-copy in-place swap — no probation,
17235
+ * no auto-rollback).
17098
17236
  *
17099
17237
  * Providers:
17100
17238
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -17202,7 +17340,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
17202
17340
  /** Explicit target version; omitted = latest from the registry. */
17203
17341
  version: string().optional() }), ServerUpdateActionResultSchema, {
17204
17342
  kind: "mutation",
17205
- auth: "admin"
17343
+ auth: "admin",
17344
+ timeoutMs: 16 * 6e4
17206
17345
  }), method(_void(), ServerUpdateActionResultSchema, {
17207
17346
  kind: "mutation",
17208
17347
  auth: "admin"
@@ -18269,22 +18408,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
18269
18408
  var RestartAddonResultSchema = unknown();
18270
18409
  var InstallPackageResultSchema = unknown();
18271
18410
  var ReloadPackagesResultSchema = unknown();
18272
- /**
18273
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
18274
- * server restarts so the admin UI can react to the `restartingAt`
18275
- * timestamp (shows reconnect overlay). The transition from
18276
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
18277
- * `system.restart-completed` event after the new process boots.
18278
- *
18279
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
18280
- */
18281
- var UpdateFrameworkPackageResultSchema = object({
18282
- packageName: string(),
18283
- fromVersion: string(),
18284
- toVersion: string(),
18285
- /** Ms-epoch the server scheduled its self-restart. */
18286
- restartingAt: number()
18287
- });
18288
18411
  var BulkUpdateItemStatusSchema = _enum([
18289
18412
  "queued",
18290
18413
  "updating",
@@ -18412,13 +18535,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
18412
18535
  }), object({ success: literal(true) }), {
18413
18536
  kind: "mutation",
18414
18537
  auth: "admin"
18415
- }), method(object({
18416
- packageName: string().min(1),
18417
- version: string().optional(),
18418
- deferRestart: boolean().optional()
18419
- }), UpdateFrameworkPackageResultSchema, {
18420
- kind: "mutation",
18421
- auth: "admin"
18422
18538
  }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
18423
18539
  kind: "mutation",
18424
18540
  auth: "admin"
@@ -19284,10 +19400,10 @@ var TopologyCategorySchema = object({
19284
19400
  addons: array(TopologyCategoryAddonSchema).readonly()
19285
19401
  });
19286
19402
  /**
19287
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
19288
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
19289
- * version visibility for the Server management surface. Nullable: offline
19290
- * rows and pre-phase-2 nodes report none.
19403
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
19404
+ * root package for every node role) as reported by its `registerNode`
19405
+ * manifest — version visibility for the Server management surface. Nullable:
19406
+ * offline rows and nodes that never reported one.
19291
19407
  */
19292
19408
  var TopologyRootPackageSchema = object({
19293
19409
  name: string(),
@@ -19675,17 +19791,28 @@ var PlatformScoreSchema = object({
19675
19791
  format: _enum([
19676
19792
  "onnx",
19677
19793
  "coreml",
19678
- "openvino"
19794
+ "openvino",
19795
+ "tflite"
19679
19796
  ]),
19680
19797
  score: number(),
19681
19798
  reason: string(),
19682
19799
  available: boolean()
19683
19800
  });
19801
+ var InferenceDeviceDescriptorSchema = object({
19802
+ key: string(),
19803
+ backend: string(),
19804
+ device: string(),
19805
+ format: ModelFormatSchema,
19806
+ runtime: literal("python"),
19807
+ score: number(),
19808
+ available: boolean()
19809
+ });
19684
19810
  var PlatformCapabilitiesSchema = object({
19685
19811
  hardware: HardwareInfoSchema,
19686
19812
  scores: array(PlatformScoreSchema).readonly(),
19687
19813
  bestScore: PlatformScoreSchema,
19688
- pythonPath: string().nullable()
19814
+ pythonPath: string().nullable(),
19815
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
19689
19816
  });
19690
19817
  var ModelRequirementSchema = object({
19691
19818
  modelId: string(),
@@ -20564,12 +20691,6 @@ Object.freeze({
20564
20691
  addonId: null,
20565
20692
  access: "delete"
20566
20693
  },
20567
- "addons.updateFrameworkPackage": {
20568
- capName: "addons",
20569
- capScope: "system",
20570
- addonId: null,
20571
- access: "create"
20572
- },
20573
20694
  "addons.updatePackage": {
20574
20695
  capName: "addons",
20575
20696
  capScope: "system",
@@ -23342,12 +23463,6 @@ Object.freeze({
23342
23463
  addonId: null,
23343
23464
  access: "view"
23344
23465
  },
23345
- "pipelineExecutor.reprobeEngine": {
23346
- capName: "pipeline-executor",
23347
- capScope: "system",
23348
- addonId: null,
23349
- access: "create"
23350
- },
23351
23466
  "pipelineExecutor.runAudioTest": {
23352
23467
  capName: "pipeline-executor",
23353
23468
  capScope: "system",
@@ -23498,6 +23613,12 @@ Object.freeze({
23498
23613
  addonId: null,
23499
23614
  access: "view"
23500
23615
  },
23616
+ "pipelineOrchestrator.getNodeInferenceDevices": {
23617
+ capName: "pipeline-orchestrator",
23618
+ capScope: "system",
23619
+ addonId: null,
23620
+ access: "view"
23621
+ },
23501
23622
  "pipelineOrchestrator.getPipelineAssignment": {
23502
23623
  capName: "pipeline-orchestrator",
23503
23624
  capScope: "system",
@@ -23510,6 +23631,12 @@ Object.freeze({
23510
23631
  addonId: null,
23511
23632
  access: "view"
23512
23633
  },
23634
+ "pipelineOrchestrator.getPipelineDevicePin": {
23635
+ capName: "pipeline-orchestrator",
23636
+ capScope: "system",
23637
+ addonId: null,
23638
+ access: "view"
23639
+ },
23513
23640
  "pipelineOrchestrator.listAgentSettings": {
23514
23641
  capName: "pipeline-orchestrator",
23515
23642
  capScope: "system",
@@ -23552,19 +23679,19 @@ Object.freeze({
23552
23679
  addonId: null,
23553
23680
  access: "create"
23554
23681
  },
23555
- "pipelineOrchestrator.setAgentAddonDefaults": {
23682
+ "pipelineOrchestrator.setAgentCapabilities": {
23556
23683
  capName: "pipeline-orchestrator",
23557
23684
  capScope: "system",
23558
23685
  addonId: null,
23559
23686
  access: "create"
23560
23687
  },
23561
- "pipelineOrchestrator.setAgentCapabilities": {
23688
+ "pipelineOrchestrator.setAgentDetectWeight": {
23562
23689
  capName: "pipeline-orchestrator",
23563
23690
  capScope: "system",
23564
23691
  addonId: null,
23565
23692
  access: "create"
23566
23693
  },
23567
- "pipelineOrchestrator.setAgentDetectWeight": {
23694
+ "pipelineOrchestrator.setAgentInferenceDevices": {
23568
23695
  capName: "pipeline-orchestrator",
23569
23696
  capScope: "system",
23570
23697
  addonId: null,
@@ -23606,6 +23733,12 @@ Object.freeze({
23606
23733
  addonId: null,
23607
23734
  access: "create"
23608
23735
  },
23736
+ "pipelineOrchestrator.setPipelineDevicePin": {
23737
+ capName: "pipeline-orchestrator",
23738
+ capScope: "system",
23739
+ addonId: null,
23740
+ access: "create"
23741
+ },
23609
23742
  "pipelineOrchestrator.unassignAudio": {
23610
23743
  capName: "pipeline-orchestrator",
23611
23744
  capScope: "system",
@@ -25158,32 +25291,6 @@ Object.freeze({
25158
25291
  "network-access": "ingress",
25159
25292
  "smtp-provider": "email"
25160
25293
  });
25161
- var frameworkSwapPackageSchema = object({
25162
- name: string(),
25163
- stagedPath: string(),
25164
- backupPath: string(),
25165
- toVersion: string(),
25166
- fromVersion: string().nullable()
25167
- });
25168
- object({
25169
- jobId: string(),
25170
- taskId: string(),
25171
- packages: array(frameworkSwapPackageSchema),
25172
- requestedAtMs: number(),
25173
- schemaVersion: literal(1)
25174
- });
25175
- object({
25176
- jobId: string(),
25177
- taskId: string(),
25178
- backups: array(object({
25179
- name: string(),
25180
- backupPath: string(),
25181
- livePath: string()
25182
- })),
25183
- appliedAtMs: number(),
25184
- bootAttempts: number(),
25185
- schemaVersion: literal(1)
25186
- });
25187
25294
  //#endregion
25188
25295
  //#region src/static-turn.addon.ts
25189
25296
  /**
@@ -7067,6 +7067,17 @@ var ModelCatalogEntrySchema = object({
7067
7067
  "imagenet",
7068
7068
  "none"
7069
7069
  ]).optional(),
7070
+ /**
7071
+ * The model already applies softmax IN-GRAPH — its raw output is a
7072
+ * probability distribution, not logits. When set, the `softmax`
7073
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7074
+ * probability vector collapses it toward uniform (top-1 score craters far
7075
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7076
+ * the output is raw logits and the postprocessor applies softmax (the normal
7077
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7078
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7079
+ */
7080
+ outputProbabilities: boolean().optional(),
7070
7081
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7071
7082
  /**
7072
7083
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -11080,10 +11091,7 @@ var ConfigUISchemaNullableBridge = custom();
11080
11091
  var InferenceCapabilitiesBridge = custom();
11081
11092
  var ModelAvailabilityListBridge = custom();
11082
11093
  var PipelineRunResultBridge = custom();
11083
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
11084
- kind: "mutation",
11085
- auth: "admin"
11086
- }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
11094
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
11087
11095
  modelId: string(),
11088
11096
  settings: record(string(), unknown()).readonly()
11089
11097
  }))), method(object({ steps: record(string(), object({
@@ -11143,13 +11151,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
11143
11151
  * (inputClasses ≠ null) are skipped and served per-track via
11144
11152
  * pipelineRunner.runDetailSubtree (two-plane design).
11145
11153
  */
11146
- plane: _enum(["full", "frame"]).optional()
11154
+ plane: _enum(["full", "frame"]).optional(),
11155
+ /**
11156
+ * Inference-device selector (Phase 2 multi-device). Format
11157
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
11158
+ * Omitted ⇒ the runner's default device (current single-engine
11159
+ * behaviour). Selects WHICH device pool of the node runs the call.
11160
+ */
11161
+ deviceKey: string().optional()
11147
11162
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
11148
11163
  engine: PipelineEngineChoiceSchema.optional(),
11149
11164
  steps: array(PipelineStepInputSchema).min(1),
11150
11165
  frames: array(FrameInputSchema).min(1).max(255),
11151
11166
  deviceId: number().optional(),
11152
- sessionId: string().optional()
11167
+ sessionId: string().optional(),
11168
+ /**
11169
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
11170
+ * the batch to the Python pool's bench preprocess cache
11171
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
11172
+ * preprocessed ONCE and every later inference is a pure-inference cache
11173
+ * hit — the sustained-throughput run measures inference, not
11174
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
11175
+ * full preprocess every call, correct). Fresh per sustained run;
11176
+ * released via `uncacheFrame`.
11177
+ */
11178
+ frameId: number().int().nonnegative().optional(),
11179
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
11180
+ deviceKey: string().optional()
11153
11181
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
11154
11182
  data: _instanceof(Uint8Array),
11155
11183
  width: number().int().positive(),
@@ -11181,8 +11209,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
11181
11209
  * - `runtime` — main camera-serving engine (no idle TTL).
11182
11210
  * - `warm-override` — benchmark/test override held in the warm
11183
11211
  * cache; auto-disposed after the idle TTL.
11212
+ * - `device-pool` — a concurrent per-device pool (Phase 2
11213
+ * multi-device, keyed by `deviceKey`) resolved
11214
+ * via `resolveDeviceFactory`. Runs alongside the
11215
+ * `runtime` engine on a DIFFERENT accelerator
11216
+ * (NPU / iGPU / Coral) — this is how the
11217
+ * Engines tab shows all pools running at once.
11184
11218
  */
11185
- kind: _enum(["runtime", "warm-override"]),
11219
+ kind: _enum([
11220
+ "runtime",
11221
+ "warm-override",
11222
+ "device-pool"
11223
+ ]),
11186
11224
  /** Native pid of the underlying Python pool (null when no pool). */
11187
11225
  poolPid: number().nullable(),
11188
11226
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -11284,7 +11322,21 @@ var NativeCropResultSchema = object({
11284
11322
  /** Packed rgb (24-bit) pixels of the crop. */
11285
11323
  bytes: _instanceof(Uint8Array),
11286
11324
  width: number().int().positive(),
11287
- height: number().int().positive()
11325
+ height: number().int().positive(),
11326
+ /**
11327
+ * Which source served this crop, so a quality-sensitive consumer (the native
11328
+ * `keyFrame`) can reject a degraded fallback:
11329
+ * - `native` — cut from the decode worker's retained NATIVE surface (the
11330
+ * quality path).
11331
+ * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
11332
+ * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
11333
+ * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
11334
+ *
11335
+ * OPTIONAL: a pre-tier runner (version skew) omits it — an ABSENT `tier` MUST be
11336
+ * treated as `native` (accepted) by every consumer so mixed-version clusters
11337
+ * keep the pre-tier behaviour. An ROI miss returns `null` (no tier at all).
11338
+ */
11339
+ tier: _enum(["native", "ram-fullframe"]).optional()
11288
11340
  });
11289
11341
  /** Parent detection context passed to `runDetailSubtree` — the crop's
11290
11342
  * originating detection, in FRAME-space coordinates. Reuses
@@ -11524,7 +11576,14 @@ var RunnerCameraConfigSchema = object({
11524
11576
  * camera's detect node differs from its source-owner (P2d, gated by the
11525
11577
  * `remoteSourcingNodes` rollout setting).
11526
11578
  */
11527
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
11579
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
11580
+ /**
11581
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
11582
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
11583
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
11584
+ * this only selects WHICH device pool of that node runs the session.
11585
+ */
11586
+ deviceKey: string().optional()
11528
11587
  });
11529
11588
  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;
11530
11589
  /**
@@ -11545,6 +11604,19 @@ var RunnerLocalLoadSchema = object({
11545
11604
  avgInferenceTimeMs: number(),
11546
11605
  /** Total queue depth across motion + detection queues. */
11547
11606
  queueDepthTotal: number(),
11607
+ /**
11608
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
11609
+ * this runner currently has attached cameras on, so the orchestrator's second
11610
+ * `balance()` pass (over a node's devices) weights on real per-pool session
11611
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
11612
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
11613
+ */
11614
+ devices: array(object({
11615
+ deviceKey: string(),
11616
+ backend: string(),
11617
+ attachedCameras: number(),
11618
+ queueDepthTotal: number()
11619
+ })).default([]),
11548
11620
  /** Hardware capability flags reported by this node. */
11549
11621
  hardware: object({
11550
11622
  hasGpu: boolean(),
@@ -13020,6 +13092,8 @@ method(_void(), _void(), { kind: "mutation" }), method(_void(), _void(), { kind:
13020
13092
  kind: "mutation",
13021
13093
  auth: "admin"
13022
13094
  });
13095
+ 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;
13096
+ new Set(Object.values(DeviceType));
13023
13097
  /**
13024
13098
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
13025
13099
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -14593,7 +14667,8 @@ var LinkedDeviceSchema = object({
14593
14667
  deviceId: number(),
14594
14668
  name: string(),
14595
14669
  location: string().nullable(),
14596
- features: array(string())
14670
+ features: array(string()),
14671
+ producesTrackedEvents: boolean().optional()
14597
14672
  });
14598
14673
  var SavedDeviceRowSchema = object({
14599
14674
  /** Numeric id reserved at allocateDeviceId time. */
@@ -16223,6 +16298,7 @@ var TrackSchema = object({
16223
16298
  deviceId: number(),
16224
16299
  className: string(),
16225
16300
  label: string().optional(),
16301
+ producingDeviceName: string().optional(),
16226
16302
  /** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
16227
16303
  source: TrackSourceSchema.optional(),
16228
16304
  firstSeen: number(),
@@ -16360,7 +16436,8 @@ var MediaFileKindEnum = _enum([
16360
16436
  "fullFrameBoxed",
16361
16437
  "faceCrop",
16362
16438
  "plateCrop",
16363
- "keyFrame"
16439
+ "keyFrame",
16440
+ "keyFrameSmall"
16364
16441
  ]);
16365
16442
  var MediaFileSchema = object({
16366
16443
  key: string(),
@@ -16689,13 +16766,11 @@ var PipelineTemplateSchema = object({
16689
16766
  createdAt: string(),
16690
16767
  updatedAt: string()
16691
16768
  });
16692
- var AgentAddonConfigSchema = object({
16693
- enabled: boolean(),
16769
+ var DeviceStepConfigSchema = object({
16694
16770
  modelId: string().optional(),
16695
- settings: record(string(), unknown()).readonly()
16771
+ settings: record(string(), unknown()).optional()
16696
16772
  });
16697
16773
  var AgentPipelineSettingsSchema = object({
16698
- addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
16699
16774
  maxCameras: number().int().nonnegative().nullable().default(null),
16700
16775
  /** Per-node detection weight (relative share for the quota balancer). */
16701
16776
  detectWeight: number().positive().optional(),
@@ -16719,7 +16794,22 @@ var AgentPipelineSettingsSchema = object({
16719
16794
  * it already uses to reach the hub). Set this only when the auto-detected
16720
16795
  * address is wrong (multi-homed host, NAT, custom interface).
16721
16796
  */
16722
- reachableHost: string().optional()
16797
+ reachableHost: string().optional(),
16798
+ /**
16799
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
16800
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
16801
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
16802
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
16803
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
16804
+ * the default model/settings for every camera landing on that accelerator;
16805
+ * a stepId absent ⇒ the step uses that device's format default.
16806
+ */
16807
+ inferenceDevices: record(string(), object({
16808
+ enabled: boolean(),
16809
+ weight: number().positive().optional(),
16810
+ maxSessions: number().int().positive().optional(),
16811
+ steps: record(string(), DeviceStepConfigSchema).optional()
16812
+ })).optional()
16723
16813
  });
16724
16814
  var CameraPipelineForAgentSchema = object({
16725
16815
  steps: array(PipelineStepInputSchema).readonly(),
@@ -16729,14 +16819,13 @@ var CameraPipelineForAgentSchema = object({
16729
16819
  }).nullable()
16730
16820
  });
16731
16821
  var CameraStepOverridePatchSchema = object({
16732
- enabled: boolean().optional(),
16733
16822
  modelId: string().optional(),
16734
16823
  settings: record(string(), unknown()).readonly().optional()
16735
16824
  });
16736
16825
  var CameraPipelineSettingsSchema = object({
16737
16826
  pinnedAgentNodeId: string().optional(),
16738
16827
  stepToggles: record(string(), boolean()).optional(),
16739
- stepOverridesByAgent: record(string(), record(string(), CameraStepOverridePatchSchema)).optional(),
16828
+ stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
16740
16829
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
16741
16830
  });
16742
16831
  /**
@@ -16950,6 +17039,44 @@ var CameraStatusSchema = object({
16950
17039
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
16951
17040
  fetchedAt: number()
16952
17041
  });
17042
+ var NodeInferenceDeviceSchema = object({
17043
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
17044
+ key: string(),
17045
+ backend: string(),
17046
+ device: string(),
17047
+ format: _enum(MODEL_FORMATS),
17048
+ /** Whether the node's live probe reports the device as usable right now. */
17049
+ available: boolean(),
17050
+ /**
17051
+ * Whether this device participates in dispatch. AUTO default (spec C2):
17052
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
17053
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
17054
+ * not a balanced target). An explicit stored value always wins; a stored-only
17055
+ * (unavailable) key keeps its stored value.
17056
+ */
17057
+ enabled: boolean(),
17058
+ /** Relative balancer weight for the enabled device (default 1). */
17059
+ weight: number(),
17060
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
17061
+ maxSessions: number().nullable(),
17062
+ /** Object-detection model the executor defaults to for this deviceKey. */
17063
+ defaultModelId: string(),
17064
+ /**
17065
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
17066
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
17067
+ * Absent/empty ⇒ no base (every step uses its device format default). The
17068
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
17069
+ * available per format; this is the stored selection that becomes the
17070
+ * default for EVERY camera landing on this accelerator.
17071
+ */
17072
+ steps: record(string(), DeviceStepConfigSchema).optional()
17073
+ });
17074
+ var NodeInferenceDevicesSchema = object({
17075
+ nodeId: string(),
17076
+ /** False when the node's platform-probe was unreachable (no live device set). */
17077
+ reachable: boolean(),
17078
+ devices: array(NodeInferenceDeviceSchema).readonly()
17079
+ });
16953
17080
  method(object({
16954
17081
  deviceId: number(),
16955
17082
  agentNodeId: string()
@@ -16959,7 +17086,13 @@ method(object({
16959
17086
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
16960
17087
  kind: "mutation",
16961
17088
  auth: "admin"
16962
- }), method(_void(), object({ migrated: number() }), {
17089
+ }), method(object({
17090
+ deviceId: number(),
17091
+ deviceKey: string()
17092
+ }), object({ success: literal(true) }), {
17093
+ kind: "mutation",
17094
+ auth: "admin"
17095
+ }), method(object({ deviceId: number() }), object({ deviceKey: string().nullable() })), method(_void(), object({ migrated: number() }), {
16963
17096
  kind: "mutation",
16964
17097
  auth: "admin"
16965
17098
  }), 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({
@@ -16993,13 +17126,7 @@ method(object({
16993
17126
  }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
16994
17127
  nodeId: string(),
16995
17128
  settings: AgentPipelineSettingsSchema
16996
- })).readonly()), method(object({
16997
- agentNodeId: string(),
16998
- defaults: record(string(), AgentAddonConfigSchema)
16999
- }), object({ success: literal(true) }), {
17000
- kind: "mutation",
17001
- auth: "admin"
17002
- }), method(object({ agentNodeId: string() }), object({
17129
+ })).readonly()), method(object({ agentNodeId: string() }), object({
17003
17130
  success: boolean(),
17004
17131
  removed: boolean()
17005
17132
  }), {
@@ -17031,7 +17158,18 @@ method(object({
17031
17158
  }), object({ success: literal(true) }), {
17032
17159
  kind: "mutation",
17033
17160
  auth: "admin"
17034
- }), method(object({ agentNodeId: string() }), object({
17161
+ }), method(object({
17162
+ agentNodeId: string(),
17163
+ inferenceDevices: record(string(), object({
17164
+ enabled: boolean(),
17165
+ weight: number().positive().optional(),
17166
+ maxSessions: number().int().positive().optional(),
17167
+ steps: record(string(), DeviceStepConfigSchema).optional()
17168
+ }))
17169
+ }), object({ success: literal(true) }), {
17170
+ kind: "mutation",
17171
+ auth: "admin"
17172
+ }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string() }), object({
17035
17173
  success: literal(true),
17036
17174
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
17037
17175
  effectiveModelId: string().nullable(),
@@ -17047,9 +17185,10 @@ method(object({
17047
17185
  }), object({ success: literal(true) }), {
17048
17186
  kind: "mutation",
17049
17187
  auth: "admin"
17050
- }), method(object({ deviceId: number() }), record(string(), record(string(), CameraStepOverridePatchSchema)).nullable()), method(object({
17188
+ }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
17051
17189
  deviceId: number(),
17052
17190
  agentNodeId: string(),
17191
+ deviceKey: string(),
17053
17192
  addonId: string(),
17054
17193
  patch: CameraStepOverridePatchSchema.nullable()
17055
17194
  }), object({ success: literal(true) }), {
@@ -17086,14 +17225,13 @@ method(object({
17086
17225
  });
17087
17226
  /**
17088
17227
  * server-management — per-NODE singleton capability for a node's ROOT
17089
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
17090
- * agents).
17228
+ * package lifecycle (runtime-updatable node packages).
17091
17229
  *
17092
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
17093
- * on agents) carries the whole software stack in its npm dep tree, so ONE
17094
- * version describes the node. Updates install into
17095
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
17096
- * starter (probation boot + auto-rollback to N-1).
17230
+ * Every node role runs the SAME root package (`@camstack/server`), which
17231
+ * carries the whole software stack in its npm dep tree, so ONE version
17232
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
17233
+ * on restart via the baked starter (single-copy in-place swap — no probation,
17234
+ * no auto-rollback).
17097
17235
  *
17098
17236
  * Providers:
17099
17237
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -17201,7 +17339,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
17201
17339
  /** Explicit target version; omitted = latest from the registry. */
17202
17340
  version: string().optional() }), ServerUpdateActionResultSchema, {
17203
17341
  kind: "mutation",
17204
- auth: "admin"
17342
+ auth: "admin",
17343
+ timeoutMs: 16 * 6e4
17205
17344
  }), method(_void(), ServerUpdateActionResultSchema, {
17206
17345
  kind: "mutation",
17207
17346
  auth: "admin"
@@ -18268,22 +18407,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
18268
18407
  var RestartAddonResultSchema = unknown();
18269
18408
  var InstallPackageResultSchema = unknown();
18270
18409
  var ReloadPackagesResultSchema = unknown();
18271
- /**
18272
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
18273
- * server restarts so the admin UI can react to the `restartingAt`
18274
- * timestamp (shows reconnect overlay). The transition from
18275
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
18276
- * `system.restart-completed` event after the new process boots.
18277
- *
18278
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
18279
- */
18280
- var UpdateFrameworkPackageResultSchema = object({
18281
- packageName: string(),
18282
- fromVersion: string(),
18283
- toVersion: string(),
18284
- /** Ms-epoch the server scheduled its self-restart. */
18285
- restartingAt: number()
18286
- });
18287
18410
  var BulkUpdateItemStatusSchema = _enum([
18288
18411
  "queued",
18289
18412
  "updating",
@@ -18411,13 +18534,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
18411
18534
  }), object({ success: literal(true) }), {
18412
18535
  kind: "mutation",
18413
18536
  auth: "admin"
18414
- }), method(object({
18415
- packageName: string().min(1),
18416
- version: string().optional(),
18417
- deferRestart: boolean().optional()
18418
- }), UpdateFrameworkPackageResultSchema, {
18419
- kind: "mutation",
18420
- auth: "admin"
18421
18537
  }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
18422
18538
  kind: "mutation",
18423
18539
  auth: "admin"
@@ -19283,10 +19399,10 @@ var TopologyCategorySchema = object({
19283
19399
  addons: array(TopologyCategoryAddonSchema).readonly()
19284
19400
  });
19285
19401
  /**
19286
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
19287
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
19288
- * version visibility for the Server management surface. Nullable: offline
19289
- * rows and pre-phase-2 nodes report none.
19402
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
19403
+ * root package for every node role) as reported by its `registerNode`
19404
+ * manifest — version visibility for the Server management surface. Nullable:
19405
+ * offline rows and nodes that never reported one.
19290
19406
  */
19291
19407
  var TopologyRootPackageSchema = object({
19292
19408
  name: string(),
@@ -19674,17 +19790,28 @@ var PlatformScoreSchema = object({
19674
19790
  format: _enum([
19675
19791
  "onnx",
19676
19792
  "coreml",
19677
- "openvino"
19793
+ "openvino",
19794
+ "tflite"
19678
19795
  ]),
19679
19796
  score: number(),
19680
19797
  reason: string(),
19681
19798
  available: boolean()
19682
19799
  });
19800
+ var InferenceDeviceDescriptorSchema = object({
19801
+ key: string(),
19802
+ backend: string(),
19803
+ device: string(),
19804
+ format: ModelFormatSchema,
19805
+ runtime: literal("python"),
19806
+ score: number(),
19807
+ available: boolean()
19808
+ });
19683
19809
  var PlatformCapabilitiesSchema = object({
19684
19810
  hardware: HardwareInfoSchema,
19685
19811
  scores: array(PlatformScoreSchema).readonly(),
19686
19812
  bestScore: PlatformScoreSchema,
19687
- pythonPath: string().nullable()
19813
+ pythonPath: string().nullable(),
19814
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
19688
19815
  });
19689
19816
  var ModelRequirementSchema = object({
19690
19817
  modelId: string(),
@@ -20563,12 +20690,6 @@ Object.freeze({
20563
20690
  addonId: null,
20564
20691
  access: "delete"
20565
20692
  },
20566
- "addons.updateFrameworkPackage": {
20567
- capName: "addons",
20568
- capScope: "system",
20569
- addonId: null,
20570
- access: "create"
20571
- },
20572
20693
  "addons.updatePackage": {
20573
20694
  capName: "addons",
20574
20695
  capScope: "system",
@@ -23341,12 +23462,6 @@ Object.freeze({
23341
23462
  addonId: null,
23342
23463
  access: "view"
23343
23464
  },
23344
- "pipelineExecutor.reprobeEngine": {
23345
- capName: "pipeline-executor",
23346
- capScope: "system",
23347
- addonId: null,
23348
- access: "create"
23349
- },
23350
23465
  "pipelineExecutor.runAudioTest": {
23351
23466
  capName: "pipeline-executor",
23352
23467
  capScope: "system",
@@ -23497,6 +23612,12 @@ Object.freeze({
23497
23612
  addonId: null,
23498
23613
  access: "view"
23499
23614
  },
23615
+ "pipelineOrchestrator.getNodeInferenceDevices": {
23616
+ capName: "pipeline-orchestrator",
23617
+ capScope: "system",
23618
+ addonId: null,
23619
+ access: "view"
23620
+ },
23500
23621
  "pipelineOrchestrator.getPipelineAssignment": {
23501
23622
  capName: "pipeline-orchestrator",
23502
23623
  capScope: "system",
@@ -23509,6 +23630,12 @@ Object.freeze({
23509
23630
  addonId: null,
23510
23631
  access: "view"
23511
23632
  },
23633
+ "pipelineOrchestrator.getPipelineDevicePin": {
23634
+ capName: "pipeline-orchestrator",
23635
+ capScope: "system",
23636
+ addonId: null,
23637
+ access: "view"
23638
+ },
23512
23639
  "pipelineOrchestrator.listAgentSettings": {
23513
23640
  capName: "pipeline-orchestrator",
23514
23641
  capScope: "system",
@@ -23551,19 +23678,19 @@ Object.freeze({
23551
23678
  addonId: null,
23552
23679
  access: "create"
23553
23680
  },
23554
- "pipelineOrchestrator.setAgentAddonDefaults": {
23681
+ "pipelineOrchestrator.setAgentCapabilities": {
23555
23682
  capName: "pipeline-orchestrator",
23556
23683
  capScope: "system",
23557
23684
  addonId: null,
23558
23685
  access: "create"
23559
23686
  },
23560
- "pipelineOrchestrator.setAgentCapabilities": {
23687
+ "pipelineOrchestrator.setAgentDetectWeight": {
23561
23688
  capName: "pipeline-orchestrator",
23562
23689
  capScope: "system",
23563
23690
  addonId: null,
23564
23691
  access: "create"
23565
23692
  },
23566
- "pipelineOrchestrator.setAgentDetectWeight": {
23693
+ "pipelineOrchestrator.setAgentInferenceDevices": {
23567
23694
  capName: "pipeline-orchestrator",
23568
23695
  capScope: "system",
23569
23696
  addonId: null,
@@ -23605,6 +23732,12 @@ Object.freeze({
23605
23732
  addonId: null,
23606
23733
  access: "create"
23607
23734
  },
23735
+ "pipelineOrchestrator.setPipelineDevicePin": {
23736
+ capName: "pipeline-orchestrator",
23737
+ capScope: "system",
23738
+ addonId: null,
23739
+ access: "create"
23740
+ },
23608
23741
  "pipelineOrchestrator.unassignAudio": {
23609
23742
  capName: "pipeline-orchestrator",
23610
23743
  capScope: "system",
@@ -25157,32 +25290,6 @@ Object.freeze({
25157
25290
  "network-access": "ingress",
25158
25291
  "smtp-provider": "email"
25159
25292
  });
25160
- var frameworkSwapPackageSchema = object({
25161
- name: string(),
25162
- stagedPath: string(),
25163
- backupPath: string(),
25164
- toVersion: string(),
25165
- fromVersion: string().nullable()
25166
- });
25167
- object({
25168
- jobId: string(),
25169
- taskId: string(),
25170
- packages: array(frameworkSwapPackageSchema),
25171
- requestedAtMs: number(),
25172
- schemaVersion: literal(1)
25173
- });
25174
- object({
25175
- jobId: string(),
25176
- taskId: string(),
25177
- backups: array(object({
25178
- name: string(),
25179
- backupPath: string(),
25180
- livePath: string()
25181
- })),
25182
- appliedAtMs: number(),
25183
- bootAttempts: number(),
25184
- schemaVersion: literal(1)
25185
- });
25186
25293
  //#endregion
25187
25294
  //#region src/static-turn.addon.ts
25188
25295
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-static-turn",
3
- "version": "1.1.28",
3
+ "version": "1.2.1",
4
4
  "description": "Static / self-hosted (coturn) TURN provider for CamStack",
5
5
  "keywords": [
6
6
  "camstack",