@camstack/addon-provider-reolink 1.1.30 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/addon.js +197 -103
  2. package/dist/addon.mjs +197 -103
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -7123,6 +7123,17 @@ var ModelCatalogEntrySchema = object({
7123
7123
  "imagenet",
7124
7124
  "none"
7125
7125
  ]).optional(),
7126
+ /**
7127
+ * The model already applies softmax IN-GRAPH — its raw output is a
7128
+ * probability distribution, not logits. When set, the `softmax`
7129
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7130
+ * probability vector collapses it toward uniform (top-1 score craters far
7131
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7132
+ * the output is raw logits and the postprocessor applies softmax (the normal
7133
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7134
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7135
+ */
7136
+ outputProbabilities: boolean().optional(),
7126
7137
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7127
7138
  /**
7128
7139
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -12627,10 +12638,7 @@ var ConfigUISchemaNullableBridge = custom$2();
12627
12638
  var InferenceCapabilitiesBridge = custom$2();
12628
12639
  var ModelAvailabilityListBridge = custom$2();
12629
12640
  var PipelineRunResultBridge = custom$2();
12630
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
12631
- kind: "mutation",
12632
- auth: "admin"
12633
- }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12641
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12634
12642
  modelId: string(),
12635
12643
  settings: record(string(), unknown()).readonly()
12636
12644
  }))), method(object({ steps: record(string(), object({
@@ -12690,13 +12698,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12690
12698
  * (inputClasses ≠ null) are skipped and served per-track via
12691
12699
  * pipelineRunner.runDetailSubtree (two-plane design).
12692
12700
  */
12693
- plane: _enum(["full", "frame"]).optional()
12701
+ plane: _enum(["full", "frame"]).optional(),
12702
+ /**
12703
+ * Inference-device selector (Phase 2 multi-device). Format
12704
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
12705
+ * Omitted ⇒ the runner's default device (current single-engine
12706
+ * behaviour). Selects WHICH device pool of the node runs the call.
12707
+ */
12708
+ deviceKey: string().optional()
12694
12709
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
12695
12710
  engine: PipelineEngineChoiceSchema.optional(),
12696
12711
  steps: array(PipelineStepInputSchema).min(1),
12697
12712
  frames: array(FrameInputSchema).min(1).max(255),
12698
12713
  deviceId: number().optional(),
12699
- sessionId: string().optional()
12714
+ sessionId: string().optional(),
12715
+ /**
12716
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
12717
+ * the batch to the Python pool's bench preprocess cache
12718
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
12719
+ * preprocessed ONCE and every later inference is a pure-inference cache
12720
+ * hit — the sustained-throughput run measures inference, not
12721
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
12722
+ * full preprocess every call, correct). Fresh per sustained run;
12723
+ * released via `uncacheFrame`.
12724
+ */
12725
+ frameId: number().int().nonnegative().optional(),
12726
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
12727
+ deviceKey: string().optional()
12700
12728
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
12701
12729
  data: _instanceof(Uint8Array),
12702
12730
  width: number().int().positive(),
@@ -12728,8 +12756,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12728
12756
  * - `runtime` — main camera-serving engine (no idle TTL).
12729
12757
  * - `warm-override` — benchmark/test override held in the warm
12730
12758
  * cache; auto-disposed after the idle TTL.
12759
+ * - `device-pool` — a concurrent per-device pool (Phase 2
12760
+ * multi-device, keyed by `deviceKey`) resolved
12761
+ * via `resolveDeviceFactory`. Runs alongside the
12762
+ * `runtime` engine on a DIFFERENT accelerator
12763
+ * (NPU / iGPU / Coral) — this is how the
12764
+ * Engines tab shows all pools running at once.
12731
12765
  */
12732
- kind: _enum(["runtime", "warm-override"]),
12766
+ kind: _enum([
12767
+ "runtime",
12768
+ "warm-override",
12769
+ "device-pool"
12770
+ ]),
12733
12771
  /** Native pid of the underlying Python pool (null when no pool). */
12734
12772
  poolPid: number().nullable(),
12735
12773
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -13104,7 +13142,14 @@ var RunnerCameraConfigSchema = object({
13104
13142
  * camera's detect node differs from its source-owner (P2d, gated by the
13105
13143
  * `remoteSourcingNodes` rollout setting).
13106
13144
  */
13107
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
13145
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
13146
+ /**
13147
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
13148
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
13149
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
13150
+ * this only selects WHICH device pool of that node runs the session.
13151
+ */
13152
+ deviceKey: string().optional()
13108
13153
  });
13109
13154
  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;
13110
13155
  /**
@@ -13125,6 +13170,19 @@ var RunnerLocalLoadSchema = object({
13125
13170
  avgInferenceTimeMs: number(),
13126
13171
  /** Total queue depth across motion + detection queues. */
13127
13172
  queueDepthTotal: number(),
13173
+ /**
13174
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
13175
+ * this runner currently has attached cameras on, so the orchestrator's second
13176
+ * `balance()` pass (over a node's devices) weights on real per-pool session
13177
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
13178
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
13179
+ */
13180
+ devices: array(object({
13181
+ deviceKey: string(),
13182
+ backend: string(),
13183
+ attachedCameras: number(),
13184
+ queueDepthTotal: number()
13185
+ })).default([]),
13128
13186
  /** Hardware capability flags reported by this node. */
13129
13187
  hardware: object({
13130
13188
  hasGpu: boolean(),
@@ -16273,6 +16331,8 @@ var BaseDeviceProvider = class extends BaseAddon {
16273
16331
  return toDeviceSummary(device, this.addonId);
16274
16332
  }
16275
16333
  };
16334
+ 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;
16335
+ new Set(Object.values(DeviceType));
16276
16336
  /**
16277
16337
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
16278
16338
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -19954,13 +20014,11 @@ var PipelineTemplateSchema = object({
19954
20014
  createdAt: string(),
19955
20015
  updatedAt: string()
19956
20016
  });
19957
- var AgentAddonConfigSchema = object({
19958
- enabled: boolean(),
20017
+ var DeviceStepConfigSchema = object({
19959
20018
  modelId: string().optional(),
19960
- settings: record(string(), unknown()).readonly()
20019
+ settings: record(string(), unknown()).optional()
19961
20020
  });
19962
20021
  var AgentPipelineSettingsSchema = object({
19963
- addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
19964
20022
  maxCameras: number().int().nonnegative().nullable().default(null),
19965
20023
  /** Per-node detection weight (relative share for the quota balancer). */
19966
20024
  detectWeight: number().positive().optional(),
@@ -19984,7 +20042,22 @@ var AgentPipelineSettingsSchema = object({
19984
20042
  * it already uses to reach the hub). Set this only when the auto-detected
19985
20043
  * address is wrong (multi-homed host, NAT, custom interface).
19986
20044
  */
19987
- reachableHost: string().optional()
20045
+ reachableHost: string().optional(),
20046
+ /**
20047
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
20048
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
20049
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
20050
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
20051
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
20052
+ * the default model/settings for every camera landing on that accelerator;
20053
+ * a stepId absent ⇒ the step uses that device's format default.
20054
+ */
20055
+ inferenceDevices: record(string(), object({
20056
+ enabled: boolean(),
20057
+ weight: number().positive().optional(),
20058
+ maxSessions: number().int().positive().optional(),
20059
+ steps: record(string(), DeviceStepConfigSchema).optional()
20060
+ })).optional()
19988
20061
  });
19989
20062
  var CameraPipelineForAgentSchema = object({
19990
20063
  steps: array(PipelineStepInputSchema).readonly(),
@@ -19994,14 +20067,13 @@ var CameraPipelineForAgentSchema = object({
19994
20067
  }).nullable()
19995
20068
  });
19996
20069
  var CameraStepOverridePatchSchema = object({
19997
- enabled: boolean().optional(),
19998
20070
  modelId: string().optional(),
19999
20071
  settings: record(string(), unknown()).readonly().optional()
20000
20072
  });
20001
20073
  var CameraPipelineSettingsSchema = object({
20002
20074
  pinnedAgentNodeId: string().optional(),
20003
20075
  stepToggles: record(string(), boolean()).optional(),
20004
- stepOverridesByAgent: record(string(), record(string(), CameraStepOverridePatchSchema)).optional(),
20076
+ stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
20005
20077
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
20006
20078
  });
20007
20079
  /**
@@ -20215,6 +20287,44 @@ var CameraStatusSchema = object({
20215
20287
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
20216
20288
  fetchedAt: number()
20217
20289
  });
20290
+ var NodeInferenceDeviceSchema = object({
20291
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
20292
+ key: string(),
20293
+ backend: string(),
20294
+ device: string(),
20295
+ format: _enum(MODEL_FORMATS),
20296
+ /** Whether the node's live probe reports the device as usable right now. */
20297
+ available: boolean(),
20298
+ /**
20299
+ * Whether this device participates in dispatch. AUTO default (spec C2):
20300
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
20301
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
20302
+ * not a balanced target). An explicit stored value always wins; a stored-only
20303
+ * (unavailable) key keeps its stored value.
20304
+ */
20305
+ enabled: boolean(),
20306
+ /** Relative balancer weight for the enabled device (default 1). */
20307
+ weight: number(),
20308
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
20309
+ maxSessions: number().nullable(),
20310
+ /** Object-detection model the executor defaults to for this deviceKey. */
20311
+ defaultModelId: string(),
20312
+ /**
20313
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
20314
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
20315
+ * Absent/empty ⇒ no base (every step uses its device format default). The
20316
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
20317
+ * available per format; this is the stored selection that becomes the
20318
+ * default for EVERY camera landing on this accelerator.
20319
+ */
20320
+ steps: record(string(), DeviceStepConfigSchema).optional()
20321
+ });
20322
+ var NodeInferenceDevicesSchema = object({
20323
+ nodeId: string(),
20324
+ /** False when the node's platform-probe was unreachable (no live device set). */
20325
+ reachable: boolean(),
20326
+ devices: array(NodeInferenceDeviceSchema).readonly()
20327
+ });
20218
20328
  method(object({
20219
20329
  deviceId: number(),
20220
20330
  agentNodeId: string()
@@ -20224,7 +20334,13 @@ method(object({
20224
20334
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
20225
20335
  kind: "mutation",
20226
20336
  auth: "admin"
20227
- }), method(_void(), object({ migrated: number() }), {
20337
+ }), method(object({
20338
+ deviceId: number(),
20339
+ deviceKey: string()
20340
+ }), object({ success: literal(true) }), {
20341
+ kind: "mutation",
20342
+ auth: "admin"
20343
+ }), method(object({ deviceId: number() }), object({ deviceKey: string().nullable() })), method(_void(), object({ migrated: number() }), {
20228
20344
  kind: "mutation",
20229
20345
  auth: "admin"
20230
20346
  }), 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({
@@ -20258,13 +20374,7 @@ method(object({
20258
20374
  }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
20259
20375
  nodeId: string(),
20260
20376
  settings: AgentPipelineSettingsSchema
20261
- })).readonly()), method(object({
20262
- agentNodeId: string(),
20263
- defaults: record(string(), AgentAddonConfigSchema)
20264
- }), object({ success: literal(true) }), {
20265
- kind: "mutation",
20266
- auth: "admin"
20267
- }), method(object({ agentNodeId: string() }), object({
20377
+ })).readonly()), method(object({ agentNodeId: string() }), object({
20268
20378
  success: boolean(),
20269
20379
  removed: boolean()
20270
20380
  }), {
@@ -20296,7 +20406,18 @@ method(object({
20296
20406
  }), object({ success: literal(true) }), {
20297
20407
  kind: "mutation",
20298
20408
  auth: "admin"
20299
- }), method(object({ agentNodeId: string() }), object({
20409
+ }), method(object({
20410
+ agentNodeId: string(),
20411
+ inferenceDevices: record(string(), object({
20412
+ enabled: boolean(),
20413
+ weight: number().positive().optional(),
20414
+ maxSessions: number().int().positive().optional(),
20415
+ steps: record(string(), DeviceStepConfigSchema).optional()
20416
+ }))
20417
+ }), object({ success: literal(true) }), {
20418
+ kind: "mutation",
20419
+ auth: "admin"
20420
+ }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string() }), object({
20300
20421
  success: literal(true),
20301
20422
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
20302
20423
  effectiveModelId: string().nullable(),
@@ -20312,9 +20433,10 @@ method(object({
20312
20433
  }), object({ success: literal(true) }), {
20313
20434
  kind: "mutation",
20314
20435
  auth: "admin"
20315
- }), method(object({ deviceId: number() }), record(string(), record(string(), CameraStepOverridePatchSchema)).nullable()), method(object({
20436
+ }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
20316
20437
  deviceId: number(),
20317
20438
  agentNodeId: string(),
20439
+ deviceKey: string(),
20318
20440
  addonId: string(),
20319
20441
  patch: CameraStepOverridePatchSchema.nullable()
20320
20442
  }), object({ success: literal(true) }), {
@@ -20351,14 +20473,13 @@ method(object({
20351
20473
  });
20352
20474
  /**
20353
20475
  * server-management — per-NODE singleton capability for a node's ROOT
20354
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
20355
- * agents).
20476
+ * package lifecycle (runtime-updatable node packages).
20356
20477
  *
20357
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
20358
- * on agents) carries the whole software stack in its npm dep tree, so ONE
20359
- * version describes the node. Updates install into
20360
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
20361
- * starter (probation boot + auto-rollback to N-1).
20478
+ * Every node role runs the SAME root package (`@camstack/server`), which
20479
+ * carries the whole software stack in its npm dep tree, so ONE version
20480
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
20481
+ * on restart via the baked starter (single-copy in-place swap — no probation,
20482
+ * no auto-rollback).
20362
20483
  *
20363
20484
  * Providers:
20364
20485
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -20466,7 +20587,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
20466
20587
  /** Explicit target version; omitted = latest from the registry. */
20467
20588
  version: string().optional() }), ServerUpdateActionResultSchema, {
20468
20589
  kind: "mutation",
20469
- auth: "admin"
20590
+ auth: "admin",
20591
+ timeoutMs: 16 * 6e4
20470
20592
  }), method(_void(), ServerUpdateActionResultSchema, {
20471
20593
  kind: "mutation",
20472
20594
  auth: "admin"
@@ -21561,22 +21683,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
21561
21683
  var RestartAddonResultSchema = unknown();
21562
21684
  var InstallPackageResultSchema = unknown();
21563
21685
  var ReloadPackagesResultSchema = unknown();
21564
- /**
21565
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
21566
- * server restarts so the admin UI can react to the `restartingAt`
21567
- * timestamp (shows reconnect overlay). The transition from
21568
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
21569
- * `system.restart-completed` event after the new process boots.
21570
- *
21571
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
21572
- */
21573
- var UpdateFrameworkPackageResultSchema = object({
21574
- packageName: string(),
21575
- fromVersion: string(),
21576
- toVersion: string(),
21577
- /** Ms-epoch the server scheduled its self-restart. */
21578
- restartingAt: number()
21579
- });
21580
21686
  var BulkUpdateItemStatusSchema = _enum([
21581
21687
  "queued",
21582
21688
  "updating",
@@ -21704,13 +21810,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
21704
21810
  }), object({ success: literal(true) }), {
21705
21811
  kind: "mutation",
21706
21812
  auth: "admin"
21707
- }), method(object({
21708
- packageName: string().min(1),
21709
- version: string().optional(),
21710
- deferRestart: boolean().optional()
21711
- }), UpdateFrameworkPackageResultSchema, {
21712
- kind: "mutation",
21713
- auth: "admin"
21714
21813
  }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
21715
21814
  kind: "mutation",
21716
21815
  auth: "admin"
@@ -22627,10 +22726,10 @@ var TopologyCategorySchema = object({
22627
22726
  addons: array(TopologyCategoryAddonSchema).readonly()
22628
22727
  });
22629
22728
  /**
22630
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
22631
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
22632
- * version visibility for the Server management surface. Nullable: offline
22633
- * rows and pre-phase-2 nodes report none.
22729
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
22730
+ * root package for every node role) as reported by its `registerNode`
22731
+ * manifest — version visibility for the Server management surface. Nullable:
22732
+ * offline rows and nodes that never reported one.
22634
22733
  */
22635
22734
  var TopologyRootPackageSchema = object({
22636
22735
  name: string(),
@@ -23018,17 +23117,28 @@ var PlatformScoreSchema = object({
23018
23117
  format: _enum([
23019
23118
  "onnx",
23020
23119
  "coreml",
23021
- "openvino"
23120
+ "openvino",
23121
+ "tflite"
23022
23122
  ]),
23023
23123
  score: number(),
23024
23124
  reason: string(),
23025
23125
  available: boolean()
23026
23126
  });
23127
+ var InferenceDeviceDescriptorSchema = object({
23128
+ key: string(),
23129
+ backend: string(),
23130
+ device: string(),
23131
+ format: ModelFormatSchema,
23132
+ runtime: literal("python"),
23133
+ score: number(),
23134
+ available: boolean()
23135
+ });
23027
23136
  var PlatformCapabilitiesSchema = object({
23028
23137
  hardware: HardwareInfoSchema,
23029
23138
  scores: array(PlatformScoreSchema).readonly(),
23030
23139
  bestScore: PlatformScoreSchema,
23031
- pythonPath: string().nullable()
23140
+ pythonPath: string().nullable(),
23141
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
23032
23142
  });
23033
23143
  var ModelRequirementSchema = object({
23034
23144
  modelId: string(),
@@ -24185,12 +24295,6 @@ Object.freeze({
24185
24295
  addonId: null,
24186
24296
  access: "delete"
24187
24297
  },
24188
- "addons.updateFrameworkPackage": {
24189
- capName: "addons",
24190
- capScope: "system",
24191
- addonId: null,
24192
- access: "create"
24193
- },
24194
24298
  "addons.updatePackage": {
24195
24299
  capName: "addons",
24196
24300
  capScope: "system",
@@ -26963,12 +27067,6 @@ Object.freeze({
26963
27067
  addonId: null,
26964
27068
  access: "view"
26965
27069
  },
26966
- "pipelineExecutor.reprobeEngine": {
26967
- capName: "pipeline-executor",
26968
- capScope: "system",
26969
- addonId: null,
26970
- access: "create"
26971
- },
26972
27070
  "pipelineExecutor.runAudioTest": {
26973
27071
  capName: "pipeline-executor",
26974
27072
  capScope: "system",
@@ -27119,6 +27217,12 @@ Object.freeze({
27119
27217
  addonId: null,
27120
27218
  access: "view"
27121
27219
  },
27220
+ "pipelineOrchestrator.getNodeInferenceDevices": {
27221
+ capName: "pipeline-orchestrator",
27222
+ capScope: "system",
27223
+ addonId: null,
27224
+ access: "view"
27225
+ },
27122
27226
  "pipelineOrchestrator.getPipelineAssignment": {
27123
27227
  capName: "pipeline-orchestrator",
27124
27228
  capScope: "system",
@@ -27131,6 +27235,12 @@ Object.freeze({
27131
27235
  addonId: null,
27132
27236
  access: "view"
27133
27237
  },
27238
+ "pipelineOrchestrator.getPipelineDevicePin": {
27239
+ capName: "pipeline-orchestrator",
27240
+ capScope: "system",
27241
+ addonId: null,
27242
+ access: "view"
27243
+ },
27134
27244
  "pipelineOrchestrator.listAgentSettings": {
27135
27245
  capName: "pipeline-orchestrator",
27136
27246
  capScope: "system",
@@ -27173,19 +27283,19 @@ Object.freeze({
27173
27283
  addonId: null,
27174
27284
  access: "create"
27175
27285
  },
27176
- "pipelineOrchestrator.setAgentAddonDefaults": {
27286
+ "pipelineOrchestrator.setAgentCapabilities": {
27177
27287
  capName: "pipeline-orchestrator",
27178
27288
  capScope: "system",
27179
27289
  addonId: null,
27180
27290
  access: "create"
27181
27291
  },
27182
- "pipelineOrchestrator.setAgentCapabilities": {
27292
+ "pipelineOrchestrator.setAgentDetectWeight": {
27183
27293
  capName: "pipeline-orchestrator",
27184
27294
  capScope: "system",
27185
27295
  addonId: null,
27186
27296
  access: "create"
27187
27297
  },
27188
- "pipelineOrchestrator.setAgentDetectWeight": {
27298
+ "pipelineOrchestrator.setAgentInferenceDevices": {
27189
27299
  capName: "pipeline-orchestrator",
27190
27300
  capScope: "system",
27191
27301
  addonId: null,
@@ -27227,6 +27337,12 @@ Object.freeze({
27227
27337
  addonId: null,
27228
27338
  access: "create"
27229
27339
  },
27340
+ "pipelineOrchestrator.setPipelineDevicePin": {
27341
+ capName: "pipeline-orchestrator",
27342
+ capScope: "system",
27343
+ addonId: null,
27344
+ access: "create"
27345
+ },
27230
27346
  "pipelineOrchestrator.unassignAudio": {
27231
27347
  capName: "pipeline-orchestrator",
27232
27348
  capScope: "system",
@@ -28779,32 +28895,6 @@ Object.freeze({
28779
28895
  "network-access": "ingress",
28780
28896
  "smtp-provider": "email"
28781
28897
  });
28782
- var frameworkSwapPackageSchema = object({
28783
- name: string(),
28784
- stagedPath: string(),
28785
- backupPath: string(),
28786
- toVersion: string(),
28787
- fromVersion: string().nullable()
28788
- });
28789
- object({
28790
- jobId: string(),
28791
- taskId: string(),
28792
- packages: array(frameworkSwapPackageSchema),
28793
- requestedAtMs: number(),
28794
- schemaVersion: literal(1)
28795
- });
28796
- object({
28797
- jobId: string(),
28798
- taskId: string(),
28799
- backups: array(object({
28800
- name: string(),
28801
- backupPath: string(),
28802
- livePath: string()
28803
- })),
28804
- appliedAtMs: number(),
28805
- bootAttempts: number(),
28806
- schemaVersion: literal(1)
28807
- });
28808
28898
  //#endregion
28809
28899
  //#region ../../node_modules/undici/lib/core/symbols.js
28810
28900
  var require_symbols = /* @__PURE__ */ require_chunk.__commonJSMin(((exports, module) => {
@@ -223223,6 +223313,10 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
223223
223313
  emitDoorbellPressed(timestamp) {
223224
223314
  this.doorbellLastPressedAt = timestamp;
223225
223315
  this.doorbellPressCountSinceStart += 1;
223316
+ this.runtimeState.setCapState(doorbellCapability.name, {
223317
+ lastPressedAt: timestamp,
223318
+ pressCountSinceStart: this.doorbellPressCountSinceStart
223319
+ });
223226
223320
  this.ctx.eventBus.emit(createEvent(EventCategory.DoorbellOnPressed, this.eventSource(), {
223227
223321
  deviceId: this.id,
223228
223322
  timestamp
package/dist/addon.mjs CHANGED
@@ -7118,6 +7118,17 @@ var ModelCatalogEntrySchema = object({
7118
7118
  "imagenet",
7119
7119
  "none"
7120
7120
  ]).optional(),
7121
+ /**
7122
+ * The model already applies softmax IN-GRAPH — its raw output is a
7123
+ * probability distribution, not logits. When set, the `softmax`
7124
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7125
+ * probability vector collapses it toward uniform (top-1 score craters far
7126
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7127
+ * the output is raw logits and the postprocessor applies softmax (the normal
7128
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7129
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7130
+ */
7131
+ outputProbabilities: boolean().optional(),
7121
7132
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7122
7133
  /**
7123
7134
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -12622,10 +12633,7 @@ var ConfigUISchemaNullableBridge = custom$2();
12622
12633
  var InferenceCapabilitiesBridge = custom$2();
12623
12634
  var ModelAvailabilityListBridge = custom$2();
12624
12635
  var PipelineRunResultBridge = custom$2();
12625
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
12626
- kind: "mutation",
12627
- auth: "admin"
12628
- }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12636
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12629
12637
  modelId: string(),
12630
12638
  settings: record(string(), unknown()).readonly()
12631
12639
  }))), method(object({ steps: record(string(), object({
@@ -12685,13 +12693,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12685
12693
  * (inputClasses ≠ null) are skipped and served per-track via
12686
12694
  * pipelineRunner.runDetailSubtree (two-plane design).
12687
12695
  */
12688
- plane: _enum(["full", "frame"]).optional()
12696
+ plane: _enum(["full", "frame"]).optional(),
12697
+ /**
12698
+ * Inference-device selector (Phase 2 multi-device). Format
12699
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
12700
+ * Omitted ⇒ the runner's default device (current single-engine
12701
+ * behaviour). Selects WHICH device pool of the node runs the call.
12702
+ */
12703
+ deviceKey: string().optional()
12689
12704
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
12690
12705
  engine: PipelineEngineChoiceSchema.optional(),
12691
12706
  steps: array(PipelineStepInputSchema).min(1),
12692
12707
  frames: array(FrameInputSchema).min(1).max(255),
12693
12708
  deviceId: number().optional(),
12694
- sessionId: string().optional()
12709
+ sessionId: string().optional(),
12710
+ /**
12711
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
12712
+ * the batch to the Python pool's bench preprocess cache
12713
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
12714
+ * preprocessed ONCE and every later inference is a pure-inference cache
12715
+ * hit — the sustained-throughput run measures inference, not
12716
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
12717
+ * full preprocess every call, correct). Fresh per sustained run;
12718
+ * released via `uncacheFrame`.
12719
+ */
12720
+ frameId: number().int().nonnegative().optional(),
12721
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
12722
+ deviceKey: string().optional()
12695
12723
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
12696
12724
  data: _instanceof(Uint8Array),
12697
12725
  width: number().int().positive(),
@@ -12723,8 +12751,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12723
12751
  * - `runtime` — main camera-serving engine (no idle TTL).
12724
12752
  * - `warm-override` — benchmark/test override held in the warm
12725
12753
  * cache; auto-disposed after the idle TTL.
12754
+ * - `device-pool` — a concurrent per-device pool (Phase 2
12755
+ * multi-device, keyed by `deviceKey`) resolved
12756
+ * via `resolveDeviceFactory`. Runs alongside the
12757
+ * `runtime` engine on a DIFFERENT accelerator
12758
+ * (NPU / iGPU / Coral) — this is how the
12759
+ * Engines tab shows all pools running at once.
12726
12760
  */
12727
- kind: _enum(["runtime", "warm-override"]),
12761
+ kind: _enum([
12762
+ "runtime",
12763
+ "warm-override",
12764
+ "device-pool"
12765
+ ]),
12728
12766
  /** Native pid of the underlying Python pool (null when no pool). */
12729
12767
  poolPid: number().nullable(),
12730
12768
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -13099,7 +13137,14 @@ var RunnerCameraConfigSchema = object({
13099
13137
  * camera's detect node differs from its source-owner (P2d, gated by the
13100
13138
  * `remoteSourcingNodes` rollout setting).
13101
13139
  */
13102
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
13140
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
13141
+ /**
13142
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
13143
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
13144
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
13145
+ * this only selects WHICH device pool of that node runs the session.
13146
+ */
13147
+ deviceKey: string().optional()
13103
13148
  });
13104
13149
  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;
13105
13150
  /**
@@ -13120,6 +13165,19 @@ var RunnerLocalLoadSchema = object({
13120
13165
  avgInferenceTimeMs: number(),
13121
13166
  /** Total queue depth across motion + detection queues. */
13122
13167
  queueDepthTotal: number(),
13168
+ /**
13169
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
13170
+ * this runner currently has attached cameras on, so the orchestrator's second
13171
+ * `balance()` pass (over a node's devices) weights on real per-pool session
13172
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
13173
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
13174
+ */
13175
+ devices: array(object({
13176
+ deviceKey: string(),
13177
+ backend: string(),
13178
+ attachedCameras: number(),
13179
+ queueDepthTotal: number()
13180
+ })).default([]),
13123
13181
  /** Hardware capability flags reported by this node. */
13124
13182
  hardware: object({
13125
13183
  hasGpu: boolean(),
@@ -16268,6 +16326,8 @@ var BaseDeviceProvider = class extends BaseAddon {
16268
16326
  return toDeviceSummary(device, this.addonId);
16269
16327
  }
16270
16328
  };
16329
+ 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;
16330
+ new Set(Object.values(DeviceType));
16271
16331
  /**
16272
16332
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
16273
16333
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -19949,13 +20009,11 @@ var PipelineTemplateSchema = object({
19949
20009
  createdAt: string(),
19950
20010
  updatedAt: string()
19951
20011
  });
19952
- var AgentAddonConfigSchema = object({
19953
- enabled: boolean(),
20012
+ var DeviceStepConfigSchema = object({
19954
20013
  modelId: string().optional(),
19955
- settings: record(string(), unknown()).readonly()
20014
+ settings: record(string(), unknown()).optional()
19956
20015
  });
19957
20016
  var AgentPipelineSettingsSchema = object({
19958
- addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
19959
20017
  maxCameras: number().int().nonnegative().nullable().default(null),
19960
20018
  /** Per-node detection weight (relative share for the quota balancer). */
19961
20019
  detectWeight: number().positive().optional(),
@@ -19979,7 +20037,22 @@ var AgentPipelineSettingsSchema = object({
19979
20037
  * it already uses to reach the hub). Set this only when the auto-detected
19980
20038
  * address is wrong (multi-homed host, NAT, custom interface).
19981
20039
  */
19982
- reachableHost: string().optional()
20040
+ reachableHost: string().optional(),
20041
+ /**
20042
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
20043
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
20044
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
20045
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
20046
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
20047
+ * the default model/settings for every camera landing on that accelerator;
20048
+ * a stepId absent ⇒ the step uses that device's format default.
20049
+ */
20050
+ inferenceDevices: record(string(), object({
20051
+ enabled: boolean(),
20052
+ weight: number().positive().optional(),
20053
+ maxSessions: number().int().positive().optional(),
20054
+ steps: record(string(), DeviceStepConfigSchema).optional()
20055
+ })).optional()
19983
20056
  });
19984
20057
  var CameraPipelineForAgentSchema = object({
19985
20058
  steps: array(PipelineStepInputSchema).readonly(),
@@ -19989,14 +20062,13 @@ var CameraPipelineForAgentSchema = object({
19989
20062
  }).nullable()
19990
20063
  });
19991
20064
  var CameraStepOverridePatchSchema = object({
19992
- enabled: boolean().optional(),
19993
20065
  modelId: string().optional(),
19994
20066
  settings: record(string(), unknown()).readonly().optional()
19995
20067
  });
19996
20068
  var CameraPipelineSettingsSchema = object({
19997
20069
  pinnedAgentNodeId: string().optional(),
19998
20070
  stepToggles: record(string(), boolean()).optional(),
19999
- stepOverridesByAgent: record(string(), record(string(), CameraStepOverridePatchSchema)).optional(),
20071
+ stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
20000
20072
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
20001
20073
  });
20002
20074
  /**
@@ -20210,6 +20282,44 @@ var CameraStatusSchema = object({
20210
20282
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
20211
20283
  fetchedAt: number()
20212
20284
  });
20285
+ var NodeInferenceDeviceSchema = object({
20286
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
20287
+ key: string(),
20288
+ backend: string(),
20289
+ device: string(),
20290
+ format: _enum(MODEL_FORMATS),
20291
+ /** Whether the node's live probe reports the device as usable right now. */
20292
+ available: boolean(),
20293
+ /**
20294
+ * Whether this device participates in dispatch. AUTO default (spec C2):
20295
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
20296
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
20297
+ * not a balanced target). An explicit stored value always wins; a stored-only
20298
+ * (unavailable) key keeps its stored value.
20299
+ */
20300
+ enabled: boolean(),
20301
+ /** Relative balancer weight for the enabled device (default 1). */
20302
+ weight: number(),
20303
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
20304
+ maxSessions: number().nullable(),
20305
+ /** Object-detection model the executor defaults to for this deviceKey. */
20306
+ defaultModelId: string(),
20307
+ /**
20308
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
20309
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
20310
+ * Absent/empty ⇒ no base (every step uses its device format default). The
20311
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
20312
+ * available per format; this is the stored selection that becomes the
20313
+ * default for EVERY camera landing on this accelerator.
20314
+ */
20315
+ steps: record(string(), DeviceStepConfigSchema).optional()
20316
+ });
20317
+ var NodeInferenceDevicesSchema = object({
20318
+ nodeId: string(),
20319
+ /** False when the node's platform-probe was unreachable (no live device set). */
20320
+ reachable: boolean(),
20321
+ devices: array(NodeInferenceDeviceSchema).readonly()
20322
+ });
20213
20323
  method(object({
20214
20324
  deviceId: number(),
20215
20325
  agentNodeId: string()
@@ -20219,7 +20329,13 @@ method(object({
20219
20329
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
20220
20330
  kind: "mutation",
20221
20331
  auth: "admin"
20222
- }), method(_void(), object({ migrated: number() }), {
20332
+ }), method(object({
20333
+ deviceId: number(),
20334
+ deviceKey: string()
20335
+ }), object({ success: literal(true) }), {
20336
+ kind: "mutation",
20337
+ auth: "admin"
20338
+ }), method(object({ deviceId: number() }), object({ deviceKey: string().nullable() })), method(_void(), object({ migrated: number() }), {
20223
20339
  kind: "mutation",
20224
20340
  auth: "admin"
20225
20341
  }), 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({
@@ -20253,13 +20369,7 @@ method(object({
20253
20369
  }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
20254
20370
  nodeId: string(),
20255
20371
  settings: AgentPipelineSettingsSchema
20256
- })).readonly()), method(object({
20257
- agentNodeId: string(),
20258
- defaults: record(string(), AgentAddonConfigSchema)
20259
- }), object({ success: literal(true) }), {
20260
- kind: "mutation",
20261
- auth: "admin"
20262
- }), method(object({ agentNodeId: string() }), object({
20372
+ })).readonly()), method(object({ agentNodeId: string() }), object({
20263
20373
  success: boolean(),
20264
20374
  removed: boolean()
20265
20375
  }), {
@@ -20291,7 +20401,18 @@ method(object({
20291
20401
  }), object({ success: literal(true) }), {
20292
20402
  kind: "mutation",
20293
20403
  auth: "admin"
20294
- }), method(object({ agentNodeId: string() }), object({
20404
+ }), method(object({
20405
+ agentNodeId: string(),
20406
+ inferenceDevices: record(string(), object({
20407
+ enabled: boolean(),
20408
+ weight: number().positive().optional(),
20409
+ maxSessions: number().int().positive().optional(),
20410
+ steps: record(string(), DeviceStepConfigSchema).optional()
20411
+ }))
20412
+ }), object({ success: literal(true) }), {
20413
+ kind: "mutation",
20414
+ auth: "admin"
20415
+ }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string() }), object({
20295
20416
  success: literal(true),
20296
20417
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
20297
20418
  effectiveModelId: string().nullable(),
@@ -20307,9 +20428,10 @@ method(object({
20307
20428
  }), object({ success: literal(true) }), {
20308
20429
  kind: "mutation",
20309
20430
  auth: "admin"
20310
- }), method(object({ deviceId: number() }), record(string(), record(string(), CameraStepOverridePatchSchema)).nullable()), method(object({
20431
+ }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
20311
20432
  deviceId: number(),
20312
20433
  agentNodeId: string(),
20434
+ deviceKey: string(),
20313
20435
  addonId: string(),
20314
20436
  patch: CameraStepOverridePatchSchema.nullable()
20315
20437
  }), object({ success: literal(true) }), {
@@ -20346,14 +20468,13 @@ method(object({
20346
20468
  });
20347
20469
  /**
20348
20470
  * server-management — per-NODE singleton capability for a node's ROOT
20349
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
20350
- * agents).
20471
+ * package lifecycle (runtime-updatable node packages).
20351
20472
  *
20352
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
20353
- * on agents) carries the whole software stack in its npm dep tree, so ONE
20354
- * version describes the node. Updates install into
20355
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
20356
- * starter (probation boot + auto-rollback to N-1).
20473
+ * Every node role runs the SAME root package (`@camstack/server`), which
20474
+ * carries the whole software stack in its npm dep tree, so ONE version
20475
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
20476
+ * on restart via the baked starter (single-copy in-place swap — no probation,
20477
+ * no auto-rollback).
20357
20478
  *
20358
20479
  * Providers:
20359
20480
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -20461,7 +20582,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
20461
20582
  /** Explicit target version; omitted = latest from the registry. */
20462
20583
  version: string().optional() }), ServerUpdateActionResultSchema, {
20463
20584
  kind: "mutation",
20464
- auth: "admin"
20585
+ auth: "admin",
20586
+ timeoutMs: 16 * 6e4
20465
20587
  }), method(_void(), ServerUpdateActionResultSchema, {
20466
20588
  kind: "mutation",
20467
20589
  auth: "admin"
@@ -21556,22 +21678,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
21556
21678
  var RestartAddonResultSchema = unknown();
21557
21679
  var InstallPackageResultSchema = unknown();
21558
21680
  var ReloadPackagesResultSchema = unknown();
21559
- /**
21560
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
21561
- * server restarts so the admin UI can react to the `restartingAt`
21562
- * timestamp (shows reconnect overlay). The transition from
21563
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
21564
- * `system.restart-completed` event after the new process boots.
21565
- *
21566
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
21567
- */
21568
- var UpdateFrameworkPackageResultSchema = object({
21569
- packageName: string(),
21570
- fromVersion: string(),
21571
- toVersion: string(),
21572
- /** Ms-epoch the server scheduled its self-restart. */
21573
- restartingAt: number()
21574
- });
21575
21681
  var BulkUpdateItemStatusSchema = _enum([
21576
21682
  "queued",
21577
21683
  "updating",
@@ -21699,13 +21805,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
21699
21805
  }), object({ success: literal(true) }), {
21700
21806
  kind: "mutation",
21701
21807
  auth: "admin"
21702
- }), method(object({
21703
- packageName: string().min(1),
21704
- version: string().optional(),
21705
- deferRestart: boolean().optional()
21706
- }), UpdateFrameworkPackageResultSchema, {
21707
- kind: "mutation",
21708
- auth: "admin"
21709
21808
  }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
21710
21809
  kind: "mutation",
21711
21810
  auth: "admin"
@@ -22622,10 +22721,10 @@ var TopologyCategorySchema = object({
22622
22721
  addons: array(TopologyCategoryAddonSchema).readonly()
22623
22722
  });
22624
22723
  /**
22625
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
22626
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
22627
- * version visibility for the Server management surface. Nullable: offline
22628
- * rows and pre-phase-2 nodes report none.
22724
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
22725
+ * root package for every node role) as reported by its `registerNode`
22726
+ * manifest — version visibility for the Server management surface. Nullable:
22727
+ * offline rows and nodes that never reported one.
22629
22728
  */
22630
22729
  var TopologyRootPackageSchema = object({
22631
22730
  name: string(),
@@ -23013,17 +23112,28 @@ var PlatformScoreSchema = object({
23013
23112
  format: _enum([
23014
23113
  "onnx",
23015
23114
  "coreml",
23016
- "openvino"
23115
+ "openvino",
23116
+ "tflite"
23017
23117
  ]),
23018
23118
  score: number(),
23019
23119
  reason: string(),
23020
23120
  available: boolean()
23021
23121
  });
23122
+ var InferenceDeviceDescriptorSchema = object({
23123
+ key: string(),
23124
+ backend: string(),
23125
+ device: string(),
23126
+ format: ModelFormatSchema,
23127
+ runtime: literal("python"),
23128
+ score: number(),
23129
+ available: boolean()
23130
+ });
23022
23131
  var PlatformCapabilitiesSchema = object({
23023
23132
  hardware: HardwareInfoSchema,
23024
23133
  scores: array(PlatformScoreSchema).readonly(),
23025
23134
  bestScore: PlatformScoreSchema,
23026
- pythonPath: string().nullable()
23135
+ pythonPath: string().nullable(),
23136
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
23027
23137
  });
23028
23138
  var ModelRequirementSchema = object({
23029
23139
  modelId: string(),
@@ -24180,12 +24290,6 @@ Object.freeze({
24180
24290
  addonId: null,
24181
24291
  access: "delete"
24182
24292
  },
24183
- "addons.updateFrameworkPackage": {
24184
- capName: "addons",
24185
- capScope: "system",
24186
- addonId: null,
24187
- access: "create"
24188
- },
24189
24293
  "addons.updatePackage": {
24190
24294
  capName: "addons",
24191
24295
  capScope: "system",
@@ -26958,12 +27062,6 @@ Object.freeze({
26958
27062
  addonId: null,
26959
27063
  access: "view"
26960
27064
  },
26961
- "pipelineExecutor.reprobeEngine": {
26962
- capName: "pipeline-executor",
26963
- capScope: "system",
26964
- addonId: null,
26965
- access: "create"
26966
- },
26967
27065
  "pipelineExecutor.runAudioTest": {
26968
27066
  capName: "pipeline-executor",
26969
27067
  capScope: "system",
@@ -27114,6 +27212,12 @@ Object.freeze({
27114
27212
  addonId: null,
27115
27213
  access: "view"
27116
27214
  },
27215
+ "pipelineOrchestrator.getNodeInferenceDevices": {
27216
+ capName: "pipeline-orchestrator",
27217
+ capScope: "system",
27218
+ addonId: null,
27219
+ access: "view"
27220
+ },
27117
27221
  "pipelineOrchestrator.getPipelineAssignment": {
27118
27222
  capName: "pipeline-orchestrator",
27119
27223
  capScope: "system",
@@ -27126,6 +27230,12 @@ Object.freeze({
27126
27230
  addonId: null,
27127
27231
  access: "view"
27128
27232
  },
27233
+ "pipelineOrchestrator.getPipelineDevicePin": {
27234
+ capName: "pipeline-orchestrator",
27235
+ capScope: "system",
27236
+ addonId: null,
27237
+ access: "view"
27238
+ },
27129
27239
  "pipelineOrchestrator.listAgentSettings": {
27130
27240
  capName: "pipeline-orchestrator",
27131
27241
  capScope: "system",
@@ -27168,19 +27278,19 @@ Object.freeze({
27168
27278
  addonId: null,
27169
27279
  access: "create"
27170
27280
  },
27171
- "pipelineOrchestrator.setAgentAddonDefaults": {
27281
+ "pipelineOrchestrator.setAgentCapabilities": {
27172
27282
  capName: "pipeline-orchestrator",
27173
27283
  capScope: "system",
27174
27284
  addonId: null,
27175
27285
  access: "create"
27176
27286
  },
27177
- "pipelineOrchestrator.setAgentCapabilities": {
27287
+ "pipelineOrchestrator.setAgentDetectWeight": {
27178
27288
  capName: "pipeline-orchestrator",
27179
27289
  capScope: "system",
27180
27290
  addonId: null,
27181
27291
  access: "create"
27182
27292
  },
27183
- "pipelineOrchestrator.setAgentDetectWeight": {
27293
+ "pipelineOrchestrator.setAgentInferenceDevices": {
27184
27294
  capName: "pipeline-orchestrator",
27185
27295
  capScope: "system",
27186
27296
  addonId: null,
@@ -27222,6 +27332,12 @@ Object.freeze({
27222
27332
  addonId: null,
27223
27333
  access: "create"
27224
27334
  },
27335
+ "pipelineOrchestrator.setPipelineDevicePin": {
27336
+ capName: "pipeline-orchestrator",
27337
+ capScope: "system",
27338
+ addonId: null,
27339
+ access: "create"
27340
+ },
27225
27341
  "pipelineOrchestrator.unassignAudio": {
27226
27342
  capName: "pipeline-orchestrator",
27227
27343
  capScope: "system",
@@ -28774,32 +28890,6 @@ Object.freeze({
28774
28890
  "network-access": "ingress",
28775
28891
  "smtp-provider": "email"
28776
28892
  });
28777
- var frameworkSwapPackageSchema = object({
28778
- name: string(),
28779
- stagedPath: string(),
28780
- backupPath: string(),
28781
- toVersion: string(),
28782
- fromVersion: string().nullable()
28783
- });
28784
- object({
28785
- jobId: string(),
28786
- taskId: string(),
28787
- packages: array(frameworkSwapPackageSchema),
28788
- requestedAtMs: number(),
28789
- schemaVersion: literal(1)
28790
- });
28791
- object({
28792
- jobId: string(),
28793
- taskId: string(),
28794
- backups: array(object({
28795
- name: string(),
28796
- backupPath: string(),
28797
- livePath: string()
28798
- })),
28799
- appliedAtMs: number(),
28800
- bootAttempts: number(),
28801
- schemaVersion: literal(1)
28802
- });
28803
28893
  //#endregion
28804
28894
  //#region ../../node_modules/undici/lib/core/symbols.js
28805
28895
  var require_symbols = /* @__PURE__ */ __commonJSMin(((exports, module) => {
@@ -223203,6 +223293,10 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
223203
223293
  emitDoorbellPressed(timestamp) {
223204
223294
  this.doorbellLastPressedAt = timestamp;
223205
223295
  this.doorbellPressCountSinceStart += 1;
223296
+ this.runtimeState.setCapState(doorbellCapability.name, {
223297
+ lastPressedAt: timestamp,
223298
+ pressCountSinceStart: this.doorbellPressCountSinceStart
223299
+ });
223206
223300
  this.ctx.eventBus.emit(createEvent(EventCategory.DoorbellOnPressed, this.eventSource(), {
223207
223301
  deviceId: this.id,
223208
223302
  timestamp
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-reolink",
3
- "version": "1.1.30",
3
+ "version": "1.2.0",
4
4
  "description": "Reolink camera device provider addon for CamStack — native Baichuan protocol",
5
5
  "keywords": [
6
6
  "camstack",