@camstack/addon-provider-wyze 0.1.25 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/addon.js +213 -106
  2. package/dist/addon.mjs +213 -106
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -7115,6 +7115,17 @@ var ModelCatalogEntrySchema = object({
7115
7115
  "imagenet",
7116
7116
  "none"
7117
7117
  ]).optional(),
7118
+ /**
7119
+ * The model already applies softmax IN-GRAPH — its raw output is a
7120
+ * probability distribution, not logits. When set, the `softmax`
7121
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7122
+ * probability vector collapses it toward uniform (top-1 score craters far
7123
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7124
+ * the output is raw logits and the postprocessor applies softmax (the normal
7125
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7126
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7127
+ */
7128
+ outputProbabilities: boolean().optional(),
7118
7129
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7119
7130
  /**
7120
7131
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -12405,10 +12416,7 @@ var ConfigUISchemaNullableBridge = custom();
12405
12416
  var InferenceCapabilitiesBridge = custom();
12406
12417
  var ModelAvailabilityListBridge = custom();
12407
12418
  var PipelineRunResultBridge = custom();
12408
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
12409
- kind: "mutation",
12410
- auth: "admin"
12411
- }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12419
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12412
12420
  modelId: string(),
12413
12421
  settings: record(string(), unknown()).readonly()
12414
12422
  }))), method(object({ steps: record(string(), object({
@@ -12468,13 +12476,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12468
12476
  * (inputClasses ≠ null) are skipped and served per-track via
12469
12477
  * pipelineRunner.runDetailSubtree (two-plane design).
12470
12478
  */
12471
- plane: _enum(["full", "frame"]).optional()
12479
+ plane: _enum(["full", "frame"]).optional(),
12480
+ /**
12481
+ * Inference-device selector (Phase 2 multi-device). Format
12482
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
12483
+ * Omitted ⇒ the runner's default device (current single-engine
12484
+ * behaviour). Selects WHICH device pool of the node runs the call.
12485
+ */
12486
+ deviceKey: string().optional()
12472
12487
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
12473
12488
  engine: PipelineEngineChoiceSchema.optional(),
12474
12489
  steps: array(PipelineStepInputSchema).min(1),
12475
12490
  frames: array(FrameInputSchema).min(1).max(255),
12476
12491
  deviceId: number().optional(),
12477
- sessionId: string().optional()
12492
+ sessionId: string().optional(),
12493
+ /**
12494
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
12495
+ * the batch to the Python pool's bench preprocess cache
12496
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
12497
+ * preprocessed ONCE and every later inference is a pure-inference cache
12498
+ * hit — the sustained-throughput run measures inference, not
12499
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
12500
+ * full preprocess every call, correct). Fresh per sustained run;
12501
+ * released via `uncacheFrame`.
12502
+ */
12503
+ frameId: number().int().nonnegative().optional(),
12504
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
12505
+ deviceKey: string().optional()
12478
12506
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
12479
12507
  data: _instanceof(Uint8Array),
12480
12508
  width: number().int().positive(),
@@ -12506,8 +12534,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12506
12534
  * - `runtime` — main camera-serving engine (no idle TTL).
12507
12535
  * - `warm-override` — benchmark/test override held in the warm
12508
12536
  * cache; auto-disposed after the idle TTL.
12537
+ * - `device-pool` — a concurrent per-device pool (Phase 2
12538
+ * multi-device, keyed by `deviceKey`) resolved
12539
+ * via `resolveDeviceFactory`. Runs alongside the
12540
+ * `runtime` engine on a DIFFERENT accelerator
12541
+ * (NPU / iGPU / Coral) — this is how the
12542
+ * Engines tab shows all pools running at once.
12509
12543
  */
12510
- kind: _enum(["runtime", "warm-override"]),
12544
+ kind: _enum([
12545
+ "runtime",
12546
+ "warm-override",
12547
+ "device-pool"
12548
+ ]),
12511
12549
  /** Native pid of the underlying Python pool (null when no pool). */
12512
12550
  poolPid: number().nullable(),
12513
12551
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -12642,7 +12680,21 @@ var NativeCropResultSchema = object({
12642
12680
  /** Packed rgb (24-bit) pixels of the crop. */
12643
12681
  bytes: _instanceof(Uint8Array),
12644
12682
  width: number().int().positive(),
12645
- height: number().int().positive()
12683
+ height: number().int().positive(),
12684
+ /**
12685
+ * Which source served this crop, so a quality-sensitive consumer (the native
12686
+ * `keyFrame`) can reject a degraded fallback:
12687
+ * - `native` — cut from the decode worker's retained NATIVE surface (the
12688
+ * quality path).
12689
+ * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
12690
+ * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
12691
+ * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
12692
+ *
12693
+ * OPTIONAL: a pre-tier runner (version skew) omits it — an ABSENT `tier` MUST be
12694
+ * treated as `native` (accepted) by every consumer so mixed-version clusters
12695
+ * keep the pre-tier behaviour. An ROI miss returns `null` (no tier at all).
12696
+ */
12697
+ tier: _enum(["native", "ram-fullframe"]).optional()
12646
12698
  });
12647
12699
  /** Parent detection context passed to `runDetailSubtree` — the crop's
12648
12700
  * originating detection, in FRAME-space coordinates. Reuses
@@ -12882,7 +12934,14 @@ var RunnerCameraConfigSchema = object({
12882
12934
  * camera's detect node differs from its source-owner (P2d, gated by the
12883
12935
  * `remoteSourcingNodes` rollout setting).
12884
12936
  */
12885
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
12937
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
12938
+ /**
12939
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
12940
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
12941
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
12942
+ * this only selects WHICH device pool of that node runs the session.
12943
+ */
12944
+ deviceKey: string().optional()
12886
12945
  });
12887
12946
  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;
12888
12947
  /**
@@ -12903,6 +12962,19 @@ var RunnerLocalLoadSchema = object({
12903
12962
  avgInferenceTimeMs: number(),
12904
12963
  /** Total queue depth across motion + detection queues. */
12905
12964
  queueDepthTotal: number(),
12965
+ /**
12966
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
12967
+ * this runner currently has attached cameras on, so the orchestrator's second
12968
+ * `balance()` pass (over a node's devices) weights on real per-pool session
12969
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
12970
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
12971
+ */
12972
+ devices: array(object({
12973
+ deviceKey: string(),
12974
+ backend: string(),
12975
+ attachedCameras: number(),
12976
+ queueDepthTotal: number()
12977
+ })).default([]),
12906
12978
  /** Hardware capability flags reported by this node. */
12907
12979
  hardware: object({
12908
12980
  hasGpu: boolean(),
@@ -16051,6 +16123,8 @@ var BaseDeviceProvider = class extends BaseAddon {
16051
16123
  return toDeviceSummary(device, this.addonId);
16052
16124
  }
16053
16125
  };
16126
+ 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;
16127
+ new Set(Object.values(DeviceType));
16054
16128
  /**
16055
16129
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
16056
16130
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -17641,7 +17715,8 @@ var LinkedDeviceSchema = object({
17641
17715
  deviceId: number(),
17642
17716
  name: string(),
17643
17717
  location: string().nullable(),
17644
- features: array(string())
17718
+ features: array(string()),
17719
+ producesTrackedEvents: boolean().optional()
17645
17720
  });
17646
17721
  var SavedDeviceRowSchema = object({
17647
17722
  /** Numeric id reserved at allocateDeviceId time. */
@@ -19271,6 +19346,7 @@ var TrackSchema = object({
19271
19346
  deviceId: number(),
19272
19347
  className: string(),
19273
19348
  label: string().optional(),
19349
+ producingDeviceName: string().optional(),
19274
19350
  /** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
19275
19351
  source: TrackSourceSchema.optional(),
19276
19352
  firstSeen: number(),
@@ -19408,7 +19484,8 @@ var MediaFileKindEnum = _enum([
19408
19484
  "fullFrameBoxed",
19409
19485
  "faceCrop",
19410
19486
  "plateCrop",
19411
- "keyFrame"
19487
+ "keyFrame",
19488
+ "keyFrameSmall"
19412
19489
  ]);
19413
19490
  var MediaFileSchema = object({
19414
19491
  key: string(),
@@ -19737,13 +19814,11 @@ var PipelineTemplateSchema = object({
19737
19814
  createdAt: string(),
19738
19815
  updatedAt: string()
19739
19816
  });
19740
- var AgentAddonConfigSchema = object({
19741
- enabled: boolean(),
19817
+ var DeviceStepConfigSchema = object({
19742
19818
  modelId: string().optional(),
19743
- settings: record(string(), unknown()).readonly()
19819
+ settings: record(string(), unknown()).optional()
19744
19820
  });
19745
19821
  var AgentPipelineSettingsSchema = object({
19746
- addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
19747
19822
  maxCameras: number().int().nonnegative().nullable().default(null),
19748
19823
  /** Per-node detection weight (relative share for the quota balancer). */
19749
19824
  detectWeight: number().positive().optional(),
@@ -19767,7 +19842,22 @@ var AgentPipelineSettingsSchema = object({
19767
19842
  * it already uses to reach the hub). Set this only when the auto-detected
19768
19843
  * address is wrong (multi-homed host, NAT, custom interface).
19769
19844
  */
19770
- reachableHost: string().optional()
19845
+ reachableHost: string().optional(),
19846
+ /**
19847
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
19848
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
19849
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
19850
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
19851
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
19852
+ * the default model/settings for every camera landing on that accelerator;
19853
+ * a stepId absent ⇒ the step uses that device's format default.
19854
+ */
19855
+ inferenceDevices: record(string(), object({
19856
+ enabled: boolean(),
19857
+ weight: number().positive().optional(),
19858
+ maxSessions: number().int().positive().optional(),
19859
+ steps: record(string(), DeviceStepConfigSchema).optional()
19860
+ })).optional()
19771
19861
  });
19772
19862
  var CameraPipelineForAgentSchema = object({
19773
19863
  steps: array(PipelineStepInputSchema).readonly(),
@@ -19777,14 +19867,13 @@ var CameraPipelineForAgentSchema = object({
19777
19867
  }).nullable()
19778
19868
  });
19779
19869
  var CameraStepOverridePatchSchema = object({
19780
- enabled: boolean().optional(),
19781
19870
  modelId: string().optional(),
19782
19871
  settings: record(string(), unknown()).readonly().optional()
19783
19872
  });
19784
19873
  var CameraPipelineSettingsSchema = object({
19785
19874
  pinnedAgentNodeId: string().optional(),
19786
19875
  stepToggles: record(string(), boolean()).optional(),
19787
- stepOverridesByAgent: record(string(), record(string(), CameraStepOverridePatchSchema)).optional(),
19876
+ stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
19788
19877
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
19789
19878
  });
19790
19879
  /**
@@ -19998,6 +20087,44 @@ var CameraStatusSchema = object({
19998
20087
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
19999
20088
  fetchedAt: number()
20000
20089
  });
20090
+ var NodeInferenceDeviceSchema = object({
20091
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
20092
+ key: string(),
20093
+ backend: string(),
20094
+ device: string(),
20095
+ format: _enum(MODEL_FORMATS),
20096
+ /** Whether the node's live probe reports the device as usable right now. */
20097
+ available: boolean(),
20098
+ /**
20099
+ * Whether this device participates in dispatch. AUTO default (spec C2):
20100
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
20101
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
20102
+ * not a balanced target). An explicit stored value always wins; a stored-only
20103
+ * (unavailable) key keeps its stored value.
20104
+ */
20105
+ enabled: boolean(),
20106
+ /** Relative balancer weight for the enabled device (default 1). */
20107
+ weight: number(),
20108
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
20109
+ maxSessions: number().nullable(),
20110
+ /** Object-detection model the executor defaults to for this deviceKey. */
20111
+ defaultModelId: string(),
20112
+ /**
20113
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
20114
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
20115
+ * Absent/empty ⇒ no base (every step uses its device format default). The
20116
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
20117
+ * available per format; this is the stored selection that becomes the
20118
+ * default for EVERY camera landing on this accelerator.
20119
+ */
20120
+ steps: record(string(), DeviceStepConfigSchema).optional()
20121
+ });
20122
+ var NodeInferenceDevicesSchema = object({
20123
+ nodeId: string(),
20124
+ /** False when the node's platform-probe was unreachable (no live device set). */
20125
+ reachable: boolean(),
20126
+ devices: array(NodeInferenceDeviceSchema).readonly()
20127
+ });
20001
20128
  method(object({
20002
20129
  deviceId: number(),
20003
20130
  agentNodeId: string()
@@ -20007,7 +20134,13 @@ method(object({
20007
20134
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
20008
20135
  kind: "mutation",
20009
20136
  auth: "admin"
20010
- }), method(_void(), object({ migrated: number() }), {
20137
+ }), method(object({
20138
+ deviceId: number(),
20139
+ deviceKey: string()
20140
+ }), object({ success: literal(true) }), {
20141
+ kind: "mutation",
20142
+ auth: "admin"
20143
+ }), method(object({ deviceId: number() }), object({ deviceKey: string().nullable() })), method(_void(), object({ migrated: number() }), {
20011
20144
  kind: "mutation",
20012
20145
  auth: "admin"
20013
20146
  }), 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({
@@ -20041,13 +20174,7 @@ method(object({
20041
20174
  }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
20042
20175
  nodeId: string(),
20043
20176
  settings: AgentPipelineSettingsSchema
20044
- })).readonly()), method(object({
20045
- agentNodeId: string(),
20046
- defaults: record(string(), AgentAddonConfigSchema)
20047
- }), object({ success: literal(true) }), {
20048
- kind: "mutation",
20049
- auth: "admin"
20050
- }), method(object({ agentNodeId: string() }), object({
20177
+ })).readonly()), method(object({ agentNodeId: string() }), object({
20051
20178
  success: boolean(),
20052
20179
  removed: boolean()
20053
20180
  }), {
@@ -20079,7 +20206,18 @@ method(object({
20079
20206
  }), object({ success: literal(true) }), {
20080
20207
  kind: "mutation",
20081
20208
  auth: "admin"
20082
- }), method(object({ agentNodeId: string() }), object({
20209
+ }), method(object({
20210
+ agentNodeId: string(),
20211
+ inferenceDevices: record(string(), object({
20212
+ enabled: boolean(),
20213
+ weight: number().positive().optional(),
20214
+ maxSessions: number().int().positive().optional(),
20215
+ steps: record(string(), DeviceStepConfigSchema).optional()
20216
+ }))
20217
+ }), object({ success: literal(true) }), {
20218
+ kind: "mutation",
20219
+ auth: "admin"
20220
+ }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string() }), object({
20083
20221
  success: literal(true),
20084
20222
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
20085
20223
  effectiveModelId: string().nullable(),
@@ -20095,9 +20233,10 @@ method(object({
20095
20233
  }), object({ success: literal(true) }), {
20096
20234
  kind: "mutation",
20097
20235
  auth: "admin"
20098
- }), method(object({ deviceId: number() }), record(string(), record(string(), CameraStepOverridePatchSchema)).nullable()), method(object({
20236
+ }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
20099
20237
  deviceId: number(),
20100
20238
  agentNodeId: string(),
20239
+ deviceKey: string(),
20101
20240
  addonId: string(),
20102
20241
  patch: CameraStepOverridePatchSchema.nullable()
20103
20242
  }), object({ success: literal(true) }), {
@@ -20134,14 +20273,13 @@ method(object({
20134
20273
  });
20135
20274
  /**
20136
20275
  * server-management — per-NODE singleton capability for a node's ROOT
20137
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
20138
- * agents).
20276
+ * package lifecycle (runtime-updatable node packages).
20139
20277
  *
20140
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
20141
- * on agents) carries the whole software stack in its npm dep tree, so ONE
20142
- * version describes the node. Updates install into
20143
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
20144
- * starter (probation boot + auto-rollback to N-1).
20278
+ * Every node role runs the SAME root package (`@camstack/server`), which
20279
+ * carries the whole software stack in its npm dep tree, so ONE version
20280
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
20281
+ * on restart via the baked starter (single-copy in-place swap — no probation,
20282
+ * no auto-rollback).
20145
20283
  *
20146
20284
  * Providers:
20147
20285
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -20249,7 +20387,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
20249
20387
  /** Explicit target version; omitted = latest from the registry. */
20250
20388
  version: string().optional() }), ServerUpdateActionResultSchema, {
20251
20389
  kind: "mutation",
20252
- auth: "admin"
20390
+ auth: "admin",
20391
+ timeoutMs: 16 * 6e4
20253
20392
  }), method(_void(), ServerUpdateActionResultSchema, {
20254
20393
  kind: "mutation",
20255
20394
  auth: "admin"
@@ -21344,22 +21483,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
21344
21483
  var RestartAddonResultSchema = unknown();
21345
21484
  var InstallPackageResultSchema = unknown();
21346
21485
  var ReloadPackagesResultSchema = unknown();
21347
- /**
21348
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
21349
- * server restarts so the admin UI can react to the `restartingAt`
21350
- * timestamp (shows reconnect overlay). The transition from
21351
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
21352
- * `system.restart-completed` event after the new process boots.
21353
- *
21354
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
21355
- */
21356
- var UpdateFrameworkPackageResultSchema = object({
21357
- packageName: string(),
21358
- fromVersion: string(),
21359
- toVersion: string(),
21360
- /** Ms-epoch the server scheduled its self-restart. */
21361
- restartingAt: number()
21362
- });
21363
21486
  var BulkUpdateItemStatusSchema = _enum([
21364
21487
  "queued",
21365
21488
  "updating",
@@ -21487,13 +21610,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
21487
21610
  }), object({ success: literal(true) }), {
21488
21611
  kind: "mutation",
21489
21612
  auth: "admin"
21490
- }), method(object({
21491
- packageName: string().min(1),
21492
- version: string().optional(),
21493
- deferRestart: boolean().optional()
21494
- }), UpdateFrameworkPackageResultSchema, {
21495
- kind: "mutation",
21496
- auth: "admin"
21497
21613
  }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
21498
21614
  kind: "mutation",
21499
21615
  auth: "admin"
@@ -22410,10 +22526,10 @@ var TopologyCategorySchema = object({
22410
22526
  addons: array(TopologyCategoryAddonSchema).readonly()
22411
22527
  });
22412
22528
  /**
22413
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
22414
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
22415
- * version visibility for the Server management surface. Nullable: offline
22416
- * rows and pre-phase-2 nodes report none.
22529
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
22530
+ * root package for every node role) as reported by its `registerNode`
22531
+ * manifest — version visibility for the Server management surface. Nullable:
22532
+ * offline rows and nodes that never reported one.
22417
22533
  */
22418
22534
  var TopologyRootPackageSchema = object({
22419
22535
  name: string(),
@@ -22801,17 +22917,28 @@ var PlatformScoreSchema = object({
22801
22917
  format: _enum([
22802
22918
  "onnx",
22803
22919
  "coreml",
22804
- "openvino"
22920
+ "openvino",
22921
+ "tflite"
22805
22922
  ]),
22806
22923
  score: number(),
22807
22924
  reason: string(),
22808
22925
  available: boolean()
22809
22926
  });
22927
+ var InferenceDeviceDescriptorSchema = object({
22928
+ key: string(),
22929
+ backend: string(),
22930
+ device: string(),
22931
+ format: ModelFormatSchema,
22932
+ runtime: literal("python"),
22933
+ score: number(),
22934
+ available: boolean()
22935
+ });
22810
22936
  var PlatformCapabilitiesSchema = object({
22811
22937
  hardware: HardwareInfoSchema,
22812
22938
  scores: array(PlatformScoreSchema).readonly(),
22813
22939
  bestScore: PlatformScoreSchema,
22814
- pythonPath: string().nullable()
22940
+ pythonPath: string().nullable(),
22941
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
22815
22942
  });
22816
22943
  var ModelRequirementSchema = object({
22817
22944
  modelId: string(),
@@ -23703,12 +23830,6 @@ Object.freeze({
23703
23830
  addonId: null,
23704
23831
  access: "delete"
23705
23832
  },
23706
- "addons.updateFrameworkPackage": {
23707
- capName: "addons",
23708
- capScope: "system",
23709
- addonId: null,
23710
- access: "create"
23711
- },
23712
23833
  "addons.updatePackage": {
23713
23834
  capName: "addons",
23714
23835
  capScope: "system",
@@ -26481,12 +26602,6 @@ Object.freeze({
26481
26602
  addonId: null,
26482
26603
  access: "view"
26483
26604
  },
26484
- "pipelineExecutor.reprobeEngine": {
26485
- capName: "pipeline-executor",
26486
- capScope: "system",
26487
- addonId: null,
26488
- access: "create"
26489
- },
26490
26605
  "pipelineExecutor.runAudioTest": {
26491
26606
  capName: "pipeline-executor",
26492
26607
  capScope: "system",
@@ -26637,6 +26752,12 @@ Object.freeze({
26637
26752
  addonId: null,
26638
26753
  access: "view"
26639
26754
  },
26755
+ "pipelineOrchestrator.getNodeInferenceDevices": {
26756
+ capName: "pipeline-orchestrator",
26757
+ capScope: "system",
26758
+ addonId: null,
26759
+ access: "view"
26760
+ },
26640
26761
  "pipelineOrchestrator.getPipelineAssignment": {
26641
26762
  capName: "pipeline-orchestrator",
26642
26763
  capScope: "system",
@@ -26649,6 +26770,12 @@ Object.freeze({
26649
26770
  addonId: null,
26650
26771
  access: "view"
26651
26772
  },
26773
+ "pipelineOrchestrator.getPipelineDevicePin": {
26774
+ capName: "pipeline-orchestrator",
26775
+ capScope: "system",
26776
+ addonId: null,
26777
+ access: "view"
26778
+ },
26652
26779
  "pipelineOrchestrator.listAgentSettings": {
26653
26780
  capName: "pipeline-orchestrator",
26654
26781
  capScope: "system",
@@ -26691,19 +26818,19 @@ Object.freeze({
26691
26818
  addonId: null,
26692
26819
  access: "create"
26693
26820
  },
26694
- "pipelineOrchestrator.setAgentAddonDefaults": {
26821
+ "pipelineOrchestrator.setAgentCapabilities": {
26695
26822
  capName: "pipeline-orchestrator",
26696
26823
  capScope: "system",
26697
26824
  addonId: null,
26698
26825
  access: "create"
26699
26826
  },
26700
- "pipelineOrchestrator.setAgentCapabilities": {
26827
+ "pipelineOrchestrator.setAgentDetectWeight": {
26701
26828
  capName: "pipeline-orchestrator",
26702
26829
  capScope: "system",
26703
26830
  addonId: null,
26704
26831
  access: "create"
26705
26832
  },
26706
- "pipelineOrchestrator.setAgentDetectWeight": {
26833
+ "pipelineOrchestrator.setAgentInferenceDevices": {
26707
26834
  capName: "pipeline-orchestrator",
26708
26835
  capScope: "system",
26709
26836
  addonId: null,
@@ -26745,6 +26872,12 @@ Object.freeze({
26745
26872
  addonId: null,
26746
26873
  access: "create"
26747
26874
  },
26875
+ "pipelineOrchestrator.setPipelineDevicePin": {
26876
+ capName: "pipeline-orchestrator",
26877
+ capScope: "system",
26878
+ addonId: null,
26879
+ access: "create"
26880
+ },
26748
26881
  "pipelineOrchestrator.unassignAudio": {
26749
26882
  capName: "pipeline-orchestrator",
26750
26883
  capScope: "system",
@@ -28297,32 +28430,6 @@ Object.freeze({
28297
28430
  "network-access": "ingress",
28298
28431
  "smtp-provider": "email"
28299
28432
  });
28300
- var frameworkSwapPackageSchema = object({
28301
- name: string(),
28302
- stagedPath: string(),
28303
- backupPath: string(),
28304
- toVersion: string(),
28305
- fromVersion: string().nullable()
28306
- });
28307
- object({
28308
- jobId: string(),
28309
- taskId: string(),
28310
- packages: array(frameworkSwapPackageSchema),
28311
- requestedAtMs: number(),
28312
- schemaVersion: literal(1)
28313
- });
28314
- object({
28315
- jobId: string(),
28316
- taskId: string(),
28317
- backups: array(object({
28318
- name: string(),
28319
- backupPath: string(),
28320
- livePath: string()
28321
- })),
28322
- appliedAtMs: number(),
28323
- bootAttempts: number(),
28324
- schemaVersion: literal(1)
28325
- });
28326
28433
  //#endregion
28327
28434
  //#region ../../node_modules/@apocaliss92/wyze-bridge-js/dist/index.js
28328
28435
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
package/dist/addon.mjs CHANGED
@@ -7094,6 +7094,17 @@ var ModelCatalogEntrySchema = object({
7094
7094
  "imagenet",
7095
7095
  "none"
7096
7096
  ]).optional(),
7097
+ /**
7098
+ * The model already applies softmax IN-GRAPH — its raw output is a
7099
+ * probability distribution, not logits. When set, the `softmax`
7100
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7101
+ * probability vector collapses it toward uniform (top-1 score craters far
7102
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7103
+ * the output is raw logits and the postprocessor applies softmax (the normal
7104
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7105
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7106
+ */
7107
+ outputProbabilities: boolean().optional(),
7097
7108
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7098
7109
  /**
7099
7110
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -12384,10 +12395,7 @@ var ConfigUISchemaNullableBridge = custom();
12384
12395
  var InferenceCapabilitiesBridge = custom();
12385
12396
  var ModelAvailabilityListBridge = custom();
12386
12397
  var PipelineRunResultBridge = custom();
12387
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
12388
- kind: "mutation",
12389
- auth: "admin"
12390
- }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12398
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12391
12399
  modelId: string(),
12392
12400
  settings: record(string(), unknown()).readonly()
12393
12401
  }))), method(object({ steps: record(string(), object({
@@ -12447,13 +12455,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12447
12455
  * (inputClasses ≠ null) are skipped and served per-track via
12448
12456
  * pipelineRunner.runDetailSubtree (two-plane design).
12449
12457
  */
12450
- plane: _enum(["full", "frame"]).optional()
12458
+ plane: _enum(["full", "frame"]).optional(),
12459
+ /**
12460
+ * Inference-device selector (Phase 2 multi-device). Format
12461
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
12462
+ * Omitted ⇒ the runner's default device (current single-engine
12463
+ * behaviour). Selects WHICH device pool of the node runs the call.
12464
+ */
12465
+ deviceKey: string().optional()
12451
12466
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
12452
12467
  engine: PipelineEngineChoiceSchema.optional(),
12453
12468
  steps: array(PipelineStepInputSchema).min(1),
12454
12469
  frames: array(FrameInputSchema).min(1).max(255),
12455
12470
  deviceId: number().optional(),
12456
- sessionId: string().optional()
12471
+ sessionId: string().optional(),
12472
+ /**
12473
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
12474
+ * the batch to the Python pool's bench preprocess cache
12475
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
12476
+ * preprocessed ONCE and every later inference is a pure-inference cache
12477
+ * hit — the sustained-throughput run measures inference, not
12478
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
12479
+ * full preprocess every call, correct). Fresh per sustained run;
12480
+ * released via `uncacheFrame`.
12481
+ */
12482
+ frameId: number().int().nonnegative().optional(),
12483
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
12484
+ deviceKey: string().optional()
12457
12485
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
12458
12486
  data: _instanceof(Uint8Array),
12459
12487
  width: number().int().positive(),
@@ -12485,8 +12513,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12485
12513
  * - `runtime` — main camera-serving engine (no idle TTL).
12486
12514
  * - `warm-override` — benchmark/test override held in the warm
12487
12515
  * cache; auto-disposed after the idle TTL.
12516
+ * - `device-pool` — a concurrent per-device pool (Phase 2
12517
+ * multi-device, keyed by `deviceKey`) resolved
12518
+ * via `resolveDeviceFactory`. Runs alongside the
12519
+ * `runtime` engine on a DIFFERENT accelerator
12520
+ * (NPU / iGPU / Coral) — this is how the
12521
+ * Engines tab shows all pools running at once.
12488
12522
  */
12489
- kind: _enum(["runtime", "warm-override"]),
12523
+ kind: _enum([
12524
+ "runtime",
12525
+ "warm-override",
12526
+ "device-pool"
12527
+ ]),
12490
12528
  /** Native pid of the underlying Python pool (null when no pool). */
12491
12529
  poolPid: number().nullable(),
12492
12530
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -12621,7 +12659,21 @@ var NativeCropResultSchema = object({
12621
12659
  /** Packed rgb (24-bit) pixels of the crop. */
12622
12660
  bytes: _instanceof(Uint8Array),
12623
12661
  width: number().int().positive(),
12624
- height: number().int().positive()
12662
+ height: number().int().positive(),
12663
+ /**
12664
+ * Which source served this crop, so a quality-sensitive consumer (the native
12665
+ * `keyFrame`) can reject a degraded fallback:
12666
+ * - `native` — cut from the decode worker's retained NATIVE surface (the
12667
+ * quality path).
12668
+ * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
12669
+ * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
12670
+ * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
12671
+ *
12672
+ * OPTIONAL: a pre-tier runner (version skew) omits it — an ABSENT `tier` MUST be
12673
+ * treated as `native` (accepted) by every consumer so mixed-version clusters
12674
+ * keep the pre-tier behaviour. An ROI miss returns `null` (no tier at all).
12675
+ */
12676
+ tier: _enum(["native", "ram-fullframe"]).optional()
12625
12677
  });
12626
12678
  /** Parent detection context passed to `runDetailSubtree` — the crop's
12627
12679
  * originating detection, in FRAME-space coordinates. Reuses
@@ -12861,7 +12913,14 @@ var RunnerCameraConfigSchema = object({
12861
12913
  * camera's detect node differs from its source-owner (P2d, gated by the
12862
12914
  * `remoteSourcingNodes` rollout setting).
12863
12915
  */
12864
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
12916
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
12917
+ /**
12918
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
12919
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
12920
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
12921
+ * this only selects WHICH device pool of that node runs the session.
12922
+ */
12923
+ deviceKey: string().optional()
12865
12924
  });
12866
12925
  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;
12867
12926
  /**
@@ -12882,6 +12941,19 @@ var RunnerLocalLoadSchema = object({
12882
12941
  avgInferenceTimeMs: number(),
12883
12942
  /** Total queue depth across motion + detection queues. */
12884
12943
  queueDepthTotal: number(),
12944
+ /**
12945
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
12946
+ * this runner currently has attached cameras on, so the orchestrator's second
12947
+ * `balance()` pass (over a node's devices) weights on real per-pool session
12948
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
12949
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
12950
+ */
12951
+ devices: array(object({
12952
+ deviceKey: string(),
12953
+ backend: string(),
12954
+ attachedCameras: number(),
12955
+ queueDepthTotal: number()
12956
+ })).default([]),
12885
12957
  /** Hardware capability flags reported by this node. */
12886
12958
  hardware: object({
12887
12959
  hasGpu: boolean(),
@@ -16030,6 +16102,8 @@ var BaseDeviceProvider = class extends BaseAddon {
16030
16102
  return toDeviceSummary(device, this.addonId);
16031
16103
  }
16032
16104
  };
16105
+ 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;
16106
+ new Set(Object.values(DeviceType));
16033
16107
  /**
16034
16108
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
16035
16109
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -17620,7 +17694,8 @@ var LinkedDeviceSchema = object({
17620
17694
  deviceId: number(),
17621
17695
  name: string(),
17622
17696
  location: string().nullable(),
17623
- features: array(string())
17697
+ features: array(string()),
17698
+ producesTrackedEvents: boolean().optional()
17624
17699
  });
17625
17700
  var SavedDeviceRowSchema = object({
17626
17701
  /** Numeric id reserved at allocateDeviceId time. */
@@ -19250,6 +19325,7 @@ var TrackSchema = object({
19250
19325
  deviceId: number(),
19251
19326
  className: string(),
19252
19327
  label: string().optional(),
19328
+ producingDeviceName: string().optional(),
19253
19329
  /** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
19254
19330
  source: TrackSourceSchema.optional(),
19255
19331
  firstSeen: number(),
@@ -19387,7 +19463,8 @@ var MediaFileKindEnum = _enum([
19387
19463
  "fullFrameBoxed",
19388
19464
  "faceCrop",
19389
19465
  "plateCrop",
19390
- "keyFrame"
19466
+ "keyFrame",
19467
+ "keyFrameSmall"
19391
19468
  ]);
19392
19469
  var MediaFileSchema = object({
19393
19470
  key: string(),
@@ -19716,13 +19793,11 @@ var PipelineTemplateSchema = object({
19716
19793
  createdAt: string(),
19717
19794
  updatedAt: string()
19718
19795
  });
19719
- var AgentAddonConfigSchema = object({
19720
- enabled: boolean(),
19796
+ var DeviceStepConfigSchema = object({
19721
19797
  modelId: string().optional(),
19722
- settings: record(string(), unknown()).readonly()
19798
+ settings: record(string(), unknown()).optional()
19723
19799
  });
19724
19800
  var AgentPipelineSettingsSchema = object({
19725
- addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
19726
19801
  maxCameras: number().int().nonnegative().nullable().default(null),
19727
19802
  /** Per-node detection weight (relative share for the quota balancer). */
19728
19803
  detectWeight: number().positive().optional(),
@@ -19746,7 +19821,22 @@ var AgentPipelineSettingsSchema = object({
19746
19821
  * it already uses to reach the hub). Set this only when the auto-detected
19747
19822
  * address is wrong (multi-homed host, NAT, custom interface).
19748
19823
  */
19749
- reachableHost: string().optional()
19824
+ reachableHost: string().optional(),
19825
+ /**
19826
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
19827
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
19828
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
19829
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
19830
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
19831
+ * the default model/settings for every camera landing on that accelerator;
19832
+ * a stepId absent ⇒ the step uses that device's format default.
19833
+ */
19834
+ inferenceDevices: record(string(), object({
19835
+ enabled: boolean(),
19836
+ weight: number().positive().optional(),
19837
+ maxSessions: number().int().positive().optional(),
19838
+ steps: record(string(), DeviceStepConfigSchema).optional()
19839
+ })).optional()
19750
19840
  });
19751
19841
  var CameraPipelineForAgentSchema = object({
19752
19842
  steps: array(PipelineStepInputSchema).readonly(),
@@ -19756,14 +19846,13 @@ var CameraPipelineForAgentSchema = object({
19756
19846
  }).nullable()
19757
19847
  });
19758
19848
  var CameraStepOverridePatchSchema = object({
19759
- enabled: boolean().optional(),
19760
19849
  modelId: string().optional(),
19761
19850
  settings: record(string(), unknown()).readonly().optional()
19762
19851
  });
19763
19852
  var CameraPipelineSettingsSchema = object({
19764
19853
  pinnedAgentNodeId: string().optional(),
19765
19854
  stepToggles: record(string(), boolean()).optional(),
19766
- stepOverridesByAgent: record(string(), record(string(), CameraStepOverridePatchSchema)).optional(),
19855
+ stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
19767
19856
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
19768
19857
  });
19769
19858
  /**
@@ -19977,6 +20066,44 @@ var CameraStatusSchema = object({
19977
20066
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
19978
20067
  fetchedAt: number()
19979
20068
  });
20069
+ var NodeInferenceDeviceSchema = object({
20070
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
20071
+ key: string(),
20072
+ backend: string(),
20073
+ device: string(),
20074
+ format: _enum(MODEL_FORMATS),
20075
+ /** Whether the node's live probe reports the device as usable right now. */
20076
+ available: boolean(),
20077
+ /**
20078
+ * Whether this device participates in dispatch. AUTO default (spec C2):
20079
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
20080
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
20081
+ * not a balanced target). An explicit stored value always wins; a stored-only
20082
+ * (unavailable) key keeps its stored value.
20083
+ */
20084
+ enabled: boolean(),
20085
+ /** Relative balancer weight for the enabled device (default 1). */
20086
+ weight: number(),
20087
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
20088
+ maxSessions: number().nullable(),
20089
+ /** Object-detection model the executor defaults to for this deviceKey. */
20090
+ defaultModelId: string(),
20091
+ /**
20092
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
20093
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
20094
+ * Absent/empty ⇒ no base (every step uses its device format default). The
20095
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
20096
+ * available per format; this is the stored selection that becomes the
20097
+ * default for EVERY camera landing on this accelerator.
20098
+ */
20099
+ steps: record(string(), DeviceStepConfigSchema).optional()
20100
+ });
20101
+ var NodeInferenceDevicesSchema = object({
20102
+ nodeId: string(),
20103
+ /** False when the node's platform-probe was unreachable (no live device set). */
20104
+ reachable: boolean(),
20105
+ devices: array(NodeInferenceDeviceSchema).readonly()
20106
+ });
19980
20107
  method(object({
19981
20108
  deviceId: number(),
19982
20109
  agentNodeId: string()
@@ -19986,7 +20113,13 @@ method(object({
19986
20113
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
19987
20114
  kind: "mutation",
19988
20115
  auth: "admin"
19989
- }), method(_void(), object({ migrated: number() }), {
20116
+ }), method(object({
20117
+ deviceId: number(),
20118
+ deviceKey: string()
20119
+ }), object({ success: literal(true) }), {
20120
+ kind: "mutation",
20121
+ auth: "admin"
20122
+ }), method(object({ deviceId: number() }), object({ deviceKey: string().nullable() })), method(_void(), object({ migrated: number() }), {
19990
20123
  kind: "mutation",
19991
20124
  auth: "admin"
19992
20125
  }), 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({
@@ -20020,13 +20153,7 @@ method(object({
20020
20153
  }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
20021
20154
  nodeId: string(),
20022
20155
  settings: AgentPipelineSettingsSchema
20023
- })).readonly()), method(object({
20024
- agentNodeId: string(),
20025
- defaults: record(string(), AgentAddonConfigSchema)
20026
- }), object({ success: literal(true) }), {
20027
- kind: "mutation",
20028
- auth: "admin"
20029
- }), method(object({ agentNodeId: string() }), object({
20156
+ })).readonly()), method(object({ agentNodeId: string() }), object({
20030
20157
  success: boolean(),
20031
20158
  removed: boolean()
20032
20159
  }), {
@@ -20058,7 +20185,18 @@ method(object({
20058
20185
  }), object({ success: literal(true) }), {
20059
20186
  kind: "mutation",
20060
20187
  auth: "admin"
20061
- }), method(object({ agentNodeId: string() }), object({
20188
+ }), method(object({
20189
+ agentNodeId: string(),
20190
+ inferenceDevices: record(string(), object({
20191
+ enabled: boolean(),
20192
+ weight: number().positive().optional(),
20193
+ maxSessions: number().int().positive().optional(),
20194
+ steps: record(string(), DeviceStepConfigSchema).optional()
20195
+ }))
20196
+ }), object({ success: literal(true) }), {
20197
+ kind: "mutation",
20198
+ auth: "admin"
20199
+ }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string() }), object({
20062
20200
  success: literal(true),
20063
20201
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
20064
20202
  effectiveModelId: string().nullable(),
@@ -20074,9 +20212,10 @@ method(object({
20074
20212
  }), object({ success: literal(true) }), {
20075
20213
  kind: "mutation",
20076
20214
  auth: "admin"
20077
- }), method(object({ deviceId: number() }), record(string(), record(string(), CameraStepOverridePatchSchema)).nullable()), method(object({
20215
+ }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
20078
20216
  deviceId: number(),
20079
20217
  agentNodeId: string(),
20218
+ deviceKey: string(),
20080
20219
  addonId: string(),
20081
20220
  patch: CameraStepOverridePatchSchema.nullable()
20082
20221
  }), object({ success: literal(true) }), {
@@ -20113,14 +20252,13 @@ method(object({
20113
20252
  });
20114
20253
  /**
20115
20254
  * server-management — per-NODE singleton capability for a node's ROOT
20116
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
20117
- * agents).
20255
+ * package lifecycle (runtime-updatable node packages).
20118
20256
  *
20119
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
20120
- * on agents) carries the whole software stack in its npm dep tree, so ONE
20121
- * version describes the node. Updates install into
20122
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
20123
- * starter (probation boot + auto-rollback to N-1).
20257
+ * Every node role runs the SAME root package (`@camstack/server`), which
20258
+ * carries the whole software stack in its npm dep tree, so ONE version
20259
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
20260
+ * on restart via the baked starter (single-copy in-place swap — no probation,
20261
+ * no auto-rollback).
20124
20262
  *
20125
20263
  * Providers:
20126
20264
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -20228,7 +20366,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
20228
20366
  /** Explicit target version; omitted = latest from the registry. */
20229
20367
  version: string().optional() }), ServerUpdateActionResultSchema, {
20230
20368
  kind: "mutation",
20231
- auth: "admin"
20369
+ auth: "admin",
20370
+ timeoutMs: 16 * 6e4
20232
20371
  }), method(_void(), ServerUpdateActionResultSchema, {
20233
20372
  kind: "mutation",
20234
20373
  auth: "admin"
@@ -21323,22 +21462,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
21323
21462
  var RestartAddonResultSchema = unknown();
21324
21463
  var InstallPackageResultSchema = unknown();
21325
21464
  var ReloadPackagesResultSchema = unknown();
21326
- /**
21327
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
21328
- * server restarts so the admin UI can react to the `restartingAt`
21329
- * timestamp (shows reconnect overlay). The transition from
21330
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
21331
- * `system.restart-completed` event after the new process boots.
21332
- *
21333
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
21334
- */
21335
- var UpdateFrameworkPackageResultSchema = object({
21336
- packageName: string(),
21337
- fromVersion: string(),
21338
- toVersion: string(),
21339
- /** Ms-epoch the server scheduled its self-restart. */
21340
- restartingAt: number()
21341
- });
21342
21465
  var BulkUpdateItemStatusSchema = _enum([
21343
21466
  "queued",
21344
21467
  "updating",
@@ -21466,13 +21589,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
21466
21589
  }), object({ success: literal(true) }), {
21467
21590
  kind: "mutation",
21468
21591
  auth: "admin"
21469
- }), method(object({
21470
- packageName: string().min(1),
21471
- version: string().optional(),
21472
- deferRestart: boolean().optional()
21473
- }), UpdateFrameworkPackageResultSchema, {
21474
- kind: "mutation",
21475
- auth: "admin"
21476
21592
  }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
21477
21593
  kind: "mutation",
21478
21594
  auth: "admin"
@@ -22389,10 +22505,10 @@ var TopologyCategorySchema = object({
22389
22505
  addons: array(TopologyCategoryAddonSchema).readonly()
22390
22506
  });
22391
22507
  /**
22392
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
22393
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
22394
- * version visibility for the Server management surface. Nullable: offline
22395
- * rows and pre-phase-2 nodes report none.
22508
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
22509
+ * root package for every node role) as reported by its `registerNode`
22510
+ * manifest — version visibility for the Server management surface. Nullable:
22511
+ * offline rows and nodes that never reported one.
22396
22512
  */
22397
22513
  var TopologyRootPackageSchema = object({
22398
22514
  name: string(),
@@ -22780,17 +22896,28 @@ var PlatformScoreSchema = object({
22780
22896
  format: _enum([
22781
22897
  "onnx",
22782
22898
  "coreml",
22783
- "openvino"
22899
+ "openvino",
22900
+ "tflite"
22784
22901
  ]),
22785
22902
  score: number(),
22786
22903
  reason: string(),
22787
22904
  available: boolean()
22788
22905
  });
22906
+ var InferenceDeviceDescriptorSchema = object({
22907
+ key: string(),
22908
+ backend: string(),
22909
+ device: string(),
22910
+ format: ModelFormatSchema,
22911
+ runtime: literal("python"),
22912
+ score: number(),
22913
+ available: boolean()
22914
+ });
22789
22915
  var PlatformCapabilitiesSchema = object({
22790
22916
  hardware: HardwareInfoSchema,
22791
22917
  scores: array(PlatformScoreSchema).readonly(),
22792
22918
  bestScore: PlatformScoreSchema,
22793
- pythonPath: string().nullable()
22919
+ pythonPath: string().nullable(),
22920
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
22794
22921
  });
22795
22922
  var ModelRequirementSchema = object({
22796
22923
  modelId: string(),
@@ -23682,12 +23809,6 @@ Object.freeze({
23682
23809
  addonId: null,
23683
23810
  access: "delete"
23684
23811
  },
23685
- "addons.updateFrameworkPackage": {
23686
- capName: "addons",
23687
- capScope: "system",
23688
- addonId: null,
23689
- access: "create"
23690
- },
23691
23812
  "addons.updatePackage": {
23692
23813
  capName: "addons",
23693
23814
  capScope: "system",
@@ -26460,12 +26581,6 @@ Object.freeze({
26460
26581
  addonId: null,
26461
26582
  access: "view"
26462
26583
  },
26463
- "pipelineExecutor.reprobeEngine": {
26464
- capName: "pipeline-executor",
26465
- capScope: "system",
26466
- addonId: null,
26467
- access: "create"
26468
- },
26469
26584
  "pipelineExecutor.runAudioTest": {
26470
26585
  capName: "pipeline-executor",
26471
26586
  capScope: "system",
@@ -26616,6 +26731,12 @@ Object.freeze({
26616
26731
  addonId: null,
26617
26732
  access: "view"
26618
26733
  },
26734
+ "pipelineOrchestrator.getNodeInferenceDevices": {
26735
+ capName: "pipeline-orchestrator",
26736
+ capScope: "system",
26737
+ addonId: null,
26738
+ access: "view"
26739
+ },
26619
26740
  "pipelineOrchestrator.getPipelineAssignment": {
26620
26741
  capName: "pipeline-orchestrator",
26621
26742
  capScope: "system",
@@ -26628,6 +26749,12 @@ Object.freeze({
26628
26749
  addonId: null,
26629
26750
  access: "view"
26630
26751
  },
26752
+ "pipelineOrchestrator.getPipelineDevicePin": {
26753
+ capName: "pipeline-orchestrator",
26754
+ capScope: "system",
26755
+ addonId: null,
26756
+ access: "view"
26757
+ },
26631
26758
  "pipelineOrchestrator.listAgentSettings": {
26632
26759
  capName: "pipeline-orchestrator",
26633
26760
  capScope: "system",
@@ -26670,19 +26797,19 @@ Object.freeze({
26670
26797
  addonId: null,
26671
26798
  access: "create"
26672
26799
  },
26673
- "pipelineOrchestrator.setAgentAddonDefaults": {
26800
+ "pipelineOrchestrator.setAgentCapabilities": {
26674
26801
  capName: "pipeline-orchestrator",
26675
26802
  capScope: "system",
26676
26803
  addonId: null,
26677
26804
  access: "create"
26678
26805
  },
26679
- "pipelineOrchestrator.setAgentCapabilities": {
26806
+ "pipelineOrchestrator.setAgentDetectWeight": {
26680
26807
  capName: "pipeline-orchestrator",
26681
26808
  capScope: "system",
26682
26809
  addonId: null,
26683
26810
  access: "create"
26684
26811
  },
26685
- "pipelineOrchestrator.setAgentDetectWeight": {
26812
+ "pipelineOrchestrator.setAgentInferenceDevices": {
26686
26813
  capName: "pipeline-orchestrator",
26687
26814
  capScope: "system",
26688
26815
  addonId: null,
@@ -26724,6 +26851,12 @@ Object.freeze({
26724
26851
  addonId: null,
26725
26852
  access: "create"
26726
26853
  },
26854
+ "pipelineOrchestrator.setPipelineDevicePin": {
26855
+ capName: "pipeline-orchestrator",
26856
+ capScope: "system",
26857
+ addonId: null,
26858
+ access: "create"
26859
+ },
26727
26860
  "pipelineOrchestrator.unassignAudio": {
26728
26861
  capName: "pipeline-orchestrator",
26729
26862
  capScope: "system",
@@ -28276,32 +28409,6 @@ Object.freeze({
28276
28409
  "network-access": "ingress",
28277
28410
  "smtp-provider": "email"
28278
28411
  });
28279
- var frameworkSwapPackageSchema = object({
28280
- name: string(),
28281
- stagedPath: string(),
28282
- backupPath: string(),
28283
- toVersion: string(),
28284
- fromVersion: string().nullable()
28285
- });
28286
- object({
28287
- jobId: string(),
28288
- taskId: string(),
28289
- packages: array(frameworkSwapPackageSchema),
28290
- requestedAtMs: number(),
28291
- schemaVersion: literal(1)
28292
- });
28293
- object({
28294
- jobId: string(),
28295
- taskId: string(),
28296
- backups: array(object({
28297
- name: string(),
28298
- backupPath: string(),
28299
- livePath: string()
28300
- })),
28301
- appliedAtMs: number(),
28302
- bootAttempts: number(),
28303
- schemaVersion: literal(1)
28304
- });
28305
28412
  //#endregion
28306
28413
  //#region ../../node_modules/@apocaliss92/wyze-bridge-js/dist/index.js
28307
28414
  var __require = /* @__PURE__ */ ((x) => typeof __require$1 !== "undefined" ? __require$1 : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof __require$1 !== "undefined" ? __require$1 : a)[b] }) : x)(function(x) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-wyze",
3
- "version": "0.1.25",
3
+ "version": "0.2.1",
4
4
  "description": "Wyze camera device-provider addon for CamStack — wraps the @apocaliss92/wyze-bridge-js P2P/DTLS client, feeding the stream-broker via the pull-rfc4571 lazy-publish path (a structural twin of addon-provider-reolink)",
5
5
  "keywords": [
6
6
  "camstack",