@camstack/addon-provider-ecowitt 0.1.27 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/addon.js +193 -103
  2. package/dist/addon.mjs +193 -103
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -7101,6 +7101,17 @@ var ModelCatalogEntrySchema = object({
7101
7101
  "imagenet",
7102
7102
  "none"
7103
7103
  ]).optional(),
7104
+ /**
7105
+ * The model already applies softmax IN-GRAPH — its raw output is a
7106
+ * probability distribution, not logits. When set, the `softmax`
7107
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7108
+ * probability vector collapses it toward uniform (top-1 score craters far
7109
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7110
+ * the output is raw logits and the postprocessor applies softmax (the normal
7111
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7112
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7113
+ */
7114
+ outputProbabilities: boolean().optional(),
7104
7115
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7105
7116
  /**
7106
7117
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -12391,10 +12402,7 @@ var ConfigUISchemaNullableBridge = custom();
12391
12402
  var InferenceCapabilitiesBridge = custom();
12392
12403
  var ModelAvailabilityListBridge = custom();
12393
12404
  var PipelineRunResultBridge = custom();
12394
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
12395
- kind: "mutation",
12396
- auth: "admin"
12397
- }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12405
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12398
12406
  modelId: string(),
12399
12407
  settings: record(string(), unknown()).readonly()
12400
12408
  }))), method(object({ steps: record(string(), object({
@@ -12454,13 +12462,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12454
12462
  * (inputClasses ≠ null) are skipped and served per-track via
12455
12463
  * pipelineRunner.runDetailSubtree (two-plane design).
12456
12464
  */
12457
- plane: _enum(["full", "frame"]).optional()
12465
+ plane: _enum(["full", "frame"]).optional(),
12466
+ /**
12467
+ * Inference-device selector (Phase 2 multi-device). Format
12468
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
12469
+ * Omitted ⇒ the runner's default device (current single-engine
12470
+ * behaviour). Selects WHICH device pool of the node runs the call.
12471
+ */
12472
+ deviceKey: string().optional()
12458
12473
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
12459
12474
  engine: PipelineEngineChoiceSchema.optional(),
12460
12475
  steps: array(PipelineStepInputSchema).min(1),
12461
12476
  frames: array(FrameInputSchema).min(1).max(255),
12462
12477
  deviceId: number().optional(),
12463
- sessionId: string().optional()
12478
+ sessionId: string().optional(),
12479
+ /**
12480
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
12481
+ * the batch to the Python pool's bench preprocess cache
12482
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
12483
+ * preprocessed ONCE and every later inference is a pure-inference cache
12484
+ * hit — the sustained-throughput run measures inference, not
12485
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
12486
+ * full preprocess every call, correct). Fresh per sustained run;
12487
+ * released via `uncacheFrame`.
12488
+ */
12489
+ frameId: number().int().nonnegative().optional(),
12490
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
12491
+ deviceKey: string().optional()
12464
12492
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
12465
12493
  data: _instanceof(Uint8Array),
12466
12494
  width: number().int().positive(),
@@ -12492,8 +12520,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12492
12520
  * - `runtime` — main camera-serving engine (no idle TTL).
12493
12521
  * - `warm-override` — benchmark/test override held in the warm
12494
12522
  * cache; auto-disposed after the idle TTL.
12523
+ * - `device-pool` — a concurrent per-device pool (Phase 2
12524
+ * multi-device, keyed by `deviceKey`) resolved
12525
+ * via `resolveDeviceFactory`. Runs alongside the
12526
+ * `runtime` engine on a DIFFERENT accelerator
12527
+ * (NPU / iGPU / Coral) — this is how the
12528
+ * Engines tab shows all pools running at once.
12495
12529
  */
12496
- kind: _enum(["runtime", "warm-override"]),
12530
+ kind: _enum([
12531
+ "runtime",
12532
+ "warm-override",
12533
+ "device-pool"
12534
+ ]),
12497
12535
  /** Native pid of the underlying Python pool (null when no pool). */
12498
12536
  poolPid: number().nullable(),
12499
12537
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -12868,7 +12906,14 @@ var RunnerCameraConfigSchema = object({
12868
12906
  * camera's detect node differs from its source-owner (P2d, gated by the
12869
12907
  * `remoteSourcingNodes` rollout setting).
12870
12908
  */
12871
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
12909
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
12910
+ /**
12911
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
12912
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
12913
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
12914
+ * this only selects WHICH device pool of that node runs the session.
12915
+ */
12916
+ deviceKey: string().optional()
12872
12917
  });
12873
12918
  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;
12874
12919
  /**
@@ -12889,6 +12934,19 @@ var RunnerLocalLoadSchema = object({
12889
12934
  avgInferenceTimeMs: number(),
12890
12935
  /** Total queue depth across motion + detection queues. */
12891
12936
  queueDepthTotal: number(),
12937
+ /**
12938
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
12939
+ * this runner currently has attached cameras on, so the orchestrator's second
12940
+ * `balance()` pass (over a node's devices) weights on real per-pool session
12941
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
12942
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
12943
+ */
12944
+ devices: array(object({
12945
+ deviceKey: string(),
12946
+ backend: string(),
12947
+ attachedCameras: number(),
12948
+ queueDepthTotal: number()
12949
+ })).default([]),
12892
12950
  /** Hardware capability flags reported by this node. */
12893
12951
  hardware: object({
12894
12952
  hasGpu: boolean(),
@@ -16037,6 +16095,8 @@ var BaseDeviceProvider = class extends BaseAddon {
16037
16095
  return toDeviceSummary(device, this.addonId);
16038
16096
  }
16039
16097
  };
16098
+ 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;
16099
+ new Set(Object.values(DeviceType));
16040
16100
  /**
16041
16101
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
16042
16102
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -19706,13 +19766,11 @@ var PipelineTemplateSchema = object({
19706
19766
  createdAt: string(),
19707
19767
  updatedAt: string()
19708
19768
  });
19709
- var AgentAddonConfigSchema = object({
19710
- enabled: boolean(),
19769
+ var DeviceStepConfigSchema = object({
19711
19770
  modelId: string().optional(),
19712
- settings: record(string(), unknown()).readonly()
19771
+ settings: record(string(), unknown()).optional()
19713
19772
  });
19714
19773
  var AgentPipelineSettingsSchema = object({
19715
- addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
19716
19774
  maxCameras: number().int().nonnegative().nullable().default(null),
19717
19775
  /** Per-node detection weight (relative share for the quota balancer). */
19718
19776
  detectWeight: number().positive().optional(),
@@ -19736,7 +19794,22 @@ var AgentPipelineSettingsSchema = object({
19736
19794
  * it already uses to reach the hub). Set this only when the auto-detected
19737
19795
  * address is wrong (multi-homed host, NAT, custom interface).
19738
19796
  */
19739
- reachableHost: string().optional()
19797
+ reachableHost: string().optional(),
19798
+ /**
19799
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
19800
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
19801
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
19802
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
19803
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
19804
+ * the default model/settings for every camera landing on that accelerator;
19805
+ * a stepId absent ⇒ the step uses that device's format default.
19806
+ */
19807
+ inferenceDevices: record(string(), object({
19808
+ enabled: boolean(),
19809
+ weight: number().positive().optional(),
19810
+ maxSessions: number().int().positive().optional(),
19811
+ steps: record(string(), DeviceStepConfigSchema).optional()
19812
+ })).optional()
19740
19813
  });
19741
19814
  var CameraPipelineForAgentSchema = object({
19742
19815
  steps: array(PipelineStepInputSchema).readonly(),
@@ -19746,14 +19819,13 @@ var CameraPipelineForAgentSchema = object({
19746
19819
  }).nullable()
19747
19820
  });
19748
19821
  var CameraStepOverridePatchSchema = object({
19749
- enabled: boolean().optional(),
19750
19822
  modelId: string().optional(),
19751
19823
  settings: record(string(), unknown()).readonly().optional()
19752
19824
  });
19753
19825
  var CameraPipelineSettingsSchema = object({
19754
19826
  pinnedAgentNodeId: string().optional(),
19755
19827
  stepToggles: record(string(), boolean()).optional(),
19756
- stepOverridesByAgent: record(string(), record(string(), CameraStepOverridePatchSchema)).optional(),
19828
+ stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
19757
19829
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
19758
19830
  });
19759
19831
  /**
@@ -19967,6 +20039,44 @@ var CameraStatusSchema = object({
19967
20039
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
19968
20040
  fetchedAt: number()
19969
20041
  });
20042
+ var NodeInferenceDeviceSchema = object({
20043
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
20044
+ key: string(),
20045
+ backend: string(),
20046
+ device: string(),
20047
+ format: _enum(MODEL_FORMATS),
20048
+ /** Whether the node's live probe reports the device as usable right now. */
20049
+ available: boolean(),
20050
+ /**
20051
+ * Whether this device participates in dispatch. AUTO default (spec C2):
20052
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
20053
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
20054
+ * not a balanced target). An explicit stored value always wins; a stored-only
20055
+ * (unavailable) key keeps its stored value.
20056
+ */
20057
+ enabled: boolean(),
20058
+ /** Relative balancer weight for the enabled device (default 1). */
20059
+ weight: number(),
20060
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
20061
+ maxSessions: number().nullable(),
20062
+ /** Object-detection model the executor defaults to for this deviceKey. */
20063
+ defaultModelId: string(),
20064
+ /**
20065
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
20066
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
20067
+ * Absent/empty ⇒ no base (every step uses its device format default). The
20068
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
20069
+ * available per format; this is the stored selection that becomes the
20070
+ * default for EVERY camera landing on this accelerator.
20071
+ */
20072
+ steps: record(string(), DeviceStepConfigSchema).optional()
20073
+ });
20074
+ var NodeInferenceDevicesSchema = object({
20075
+ nodeId: string(),
20076
+ /** False when the node's platform-probe was unreachable (no live device set). */
20077
+ reachable: boolean(),
20078
+ devices: array(NodeInferenceDeviceSchema).readonly()
20079
+ });
19970
20080
  method(object({
19971
20081
  deviceId: number(),
19972
20082
  agentNodeId: string()
@@ -19976,7 +20086,13 @@ method(object({
19976
20086
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
19977
20087
  kind: "mutation",
19978
20088
  auth: "admin"
19979
- }), method(_void(), object({ migrated: number() }), {
20089
+ }), method(object({
20090
+ deviceId: number(),
20091
+ deviceKey: string()
20092
+ }), object({ success: literal(true) }), {
20093
+ kind: "mutation",
20094
+ auth: "admin"
20095
+ }), method(object({ deviceId: number() }), object({ deviceKey: string().nullable() })), method(_void(), object({ migrated: number() }), {
19980
20096
  kind: "mutation",
19981
20097
  auth: "admin"
19982
20098
  }), 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({
@@ -20010,13 +20126,7 @@ method(object({
20010
20126
  }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
20011
20127
  nodeId: string(),
20012
20128
  settings: AgentPipelineSettingsSchema
20013
- })).readonly()), method(object({
20014
- agentNodeId: string(),
20015
- defaults: record(string(), AgentAddonConfigSchema)
20016
- }), object({ success: literal(true) }), {
20017
- kind: "mutation",
20018
- auth: "admin"
20019
- }), method(object({ agentNodeId: string() }), object({
20129
+ })).readonly()), method(object({ agentNodeId: string() }), object({
20020
20130
  success: boolean(),
20021
20131
  removed: boolean()
20022
20132
  }), {
@@ -20048,7 +20158,18 @@ method(object({
20048
20158
  }), object({ success: literal(true) }), {
20049
20159
  kind: "mutation",
20050
20160
  auth: "admin"
20051
- }), method(object({ agentNodeId: string() }), object({
20161
+ }), method(object({
20162
+ agentNodeId: string(),
20163
+ inferenceDevices: record(string(), object({
20164
+ enabled: boolean(),
20165
+ weight: number().positive().optional(),
20166
+ maxSessions: number().int().positive().optional(),
20167
+ steps: record(string(), DeviceStepConfigSchema).optional()
20168
+ }))
20169
+ }), object({ success: literal(true) }), {
20170
+ kind: "mutation",
20171
+ auth: "admin"
20172
+ }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string() }), object({
20052
20173
  success: literal(true),
20053
20174
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
20054
20175
  effectiveModelId: string().nullable(),
@@ -20064,9 +20185,10 @@ method(object({
20064
20185
  }), object({ success: literal(true) }), {
20065
20186
  kind: "mutation",
20066
20187
  auth: "admin"
20067
- }), method(object({ deviceId: number() }), record(string(), record(string(), CameraStepOverridePatchSchema)).nullable()), method(object({
20188
+ }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
20068
20189
  deviceId: number(),
20069
20190
  agentNodeId: string(),
20191
+ deviceKey: string(),
20070
20192
  addonId: string(),
20071
20193
  patch: CameraStepOverridePatchSchema.nullable()
20072
20194
  }), object({ success: literal(true) }), {
@@ -20103,14 +20225,13 @@ method(object({
20103
20225
  });
20104
20226
  /**
20105
20227
  * server-management — per-NODE singleton capability for a node's ROOT
20106
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
20107
- * agents).
20228
+ * package lifecycle (runtime-updatable node packages).
20108
20229
  *
20109
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
20110
- * on agents) carries the whole software stack in its npm dep tree, so ONE
20111
- * version describes the node. Updates install into
20112
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
20113
- * starter (probation boot + auto-rollback to N-1).
20230
+ * Every node role runs the SAME root package (`@camstack/server`), which
20231
+ * carries the whole software stack in its npm dep tree, so ONE version
20232
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
20233
+ * on restart via the baked starter (single-copy in-place swap — no probation,
20234
+ * no auto-rollback).
20114
20235
  *
20115
20236
  * Providers:
20116
20237
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -20218,7 +20339,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
20218
20339
  /** Explicit target version; omitted = latest from the registry. */
20219
20340
  version: string().optional() }), ServerUpdateActionResultSchema, {
20220
20341
  kind: "mutation",
20221
- auth: "admin"
20342
+ auth: "admin",
20343
+ timeoutMs: 16 * 6e4
20222
20344
  }), method(_void(), ServerUpdateActionResultSchema, {
20223
20345
  kind: "mutation",
20224
20346
  auth: "admin"
@@ -21262,22 +21384,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
21262
21384
  var RestartAddonResultSchema = unknown();
21263
21385
  var InstallPackageResultSchema = unknown();
21264
21386
  var ReloadPackagesResultSchema = unknown();
21265
- /**
21266
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
21267
- * server restarts so the admin UI can react to the `restartingAt`
21268
- * timestamp (shows reconnect overlay). The transition from
21269
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
21270
- * `system.restart-completed` event after the new process boots.
21271
- *
21272
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
21273
- */
21274
- var UpdateFrameworkPackageResultSchema = object({
21275
- packageName: string(),
21276
- fromVersion: string(),
21277
- toVersion: string(),
21278
- /** Ms-epoch the server scheduled its self-restart. */
21279
- restartingAt: number()
21280
- });
21281
21387
  var BulkUpdateItemStatusSchema = _enum([
21282
21388
  "queued",
21283
21389
  "updating",
@@ -21405,13 +21511,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
21405
21511
  }), object({ success: literal(true) }), {
21406
21512
  kind: "mutation",
21407
21513
  auth: "admin"
21408
- }), method(object({
21409
- packageName: string().min(1),
21410
- version: string().optional(),
21411
- deferRestart: boolean().optional()
21412
- }), UpdateFrameworkPackageResultSchema, {
21413
- kind: "mutation",
21414
- auth: "admin"
21415
21514
  }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
21416
21515
  kind: "mutation",
21417
21516
  auth: "admin"
@@ -22277,10 +22376,10 @@ var TopologyCategorySchema = object({
22277
22376
  addons: array(TopologyCategoryAddonSchema).readonly()
22278
22377
  });
22279
22378
  /**
22280
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
22281
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
22282
- * version visibility for the Server management surface. Nullable: offline
22283
- * rows and pre-phase-2 nodes report none.
22379
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
22380
+ * root package for every node role) as reported by its `registerNode`
22381
+ * manifest — version visibility for the Server management surface. Nullable:
22382
+ * offline rows and nodes that never reported one.
22284
22383
  */
22285
22384
  var TopologyRootPackageSchema = object({
22286
22385
  name: string(),
@@ -22668,17 +22767,28 @@ var PlatformScoreSchema = object({
22668
22767
  format: _enum([
22669
22768
  "onnx",
22670
22769
  "coreml",
22671
- "openvino"
22770
+ "openvino",
22771
+ "tflite"
22672
22772
  ]),
22673
22773
  score: number(),
22674
22774
  reason: string(),
22675
22775
  available: boolean()
22676
22776
  });
22777
+ var InferenceDeviceDescriptorSchema = object({
22778
+ key: string(),
22779
+ backend: string(),
22780
+ device: string(),
22781
+ format: ModelFormatSchema,
22782
+ runtime: literal("python"),
22783
+ score: number(),
22784
+ available: boolean()
22785
+ });
22677
22786
  var PlatformCapabilitiesSchema = object({
22678
22787
  hardware: HardwareInfoSchema,
22679
22788
  scores: array(PlatformScoreSchema).readonly(),
22680
22789
  bestScore: PlatformScoreSchema,
22681
- pythonPath: string().nullable()
22790
+ pythonPath: string().nullable(),
22791
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
22682
22792
  });
22683
22793
  var ModelRequirementSchema = object({
22684
22794
  modelId: string(),
@@ -23557,12 +23667,6 @@ Object.freeze({
23557
23667
  addonId: null,
23558
23668
  access: "delete"
23559
23669
  },
23560
- "addons.updateFrameworkPackage": {
23561
- capName: "addons",
23562
- capScope: "system",
23563
- addonId: null,
23564
- access: "create"
23565
- },
23566
23670
  "addons.updatePackage": {
23567
23671
  capName: "addons",
23568
23672
  capScope: "system",
@@ -26335,12 +26439,6 @@ Object.freeze({
26335
26439
  addonId: null,
26336
26440
  access: "view"
26337
26441
  },
26338
- "pipelineExecutor.reprobeEngine": {
26339
- capName: "pipeline-executor",
26340
- capScope: "system",
26341
- addonId: null,
26342
- access: "create"
26343
- },
26344
26442
  "pipelineExecutor.runAudioTest": {
26345
26443
  capName: "pipeline-executor",
26346
26444
  capScope: "system",
@@ -26491,6 +26589,12 @@ Object.freeze({
26491
26589
  addonId: null,
26492
26590
  access: "view"
26493
26591
  },
26592
+ "pipelineOrchestrator.getNodeInferenceDevices": {
26593
+ capName: "pipeline-orchestrator",
26594
+ capScope: "system",
26595
+ addonId: null,
26596
+ access: "view"
26597
+ },
26494
26598
  "pipelineOrchestrator.getPipelineAssignment": {
26495
26599
  capName: "pipeline-orchestrator",
26496
26600
  capScope: "system",
@@ -26503,6 +26607,12 @@ Object.freeze({
26503
26607
  addonId: null,
26504
26608
  access: "view"
26505
26609
  },
26610
+ "pipelineOrchestrator.getPipelineDevicePin": {
26611
+ capName: "pipeline-orchestrator",
26612
+ capScope: "system",
26613
+ addonId: null,
26614
+ access: "view"
26615
+ },
26506
26616
  "pipelineOrchestrator.listAgentSettings": {
26507
26617
  capName: "pipeline-orchestrator",
26508
26618
  capScope: "system",
@@ -26545,19 +26655,19 @@ Object.freeze({
26545
26655
  addonId: null,
26546
26656
  access: "create"
26547
26657
  },
26548
- "pipelineOrchestrator.setAgentAddonDefaults": {
26658
+ "pipelineOrchestrator.setAgentCapabilities": {
26549
26659
  capName: "pipeline-orchestrator",
26550
26660
  capScope: "system",
26551
26661
  addonId: null,
26552
26662
  access: "create"
26553
26663
  },
26554
- "pipelineOrchestrator.setAgentCapabilities": {
26664
+ "pipelineOrchestrator.setAgentDetectWeight": {
26555
26665
  capName: "pipeline-orchestrator",
26556
26666
  capScope: "system",
26557
26667
  addonId: null,
26558
26668
  access: "create"
26559
26669
  },
26560
- "pipelineOrchestrator.setAgentDetectWeight": {
26670
+ "pipelineOrchestrator.setAgentInferenceDevices": {
26561
26671
  capName: "pipeline-orchestrator",
26562
26672
  capScope: "system",
26563
26673
  addonId: null,
@@ -26599,6 +26709,12 @@ Object.freeze({
26599
26709
  addonId: null,
26600
26710
  access: "create"
26601
26711
  },
26712
+ "pipelineOrchestrator.setPipelineDevicePin": {
26713
+ capName: "pipeline-orchestrator",
26714
+ capScope: "system",
26715
+ addonId: null,
26716
+ access: "create"
26717
+ },
26602
26718
  "pipelineOrchestrator.unassignAudio": {
26603
26719
  capName: "pipeline-orchestrator",
26604
26720
  capScope: "system",
@@ -28151,32 +28267,6 @@ Object.freeze({
28151
28267
  "network-access": "ingress",
28152
28268
  "smtp-provider": "email"
28153
28269
  });
28154
- var frameworkSwapPackageSchema = object({
28155
- name: string(),
28156
- stagedPath: string(),
28157
- backupPath: string(),
28158
- toVersion: string(),
28159
- fromVersion: string().nullable()
28160
- });
28161
- object({
28162
- jobId: string(),
28163
- taskId: string(),
28164
- packages: array(frameworkSwapPackageSchema),
28165
- requestedAtMs: number(),
28166
- schemaVersion: literal(1)
28167
- });
28168
- object({
28169
- jobId: string(),
28170
- taskId: string(),
28171
- backups: array(object({
28172
- name: string(),
28173
- backupPath: string(),
28174
- livePath: string()
28175
- })),
28176
- appliedAtMs: number(),
28177
- bootAttempts: number(),
28178
- schemaVersion: literal(1)
28179
- });
28180
28270
  //#endregion
28181
28271
  //#region node_modules/@apocaliss92/nodewitt/node_modules/zod/v3/helpers/util.js
28182
28272
  var util;
package/dist/addon.mjs CHANGED
@@ -7100,6 +7100,17 @@ var ModelCatalogEntrySchema = object({
7100
7100
  "imagenet",
7101
7101
  "none"
7102
7102
  ]).optional(),
7103
+ /**
7104
+ * The model already applies softmax IN-GRAPH — its raw output is a
7105
+ * probability distribution, not logits. When set, the `softmax`
7106
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7107
+ * probability vector collapses it toward uniform (top-1 score craters far
7108
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7109
+ * the output is raw logits and the postprocessor applies softmax (the normal
7110
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7111
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7112
+ */
7113
+ outputProbabilities: boolean().optional(),
7103
7114
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7104
7115
  /**
7105
7116
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -12390,10 +12401,7 @@ var ConfigUISchemaNullableBridge = custom();
12390
12401
  var InferenceCapabilitiesBridge = custom();
12391
12402
  var ModelAvailabilityListBridge = custom();
12392
12403
  var PipelineRunResultBridge = custom();
12393
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
12394
- kind: "mutation",
12395
- auth: "admin"
12396
- }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12404
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12397
12405
  modelId: string(),
12398
12406
  settings: record(string(), unknown()).readonly()
12399
12407
  }))), method(object({ steps: record(string(), object({
@@ -12453,13 +12461,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12453
12461
  * (inputClasses ≠ null) are skipped and served per-track via
12454
12462
  * pipelineRunner.runDetailSubtree (two-plane design).
12455
12463
  */
12456
- plane: _enum(["full", "frame"]).optional()
12464
+ plane: _enum(["full", "frame"]).optional(),
12465
+ /**
12466
+ * Inference-device selector (Phase 2 multi-device). Format
12467
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
12468
+ * Omitted ⇒ the runner's default device (current single-engine
12469
+ * behaviour). Selects WHICH device pool of the node runs the call.
12470
+ */
12471
+ deviceKey: string().optional()
12457
12472
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
12458
12473
  engine: PipelineEngineChoiceSchema.optional(),
12459
12474
  steps: array(PipelineStepInputSchema).min(1),
12460
12475
  frames: array(FrameInputSchema).min(1).max(255),
12461
12476
  deviceId: number().optional(),
12462
- sessionId: string().optional()
12477
+ sessionId: string().optional(),
12478
+ /**
12479
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
12480
+ * the batch to the Python pool's bench preprocess cache
12481
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
12482
+ * preprocessed ONCE and every later inference is a pure-inference cache
12483
+ * hit — the sustained-throughput run measures inference, not
12484
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
12485
+ * full preprocess every call, correct). Fresh per sustained run;
12486
+ * released via `uncacheFrame`.
12487
+ */
12488
+ frameId: number().int().nonnegative().optional(),
12489
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
12490
+ deviceKey: string().optional()
12463
12491
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
12464
12492
  data: _instanceof(Uint8Array),
12465
12493
  width: number().int().positive(),
@@ -12491,8 +12519,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12491
12519
  * - `runtime` — main camera-serving engine (no idle TTL).
12492
12520
  * - `warm-override` — benchmark/test override held in the warm
12493
12521
  * cache; auto-disposed after the idle TTL.
12522
+ * - `device-pool` — a concurrent per-device pool (Phase 2
12523
+ * multi-device, keyed by `deviceKey`) resolved
12524
+ * via `resolveDeviceFactory`. Runs alongside the
12525
+ * `runtime` engine on a DIFFERENT accelerator
12526
+ * (NPU / iGPU / Coral) — this is how the
12527
+ * Engines tab shows all pools running at once.
12494
12528
  */
12495
- kind: _enum(["runtime", "warm-override"]),
12529
+ kind: _enum([
12530
+ "runtime",
12531
+ "warm-override",
12532
+ "device-pool"
12533
+ ]),
12496
12534
  /** Native pid of the underlying Python pool (null when no pool). */
12497
12535
  poolPid: number().nullable(),
12498
12536
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -12867,7 +12905,14 @@ var RunnerCameraConfigSchema = object({
12867
12905
  * camera's detect node differs from its source-owner (P2d, gated by the
12868
12906
  * `remoteSourcingNodes` rollout setting).
12869
12907
  */
12870
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
12908
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
12909
+ /**
12910
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
12911
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
12912
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
12913
+ * this only selects WHICH device pool of that node runs the session.
12914
+ */
12915
+ deviceKey: string().optional()
12871
12916
  });
12872
12917
  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;
12873
12918
  /**
@@ -12888,6 +12933,19 @@ var RunnerLocalLoadSchema = object({
12888
12933
  avgInferenceTimeMs: number(),
12889
12934
  /** Total queue depth across motion + detection queues. */
12890
12935
  queueDepthTotal: number(),
12936
+ /**
12937
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
12938
+ * this runner currently has attached cameras on, so the orchestrator's second
12939
+ * `balance()` pass (over a node's devices) weights on real per-pool session
12940
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
12941
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
12942
+ */
12943
+ devices: array(object({
12944
+ deviceKey: string(),
12945
+ backend: string(),
12946
+ attachedCameras: number(),
12947
+ queueDepthTotal: number()
12948
+ })).default([]),
12891
12949
  /** Hardware capability flags reported by this node. */
12892
12950
  hardware: object({
12893
12951
  hasGpu: boolean(),
@@ -16036,6 +16094,8 @@ var BaseDeviceProvider = class extends BaseAddon {
16036
16094
  return toDeviceSummary(device, this.addonId);
16037
16095
  }
16038
16096
  };
16097
+ 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;
16098
+ new Set(Object.values(DeviceType));
16039
16099
  /**
16040
16100
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
16041
16101
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -19705,13 +19765,11 @@ var PipelineTemplateSchema = object({
19705
19765
  createdAt: string(),
19706
19766
  updatedAt: string()
19707
19767
  });
19708
- var AgentAddonConfigSchema = object({
19709
- enabled: boolean(),
19768
+ var DeviceStepConfigSchema = object({
19710
19769
  modelId: string().optional(),
19711
- settings: record(string(), unknown()).readonly()
19770
+ settings: record(string(), unknown()).optional()
19712
19771
  });
19713
19772
  var AgentPipelineSettingsSchema = object({
19714
- addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
19715
19773
  maxCameras: number().int().nonnegative().nullable().default(null),
19716
19774
  /** Per-node detection weight (relative share for the quota balancer). */
19717
19775
  detectWeight: number().positive().optional(),
@@ -19735,7 +19793,22 @@ var AgentPipelineSettingsSchema = object({
19735
19793
  * it already uses to reach the hub). Set this only when the auto-detected
19736
19794
  * address is wrong (multi-homed host, NAT, custom interface).
19737
19795
  */
19738
- reachableHost: string().optional()
19796
+ reachableHost: string().optional(),
19797
+ /**
19798
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
19799
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
19800
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
19801
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
19802
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
19803
+ * the default model/settings for every camera landing on that accelerator;
19804
+ * a stepId absent ⇒ the step uses that device's format default.
19805
+ */
19806
+ inferenceDevices: record(string(), object({
19807
+ enabled: boolean(),
19808
+ weight: number().positive().optional(),
19809
+ maxSessions: number().int().positive().optional(),
19810
+ steps: record(string(), DeviceStepConfigSchema).optional()
19811
+ })).optional()
19739
19812
  });
19740
19813
  var CameraPipelineForAgentSchema = object({
19741
19814
  steps: array(PipelineStepInputSchema).readonly(),
@@ -19745,14 +19818,13 @@ var CameraPipelineForAgentSchema = object({
19745
19818
  }).nullable()
19746
19819
  });
19747
19820
  var CameraStepOverridePatchSchema = object({
19748
- enabled: boolean().optional(),
19749
19821
  modelId: string().optional(),
19750
19822
  settings: record(string(), unknown()).readonly().optional()
19751
19823
  });
19752
19824
  var CameraPipelineSettingsSchema = object({
19753
19825
  pinnedAgentNodeId: string().optional(),
19754
19826
  stepToggles: record(string(), boolean()).optional(),
19755
- stepOverridesByAgent: record(string(), record(string(), CameraStepOverridePatchSchema)).optional(),
19827
+ stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
19756
19828
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
19757
19829
  });
19758
19830
  /**
@@ -19966,6 +20038,44 @@ var CameraStatusSchema = object({
19966
20038
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
19967
20039
  fetchedAt: number()
19968
20040
  });
20041
+ var NodeInferenceDeviceSchema = object({
20042
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
20043
+ key: string(),
20044
+ backend: string(),
20045
+ device: string(),
20046
+ format: _enum(MODEL_FORMATS),
20047
+ /** Whether the node's live probe reports the device as usable right now. */
20048
+ available: boolean(),
20049
+ /**
20050
+ * Whether this device participates in dispatch. AUTO default (spec C2):
20051
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
20052
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
20053
+ * not a balanced target). An explicit stored value always wins; a stored-only
20054
+ * (unavailable) key keeps its stored value.
20055
+ */
20056
+ enabled: boolean(),
20057
+ /** Relative balancer weight for the enabled device (default 1). */
20058
+ weight: number(),
20059
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
20060
+ maxSessions: number().nullable(),
20061
+ /** Object-detection model the executor defaults to for this deviceKey. */
20062
+ defaultModelId: string(),
20063
+ /**
20064
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
20065
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
20066
+ * Absent/empty ⇒ no base (every step uses its device format default). The
20067
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
20068
+ * available per format; this is the stored selection that becomes the
20069
+ * default for EVERY camera landing on this accelerator.
20070
+ */
20071
+ steps: record(string(), DeviceStepConfigSchema).optional()
20072
+ });
20073
+ var NodeInferenceDevicesSchema = object({
20074
+ nodeId: string(),
20075
+ /** False when the node's platform-probe was unreachable (no live device set). */
20076
+ reachable: boolean(),
20077
+ devices: array(NodeInferenceDeviceSchema).readonly()
20078
+ });
19969
20079
  method(object({
19970
20080
  deviceId: number(),
19971
20081
  agentNodeId: string()
@@ -19975,7 +20085,13 @@ method(object({
19975
20085
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
19976
20086
  kind: "mutation",
19977
20087
  auth: "admin"
19978
- }), method(_void(), object({ migrated: number() }), {
20088
+ }), method(object({
20089
+ deviceId: number(),
20090
+ deviceKey: string()
20091
+ }), object({ success: literal(true) }), {
20092
+ kind: "mutation",
20093
+ auth: "admin"
20094
+ }), method(object({ deviceId: number() }), object({ deviceKey: string().nullable() })), method(_void(), object({ migrated: number() }), {
19979
20095
  kind: "mutation",
19980
20096
  auth: "admin"
19981
20097
  }), 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({
@@ -20009,13 +20125,7 @@ method(object({
20009
20125
  }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
20010
20126
  nodeId: string(),
20011
20127
  settings: AgentPipelineSettingsSchema
20012
- })).readonly()), method(object({
20013
- agentNodeId: string(),
20014
- defaults: record(string(), AgentAddonConfigSchema)
20015
- }), object({ success: literal(true) }), {
20016
- kind: "mutation",
20017
- auth: "admin"
20018
- }), method(object({ agentNodeId: string() }), object({
20128
+ })).readonly()), method(object({ agentNodeId: string() }), object({
20019
20129
  success: boolean(),
20020
20130
  removed: boolean()
20021
20131
  }), {
@@ -20047,7 +20157,18 @@ method(object({
20047
20157
  }), object({ success: literal(true) }), {
20048
20158
  kind: "mutation",
20049
20159
  auth: "admin"
20050
- }), method(object({ agentNodeId: string() }), object({
20160
+ }), method(object({
20161
+ agentNodeId: string(),
20162
+ inferenceDevices: record(string(), object({
20163
+ enabled: boolean(),
20164
+ weight: number().positive().optional(),
20165
+ maxSessions: number().int().positive().optional(),
20166
+ steps: record(string(), DeviceStepConfigSchema).optional()
20167
+ }))
20168
+ }), object({ success: literal(true) }), {
20169
+ kind: "mutation",
20170
+ auth: "admin"
20171
+ }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string() }), object({
20051
20172
  success: literal(true),
20052
20173
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
20053
20174
  effectiveModelId: string().nullable(),
@@ -20063,9 +20184,10 @@ method(object({
20063
20184
  }), object({ success: literal(true) }), {
20064
20185
  kind: "mutation",
20065
20186
  auth: "admin"
20066
- }), method(object({ deviceId: number() }), record(string(), record(string(), CameraStepOverridePatchSchema)).nullable()), method(object({
20187
+ }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
20067
20188
  deviceId: number(),
20068
20189
  agentNodeId: string(),
20190
+ deviceKey: string(),
20069
20191
  addonId: string(),
20070
20192
  patch: CameraStepOverridePatchSchema.nullable()
20071
20193
  }), object({ success: literal(true) }), {
@@ -20102,14 +20224,13 @@ method(object({
20102
20224
  });
20103
20225
  /**
20104
20226
  * server-management — per-NODE singleton capability for a node's ROOT
20105
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
20106
- * agents).
20227
+ * package lifecycle (runtime-updatable node packages).
20107
20228
  *
20108
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
20109
- * on agents) carries the whole software stack in its npm dep tree, so ONE
20110
- * version describes the node. Updates install into
20111
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
20112
- * starter (probation boot + auto-rollback to N-1).
20229
+ * Every node role runs the SAME root package (`@camstack/server`), which
20230
+ * carries the whole software stack in its npm dep tree, so ONE version
20231
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
20232
+ * on restart via the baked starter (single-copy in-place swap — no probation,
20233
+ * no auto-rollback).
20113
20234
  *
20114
20235
  * Providers:
20115
20236
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -20217,7 +20338,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
20217
20338
  /** Explicit target version; omitted = latest from the registry. */
20218
20339
  version: string().optional() }), ServerUpdateActionResultSchema, {
20219
20340
  kind: "mutation",
20220
- auth: "admin"
20341
+ auth: "admin",
20342
+ timeoutMs: 16 * 6e4
20221
20343
  }), method(_void(), ServerUpdateActionResultSchema, {
20222
20344
  kind: "mutation",
20223
20345
  auth: "admin"
@@ -21261,22 +21383,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
21261
21383
  var RestartAddonResultSchema = unknown();
21262
21384
  var InstallPackageResultSchema = unknown();
21263
21385
  var ReloadPackagesResultSchema = unknown();
21264
- /**
21265
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
21266
- * server restarts so the admin UI can react to the `restartingAt`
21267
- * timestamp (shows reconnect overlay). The transition from
21268
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
21269
- * `system.restart-completed` event after the new process boots.
21270
- *
21271
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
21272
- */
21273
- var UpdateFrameworkPackageResultSchema = object({
21274
- packageName: string(),
21275
- fromVersion: string(),
21276
- toVersion: string(),
21277
- /** Ms-epoch the server scheduled its self-restart. */
21278
- restartingAt: number()
21279
- });
21280
21386
  var BulkUpdateItemStatusSchema = _enum([
21281
21387
  "queued",
21282
21388
  "updating",
@@ -21404,13 +21510,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
21404
21510
  }), object({ success: literal(true) }), {
21405
21511
  kind: "mutation",
21406
21512
  auth: "admin"
21407
- }), method(object({
21408
- packageName: string().min(1),
21409
- version: string().optional(),
21410
- deferRestart: boolean().optional()
21411
- }), UpdateFrameworkPackageResultSchema, {
21412
- kind: "mutation",
21413
- auth: "admin"
21414
21513
  }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
21415
21514
  kind: "mutation",
21416
21515
  auth: "admin"
@@ -22276,10 +22375,10 @@ var TopologyCategorySchema = object({
22276
22375
  addons: array(TopologyCategoryAddonSchema).readonly()
22277
22376
  });
22278
22377
  /**
22279
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
22280
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
22281
- * version visibility for the Server management surface. Nullable: offline
22282
- * rows and pre-phase-2 nodes report none.
22378
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
22379
+ * root package for every node role) as reported by its `registerNode`
22380
+ * manifest — version visibility for the Server management surface. Nullable:
22381
+ * offline rows and nodes that never reported one.
22283
22382
  */
22284
22383
  var TopologyRootPackageSchema = object({
22285
22384
  name: string(),
@@ -22667,17 +22766,28 @@ var PlatformScoreSchema = object({
22667
22766
  format: _enum([
22668
22767
  "onnx",
22669
22768
  "coreml",
22670
- "openvino"
22769
+ "openvino",
22770
+ "tflite"
22671
22771
  ]),
22672
22772
  score: number(),
22673
22773
  reason: string(),
22674
22774
  available: boolean()
22675
22775
  });
22776
+ var InferenceDeviceDescriptorSchema = object({
22777
+ key: string(),
22778
+ backend: string(),
22779
+ device: string(),
22780
+ format: ModelFormatSchema,
22781
+ runtime: literal("python"),
22782
+ score: number(),
22783
+ available: boolean()
22784
+ });
22676
22785
  var PlatformCapabilitiesSchema = object({
22677
22786
  hardware: HardwareInfoSchema,
22678
22787
  scores: array(PlatformScoreSchema).readonly(),
22679
22788
  bestScore: PlatformScoreSchema,
22680
- pythonPath: string().nullable()
22789
+ pythonPath: string().nullable(),
22790
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
22681
22791
  });
22682
22792
  var ModelRequirementSchema = object({
22683
22793
  modelId: string(),
@@ -23556,12 +23666,6 @@ Object.freeze({
23556
23666
  addonId: null,
23557
23667
  access: "delete"
23558
23668
  },
23559
- "addons.updateFrameworkPackage": {
23560
- capName: "addons",
23561
- capScope: "system",
23562
- addonId: null,
23563
- access: "create"
23564
- },
23565
23669
  "addons.updatePackage": {
23566
23670
  capName: "addons",
23567
23671
  capScope: "system",
@@ -26334,12 +26438,6 @@ Object.freeze({
26334
26438
  addonId: null,
26335
26439
  access: "view"
26336
26440
  },
26337
- "pipelineExecutor.reprobeEngine": {
26338
- capName: "pipeline-executor",
26339
- capScope: "system",
26340
- addonId: null,
26341
- access: "create"
26342
- },
26343
26441
  "pipelineExecutor.runAudioTest": {
26344
26442
  capName: "pipeline-executor",
26345
26443
  capScope: "system",
@@ -26490,6 +26588,12 @@ Object.freeze({
26490
26588
  addonId: null,
26491
26589
  access: "view"
26492
26590
  },
26591
+ "pipelineOrchestrator.getNodeInferenceDevices": {
26592
+ capName: "pipeline-orchestrator",
26593
+ capScope: "system",
26594
+ addonId: null,
26595
+ access: "view"
26596
+ },
26493
26597
  "pipelineOrchestrator.getPipelineAssignment": {
26494
26598
  capName: "pipeline-orchestrator",
26495
26599
  capScope: "system",
@@ -26502,6 +26606,12 @@ Object.freeze({
26502
26606
  addonId: null,
26503
26607
  access: "view"
26504
26608
  },
26609
+ "pipelineOrchestrator.getPipelineDevicePin": {
26610
+ capName: "pipeline-orchestrator",
26611
+ capScope: "system",
26612
+ addonId: null,
26613
+ access: "view"
26614
+ },
26505
26615
  "pipelineOrchestrator.listAgentSettings": {
26506
26616
  capName: "pipeline-orchestrator",
26507
26617
  capScope: "system",
@@ -26544,19 +26654,19 @@ Object.freeze({
26544
26654
  addonId: null,
26545
26655
  access: "create"
26546
26656
  },
26547
- "pipelineOrchestrator.setAgentAddonDefaults": {
26657
+ "pipelineOrchestrator.setAgentCapabilities": {
26548
26658
  capName: "pipeline-orchestrator",
26549
26659
  capScope: "system",
26550
26660
  addonId: null,
26551
26661
  access: "create"
26552
26662
  },
26553
- "pipelineOrchestrator.setAgentCapabilities": {
26663
+ "pipelineOrchestrator.setAgentDetectWeight": {
26554
26664
  capName: "pipeline-orchestrator",
26555
26665
  capScope: "system",
26556
26666
  addonId: null,
26557
26667
  access: "create"
26558
26668
  },
26559
- "pipelineOrchestrator.setAgentDetectWeight": {
26669
+ "pipelineOrchestrator.setAgentInferenceDevices": {
26560
26670
  capName: "pipeline-orchestrator",
26561
26671
  capScope: "system",
26562
26672
  addonId: null,
@@ -26598,6 +26708,12 @@ Object.freeze({
26598
26708
  addonId: null,
26599
26709
  access: "create"
26600
26710
  },
26711
+ "pipelineOrchestrator.setPipelineDevicePin": {
26712
+ capName: "pipeline-orchestrator",
26713
+ capScope: "system",
26714
+ addonId: null,
26715
+ access: "create"
26716
+ },
26601
26717
  "pipelineOrchestrator.unassignAudio": {
26602
26718
  capName: "pipeline-orchestrator",
26603
26719
  capScope: "system",
@@ -28150,32 +28266,6 @@ Object.freeze({
28150
28266
  "network-access": "ingress",
28151
28267
  "smtp-provider": "email"
28152
28268
  });
28153
- var frameworkSwapPackageSchema = object({
28154
- name: string(),
28155
- stagedPath: string(),
28156
- backupPath: string(),
28157
- toVersion: string(),
28158
- fromVersion: string().nullable()
28159
- });
28160
- object({
28161
- jobId: string(),
28162
- taskId: string(),
28163
- packages: array(frameworkSwapPackageSchema),
28164
- requestedAtMs: number(),
28165
- schemaVersion: literal(1)
28166
- });
28167
- object({
28168
- jobId: string(),
28169
- taskId: string(),
28170
- backups: array(object({
28171
- name: string(),
28172
- backupPath: string(),
28173
- livePath: string()
28174
- })),
28175
- appliedAtMs: number(),
28176
- bootAttempts: number(),
28177
- schemaVersion: literal(1)
28178
- });
28179
28269
  //#endregion
28180
28270
  //#region node_modules/@apocaliss92/nodewitt/node_modules/zod/v3/helpers/util.js
28181
28271
  var util;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-ecowitt",
3
- "version": "0.1.27",
3
+ "version": "0.2.0",
4
4
  "description": "Ecowitt weather-station device-provider addon for CamStack — wraps the @apocaliss92/nodewitt local-poll / push client",
5
5
  "keywords": [
6
6
  "camstack",