@camstack/addon-matter-broker 0.1.25 → 0.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.
Files changed (3) hide show
  1. package/dist/addon.js +213 -106
  2. package/dist/addon.mjs +213 -106
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -7112,6 +7112,17 @@ var ModelCatalogEntrySchema = object({
7112
7112
  "imagenet",
7113
7113
  "none"
7114
7114
  ]).optional(),
7115
+ /**
7116
+ * The model already applies softmax IN-GRAPH — its raw output is a
7117
+ * probability distribution, not logits. When set, the `softmax`
7118
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7119
+ * probability vector collapses it toward uniform (top-1 score craters far
7120
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7121
+ * the output is raw logits and the postprocessor applies softmax (the normal
7122
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7123
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7124
+ */
7125
+ outputProbabilities: boolean().optional(),
7115
7126
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7116
7127
  /**
7117
7128
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -12402,10 +12413,7 @@ var ConfigUISchemaNullableBridge = custom();
12402
12413
  var InferenceCapabilitiesBridge = custom();
12403
12414
  var ModelAvailabilityListBridge = custom();
12404
12415
  var PipelineRunResultBridge = custom();
12405
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
12406
- kind: "mutation",
12407
- auth: "admin"
12408
- }), method(object({ nodeId: string$2() }), EngineProvisioningSchema), method(_void(), record(string$2(), object({
12416
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string$2() }), EngineProvisioningSchema), method(_void(), record(string$2(), object({
12409
12417
  modelId: string$2(),
12410
12418
  settings: record(string$2(), unknown()).readonly()
12411
12419
  }))), method(object({ steps: record(string$2(), object({
@@ -12465,13 +12473,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12465
12473
  * (inputClasses ≠ null) are skipped and served per-track via
12466
12474
  * pipelineRunner.runDetailSubtree (two-plane design).
12467
12475
  */
12468
- plane: _enum(["full", "frame"]).optional()
12476
+ plane: _enum(["full", "frame"]).optional(),
12477
+ /**
12478
+ * Inference-device selector (Phase 2 multi-device). Format
12479
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
12480
+ * Omitted ⇒ the runner's default device (current single-engine
12481
+ * behaviour). Selects WHICH device pool of the node runs the call.
12482
+ */
12483
+ deviceKey: string$2().optional()
12469
12484
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
12470
12485
  engine: PipelineEngineChoiceSchema.optional(),
12471
12486
  steps: array(PipelineStepInputSchema).min(1),
12472
12487
  frames: array(FrameInputSchema).min(1).max(255),
12473
12488
  deviceId: number().optional(),
12474
- sessionId: string$2().optional()
12489
+ sessionId: string$2().optional(),
12490
+ /**
12491
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
12492
+ * the batch to the Python pool's bench preprocess cache
12493
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
12494
+ * preprocessed ONCE and every later inference is a pure-inference cache
12495
+ * hit — the sustained-throughput run measures inference, not
12496
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
12497
+ * full preprocess every call, correct). Fresh per sustained run;
12498
+ * released via `uncacheFrame`.
12499
+ */
12500
+ frameId: number().int().nonnegative().optional(),
12501
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
12502
+ deviceKey: string$2().optional()
12475
12503
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
12476
12504
  data: _instanceof(Uint8Array),
12477
12505
  width: number().int().positive(),
@@ -12503,8 +12531,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12503
12531
  * - `runtime` — main camera-serving engine (no idle TTL).
12504
12532
  * - `warm-override` — benchmark/test override held in the warm
12505
12533
  * cache; auto-disposed after the idle TTL.
12534
+ * - `device-pool` — a concurrent per-device pool (Phase 2
12535
+ * multi-device, keyed by `deviceKey`) resolved
12536
+ * via `resolveDeviceFactory`. Runs alongside the
12537
+ * `runtime` engine on a DIFFERENT accelerator
12538
+ * (NPU / iGPU / Coral) — this is how the
12539
+ * Engines tab shows all pools running at once.
12506
12540
  */
12507
- kind: _enum(["runtime", "warm-override"]),
12541
+ kind: _enum([
12542
+ "runtime",
12543
+ "warm-override",
12544
+ "device-pool"
12545
+ ]),
12508
12546
  /** Native pid of the underlying Python pool (null when no pool). */
12509
12547
  poolPid: number().nullable(),
12510
12548
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -12639,7 +12677,21 @@ var NativeCropResultSchema = object({
12639
12677
  /** Packed rgb (24-bit) pixels of the crop. */
12640
12678
  bytes: _instanceof(Uint8Array),
12641
12679
  width: number().int().positive(),
12642
- height: number().int().positive()
12680
+ height: number().int().positive(),
12681
+ /**
12682
+ * Which source served this crop, so a quality-sensitive consumer (the native
12683
+ * `keyFrame`) can reject a degraded fallback:
12684
+ * - `native` — cut from the decode worker's retained NATIVE surface (the
12685
+ * quality path).
12686
+ * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
12687
+ * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
12688
+ * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
12689
+ *
12690
+ * OPTIONAL: a pre-tier runner (version skew) omits it — an ABSENT `tier` MUST be
12691
+ * treated as `native` (accepted) by every consumer so mixed-version clusters
12692
+ * keep the pre-tier behaviour. An ROI miss returns `null` (no tier at all).
12693
+ */
12694
+ tier: _enum(["native", "ram-fullframe"]).optional()
12643
12695
  });
12644
12696
  /** Parent detection context passed to `runDetailSubtree` — the crop's
12645
12697
  * originating detection, in FRAME-space coordinates. Reuses
@@ -12879,7 +12931,14 @@ var RunnerCameraConfigSchema = object({
12879
12931
  * camera's detect node differs from its source-owner (P2d, gated by the
12880
12932
  * `remoteSourcingNodes` rollout setting).
12881
12933
  */
12882
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
12934
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
12935
+ /**
12936
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
12937
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
12938
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
12939
+ * this only selects WHICH device pool of that node runs the session.
12940
+ */
12941
+ deviceKey: string$2().optional()
12883
12942
  });
12884
12943
  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;
12885
12944
  /**
@@ -12900,6 +12959,19 @@ var RunnerLocalLoadSchema = object({
12900
12959
  avgInferenceTimeMs: number(),
12901
12960
  /** Total queue depth across motion + detection queues. */
12902
12961
  queueDepthTotal: number(),
12962
+ /**
12963
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
12964
+ * this runner currently has attached cameras on, so the orchestrator's second
12965
+ * `balance()` pass (over a node's devices) weights on real per-pool session
12966
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
12967
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
12968
+ */
12969
+ devices: array(object({
12970
+ deviceKey: string$2(),
12971
+ backend: string$2(),
12972
+ attachedCameras: number(),
12973
+ queueDepthTotal: number()
12974
+ })).default([]),
12903
12975
  /** Hardware capability flags reported by this node. */
12904
12976
  hardware: object({
12905
12977
  hasGpu: boolean(),
@@ -16048,6 +16120,8 @@ var BaseDeviceProvider = class extends BaseAddon {
16048
16120
  return toDeviceSummary(device, this.addonId);
16049
16121
  }
16050
16122
  };
16123
+ 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;
16124
+ new Set(Object.values(DeviceType));
16051
16125
  /**
16052
16126
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
16053
16127
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -17687,7 +17761,8 @@ var LinkedDeviceSchema = object({
17687
17761
  deviceId: number(),
17688
17762
  name: string$2(),
17689
17763
  location: string$2().nullable(),
17690
- features: array(string$2())
17764
+ features: array(string$2()),
17765
+ producesTrackedEvents: boolean().optional()
17691
17766
  });
17692
17767
  var SavedDeviceRowSchema = object({
17693
17768
  /** Numeric id reserved at allocateDeviceId time. */
@@ -19317,6 +19392,7 @@ var TrackSchema = object({
19317
19392
  deviceId: number(),
19318
19393
  className: string$2(),
19319
19394
  label: string$2().optional(),
19395
+ producingDeviceName: string$2().optional(),
19320
19396
  /** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
19321
19397
  source: TrackSourceSchema.optional(),
19322
19398
  firstSeen: number(),
@@ -19454,7 +19530,8 @@ var MediaFileKindEnum = _enum([
19454
19530
  "fullFrameBoxed",
19455
19531
  "faceCrop",
19456
19532
  "plateCrop",
19457
- "keyFrame"
19533
+ "keyFrame",
19534
+ "keyFrameSmall"
19458
19535
  ]);
19459
19536
  var MediaFileSchema = object({
19460
19537
  key: string$2(),
@@ -19783,13 +19860,11 @@ var PipelineTemplateSchema = object({
19783
19860
  createdAt: string$2(),
19784
19861
  updatedAt: string$2()
19785
19862
  });
19786
- var AgentAddonConfigSchema = object({
19787
- enabled: boolean(),
19863
+ var DeviceStepConfigSchema = object({
19788
19864
  modelId: string$2().optional(),
19789
- settings: record(string$2(), unknown()).readonly()
19865
+ settings: record(string$2(), unknown()).optional()
19790
19866
  });
19791
19867
  var AgentPipelineSettingsSchema = object({
19792
- addonDefaults: record(string$2(), AgentAddonConfigSchema).readonly(),
19793
19868
  maxCameras: number().int().nonnegative().nullable().default(null),
19794
19869
  /** Per-node detection weight (relative share for the quota balancer). */
19795
19870
  detectWeight: number().positive().optional(),
@@ -19813,7 +19888,22 @@ var AgentPipelineSettingsSchema = object({
19813
19888
  * it already uses to reach the hub). Set this only when the auto-detected
19814
19889
  * address is wrong (multi-homed host, NAT, custom interface).
19815
19890
  */
19816
- reachableHost: string$2().optional()
19891
+ reachableHost: string$2().optional(),
19892
+ /**
19893
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
19894
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
19895
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
19896
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
19897
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
19898
+ * the default model/settings for every camera landing on that accelerator;
19899
+ * a stepId absent ⇒ the step uses that device's format default.
19900
+ */
19901
+ inferenceDevices: record(string$2(), object({
19902
+ enabled: boolean(),
19903
+ weight: number().positive().optional(),
19904
+ maxSessions: number().int().positive().optional(),
19905
+ steps: record(string$2(), DeviceStepConfigSchema).optional()
19906
+ })).optional()
19817
19907
  });
19818
19908
  var CameraPipelineForAgentSchema = object({
19819
19909
  steps: array(PipelineStepInputSchema).readonly(),
@@ -19823,14 +19913,13 @@ var CameraPipelineForAgentSchema = object({
19823
19913
  }).nullable()
19824
19914
  });
19825
19915
  var CameraStepOverridePatchSchema = object({
19826
- enabled: boolean().optional(),
19827
19916
  modelId: string$2().optional(),
19828
19917
  settings: record(string$2(), unknown()).readonly().optional()
19829
19918
  });
19830
19919
  var CameraPipelineSettingsSchema = object({
19831
19920
  pinnedAgentNodeId: string$2().optional(),
19832
19921
  stepToggles: record(string$2(), boolean()).optional(),
19833
- stepOverridesByAgent: record(string$2(), record(string$2(), CameraStepOverridePatchSchema)).optional(),
19922
+ stepOverridesByDevice: record(string$2(), record(string$2(), record(string$2(), CameraStepOverridePatchSchema))).optional(),
19834
19923
  pipelineByAgent: record(string$2(), CameraPipelineForAgentSchema).optional()
19835
19924
  });
19836
19925
  /**
@@ -20044,6 +20133,44 @@ var CameraStatusSchema = object({
20044
20133
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
20045
20134
  fetchedAt: number()
20046
20135
  });
20136
+ var NodeInferenceDeviceSchema = object({
20137
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
20138
+ key: string$2(),
20139
+ backend: string$2(),
20140
+ device: string$2(),
20141
+ format: _enum(MODEL_FORMATS),
20142
+ /** Whether the node's live probe reports the device as usable right now. */
20143
+ available: boolean(),
20144
+ /**
20145
+ * Whether this device participates in dispatch. AUTO default (spec C2):
20146
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
20147
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
20148
+ * not a balanced target). An explicit stored value always wins; a stored-only
20149
+ * (unavailable) key keeps its stored value.
20150
+ */
20151
+ enabled: boolean(),
20152
+ /** Relative balancer weight for the enabled device (default 1). */
20153
+ weight: number(),
20154
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
20155
+ maxSessions: number().nullable(),
20156
+ /** Object-detection model the executor defaults to for this deviceKey. */
20157
+ defaultModelId: string$2(),
20158
+ /**
20159
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
20160
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
20161
+ * Absent/empty ⇒ no base (every step uses its device format default). The
20162
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
20163
+ * available per format; this is the stored selection that becomes the
20164
+ * default for EVERY camera landing on this accelerator.
20165
+ */
20166
+ steps: record(string$2(), DeviceStepConfigSchema).optional()
20167
+ });
20168
+ var NodeInferenceDevicesSchema = object({
20169
+ nodeId: string$2(),
20170
+ /** False when the node's platform-probe was unreachable (no live device set). */
20171
+ reachable: boolean(),
20172
+ devices: array(NodeInferenceDeviceSchema).readonly()
20173
+ });
20047
20174
  method(object({
20048
20175
  deviceId: number(),
20049
20176
  agentNodeId: string$2()
@@ -20053,7 +20180,13 @@ method(object({
20053
20180
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
20054
20181
  kind: "mutation",
20055
20182
  auth: "admin"
20056
- }), method(_void(), object({ migrated: number() }), {
20183
+ }), method(object({
20184
+ deviceId: number(),
20185
+ deviceKey: string$2()
20186
+ }), object({ success: literal(true) }), {
20187
+ kind: "mutation",
20188
+ auth: "admin"
20189
+ }), method(object({ deviceId: number() }), object({ deviceKey: string$2().nullable() })), method(_void(), object({ migrated: number() }), {
20057
20190
  kind: "mutation",
20058
20191
  auth: "admin"
20059
20192
  }), 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$2() }), CapabilityBindingsSchema), method(object({
@@ -20087,13 +20220,7 @@ method(object({
20087
20220
  }))), method(object({ agentNodeId: string$2() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
20088
20221
  nodeId: string$2(),
20089
20222
  settings: AgentPipelineSettingsSchema
20090
- })).readonly()), method(object({
20091
- agentNodeId: string$2(),
20092
- defaults: record(string$2(), AgentAddonConfigSchema)
20093
- }), object({ success: literal(true) }), {
20094
- kind: "mutation",
20095
- auth: "admin"
20096
- }), method(object({ agentNodeId: string$2() }), object({
20223
+ })).readonly()), method(object({ agentNodeId: string$2() }), object({
20097
20224
  success: boolean(),
20098
20225
  removed: boolean()
20099
20226
  }), {
@@ -20125,7 +20252,18 @@ method(object({
20125
20252
  }), object({ success: literal(true) }), {
20126
20253
  kind: "mutation",
20127
20254
  auth: "admin"
20128
- }), method(object({ agentNodeId: string$2() }), object({
20255
+ }), method(object({
20256
+ agentNodeId: string$2(),
20257
+ inferenceDevices: record(string$2(), object({
20258
+ enabled: boolean(),
20259
+ weight: number().positive().optional(),
20260
+ maxSessions: number().int().positive().optional(),
20261
+ steps: record(string$2(), DeviceStepConfigSchema).optional()
20262
+ }))
20263
+ }), object({ success: literal(true) }), {
20264
+ kind: "mutation",
20265
+ auth: "admin"
20266
+ }), method(object({ nodeId: string$2() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string$2() }), object({
20129
20267
  success: literal(true),
20130
20268
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
20131
20269
  effectiveModelId: string$2().nullable(),
@@ -20141,9 +20279,10 @@ method(object({
20141
20279
  }), object({ success: literal(true) }), {
20142
20280
  kind: "mutation",
20143
20281
  auth: "admin"
20144
- }), method(object({ deviceId: number() }), record(string$2(), record(string$2(), CameraStepOverridePatchSchema)).nullable()), method(object({
20282
+ }), method(object({ deviceId: number() }), record(string$2(), record(string$2(), record(string$2(), CameraStepOverridePatchSchema))).nullable()), method(object({
20145
20283
  deviceId: number(),
20146
20284
  agentNodeId: string$2(),
20285
+ deviceKey: string$2(),
20147
20286
  addonId: string$2(),
20148
20287
  patch: CameraStepOverridePatchSchema.nullable()
20149
20288
  }), object({ success: literal(true) }), {
@@ -20180,14 +20319,13 @@ method(object({
20180
20319
  });
20181
20320
  /**
20182
20321
  * server-management — per-NODE singleton capability for a node's ROOT
20183
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
20184
- * agents).
20322
+ * package lifecycle (runtime-updatable node packages).
20185
20323
  *
20186
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
20187
- * on agents) carries the whole software stack in its npm dep tree, so ONE
20188
- * version describes the node. Updates install into
20189
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
20190
- * starter (probation boot + auto-rollback to N-1).
20324
+ * Every node role runs the SAME root package (`@camstack/server`), which
20325
+ * carries the whole software stack in its npm dep tree, so ONE version
20326
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
20327
+ * on restart via the baked starter (single-copy in-place swap — no probation,
20328
+ * no auto-rollback).
20191
20329
  *
20192
20330
  * Providers:
20193
20331
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -20295,7 +20433,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
20295
20433
  /** Explicit target version; omitted = latest from the registry. */
20296
20434
  version: string$2().optional() }), ServerUpdateActionResultSchema, {
20297
20435
  kind: "mutation",
20298
- auth: "admin"
20436
+ auth: "admin",
20437
+ timeoutMs: 16 * 6e4
20299
20438
  }), method(_void(), ServerUpdateActionResultSchema, {
20300
20439
  kind: "mutation",
20301
20440
  auth: "admin"
@@ -21339,22 +21478,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
21339
21478
  var RestartAddonResultSchema = unknown();
21340
21479
  var InstallPackageResultSchema = unknown();
21341
21480
  var ReloadPackagesResultSchema = unknown();
21342
- /**
21343
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
21344
- * server restarts so the admin UI can react to the `restartingAt`
21345
- * timestamp (shows reconnect overlay). The transition from
21346
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
21347
- * `system.restart-completed` event after the new process boots.
21348
- *
21349
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
21350
- */
21351
- var UpdateFrameworkPackageResultSchema = object({
21352
- packageName: string$2(),
21353
- fromVersion: string$2(),
21354
- toVersion: string$2(),
21355
- /** Ms-epoch the server scheduled its self-restart. */
21356
- restartingAt: number()
21357
- });
21358
21481
  var BulkUpdateItemStatusSchema = _enum([
21359
21482
  "queued",
21360
21483
  "updating",
@@ -21482,13 +21605,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
21482
21605
  }), object({ success: literal(true) }), {
21483
21606
  kind: "mutation",
21484
21607
  auth: "admin"
21485
- }), method(object({
21486
- packageName: string$2().min(1),
21487
- version: string$2().optional(),
21488
- deferRestart: boolean().optional()
21489
- }), UpdateFrameworkPackageResultSchema, {
21490
- kind: "mutation",
21491
- auth: "admin"
21492
21608
  }), method(object({ name: string$2() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string$2() }), RestartAddonResultSchema, {
21493
21609
  kind: "mutation",
21494
21610
  auth: "admin"
@@ -22371,10 +22487,10 @@ var TopologyCategorySchema = object({
22371
22487
  addons: array(TopologyCategoryAddonSchema).readonly()
22372
22488
  });
22373
22489
  /**
22374
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
22375
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
22376
- * version visibility for the Server management surface. Nullable: offline
22377
- * rows and pre-phase-2 nodes report none.
22490
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
22491
+ * root package for every node role) as reported by its `registerNode`
22492
+ * manifest — version visibility for the Server management surface. Nullable:
22493
+ * offline rows and nodes that never reported one.
22378
22494
  */
22379
22495
  var TopologyRootPackageSchema = object({
22380
22496
  name: string$2(),
@@ -22762,17 +22878,28 @@ var PlatformScoreSchema = object({
22762
22878
  format: _enum([
22763
22879
  "onnx",
22764
22880
  "coreml",
22765
- "openvino"
22881
+ "openvino",
22882
+ "tflite"
22766
22883
  ]),
22767
22884
  score: number(),
22768
22885
  reason: string$2(),
22769
22886
  available: boolean()
22770
22887
  });
22888
+ var InferenceDeviceDescriptorSchema = object({
22889
+ key: string$2(),
22890
+ backend: string$2(),
22891
+ device: string$2(),
22892
+ format: ModelFormatSchema,
22893
+ runtime: literal("python"),
22894
+ score: number(),
22895
+ available: boolean()
22896
+ });
22771
22897
  var PlatformCapabilitiesSchema = object({
22772
22898
  hardware: HardwareInfoSchema,
22773
22899
  scores: array(PlatformScoreSchema).readonly(),
22774
22900
  bestScore: PlatformScoreSchema,
22775
- pythonPath: string$2().nullable()
22901
+ pythonPath: string$2().nullable(),
22902
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
22776
22903
  });
22777
22904
  var ModelRequirementSchema = object({
22778
22905
  modelId: string$2(),
@@ -23651,12 +23778,6 @@ Object.freeze({
23651
23778
  addonId: null,
23652
23779
  access: "delete"
23653
23780
  },
23654
- "addons.updateFrameworkPackage": {
23655
- capName: "addons",
23656
- capScope: "system",
23657
- addonId: null,
23658
- access: "create"
23659
- },
23660
23781
  "addons.updatePackage": {
23661
23782
  capName: "addons",
23662
23783
  capScope: "system",
@@ -26429,12 +26550,6 @@ Object.freeze({
26429
26550
  addonId: null,
26430
26551
  access: "view"
26431
26552
  },
26432
- "pipelineExecutor.reprobeEngine": {
26433
- capName: "pipeline-executor",
26434
- capScope: "system",
26435
- addonId: null,
26436
- access: "create"
26437
- },
26438
26553
  "pipelineExecutor.runAudioTest": {
26439
26554
  capName: "pipeline-executor",
26440
26555
  capScope: "system",
@@ -26585,6 +26700,12 @@ Object.freeze({
26585
26700
  addonId: null,
26586
26701
  access: "view"
26587
26702
  },
26703
+ "pipelineOrchestrator.getNodeInferenceDevices": {
26704
+ capName: "pipeline-orchestrator",
26705
+ capScope: "system",
26706
+ addonId: null,
26707
+ access: "view"
26708
+ },
26588
26709
  "pipelineOrchestrator.getPipelineAssignment": {
26589
26710
  capName: "pipeline-orchestrator",
26590
26711
  capScope: "system",
@@ -26597,6 +26718,12 @@ Object.freeze({
26597
26718
  addonId: null,
26598
26719
  access: "view"
26599
26720
  },
26721
+ "pipelineOrchestrator.getPipelineDevicePin": {
26722
+ capName: "pipeline-orchestrator",
26723
+ capScope: "system",
26724
+ addonId: null,
26725
+ access: "view"
26726
+ },
26600
26727
  "pipelineOrchestrator.listAgentSettings": {
26601
26728
  capName: "pipeline-orchestrator",
26602
26729
  capScope: "system",
@@ -26639,19 +26766,19 @@ Object.freeze({
26639
26766
  addonId: null,
26640
26767
  access: "create"
26641
26768
  },
26642
- "pipelineOrchestrator.setAgentAddonDefaults": {
26769
+ "pipelineOrchestrator.setAgentCapabilities": {
26643
26770
  capName: "pipeline-orchestrator",
26644
26771
  capScope: "system",
26645
26772
  addonId: null,
26646
26773
  access: "create"
26647
26774
  },
26648
- "pipelineOrchestrator.setAgentCapabilities": {
26775
+ "pipelineOrchestrator.setAgentDetectWeight": {
26649
26776
  capName: "pipeline-orchestrator",
26650
26777
  capScope: "system",
26651
26778
  addonId: null,
26652
26779
  access: "create"
26653
26780
  },
26654
- "pipelineOrchestrator.setAgentDetectWeight": {
26781
+ "pipelineOrchestrator.setAgentInferenceDevices": {
26655
26782
  capName: "pipeline-orchestrator",
26656
26783
  capScope: "system",
26657
26784
  addonId: null,
@@ -26693,6 +26820,12 @@ Object.freeze({
26693
26820
  addonId: null,
26694
26821
  access: "create"
26695
26822
  },
26823
+ "pipelineOrchestrator.setPipelineDevicePin": {
26824
+ capName: "pipeline-orchestrator",
26825
+ capScope: "system",
26826
+ addonId: null,
26827
+ access: "create"
26828
+ },
26696
26829
  "pipelineOrchestrator.unassignAudio": {
26697
26830
  capName: "pipeline-orchestrator",
26698
26831
  capScope: "system",
@@ -28245,32 +28378,6 @@ Object.freeze({
28245
28378
  "network-access": "ingress",
28246
28379
  "smtp-provider": "email"
28247
28380
  });
28248
- var frameworkSwapPackageSchema = object({
28249
- name: string$2(),
28250
- stagedPath: string$2(),
28251
- backupPath: string$2(),
28252
- toVersion: string$2(),
28253
- fromVersion: string$2().nullable()
28254
- });
28255
- object({
28256
- jobId: string$2(),
28257
- taskId: string$2(),
28258
- packages: array(frameworkSwapPackageSchema),
28259
- requestedAtMs: number(),
28260
- schemaVersion: literal(1)
28261
- });
28262
- object({
28263
- jobId: string$2(),
28264
- taskId: string$2(),
28265
- backups: array(object({
28266
- name: string$2(),
28267
- backupPath: string$2(),
28268
- livePath: string$2()
28269
- })),
28270
- appliedAtMs: number(),
28271
- bootAttempts: number(),
28272
- schemaVersion: literal(1)
28273
- });
28274
28381
  //#endregion
28275
28382
  //#region ../../node_modules/@matter/general/dist/esm/net/tcp/TcpConnection.js
28276
28383
  /**
package/dist/addon.mjs CHANGED
@@ -7110,6 +7110,17 @@ var ModelCatalogEntrySchema = object({
7110
7110
  "imagenet",
7111
7111
  "none"
7112
7112
  ]).optional(),
7113
+ /**
7114
+ * The model already applies softmax IN-GRAPH — its raw output is a
7115
+ * probability distribution, not logits. When set, the `softmax`
7116
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7117
+ * probability vector collapses it toward uniform (top-1 score craters far
7118
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7119
+ * the output is raw logits and the postprocessor applies softmax (the normal
7120
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7121
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7122
+ */
7123
+ outputProbabilities: boolean().optional(),
7113
7124
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7114
7125
  /**
7115
7126
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -12400,10 +12411,7 @@ var ConfigUISchemaNullableBridge = custom();
12400
12411
  var InferenceCapabilitiesBridge = custom();
12401
12412
  var ModelAvailabilityListBridge = custom();
12402
12413
  var PipelineRunResultBridge = custom();
12403
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
12404
- kind: "mutation",
12405
- auth: "admin"
12406
- }), method(object({ nodeId: string$2() }), EngineProvisioningSchema), method(_void(), record(string$2(), object({
12414
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string$2() }), EngineProvisioningSchema), method(_void(), record(string$2(), object({
12407
12415
  modelId: string$2(),
12408
12416
  settings: record(string$2(), unknown()).readonly()
12409
12417
  }))), method(object({ steps: record(string$2(), object({
@@ -12463,13 +12471,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12463
12471
  * (inputClasses ≠ null) are skipped and served per-track via
12464
12472
  * pipelineRunner.runDetailSubtree (two-plane design).
12465
12473
  */
12466
- plane: _enum(["full", "frame"]).optional()
12474
+ plane: _enum(["full", "frame"]).optional(),
12475
+ /**
12476
+ * Inference-device selector (Phase 2 multi-device). Format
12477
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
12478
+ * Omitted ⇒ the runner's default device (current single-engine
12479
+ * behaviour). Selects WHICH device pool of the node runs the call.
12480
+ */
12481
+ deviceKey: string$2().optional()
12467
12482
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
12468
12483
  engine: PipelineEngineChoiceSchema.optional(),
12469
12484
  steps: array(PipelineStepInputSchema).min(1),
12470
12485
  frames: array(FrameInputSchema).min(1).max(255),
12471
12486
  deviceId: number().optional(),
12472
- sessionId: string$2().optional()
12487
+ sessionId: string$2().optional(),
12488
+ /**
12489
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
12490
+ * the batch to the Python pool's bench preprocess cache
12491
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
12492
+ * preprocessed ONCE and every later inference is a pure-inference cache
12493
+ * hit — the sustained-throughput run measures inference, not
12494
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
12495
+ * full preprocess every call, correct). Fresh per sustained run;
12496
+ * released via `uncacheFrame`.
12497
+ */
12498
+ frameId: number().int().nonnegative().optional(),
12499
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
12500
+ deviceKey: string$2().optional()
12473
12501
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
12474
12502
  data: _instanceof(Uint8Array),
12475
12503
  width: number().int().positive(),
@@ -12501,8 +12529,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12501
12529
  * - `runtime` — main camera-serving engine (no idle TTL).
12502
12530
  * - `warm-override` — benchmark/test override held in the warm
12503
12531
  * cache; auto-disposed after the idle TTL.
12532
+ * - `device-pool` — a concurrent per-device pool (Phase 2
12533
+ * multi-device, keyed by `deviceKey`) resolved
12534
+ * via `resolveDeviceFactory`. Runs alongside the
12535
+ * `runtime` engine on a DIFFERENT accelerator
12536
+ * (NPU / iGPU / Coral) — this is how the
12537
+ * Engines tab shows all pools running at once.
12504
12538
  */
12505
- kind: _enum(["runtime", "warm-override"]),
12539
+ kind: _enum([
12540
+ "runtime",
12541
+ "warm-override",
12542
+ "device-pool"
12543
+ ]),
12506
12544
  /** Native pid of the underlying Python pool (null when no pool). */
12507
12545
  poolPid: number().nullable(),
12508
12546
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -12637,7 +12675,21 @@ var NativeCropResultSchema = object({
12637
12675
  /** Packed rgb (24-bit) pixels of the crop. */
12638
12676
  bytes: _instanceof(Uint8Array),
12639
12677
  width: number().int().positive(),
12640
- height: number().int().positive()
12678
+ height: number().int().positive(),
12679
+ /**
12680
+ * Which source served this crop, so a quality-sensitive consumer (the native
12681
+ * `keyFrame`) can reject a degraded fallback:
12682
+ * - `native` — cut from the decode worker's retained NATIVE surface (the
12683
+ * quality path).
12684
+ * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
12685
+ * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
12686
+ * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
12687
+ *
12688
+ * OPTIONAL: a pre-tier runner (version skew) omits it — an ABSENT `tier` MUST be
12689
+ * treated as `native` (accepted) by every consumer so mixed-version clusters
12690
+ * keep the pre-tier behaviour. An ROI miss returns `null` (no tier at all).
12691
+ */
12692
+ tier: _enum(["native", "ram-fullframe"]).optional()
12641
12693
  });
12642
12694
  /** Parent detection context passed to `runDetailSubtree` — the crop's
12643
12695
  * originating detection, in FRAME-space coordinates. Reuses
@@ -12877,7 +12929,14 @@ var RunnerCameraConfigSchema = object({
12877
12929
  * camera's detect node differs from its source-owner (P2d, gated by the
12878
12930
  * `remoteSourcingNodes` rollout setting).
12879
12931
  */
12880
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
12932
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
12933
+ /**
12934
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
12935
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
12936
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
12937
+ * this only selects WHICH device pool of that node runs the session.
12938
+ */
12939
+ deviceKey: string$2().optional()
12881
12940
  });
12882
12941
  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;
12883
12942
  /**
@@ -12898,6 +12957,19 @@ var RunnerLocalLoadSchema = object({
12898
12957
  avgInferenceTimeMs: number(),
12899
12958
  /** Total queue depth across motion + detection queues. */
12900
12959
  queueDepthTotal: number(),
12960
+ /**
12961
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
12962
+ * this runner currently has attached cameras on, so the orchestrator's second
12963
+ * `balance()` pass (over a node's devices) weights on real per-pool session
12964
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
12965
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
12966
+ */
12967
+ devices: array(object({
12968
+ deviceKey: string$2(),
12969
+ backend: string$2(),
12970
+ attachedCameras: number(),
12971
+ queueDepthTotal: number()
12972
+ })).default([]),
12901
12973
  /** Hardware capability flags reported by this node. */
12902
12974
  hardware: object({
12903
12975
  hasGpu: boolean(),
@@ -16046,6 +16118,8 @@ var BaseDeviceProvider = class extends BaseAddon {
16046
16118
  return toDeviceSummary(device, this.addonId);
16047
16119
  }
16048
16120
  };
16121
+ 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;
16122
+ new Set(Object.values(DeviceType));
16049
16123
  /**
16050
16124
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
16051
16125
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -17685,7 +17759,8 @@ var LinkedDeviceSchema = object({
17685
17759
  deviceId: number(),
17686
17760
  name: string$2(),
17687
17761
  location: string$2().nullable(),
17688
- features: array(string$2())
17762
+ features: array(string$2()),
17763
+ producesTrackedEvents: boolean().optional()
17689
17764
  });
17690
17765
  var SavedDeviceRowSchema = object({
17691
17766
  /** Numeric id reserved at allocateDeviceId time. */
@@ -19315,6 +19390,7 @@ var TrackSchema = object({
19315
19390
  deviceId: number(),
19316
19391
  className: string$2(),
19317
19392
  label: string$2().optional(),
19393
+ producingDeviceName: string$2().optional(),
19318
19394
  /** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
19319
19395
  source: TrackSourceSchema.optional(),
19320
19396
  firstSeen: number(),
@@ -19452,7 +19528,8 @@ var MediaFileKindEnum = _enum([
19452
19528
  "fullFrameBoxed",
19453
19529
  "faceCrop",
19454
19530
  "plateCrop",
19455
- "keyFrame"
19531
+ "keyFrame",
19532
+ "keyFrameSmall"
19456
19533
  ]);
19457
19534
  var MediaFileSchema = object({
19458
19535
  key: string$2(),
@@ -19781,13 +19858,11 @@ var PipelineTemplateSchema = object({
19781
19858
  createdAt: string$2(),
19782
19859
  updatedAt: string$2()
19783
19860
  });
19784
- var AgentAddonConfigSchema = object({
19785
- enabled: boolean(),
19861
+ var DeviceStepConfigSchema = object({
19786
19862
  modelId: string$2().optional(),
19787
- settings: record(string$2(), unknown()).readonly()
19863
+ settings: record(string$2(), unknown()).optional()
19788
19864
  });
19789
19865
  var AgentPipelineSettingsSchema = object({
19790
- addonDefaults: record(string$2(), AgentAddonConfigSchema).readonly(),
19791
19866
  maxCameras: number().int().nonnegative().nullable().default(null),
19792
19867
  /** Per-node detection weight (relative share for the quota balancer). */
19793
19868
  detectWeight: number().positive().optional(),
@@ -19811,7 +19886,22 @@ var AgentPipelineSettingsSchema = object({
19811
19886
  * it already uses to reach the hub). Set this only when the auto-detected
19812
19887
  * address is wrong (multi-homed host, NAT, custom interface).
19813
19888
  */
19814
- reachableHost: string$2().optional()
19889
+ reachableHost: string$2().optional(),
19890
+ /**
19891
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
19892
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
19893
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
19894
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
19895
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
19896
+ * the default model/settings for every camera landing on that accelerator;
19897
+ * a stepId absent ⇒ the step uses that device's format default.
19898
+ */
19899
+ inferenceDevices: record(string$2(), object({
19900
+ enabled: boolean(),
19901
+ weight: number().positive().optional(),
19902
+ maxSessions: number().int().positive().optional(),
19903
+ steps: record(string$2(), DeviceStepConfigSchema).optional()
19904
+ })).optional()
19815
19905
  });
19816
19906
  var CameraPipelineForAgentSchema = object({
19817
19907
  steps: array(PipelineStepInputSchema).readonly(),
@@ -19821,14 +19911,13 @@ var CameraPipelineForAgentSchema = object({
19821
19911
  }).nullable()
19822
19912
  });
19823
19913
  var CameraStepOverridePatchSchema = object({
19824
- enabled: boolean().optional(),
19825
19914
  modelId: string$2().optional(),
19826
19915
  settings: record(string$2(), unknown()).readonly().optional()
19827
19916
  });
19828
19917
  var CameraPipelineSettingsSchema = object({
19829
19918
  pinnedAgentNodeId: string$2().optional(),
19830
19919
  stepToggles: record(string$2(), boolean()).optional(),
19831
- stepOverridesByAgent: record(string$2(), record(string$2(), CameraStepOverridePatchSchema)).optional(),
19920
+ stepOverridesByDevice: record(string$2(), record(string$2(), record(string$2(), CameraStepOverridePatchSchema))).optional(),
19832
19921
  pipelineByAgent: record(string$2(), CameraPipelineForAgentSchema).optional()
19833
19922
  });
19834
19923
  /**
@@ -20042,6 +20131,44 @@ var CameraStatusSchema = object({
20042
20131
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
20043
20132
  fetchedAt: number()
20044
20133
  });
20134
+ var NodeInferenceDeviceSchema = object({
20135
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
20136
+ key: string$2(),
20137
+ backend: string$2(),
20138
+ device: string$2(),
20139
+ format: _enum(MODEL_FORMATS),
20140
+ /** Whether the node's live probe reports the device as usable right now. */
20141
+ available: boolean(),
20142
+ /**
20143
+ * Whether this device participates in dispatch. AUTO default (spec C2):
20144
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
20145
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
20146
+ * not a balanced target). An explicit stored value always wins; a stored-only
20147
+ * (unavailable) key keeps its stored value.
20148
+ */
20149
+ enabled: boolean(),
20150
+ /** Relative balancer weight for the enabled device (default 1). */
20151
+ weight: number(),
20152
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
20153
+ maxSessions: number().nullable(),
20154
+ /** Object-detection model the executor defaults to for this deviceKey. */
20155
+ defaultModelId: string$2(),
20156
+ /**
20157
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
20158
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
20159
+ * Absent/empty ⇒ no base (every step uses its device format default). The
20160
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
20161
+ * available per format; this is the stored selection that becomes the
20162
+ * default for EVERY camera landing on this accelerator.
20163
+ */
20164
+ steps: record(string$2(), DeviceStepConfigSchema).optional()
20165
+ });
20166
+ var NodeInferenceDevicesSchema = object({
20167
+ nodeId: string$2(),
20168
+ /** False when the node's platform-probe was unreachable (no live device set). */
20169
+ reachable: boolean(),
20170
+ devices: array(NodeInferenceDeviceSchema).readonly()
20171
+ });
20045
20172
  method(object({
20046
20173
  deviceId: number(),
20047
20174
  agentNodeId: string$2()
@@ -20051,7 +20178,13 @@ method(object({
20051
20178
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
20052
20179
  kind: "mutation",
20053
20180
  auth: "admin"
20054
- }), method(_void(), object({ migrated: number() }), {
20181
+ }), method(object({
20182
+ deviceId: number(),
20183
+ deviceKey: string$2()
20184
+ }), object({ success: literal(true) }), {
20185
+ kind: "mutation",
20186
+ auth: "admin"
20187
+ }), method(object({ deviceId: number() }), object({ deviceKey: string$2().nullable() })), method(_void(), object({ migrated: number() }), {
20055
20188
  kind: "mutation",
20056
20189
  auth: "admin"
20057
20190
  }), 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$2() }), CapabilityBindingsSchema), method(object({
@@ -20085,13 +20218,7 @@ method(object({
20085
20218
  }))), method(object({ agentNodeId: string$2() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
20086
20219
  nodeId: string$2(),
20087
20220
  settings: AgentPipelineSettingsSchema
20088
- })).readonly()), method(object({
20089
- agentNodeId: string$2(),
20090
- defaults: record(string$2(), AgentAddonConfigSchema)
20091
- }), object({ success: literal(true) }), {
20092
- kind: "mutation",
20093
- auth: "admin"
20094
- }), method(object({ agentNodeId: string$2() }), object({
20221
+ })).readonly()), method(object({ agentNodeId: string$2() }), object({
20095
20222
  success: boolean(),
20096
20223
  removed: boolean()
20097
20224
  }), {
@@ -20123,7 +20250,18 @@ method(object({
20123
20250
  }), object({ success: literal(true) }), {
20124
20251
  kind: "mutation",
20125
20252
  auth: "admin"
20126
- }), method(object({ agentNodeId: string$2() }), object({
20253
+ }), method(object({
20254
+ agentNodeId: string$2(),
20255
+ inferenceDevices: record(string$2(), object({
20256
+ enabled: boolean(),
20257
+ weight: number().positive().optional(),
20258
+ maxSessions: number().int().positive().optional(),
20259
+ steps: record(string$2(), DeviceStepConfigSchema).optional()
20260
+ }))
20261
+ }), object({ success: literal(true) }), {
20262
+ kind: "mutation",
20263
+ auth: "admin"
20264
+ }), method(object({ nodeId: string$2() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string$2() }), object({
20127
20265
  success: literal(true),
20128
20266
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
20129
20267
  effectiveModelId: string$2().nullable(),
@@ -20139,9 +20277,10 @@ method(object({
20139
20277
  }), object({ success: literal(true) }), {
20140
20278
  kind: "mutation",
20141
20279
  auth: "admin"
20142
- }), method(object({ deviceId: number() }), record(string$2(), record(string$2(), CameraStepOverridePatchSchema)).nullable()), method(object({
20280
+ }), method(object({ deviceId: number() }), record(string$2(), record(string$2(), record(string$2(), CameraStepOverridePatchSchema))).nullable()), method(object({
20143
20281
  deviceId: number(),
20144
20282
  agentNodeId: string$2(),
20283
+ deviceKey: string$2(),
20145
20284
  addonId: string$2(),
20146
20285
  patch: CameraStepOverridePatchSchema.nullable()
20147
20286
  }), object({ success: literal(true) }), {
@@ -20178,14 +20317,13 @@ method(object({
20178
20317
  });
20179
20318
  /**
20180
20319
  * server-management — per-NODE singleton capability for a node's ROOT
20181
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
20182
- * agents).
20320
+ * package lifecycle (runtime-updatable node packages).
20183
20321
  *
20184
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
20185
- * on agents) carries the whole software stack in its npm dep tree, so ONE
20186
- * version describes the node. Updates install into
20187
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
20188
- * starter (probation boot + auto-rollback to N-1).
20322
+ * Every node role runs the SAME root package (`@camstack/server`), which
20323
+ * carries the whole software stack in its npm dep tree, so ONE version
20324
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
20325
+ * on restart via the baked starter (single-copy in-place swap — no probation,
20326
+ * no auto-rollback).
20189
20327
  *
20190
20328
  * Providers:
20191
20329
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -20293,7 +20431,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
20293
20431
  /** Explicit target version; omitted = latest from the registry. */
20294
20432
  version: string$2().optional() }), ServerUpdateActionResultSchema, {
20295
20433
  kind: "mutation",
20296
- auth: "admin"
20434
+ auth: "admin",
20435
+ timeoutMs: 16 * 6e4
20297
20436
  }), method(_void(), ServerUpdateActionResultSchema, {
20298
20437
  kind: "mutation",
20299
20438
  auth: "admin"
@@ -21337,22 +21476,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
21337
21476
  var RestartAddonResultSchema = unknown();
21338
21477
  var InstallPackageResultSchema = unknown();
21339
21478
  var ReloadPackagesResultSchema = unknown();
21340
- /**
21341
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
21342
- * server restarts so the admin UI can react to the `restartingAt`
21343
- * timestamp (shows reconnect overlay). The transition from
21344
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
21345
- * `system.restart-completed` event after the new process boots.
21346
- *
21347
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
21348
- */
21349
- var UpdateFrameworkPackageResultSchema = object({
21350
- packageName: string$2(),
21351
- fromVersion: string$2(),
21352
- toVersion: string$2(),
21353
- /** Ms-epoch the server scheduled its self-restart. */
21354
- restartingAt: number()
21355
- });
21356
21479
  var BulkUpdateItemStatusSchema = _enum([
21357
21480
  "queued",
21358
21481
  "updating",
@@ -21480,13 +21603,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
21480
21603
  }), object({ success: literal(true) }), {
21481
21604
  kind: "mutation",
21482
21605
  auth: "admin"
21483
- }), method(object({
21484
- packageName: string$2().min(1),
21485
- version: string$2().optional(),
21486
- deferRestart: boolean().optional()
21487
- }), UpdateFrameworkPackageResultSchema, {
21488
- kind: "mutation",
21489
- auth: "admin"
21490
21606
  }), method(object({ name: string$2() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string$2() }), RestartAddonResultSchema, {
21491
21607
  kind: "mutation",
21492
21608
  auth: "admin"
@@ -22369,10 +22485,10 @@ var TopologyCategorySchema = object({
22369
22485
  addons: array(TopologyCategoryAddonSchema).readonly()
22370
22486
  });
22371
22487
  /**
22372
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
22373
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
22374
- * version visibility for the Server management surface. Nullable: offline
22375
- * rows and pre-phase-2 nodes report none.
22488
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
22489
+ * root package for every node role) as reported by its `registerNode`
22490
+ * manifest — version visibility for the Server management surface. Nullable:
22491
+ * offline rows and nodes that never reported one.
22376
22492
  */
22377
22493
  var TopologyRootPackageSchema = object({
22378
22494
  name: string$2(),
@@ -22760,17 +22876,28 @@ var PlatformScoreSchema = object({
22760
22876
  format: _enum([
22761
22877
  "onnx",
22762
22878
  "coreml",
22763
- "openvino"
22879
+ "openvino",
22880
+ "tflite"
22764
22881
  ]),
22765
22882
  score: number(),
22766
22883
  reason: string$2(),
22767
22884
  available: boolean()
22768
22885
  });
22886
+ var InferenceDeviceDescriptorSchema = object({
22887
+ key: string$2(),
22888
+ backend: string$2(),
22889
+ device: string$2(),
22890
+ format: ModelFormatSchema,
22891
+ runtime: literal("python"),
22892
+ score: number(),
22893
+ available: boolean()
22894
+ });
22769
22895
  var PlatformCapabilitiesSchema = object({
22770
22896
  hardware: HardwareInfoSchema,
22771
22897
  scores: array(PlatformScoreSchema).readonly(),
22772
22898
  bestScore: PlatformScoreSchema,
22773
- pythonPath: string$2().nullable()
22899
+ pythonPath: string$2().nullable(),
22900
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
22774
22901
  });
22775
22902
  var ModelRequirementSchema = object({
22776
22903
  modelId: string$2(),
@@ -23649,12 +23776,6 @@ Object.freeze({
23649
23776
  addonId: null,
23650
23777
  access: "delete"
23651
23778
  },
23652
- "addons.updateFrameworkPackage": {
23653
- capName: "addons",
23654
- capScope: "system",
23655
- addonId: null,
23656
- access: "create"
23657
- },
23658
23779
  "addons.updatePackage": {
23659
23780
  capName: "addons",
23660
23781
  capScope: "system",
@@ -26427,12 +26548,6 @@ Object.freeze({
26427
26548
  addonId: null,
26428
26549
  access: "view"
26429
26550
  },
26430
- "pipelineExecutor.reprobeEngine": {
26431
- capName: "pipeline-executor",
26432
- capScope: "system",
26433
- addonId: null,
26434
- access: "create"
26435
- },
26436
26551
  "pipelineExecutor.runAudioTest": {
26437
26552
  capName: "pipeline-executor",
26438
26553
  capScope: "system",
@@ -26583,6 +26698,12 @@ Object.freeze({
26583
26698
  addonId: null,
26584
26699
  access: "view"
26585
26700
  },
26701
+ "pipelineOrchestrator.getNodeInferenceDevices": {
26702
+ capName: "pipeline-orchestrator",
26703
+ capScope: "system",
26704
+ addonId: null,
26705
+ access: "view"
26706
+ },
26586
26707
  "pipelineOrchestrator.getPipelineAssignment": {
26587
26708
  capName: "pipeline-orchestrator",
26588
26709
  capScope: "system",
@@ -26595,6 +26716,12 @@ Object.freeze({
26595
26716
  addonId: null,
26596
26717
  access: "view"
26597
26718
  },
26719
+ "pipelineOrchestrator.getPipelineDevicePin": {
26720
+ capName: "pipeline-orchestrator",
26721
+ capScope: "system",
26722
+ addonId: null,
26723
+ access: "view"
26724
+ },
26598
26725
  "pipelineOrchestrator.listAgentSettings": {
26599
26726
  capName: "pipeline-orchestrator",
26600
26727
  capScope: "system",
@@ -26637,19 +26764,19 @@ Object.freeze({
26637
26764
  addonId: null,
26638
26765
  access: "create"
26639
26766
  },
26640
- "pipelineOrchestrator.setAgentAddonDefaults": {
26767
+ "pipelineOrchestrator.setAgentCapabilities": {
26641
26768
  capName: "pipeline-orchestrator",
26642
26769
  capScope: "system",
26643
26770
  addonId: null,
26644
26771
  access: "create"
26645
26772
  },
26646
- "pipelineOrchestrator.setAgentCapabilities": {
26773
+ "pipelineOrchestrator.setAgentDetectWeight": {
26647
26774
  capName: "pipeline-orchestrator",
26648
26775
  capScope: "system",
26649
26776
  addonId: null,
26650
26777
  access: "create"
26651
26778
  },
26652
- "pipelineOrchestrator.setAgentDetectWeight": {
26779
+ "pipelineOrchestrator.setAgentInferenceDevices": {
26653
26780
  capName: "pipeline-orchestrator",
26654
26781
  capScope: "system",
26655
26782
  addonId: null,
@@ -26691,6 +26818,12 @@ Object.freeze({
26691
26818
  addonId: null,
26692
26819
  access: "create"
26693
26820
  },
26821
+ "pipelineOrchestrator.setPipelineDevicePin": {
26822
+ capName: "pipeline-orchestrator",
26823
+ capScope: "system",
26824
+ addonId: null,
26825
+ access: "create"
26826
+ },
26694
26827
  "pipelineOrchestrator.unassignAudio": {
26695
26828
  capName: "pipeline-orchestrator",
26696
26829
  capScope: "system",
@@ -28243,32 +28376,6 @@ Object.freeze({
28243
28376
  "network-access": "ingress",
28244
28377
  "smtp-provider": "email"
28245
28378
  });
28246
- var frameworkSwapPackageSchema = object({
28247
- name: string$2(),
28248
- stagedPath: string$2(),
28249
- backupPath: string$2(),
28250
- toVersion: string$2(),
28251
- fromVersion: string$2().nullable()
28252
- });
28253
- object({
28254
- jobId: string$2(),
28255
- taskId: string$2(),
28256
- packages: array(frameworkSwapPackageSchema),
28257
- requestedAtMs: number(),
28258
- schemaVersion: literal(1)
28259
- });
28260
- object({
28261
- jobId: string$2(),
28262
- taskId: string$2(),
28263
- backups: array(object({
28264
- name: string$2(),
28265
- backupPath: string$2(),
28266
- livePath: string$2()
28267
- })),
28268
- appliedAtMs: number(),
28269
- bootAttempts: number(),
28270
- schemaVersion: literal(1)
28271
- });
28272
28379
  //#endregion
28273
28380
  //#region ../../node_modules/@matter/general/dist/esm/net/tcp/TcpConnection.js
28274
28381
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-matter-broker",
3
- "version": "0.1.25",
3
+ "version": "0.2.1",
4
4
  "description": "Matter broker addon for CamStack — owns a Matter fabric (commissioning + the long-lived controller) via the matter.js controller and brokers commissioned Matter nodes into CamStack",
5
5
  "keywords": [
6
6
  "camstack",