@camstack/addon-provider-petkit 0.1.14 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/addon.js +193 -103
  2. package/dist/addon.mjs +193 -103
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -7100,6 +7100,17 @@ var ModelCatalogEntrySchema = object({
7100
7100
  "imagenet",
7101
7101
  "none"
7102
7102
  ]).optional(),
7103
+ /**
7104
+ * The model already applies softmax IN-GRAPH — its raw output is a
7105
+ * probability distribution, not logits. When set, the `softmax`
7106
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7107
+ * probability vector collapses it toward uniform (top-1 score craters far
7108
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7109
+ * the output is raw logits and the postprocessor applies softmax (the normal
7110
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7111
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7112
+ */
7113
+ outputProbabilities: boolean().optional(),
7103
7114
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7104
7115
  /**
7105
7116
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -12390,10 +12401,7 @@ var ConfigUISchemaNullableBridge = custom();
12390
12401
  var InferenceCapabilitiesBridge = custom();
12391
12402
  var ModelAvailabilityListBridge = custom();
12392
12403
  var PipelineRunResultBridge = custom();
12393
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
12394
- kind: "mutation",
12395
- auth: "admin"
12396
- }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12404
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12397
12405
  modelId: string(),
12398
12406
  settings: record(string(), unknown()).readonly()
12399
12407
  }))), method(object({ steps: record(string(), object({
@@ -12453,13 +12461,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12453
12461
  * (inputClasses ≠ null) are skipped and served per-track via
12454
12462
  * pipelineRunner.runDetailSubtree (two-plane design).
12455
12463
  */
12456
- plane: _enum(["full", "frame"]).optional()
12464
+ plane: _enum(["full", "frame"]).optional(),
12465
+ /**
12466
+ * Inference-device selector (Phase 2 multi-device). Format
12467
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
12468
+ * Omitted ⇒ the runner's default device (current single-engine
12469
+ * behaviour). Selects WHICH device pool of the node runs the call.
12470
+ */
12471
+ deviceKey: string().optional()
12457
12472
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
12458
12473
  engine: PipelineEngineChoiceSchema.optional(),
12459
12474
  steps: array(PipelineStepInputSchema).min(1),
12460
12475
  frames: array(FrameInputSchema).min(1).max(255),
12461
12476
  deviceId: number().optional(),
12462
- sessionId: string().optional()
12477
+ sessionId: string().optional(),
12478
+ /**
12479
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
12480
+ * the batch to the Python pool's bench preprocess cache
12481
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
12482
+ * preprocessed ONCE and every later inference is a pure-inference cache
12483
+ * hit — the sustained-throughput run measures inference, not
12484
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
12485
+ * full preprocess every call, correct). Fresh per sustained run;
12486
+ * released via `uncacheFrame`.
12487
+ */
12488
+ frameId: number().int().nonnegative().optional(),
12489
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
12490
+ deviceKey: string().optional()
12463
12491
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
12464
12492
  data: _instanceof(Uint8Array),
12465
12493
  width: number().int().positive(),
@@ -12491,8 +12519,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12491
12519
  * - `runtime` — main camera-serving engine (no idle TTL).
12492
12520
  * - `warm-override` — benchmark/test override held in the warm
12493
12521
  * cache; auto-disposed after the idle TTL.
12522
+ * - `device-pool` — a concurrent per-device pool (Phase 2
12523
+ * multi-device, keyed by `deviceKey`) resolved
12524
+ * via `resolveDeviceFactory`. Runs alongside the
12525
+ * `runtime` engine on a DIFFERENT accelerator
12526
+ * (NPU / iGPU / Coral) — this is how the
12527
+ * Engines tab shows all pools running at once.
12494
12528
  */
12495
- kind: _enum(["runtime", "warm-override"]),
12529
+ kind: _enum([
12530
+ "runtime",
12531
+ "warm-override",
12532
+ "device-pool"
12533
+ ]),
12496
12534
  /** Native pid of the underlying Python pool (null when no pool). */
12497
12535
  poolPid: number().nullable(),
12498
12536
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -12867,7 +12905,14 @@ var RunnerCameraConfigSchema = object({
12867
12905
  * camera's detect node differs from its source-owner (P2d, gated by the
12868
12906
  * `remoteSourcingNodes` rollout setting).
12869
12907
  */
12870
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
12908
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
12909
+ /**
12910
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
12911
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
12912
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
12913
+ * this only selects WHICH device pool of that node runs the session.
12914
+ */
12915
+ deviceKey: string().optional()
12871
12916
  });
12872
12917
  motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
12873
12918
  /**
@@ -12888,6 +12933,19 @@ var RunnerLocalLoadSchema = object({
12888
12933
  avgInferenceTimeMs: number(),
12889
12934
  /** Total queue depth across motion + detection queues. */
12890
12935
  queueDepthTotal: number(),
12936
+ /**
12937
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
12938
+ * this runner currently has attached cameras on, so the orchestrator's second
12939
+ * `balance()` pass (over a node's devices) weights on real per-pool session
12940
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
12941
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
12942
+ */
12943
+ devices: array(object({
12944
+ deviceKey: string(),
12945
+ backend: string(),
12946
+ attachedCameras: number(),
12947
+ queueDepthTotal: number()
12948
+ })).default([]),
12891
12949
  /** Hardware capability flags reported by this node. */
12892
12950
  hardware: object({
12893
12951
  hasGpu: boolean(),
@@ -16036,6 +16094,8 @@ var BaseDeviceProvider = class extends BaseAddon {
16036
16094
  return toDeviceSummary(device, this.addonId);
16037
16095
  }
16038
16096
  };
16097
+ DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder;
16098
+ new Set(Object.values(DeviceType));
16039
16099
  /**
16040
16100
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
16041
16101
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -19722,13 +19782,11 @@ var PipelineTemplateSchema = object({
19722
19782
  createdAt: string(),
19723
19783
  updatedAt: string()
19724
19784
  });
19725
- var AgentAddonConfigSchema = object({
19726
- enabled: boolean(),
19785
+ var DeviceStepConfigSchema = object({
19727
19786
  modelId: string().optional(),
19728
- settings: record(string(), unknown()).readonly()
19787
+ settings: record(string(), unknown()).optional()
19729
19788
  });
19730
19789
  var AgentPipelineSettingsSchema = object({
19731
- addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
19732
19790
  maxCameras: number().int().nonnegative().nullable().default(null),
19733
19791
  /** Per-node detection weight (relative share for the quota balancer). */
19734
19792
  detectWeight: number().positive().optional(),
@@ -19752,7 +19810,22 @@ var AgentPipelineSettingsSchema = object({
19752
19810
  * it already uses to reach the hub). Set this only when the auto-detected
19753
19811
  * address is wrong (multi-homed host, NAT, custom interface).
19754
19812
  */
19755
- reachableHost: string().optional()
19813
+ reachableHost: string().optional(),
19814
+ /**
19815
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
19816
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
19817
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
19818
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
19819
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
19820
+ * the default model/settings for every camera landing on that accelerator;
19821
+ * a stepId absent ⇒ the step uses that device's format default.
19822
+ */
19823
+ inferenceDevices: record(string(), object({
19824
+ enabled: boolean(),
19825
+ weight: number().positive().optional(),
19826
+ maxSessions: number().int().positive().optional(),
19827
+ steps: record(string(), DeviceStepConfigSchema).optional()
19828
+ })).optional()
19756
19829
  });
19757
19830
  var CameraPipelineForAgentSchema = object({
19758
19831
  steps: array(PipelineStepInputSchema).readonly(),
@@ -19762,14 +19835,13 @@ var CameraPipelineForAgentSchema = object({
19762
19835
  }).nullable()
19763
19836
  });
19764
19837
  var CameraStepOverridePatchSchema = object({
19765
- enabled: boolean().optional(),
19766
19838
  modelId: string().optional(),
19767
19839
  settings: record(string(), unknown()).readonly().optional()
19768
19840
  });
19769
19841
  var CameraPipelineSettingsSchema = object({
19770
19842
  pinnedAgentNodeId: string().optional(),
19771
19843
  stepToggles: record(string(), boolean()).optional(),
19772
- stepOverridesByAgent: record(string(), record(string(), CameraStepOverridePatchSchema)).optional(),
19844
+ stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
19773
19845
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
19774
19846
  });
19775
19847
  /**
@@ -19983,6 +20055,44 @@ var CameraStatusSchema = object({
19983
20055
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
19984
20056
  fetchedAt: number()
19985
20057
  });
20058
+ var NodeInferenceDeviceSchema = object({
20059
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
20060
+ key: string(),
20061
+ backend: string(),
20062
+ device: string(),
20063
+ format: _enum(MODEL_FORMATS),
20064
+ /** Whether the node's live probe reports the device as usable right now. */
20065
+ available: boolean(),
20066
+ /**
20067
+ * Whether this device participates in dispatch. AUTO default (spec C2):
20068
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
20069
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
20070
+ * not a balanced target). An explicit stored value always wins; a stored-only
20071
+ * (unavailable) key keeps its stored value.
20072
+ */
20073
+ enabled: boolean(),
20074
+ /** Relative balancer weight for the enabled device (default 1). */
20075
+ weight: number(),
20076
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
20077
+ maxSessions: number().nullable(),
20078
+ /** Object-detection model the executor defaults to for this deviceKey. */
20079
+ defaultModelId: string(),
20080
+ /**
20081
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
20082
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
20083
+ * Absent/empty ⇒ no base (every step uses its device format default). The
20084
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
20085
+ * available per format; this is the stored selection that becomes the
20086
+ * default for EVERY camera landing on this accelerator.
20087
+ */
20088
+ steps: record(string(), DeviceStepConfigSchema).optional()
20089
+ });
20090
+ var NodeInferenceDevicesSchema = object({
20091
+ nodeId: string(),
20092
+ /** False when the node's platform-probe was unreachable (no live device set). */
20093
+ reachable: boolean(),
20094
+ devices: array(NodeInferenceDeviceSchema).readonly()
20095
+ });
19986
20096
  method(object({
19987
20097
  deviceId: number(),
19988
20098
  agentNodeId: string()
@@ -19992,7 +20102,13 @@ method(object({
19992
20102
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
19993
20103
  kind: "mutation",
19994
20104
  auth: "admin"
19995
- }), method(_void(), object({ migrated: number() }), {
20105
+ }), method(object({
20106
+ deviceId: number(),
20107
+ deviceKey: string()
20108
+ }), object({ success: literal(true) }), {
20109
+ kind: "mutation",
20110
+ auth: "admin"
20111
+ }), method(object({ deviceId: number() }), object({ deviceKey: string().nullable() })), method(_void(), object({ migrated: number() }), {
19996
20112
  kind: "mutation",
19997
20113
  auth: "admin"
19998
20114
  }), 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({
@@ -20026,13 +20142,7 @@ method(object({
20026
20142
  }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
20027
20143
  nodeId: string(),
20028
20144
  settings: AgentPipelineSettingsSchema
20029
- })).readonly()), method(object({
20030
- agentNodeId: string(),
20031
- defaults: record(string(), AgentAddonConfigSchema)
20032
- }), object({ success: literal(true) }), {
20033
- kind: "mutation",
20034
- auth: "admin"
20035
- }), method(object({ agentNodeId: string() }), object({
20145
+ })).readonly()), method(object({ agentNodeId: string() }), object({
20036
20146
  success: boolean(),
20037
20147
  removed: boolean()
20038
20148
  }), {
@@ -20064,7 +20174,18 @@ method(object({
20064
20174
  }), object({ success: literal(true) }), {
20065
20175
  kind: "mutation",
20066
20176
  auth: "admin"
20067
- }), method(object({ agentNodeId: string() }), object({
20177
+ }), method(object({
20178
+ agentNodeId: string(),
20179
+ inferenceDevices: record(string(), object({
20180
+ enabled: boolean(),
20181
+ weight: number().positive().optional(),
20182
+ maxSessions: number().int().positive().optional(),
20183
+ steps: record(string(), DeviceStepConfigSchema).optional()
20184
+ }))
20185
+ }), object({ success: literal(true) }), {
20186
+ kind: "mutation",
20187
+ auth: "admin"
20188
+ }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string() }), object({
20068
20189
  success: literal(true),
20069
20190
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
20070
20191
  effectiveModelId: string().nullable(),
@@ -20080,9 +20201,10 @@ method(object({
20080
20201
  }), object({ success: literal(true) }), {
20081
20202
  kind: "mutation",
20082
20203
  auth: "admin"
20083
- }), method(object({ deviceId: number() }), record(string(), record(string(), CameraStepOverridePatchSchema)).nullable()), method(object({
20204
+ }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
20084
20205
  deviceId: number(),
20085
20206
  agentNodeId: string(),
20207
+ deviceKey: string(),
20086
20208
  addonId: string(),
20087
20209
  patch: CameraStepOverridePatchSchema.nullable()
20088
20210
  }), object({ success: literal(true) }), {
@@ -20119,14 +20241,13 @@ method(object({
20119
20241
  });
20120
20242
  /**
20121
20243
  * server-management — per-NODE singleton capability for a node's ROOT
20122
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
20123
- * agents).
20244
+ * package lifecycle (runtime-updatable node packages).
20124
20245
  *
20125
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
20126
- * on agents) carries the whole software stack in its npm dep tree, so ONE
20127
- * version describes the node. Updates install into
20128
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
20129
- * starter (probation boot + auto-rollback to N-1).
20246
+ * Every node role runs the SAME root package (`@camstack/server`), which
20247
+ * carries the whole software stack in its npm dep tree, so ONE version
20248
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
20249
+ * on restart via the baked starter (single-copy in-place swap — no probation,
20250
+ * no auto-rollback).
20130
20251
  *
20131
20252
  * Providers:
20132
20253
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -20234,7 +20355,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
20234
20355
  /** Explicit target version; omitted = latest from the registry. */
20235
20356
  version: string().optional() }), ServerUpdateActionResultSchema, {
20236
20357
  kind: "mutation",
20237
- auth: "admin"
20358
+ auth: "admin",
20359
+ timeoutMs: 16 * 6e4
20238
20360
  }), method(_void(), ServerUpdateActionResultSchema, {
20239
20361
  kind: "mutation",
20240
20362
  auth: "admin"
@@ -21278,22 +21400,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
21278
21400
  var RestartAddonResultSchema = unknown();
21279
21401
  var InstallPackageResultSchema = unknown();
21280
21402
  var ReloadPackagesResultSchema = unknown();
21281
- /**
21282
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
21283
- * server restarts so the admin UI can react to the `restartingAt`
21284
- * timestamp (shows reconnect overlay). The transition from
21285
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
21286
- * `system.restart-completed` event after the new process boots.
21287
- *
21288
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
21289
- */
21290
- var UpdateFrameworkPackageResultSchema = object({
21291
- packageName: string(),
21292
- fromVersion: string(),
21293
- toVersion: string(),
21294
- /** Ms-epoch the server scheduled its self-restart. */
21295
- restartingAt: number()
21296
- });
21297
21403
  var BulkUpdateItemStatusSchema = _enum([
21298
21404
  "queued",
21299
21405
  "updating",
@@ -21421,13 +21527,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
21421
21527
  }), object({ success: literal(true) }), {
21422
21528
  kind: "mutation",
21423
21529
  auth: "admin"
21424
- }), method(object({
21425
- packageName: string().min(1),
21426
- version: string().optional(),
21427
- deferRestart: boolean().optional()
21428
- }), UpdateFrameworkPackageResultSchema, {
21429
- kind: "mutation",
21430
- auth: "admin"
21431
21530
  }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
21432
21531
  kind: "mutation",
21433
21532
  auth: "admin"
@@ -22293,10 +22392,10 @@ var TopologyCategorySchema = object({
22293
22392
  addons: array(TopologyCategoryAddonSchema).readonly()
22294
22393
  });
22295
22394
  /**
22296
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
22297
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
22298
- * version visibility for the Server management surface. Nullable: offline
22299
- * rows and pre-phase-2 nodes report none.
22395
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
22396
+ * root package for every node role) as reported by its `registerNode`
22397
+ * manifest — version visibility for the Server management surface. Nullable:
22398
+ * offline rows and nodes that never reported one.
22300
22399
  */
22301
22400
  var TopologyRootPackageSchema = object({
22302
22401
  name: string(),
@@ -22684,17 +22783,28 @@ var PlatformScoreSchema = object({
22684
22783
  format: _enum([
22685
22784
  "onnx",
22686
22785
  "coreml",
22687
- "openvino"
22786
+ "openvino",
22787
+ "tflite"
22688
22788
  ]),
22689
22789
  score: number(),
22690
22790
  reason: string(),
22691
22791
  available: boolean()
22692
22792
  });
22793
+ var InferenceDeviceDescriptorSchema = object({
22794
+ key: string(),
22795
+ backend: string(),
22796
+ device: string(),
22797
+ format: ModelFormatSchema,
22798
+ runtime: literal("python"),
22799
+ score: number(),
22800
+ available: boolean()
22801
+ });
22693
22802
  var PlatformCapabilitiesSchema = object({
22694
22803
  hardware: HardwareInfoSchema,
22695
22804
  scores: array(PlatformScoreSchema).readonly(),
22696
22805
  bestScore: PlatformScoreSchema,
22697
- pythonPath: string().nullable()
22806
+ pythonPath: string().nullable(),
22807
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
22698
22808
  });
22699
22809
  var ModelRequirementSchema = object({
22700
22810
  modelId: string(),
@@ -23573,12 +23683,6 @@ Object.freeze({
23573
23683
  addonId: null,
23574
23684
  access: "delete"
23575
23685
  },
23576
- "addons.updateFrameworkPackage": {
23577
- capName: "addons",
23578
- capScope: "system",
23579
- addonId: null,
23580
- access: "create"
23581
- },
23582
23686
  "addons.updatePackage": {
23583
23687
  capName: "addons",
23584
23688
  capScope: "system",
@@ -26351,12 +26455,6 @@ Object.freeze({
26351
26455
  addonId: null,
26352
26456
  access: "view"
26353
26457
  },
26354
- "pipelineExecutor.reprobeEngine": {
26355
- capName: "pipeline-executor",
26356
- capScope: "system",
26357
- addonId: null,
26358
- access: "create"
26359
- },
26360
26458
  "pipelineExecutor.runAudioTest": {
26361
26459
  capName: "pipeline-executor",
26362
26460
  capScope: "system",
@@ -26507,6 +26605,12 @@ Object.freeze({
26507
26605
  addonId: null,
26508
26606
  access: "view"
26509
26607
  },
26608
+ "pipelineOrchestrator.getNodeInferenceDevices": {
26609
+ capName: "pipeline-orchestrator",
26610
+ capScope: "system",
26611
+ addonId: null,
26612
+ access: "view"
26613
+ },
26510
26614
  "pipelineOrchestrator.getPipelineAssignment": {
26511
26615
  capName: "pipeline-orchestrator",
26512
26616
  capScope: "system",
@@ -26519,6 +26623,12 @@ Object.freeze({
26519
26623
  addonId: null,
26520
26624
  access: "view"
26521
26625
  },
26626
+ "pipelineOrchestrator.getPipelineDevicePin": {
26627
+ capName: "pipeline-orchestrator",
26628
+ capScope: "system",
26629
+ addonId: null,
26630
+ access: "view"
26631
+ },
26522
26632
  "pipelineOrchestrator.listAgentSettings": {
26523
26633
  capName: "pipeline-orchestrator",
26524
26634
  capScope: "system",
@@ -26561,19 +26671,19 @@ Object.freeze({
26561
26671
  addonId: null,
26562
26672
  access: "create"
26563
26673
  },
26564
- "pipelineOrchestrator.setAgentAddonDefaults": {
26674
+ "pipelineOrchestrator.setAgentCapabilities": {
26565
26675
  capName: "pipeline-orchestrator",
26566
26676
  capScope: "system",
26567
26677
  addonId: null,
26568
26678
  access: "create"
26569
26679
  },
26570
- "pipelineOrchestrator.setAgentCapabilities": {
26680
+ "pipelineOrchestrator.setAgentDetectWeight": {
26571
26681
  capName: "pipeline-orchestrator",
26572
26682
  capScope: "system",
26573
26683
  addonId: null,
26574
26684
  access: "create"
26575
26685
  },
26576
- "pipelineOrchestrator.setAgentDetectWeight": {
26686
+ "pipelineOrchestrator.setAgentInferenceDevices": {
26577
26687
  capName: "pipeline-orchestrator",
26578
26688
  capScope: "system",
26579
26689
  addonId: null,
@@ -26615,6 +26725,12 @@ Object.freeze({
26615
26725
  addonId: null,
26616
26726
  access: "create"
26617
26727
  },
26728
+ "pipelineOrchestrator.setPipelineDevicePin": {
26729
+ capName: "pipeline-orchestrator",
26730
+ capScope: "system",
26731
+ addonId: null,
26732
+ access: "create"
26733
+ },
26618
26734
  "pipelineOrchestrator.unassignAudio": {
26619
26735
  capName: "pipeline-orchestrator",
26620
26736
  capScope: "system",
@@ -28167,32 +28283,6 @@ Object.freeze({
28167
28283
  "network-access": "ingress",
28168
28284
  "smtp-provider": "email"
28169
28285
  });
28170
- var frameworkSwapPackageSchema = object({
28171
- name: string(),
28172
- stagedPath: string(),
28173
- backupPath: string(),
28174
- toVersion: string(),
28175
- fromVersion: string().nullable()
28176
- });
28177
- object({
28178
- jobId: string(),
28179
- taskId: string(),
28180
- packages: array(frameworkSwapPackageSchema),
28181
- requestedAtMs: number(),
28182
- schemaVersion: literal(1)
28183
- });
28184
- object({
28185
- jobId: string(),
28186
- taskId: string(),
28187
- backups: array(object({
28188
- name: string(),
28189
- backupPath: string(),
28190
- livePath: string()
28191
- })),
28192
- appliedAtMs: number(),
28193
- bootAttempts: number(),
28194
- schemaVersion: literal(1)
28195
- });
28196
28286
  //#endregion
28197
28287
  //#region ../../node_modules/@apocaliss92/nodepetkit/dist/index.js
28198
28288
  var PetkitError = class extends Error {
package/dist/addon.mjs CHANGED
@@ -7099,6 +7099,17 @@ var ModelCatalogEntrySchema = object({
7099
7099
  "imagenet",
7100
7100
  "none"
7101
7101
  ]).optional(),
7102
+ /**
7103
+ * The model already applies softmax IN-GRAPH — its raw output is a
7104
+ * probability distribution, not logits. When set, the `softmax`
7105
+ * postprocessor must NOT re-apply softmax: re-softmaxing an already-normalised
7106
+ * probability vector collapses it toward uniform (top-1 score craters far
7107
+ * below its true value, making every confidence gate meaningless). Absent ⇒
7108
+ * the output is raw logits and the postprocessor applies softmax (the normal
7109
+ * case). Set on the Google AIY Birds `bird-classifier` (softmax baked into the
7110
+ * TF graph). Threaded to the Python pool via `PoolModelConfig.outputProbabilities`.
7111
+ */
7112
+ outputProbabilities: boolean().optional(),
7102
7113
  preprocessMode: _enum(["letterbox", "resize"]).optional(),
7103
7114
  /**
7104
7115
  * Per-MODEL postprocessor override. Absent ⇒ the step's own
@@ -12389,10 +12400,7 @@ var ConfigUISchemaNullableBridge = custom();
12389
12400
  var InferenceCapabilitiesBridge = custom();
12390
12401
  var ModelAvailabilityListBridge = custom();
12391
12402
  var PipelineRunResultBridge = custom();
12392
- method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
12393
- kind: "mutation",
12394
- auth: "admin"
12395
- }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12403
+ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
12396
12404
  modelId: string(),
12397
12405
  settings: record(string(), unknown()).readonly()
12398
12406
  }))), method(object({ steps: record(string(), object({
@@ -12452,13 +12460,33 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12452
12460
  * (inputClasses ≠ null) are skipped and served per-track via
12453
12461
  * pipelineRunner.runDetailSubtree (two-plane design).
12454
12462
  */
12455
- plane: _enum(["full", "frame"]).optional()
12463
+ plane: _enum(["full", "frame"]).optional(),
12464
+ /**
12465
+ * Inference-device selector (Phase 2 multi-device). Format
12466
+ * `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
12467
+ * Omitted ⇒ the runner's default device (current single-engine
12468
+ * behaviour). Selects WHICH device pool of the node runs the call.
12469
+ */
12470
+ deviceKey: string().optional()
12456
12471
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
12457
12472
  engine: PipelineEngineChoiceSchema.optional(),
12458
12473
  steps: array(PipelineStepInputSchema).min(1),
12459
12474
  frames: array(FrameInputSchema).min(1).max(255),
12460
12475
  deviceId: number().optional(),
12461
- sessionId: string().optional()
12476
+ sessionId: string().optional(),
12477
+ /**
12478
+ * Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
12479
+ * the batch to the Python pool's bench preprocess cache
12480
+ * (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
12481
+ * preprocessed ONCE and every later inference is a pure-inference cache
12482
+ * hit — the sustained-throughput run measures inference, not
12483
+ * decode+preprocess+infer. Omitted/0 for live frames (all different →
12484
+ * full preprocess every call, correct). Fresh per sustained run;
12485
+ * released via `uncacheFrame`.
12486
+ */
12487
+ frameId: number().int().nonnegative().optional(),
12488
+ /** Inference-device selector (Phase 2 multi-device); see runPipeline. */
12489
+ deviceKey: string().optional()
12462
12490
  }), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
12463
12491
  data: _instanceof(Uint8Array),
12464
12492
  width: number().int().positive(),
@@ -12490,8 +12518,18 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12490
12518
  * - `runtime` — main camera-serving engine (no idle TTL).
12491
12519
  * - `warm-override` — benchmark/test override held in the warm
12492
12520
  * cache; auto-disposed after the idle TTL.
12521
+ * - `device-pool` — a concurrent per-device pool (Phase 2
12522
+ * multi-device, keyed by `deviceKey`) resolved
12523
+ * via `resolveDeviceFactory`. Runs alongside the
12524
+ * `runtime` engine on a DIFFERENT accelerator
12525
+ * (NPU / iGPU / Coral) — this is how the
12526
+ * Engines tab shows all pools running at once.
12493
12527
  */
12494
- kind: _enum(["runtime", "warm-override"]),
12528
+ kind: _enum([
12529
+ "runtime",
12530
+ "warm-override",
12531
+ "device-pool"
12532
+ ]),
12495
12533
  /** Native pid of the underlying Python pool (null when no pool). */
12496
12534
  poolPid: number().nullable(),
12497
12535
  /** ms since this factory was last used (null when not warm-tracked). */
@@ -12866,7 +12904,14 @@ var RunnerCameraConfigSchema = object({
12866
12904
  * camera's detect node differs from its source-owner (P2d, gated by the
12867
12905
  * `remoteSourcingNodes` rollout setting).
12868
12906
  */
12869
- frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" })
12907
+ frameSource: RunnerFrameSourceSchema.default({ kind: "local-broker" }),
12908
+ /**
12909
+ * Inference-device selector for this camera's sessions (Phase 2 multi-device).
12910
+ * Format `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`);
12911
+ * omitted ⇒ the runner's default device. The engine itself stays node-local —
12912
+ * this only selects WHICH device pool of that node runs the session.
12913
+ */
12914
+ deviceKey: string().optional()
12870
12915
  });
12871
12916
  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;
12872
12917
  /**
@@ -12887,6 +12932,19 @@ var RunnerLocalLoadSchema = object({
12887
12932
  avgInferenceTimeMs: number(),
12888
12933
  /** Total queue depth across motion + detection queues. */
12889
12934
  queueDepthTotal: number(),
12935
+ /**
12936
+ * Per-inference-device live load (multi-device C4). One entry per deviceKey
12937
+ * this runner currently has attached cameras on, so the orchestrator's second
12938
+ * `balance()` pass (over a node's devices) weights on real per-pool session
12939
+ * counts. Empty on single-device / pre-multi-device runners. `queueDepthTotal`
12940
+ * per device is 0 until the pool backlog gets a public accessor (follow-up).
12941
+ */
12942
+ devices: array(object({
12943
+ deviceKey: string(),
12944
+ backend: string(),
12945
+ attachedCameras: number(),
12946
+ queueDepthTotal: number()
12947
+ })).default([]),
12890
12948
  /** Hardware capability flags reported by this node. */
12891
12949
  hardware: object({
12892
12950
  hasGpu: boolean(),
@@ -16035,6 +16093,8 @@ var BaseDeviceProvider = class extends BaseAddon {
16035
16093
  return toDeviceSummary(device, this.addonId);
16036
16094
  }
16037
16095
  };
16096
+ 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;
16097
+ new Set(Object.values(DeviceType));
16038
16098
  /**
16039
16099
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
16040
16100
  * surface that admin-ui consumes through `useAddonPagesListPages()`.
@@ -19721,13 +19781,11 @@ var PipelineTemplateSchema = object({
19721
19781
  createdAt: string(),
19722
19782
  updatedAt: string()
19723
19783
  });
19724
- var AgentAddonConfigSchema = object({
19725
- enabled: boolean(),
19784
+ var DeviceStepConfigSchema = object({
19726
19785
  modelId: string().optional(),
19727
- settings: record(string(), unknown()).readonly()
19786
+ settings: record(string(), unknown()).optional()
19728
19787
  });
19729
19788
  var AgentPipelineSettingsSchema = object({
19730
- addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
19731
19789
  maxCameras: number().int().nonnegative().nullable().default(null),
19732
19790
  /** Per-node detection weight (relative share for the quota balancer). */
19733
19791
  detectWeight: number().positive().optional(),
@@ -19751,7 +19809,22 @@ var AgentPipelineSettingsSchema = object({
19751
19809
  * it already uses to reach the hub). Set this only when the auto-detected
19752
19810
  * address is wrong (multi-homed host, NAT, custom interface).
19753
19811
  */
19754
- reachableHost: string().optional()
19812
+ reachableHost: string().optional(),
19813
+ /**
19814
+ * Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
19815
+ * weight, steps}. Absent / all-disabled ⇒ the node's single default
19816
+ * accelerator (safe default); two+ enabled ⇒ the dispatcher balances
19817
+ * detection sessions across them so they run CONCURRENTLY. `steps` is the
19818
+ * per-(node,device) BASE provisioning (`stepId → {modelId?, settings?}`) —
19819
+ * the default model/settings for every camera landing on that accelerator;
19820
+ * a stepId absent ⇒ the step uses that device's format default.
19821
+ */
19822
+ inferenceDevices: record(string(), object({
19823
+ enabled: boolean(),
19824
+ weight: number().positive().optional(),
19825
+ maxSessions: number().int().positive().optional(),
19826
+ steps: record(string(), DeviceStepConfigSchema).optional()
19827
+ })).optional()
19755
19828
  });
19756
19829
  var CameraPipelineForAgentSchema = object({
19757
19830
  steps: array(PipelineStepInputSchema).readonly(),
@@ -19761,14 +19834,13 @@ var CameraPipelineForAgentSchema = object({
19761
19834
  }).nullable()
19762
19835
  });
19763
19836
  var CameraStepOverridePatchSchema = object({
19764
- enabled: boolean().optional(),
19765
19837
  modelId: string().optional(),
19766
19838
  settings: record(string(), unknown()).readonly().optional()
19767
19839
  });
19768
19840
  var CameraPipelineSettingsSchema = object({
19769
19841
  pinnedAgentNodeId: string().optional(),
19770
19842
  stepToggles: record(string(), boolean()).optional(),
19771
- stepOverridesByAgent: record(string(), record(string(), CameraStepOverridePatchSchema)).optional(),
19843
+ stepOverridesByDevice: record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).optional(),
19772
19844
  pipelineByAgent: record(string(), CameraPipelineForAgentSchema).optional()
19773
19845
  });
19774
19846
  /**
@@ -19982,6 +20054,44 @@ var CameraStatusSchema = object({
19982
20054
  /** Unix timestamp (ms) when this snapshot was composed server-side. */
19983
20055
  fetchedAt: number()
19984
20056
  });
20057
+ var NodeInferenceDeviceSchema = object({
20058
+ /** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
20059
+ key: string(),
20060
+ backend: string(),
20061
+ device: string(),
20062
+ format: _enum(MODEL_FORMATS),
20063
+ /** Whether the node's live probe reports the device as usable right now. */
20064
+ available: boolean(),
20065
+ /**
20066
+ * Whether this device participates in dispatch. AUTO default (spec C2):
20067
+ * accelerators are opt-OUT (a discovered NPU/iGPU/Coral/ANE with no stored
20068
+ * entry is `true`); CPU is opt-IN (`false` by default — the fallback pool,
20069
+ * not a balanced target). An explicit stored value always wins; a stored-only
20070
+ * (unavailable) key keeps its stored value.
20071
+ */
20072
+ enabled: boolean(),
20073
+ /** Relative balancer weight for the enabled device (default 1). */
20074
+ weight: number(),
20075
+ /** Per-device concurrent-session cap; null = unlimited (multi-device C4). */
20076
+ maxSessions: number().nullable(),
20077
+ /** Object-detection model the executor defaults to for this deviceKey. */
20078
+ defaultModelId: string(),
20079
+ /**
20080
+ * Per-(node,device) BASE provisioning (C7.2/C7.4) — the RAW stored
20081
+ * `stepId → {modelId?, settings?}` map from `inferenceDevices[key].steps`.
20082
+ * Absent/empty ⇒ no base (every step uses its device format default). The
20083
+ * UI cross-references `pipelineExecutor.getSchema` for the models actually
20084
+ * available per format; this is the stored selection that becomes the
20085
+ * default for EVERY camera landing on this accelerator.
20086
+ */
20087
+ steps: record(string(), DeviceStepConfigSchema).optional()
20088
+ });
20089
+ var NodeInferenceDevicesSchema = object({
20090
+ nodeId: string(),
20091
+ /** False when the node's platform-probe was unreachable (no live device set). */
20092
+ reachable: boolean(),
20093
+ devices: array(NodeInferenceDeviceSchema).readonly()
20094
+ });
19985
20095
  method(object({
19986
20096
  deviceId: number(),
19987
20097
  agentNodeId: string()
@@ -19991,7 +20101,13 @@ method(object({
19991
20101
  }), method(object({ deviceId: number() }), object({ success: literal(true) }), {
19992
20102
  kind: "mutation",
19993
20103
  auth: "admin"
19994
- }), method(_void(), object({ migrated: number() }), {
20104
+ }), method(object({
20105
+ deviceId: number(),
20106
+ deviceKey: string()
20107
+ }), object({ success: literal(true) }), {
20108
+ kind: "mutation",
20109
+ auth: "admin"
20110
+ }), method(object({ deviceId: number() }), object({ deviceKey: string().nullable() })), method(_void(), object({ migrated: number() }), {
19995
20111
  kind: "mutation",
19996
20112
  auth: "admin"
19997
20113
  }), 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({
@@ -20025,13 +20141,7 @@ method(object({
20025
20141
  }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
20026
20142
  nodeId: string(),
20027
20143
  settings: AgentPipelineSettingsSchema
20028
- })).readonly()), method(object({
20029
- agentNodeId: string(),
20030
- defaults: record(string(), AgentAddonConfigSchema)
20031
- }), object({ success: literal(true) }), {
20032
- kind: "mutation",
20033
- auth: "admin"
20034
- }), method(object({ agentNodeId: string() }), object({
20144
+ })).readonly()), method(object({ agentNodeId: string() }), object({
20035
20145
  success: boolean(),
20036
20146
  removed: boolean()
20037
20147
  }), {
@@ -20063,7 +20173,18 @@ method(object({
20063
20173
  }), object({ success: literal(true) }), {
20064
20174
  kind: "mutation",
20065
20175
  auth: "admin"
20066
- }), method(object({ agentNodeId: string() }), object({
20176
+ }), method(object({
20177
+ agentNodeId: string(),
20178
+ inferenceDevices: record(string(), object({
20179
+ enabled: boolean(),
20180
+ weight: number().positive().optional(),
20181
+ maxSessions: number().int().positive().optional(),
20182
+ steps: record(string(), DeviceStepConfigSchema).optional()
20183
+ }))
20184
+ }), object({ success: literal(true) }), {
20185
+ kind: "mutation",
20186
+ auth: "admin"
20187
+ }), method(object({ nodeId: string() }), NodeInferenceDevicesSchema), method(object({ agentNodeId: string() }), object({
20067
20188
  success: literal(true),
20068
20189
  /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
20069
20190
  effectiveModelId: string().nullable(),
@@ -20079,9 +20200,10 @@ method(object({
20079
20200
  }), object({ success: literal(true) }), {
20080
20201
  kind: "mutation",
20081
20202
  auth: "admin"
20082
- }), method(object({ deviceId: number() }), record(string(), record(string(), CameraStepOverridePatchSchema)).nullable()), method(object({
20203
+ }), method(object({ deviceId: number() }), record(string(), record(string(), record(string(), CameraStepOverridePatchSchema))).nullable()), method(object({
20083
20204
  deviceId: number(),
20084
20205
  agentNodeId: string(),
20206
+ deviceKey: string(),
20085
20207
  addonId: string(),
20086
20208
  patch: CameraStepOverridePatchSchema.nullable()
20087
20209
  }), object({ success: literal(true) }), {
@@ -20118,14 +20240,13 @@ method(object({
20118
20240
  });
20119
20241
  /**
20120
20242
  * server-management — per-NODE singleton capability for a node's ROOT
20121
- * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
20122
- * agents).
20243
+ * package lifecycle (runtime-updatable node packages).
20123
20244
  *
20124
- * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
20125
- * on agents) carries the whole software stack in its npm dep tree, so ONE
20126
- * version describes the node. Updates install into
20127
- * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
20128
- * starter (probation boot + auto-rollback to N-1).
20245
+ * Every node role runs the SAME root package (`@camstack/server`), which
20246
+ * carries the whole software stack in its npm dep tree, so ONE version
20247
+ * describes the node. Updates stage into `<dataDir>/server-root/` and apply
20248
+ * on restart via the baked starter (single-copy in-place swap — no probation,
20249
+ * no auto-rollback).
20129
20250
  *
20130
20251
  * Providers:
20131
20252
  * - HUB: `ServerUpdateService` behind the `server-provided` mount
@@ -20233,7 +20354,8 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
20233
20354
  /** Explicit target version; omitted = latest from the registry. */
20234
20355
  version: string().optional() }), ServerUpdateActionResultSchema, {
20235
20356
  kind: "mutation",
20236
- auth: "admin"
20357
+ auth: "admin",
20358
+ timeoutMs: 16 * 6e4
20237
20359
  }), method(_void(), ServerUpdateActionResultSchema, {
20238
20360
  kind: "mutation",
20239
20361
  auth: "admin"
@@ -21277,22 +21399,6 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
21277
21399
  var RestartAddonResultSchema = unknown();
21278
21400
  var InstallPackageResultSchema = unknown();
21279
21401
  var ReloadPackagesResultSchema = unknown();
21280
- /**
21281
- * Result of `updateFrameworkPackage`. The cap method returns BEFORE the
21282
- * server restarts so the admin UI can react to the `restartingAt`
21283
- * timestamp (shows reconnect overlay). The transition from
21284
- * `fromVersion` to `toVersion` will be confirmed by a subsequent
21285
- * `system.restart-completed` event after the new process boots.
21286
- *
21287
- * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
21288
- */
21289
- var UpdateFrameworkPackageResultSchema = object({
21290
- packageName: string(),
21291
- fromVersion: string(),
21292
- toVersion: string(),
21293
- /** Ms-epoch the server scheduled its self-restart. */
21294
- restartingAt: number()
21295
- });
21296
21402
  var BulkUpdateItemStatusSchema = _enum([
21297
21403
  "queued",
21298
21404
  "updating",
@@ -21420,13 +21526,6 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
21420
21526
  }), object({ success: literal(true) }), {
21421
21527
  kind: "mutation",
21422
21528
  auth: "admin"
21423
- }), method(object({
21424
- packageName: string().min(1),
21425
- version: string().optional(),
21426
- deferRestart: boolean().optional()
21427
- }), UpdateFrameworkPackageResultSchema, {
21428
- kind: "mutation",
21429
- auth: "admin"
21430
21529
  }), method(object({ name: string() }), array(PackageVersionInfoSchema).readonly()), method(object({ addonId: string() }), RestartAddonResultSchema, {
21431
21530
  kind: "mutation",
21432
21531
  auth: "admin"
@@ -22292,10 +22391,10 @@ var TopologyCategorySchema = object({
22292
22391
  addons: array(TopologyCategoryAddonSchema).readonly()
22293
22392
  });
22294
22393
  /**
22295
- * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
22296
- * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
22297
- * version visibility for the Server management surface. Nullable: offline
22298
- * rows and pre-phase-2 nodes report none.
22394
+ * The node's runtime-updatable ROOT package (`@camstack/server` the single
22395
+ * root package for every node role) as reported by its `registerNode`
22396
+ * manifest — version visibility for the Server management surface. Nullable:
22397
+ * offline rows and nodes that never reported one.
22299
22398
  */
22300
22399
  var TopologyRootPackageSchema = object({
22301
22400
  name: string(),
@@ -22683,17 +22782,28 @@ var PlatformScoreSchema = object({
22683
22782
  format: _enum([
22684
22783
  "onnx",
22685
22784
  "coreml",
22686
- "openvino"
22785
+ "openvino",
22786
+ "tflite"
22687
22787
  ]),
22688
22788
  score: number(),
22689
22789
  reason: string(),
22690
22790
  available: boolean()
22691
22791
  });
22792
+ var InferenceDeviceDescriptorSchema = object({
22793
+ key: string(),
22794
+ backend: string(),
22795
+ device: string(),
22796
+ format: ModelFormatSchema,
22797
+ runtime: literal("python"),
22798
+ score: number(),
22799
+ available: boolean()
22800
+ });
22692
22801
  var PlatformCapabilitiesSchema = object({
22693
22802
  hardware: HardwareInfoSchema,
22694
22803
  scores: array(PlatformScoreSchema).readonly(),
22695
22804
  bestScore: PlatformScoreSchema,
22696
- pythonPath: string().nullable()
22805
+ pythonPath: string().nullable(),
22806
+ devices: array(InferenceDeviceDescriptorSchema).readonly()
22697
22807
  });
22698
22808
  var ModelRequirementSchema = object({
22699
22809
  modelId: string(),
@@ -23572,12 +23682,6 @@ Object.freeze({
23572
23682
  addonId: null,
23573
23683
  access: "delete"
23574
23684
  },
23575
- "addons.updateFrameworkPackage": {
23576
- capName: "addons",
23577
- capScope: "system",
23578
- addonId: null,
23579
- access: "create"
23580
- },
23581
23685
  "addons.updatePackage": {
23582
23686
  capName: "addons",
23583
23687
  capScope: "system",
@@ -26350,12 +26454,6 @@ Object.freeze({
26350
26454
  addonId: null,
26351
26455
  access: "view"
26352
26456
  },
26353
- "pipelineExecutor.reprobeEngine": {
26354
- capName: "pipeline-executor",
26355
- capScope: "system",
26356
- addonId: null,
26357
- access: "create"
26358
- },
26359
26457
  "pipelineExecutor.runAudioTest": {
26360
26458
  capName: "pipeline-executor",
26361
26459
  capScope: "system",
@@ -26506,6 +26604,12 @@ Object.freeze({
26506
26604
  addonId: null,
26507
26605
  access: "view"
26508
26606
  },
26607
+ "pipelineOrchestrator.getNodeInferenceDevices": {
26608
+ capName: "pipeline-orchestrator",
26609
+ capScope: "system",
26610
+ addonId: null,
26611
+ access: "view"
26612
+ },
26509
26613
  "pipelineOrchestrator.getPipelineAssignment": {
26510
26614
  capName: "pipeline-orchestrator",
26511
26615
  capScope: "system",
@@ -26518,6 +26622,12 @@ Object.freeze({
26518
26622
  addonId: null,
26519
26623
  access: "view"
26520
26624
  },
26625
+ "pipelineOrchestrator.getPipelineDevicePin": {
26626
+ capName: "pipeline-orchestrator",
26627
+ capScope: "system",
26628
+ addonId: null,
26629
+ access: "view"
26630
+ },
26521
26631
  "pipelineOrchestrator.listAgentSettings": {
26522
26632
  capName: "pipeline-orchestrator",
26523
26633
  capScope: "system",
@@ -26560,19 +26670,19 @@ Object.freeze({
26560
26670
  addonId: null,
26561
26671
  access: "create"
26562
26672
  },
26563
- "pipelineOrchestrator.setAgentAddonDefaults": {
26673
+ "pipelineOrchestrator.setAgentCapabilities": {
26564
26674
  capName: "pipeline-orchestrator",
26565
26675
  capScope: "system",
26566
26676
  addonId: null,
26567
26677
  access: "create"
26568
26678
  },
26569
- "pipelineOrchestrator.setAgentCapabilities": {
26679
+ "pipelineOrchestrator.setAgentDetectWeight": {
26570
26680
  capName: "pipeline-orchestrator",
26571
26681
  capScope: "system",
26572
26682
  addonId: null,
26573
26683
  access: "create"
26574
26684
  },
26575
- "pipelineOrchestrator.setAgentDetectWeight": {
26685
+ "pipelineOrchestrator.setAgentInferenceDevices": {
26576
26686
  capName: "pipeline-orchestrator",
26577
26687
  capScope: "system",
26578
26688
  addonId: null,
@@ -26614,6 +26724,12 @@ Object.freeze({
26614
26724
  addonId: null,
26615
26725
  access: "create"
26616
26726
  },
26727
+ "pipelineOrchestrator.setPipelineDevicePin": {
26728
+ capName: "pipeline-orchestrator",
26729
+ capScope: "system",
26730
+ addonId: null,
26731
+ access: "create"
26732
+ },
26617
26733
  "pipelineOrchestrator.unassignAudio": {
26618
26734
  capName: "pipeline-orchestrator",
26619
26735
  capScope: "system",
@@ -28166,32 +28282,6 @@ Object.freeze({
28166
28282
  "network-access": "ingress",
28167
28283
  "smtp-provider": "email"
28168
28284
  });
28169
- var frameworkSwapPackageSchema = object({
28170
- name: string(),
28171
- stagedPath: string(),
28172
- backupPath: string(),
28173
- toVersion: string(),
28174
- fromVersion: string().nullable()
28175
- });
28176
- object({
28177
- jobId: string(),
28178
- taskId: string(),
28179
- packages: array(frameworkSwapPackageSchema),
28180
- requestedAtMs: number(),
28181
- schemaVersion: literal(1)
28182
- });
28183
- object({
28184
- jobId: string(),
28185
- taskId: string(),
28186
- backups: array(object({
28187
- name: string(),
28188
- backupPath: string(),
28189
- livePath: string()
28190
- })),
28191
- appliedAtMs: number(),
28192
- bootAttempts: number(),
28193
- schemaVersion: literal(1)
28194
- });
28195
28285
  //#endregion
28196
28286
  //#region ../../node_modules/@apocaliss92/nodepetkit/dist/index.js
28197
28287
  var PetkitError = class extends Error {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-petkit",
3
- "version": "0.1.14",
3
+ "version": "0.2.0",
4
4
  "description": "PetKit smart-feeder device-provider addon for CamStack — wraps the @apocaliss92/nodepetkit PetKit cloud client",
5
5
  "keywords": [
6
6
  "camstack",