@camstack/addon-agent-ui 1.2.180 → 1.2.182

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 (2) hide show
  1. package/dist/addon.js +332 -10
  2. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -10518,7 +10518,53 @@ var ModelFormatEntrySchema = object({
10518
10518
  /** Multi-file payload (directory members or sibling files). */
10519
10519
  files: array(string()).readonly().optional(),
10520
10520
  /** Runtime(s) that can use this format. If omitted, inferred from ModelFormat key */
10521
- runtimes: array(_enum(["python"])).readonly().optional()
10521
+ runtimes: array(_enum(["python"])).readonly().optional(),
10522
+ /**
10523
+ * Content revision of the artefact, for one hosted OFF the CamStack mirror.
10524
+ * A format on the mirror leaves it unset: its revision (the sha256 of its
10525
+ * weight file) comes from the downloader's generated table, kept in step
10526
+ * with the mirror by `scripts/check-hosted-model-revisions.ts` (D744). A
10527
+ * node records the revision it downloaded next to the file
10528
+ * (`<file>.revision`); a copy with no record or a different one is stale
10529
+ * unless its weight file hashes to the revision, and a stale copy is
10530
+ * downloaded again, the old one serving until the new one is complete. No
10531
+ * revision at all ⇒ a file on disk is current, whatever it holds (D743).
10532
+ */
10533
+ revision: string().min(1).optional()
10534
+ });
10535
+ /**
10536
+ * What a node holds for one (model, format) (D746). `current` is a complete
10537
+ * copy at its catalog revision — exactly what `downloaded: true` means.
10538
+ * `stale` is bytes on disk that are not (yet) proven current under D743/D744:
10539
+ * no or a different revision record, or a missing sibling. `missing` is no
10540
+ * copy. `downloaded` alone folds `stale` into "not downloaded", which hid
10541
+ * reclaimable bytes and a copy about to be replaced.
10542
+ */
10543
+ var ModelOnDiskStateSchema = _enum([
10544
+ "current",
10545
+ "stale",
10546
+ "missing"
10547
+ ]);
10548
+ /**
10549
+ * The numeric precision of one format's BUILD (D746) — reported only when the
10550
+ * build states it (file-name token, an INT8 variant, an EdgeTPU compile, a
10551
+ * CamStack Core ML export). Absent means "not stated", never "fp32".
10552
+ */
10553
+ var ModelFormatPrecisionSchema = _enum([
10554
+ "fp32",
10555
+ "fp16",
10556
+ "int8"
10557
+ ]);
10558
+ /**
10559
+ * One format of one model as a node's `pipelineExecutor.getSchema` reports it.
10560
+ * `onDisk` / `precision` are optional for version skew: a runner that predates
10561
+ * them omits them, and a reader falls back to `downloaded`.
10562
+ */
10563
+ var PipelineModelFormatStatusSchema = object({
10564
+ downloaded: boolean(),
10565
+ sizeMB: number(),
10566
+ onDisk: ModelOnDiskStateSchema.optional(),
10567
+ precision: ModelFormatPrecisionSchema.optional()
10522
10568
  });
10523
10569
  /**
10524
10570
  * Extra file that must be downloaded alongside the model (e.g., labels JSON, dict.txt).
@@ -10727,6 +10773,35 @@ var ModelCatalogEntrySchema = object({
10727
10773
  */
10728
10774
  defaultConfidence: number().min(0).max(1).optional(),
10729
10775
  /**
10776
+ * Per-MODEL default of the per-class confidence floors (`minConfidence<Macro>`
10777
+ * on a detector step), keyed by macro class: `{ person: 0.45 }`. A class
10778
+ * absent here runs at the step slider's global default. The same row shape
10779
+ * the floor measurement produces (`model-floors.json`: modelId → floors), so
10780
+ * a measured table is copied in as-is. An operator override is bound to the
10781
+ * model it was made for and does not survive a model change (D738). A custom
10782
+ * / imported model may declare it; without it, the global defaults apply.
10783
+ */
10784
+ defaultClassFloors: record(string(), number().min(0).max(1)).optional(),
10785
+ /**
10786
+ * The inference precision this model's OpenVINO IR needs on an Intel GPU.
10787
+ * Absent ⇒ the device default (f16 on a GPU). Set to `'f32'` for an FP32 IR
10788
+ * that produces invalid output at f16 — measured 2026-10-07 for YOLO26
10789
+ * base IRs (`yolo26s`: 0 true / 146 false positives; `yolo26m*`: NaN
10790
+ * scores) on the Core Ultra iGPU and the N100. Threaded to the pool as
10791
+ * `PoolModelConfig.gpuInferencePrecision`; the pool sets
10792
+ * INFERENCE_PRECISION_HINT on a GPU only. Costs ~60% latency on the GPU.
10793
+ */
10794
+ gpuInferencePrecision: _enum(["f32", "f16"]).optional(),
10795
+ /**
10796
+ * ROOT detectors only: per supplied step (`animal-classifier`, …), the
10797
+ * minimum DETECTION score from which this root's own fine label (species,
10798
+ * vehicle type — D736 root supply) is taken (D741). Below it the detection
10799
+ * keeps its macro class without the fine label. `1` = never take it from
10800
+ * this root. Absent ⇒ no floor beyond the macro floor. The supplied step's
10801
+ * `minConfidence` slider, bound to the ROOT model, overrides it.
10802
+ */
10803
+ suppliedLabelFloors: record(string(), number().min(0).max(1)).optional(),
10804
+ /**
10730
10805
  * When true, the executor produces a landmark-aligned crop (similarity warp
10731
10806
  * onto the canonical template) before this step runs, instead of a plain
10732
10807
  * axis-aligned bbox crop. Required for face-recognition embedders (ArcFace):
@@ -23128,7 +23203,7 @@ var FrameRefSchema = object({
23128
23203
  timestamp: number(),
23129
23204
  capturedAt: number().optional()
23130
23205
  });
23131
- var ModelFormatSchema$1 = _enum([
23206
+ var ModelFormatSchema$2 = _enum([
23132
23207
  "onnx",
23133
23208
  "coreml",
23134
23209
  "openvino",
@@ -23146,7 +23221,7 @@ var PipelineSlotSchema = _enum([
23146
23221
  var PipelineEngineChoiceSchema = object({
23147
23222
  runtime: literal("python"),
23148
23223
  backend: string(),
23149
- format: ModelFormatSchema$1,
23224
+ format: ModelFormatSchema$2,
23150
23225
  device: string().optional()
23151
23226
  });
23152
23227
  /**
@@ -23203,10 +23278,7 @@ var PipelineTemplateSchema$1 = object({
23203
23278
  var PipelineModelOptionSchema = object({
23204
23279
  id: string(),
23205
23280
  name: string(),
23206
- formats: record(string(), object({
23207
- downloaded: boolean(),
23208
- sizeMB: number()
23209
- })),
23281
+ formats: record(string(), PipelineModelFormatStatusSchema),
23210
23282
  group: ModelVariantGroupSchema.optional(),
23211
23283
  legacy: boolean().optional(),
23212
23284
  provider: ModelProviderIdSchema.optional(),
@@ -23373,6 +23445,22 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
23373
23445
  }), {
23374
23446
  kind: "mutation",
23375
23447
  auth: "admin"
23448
+ }), method(object({
23449
+ nodeId: string(),
23450
+ deviceIds: array(number()).readonly().optional(),
23451
+ dryRun: boolean()
23452
+ }), object({
23453
+ entries: array(object({
23454
+ deviceId: number(),
23455
+ keys: array(string()).readonly()
23456
+ })).readonly(),
23457
+ refused: array(object({
23458
+ deviceId: number(),
23459
+ reason: string()
23460
+ })).readonly()
23461
+ }), {
23462
+ kind: "mutation",
23463
+ auth: "admin"
23376
23464
  }), method(object({ nodeId: string() }), object({ unhealthy: array(object({
23377
23465
  /** `<backend>:<device>`, e.g. `openvino:gpu`. */
23378
23466
  deviceKey: string(),
@@ -23409,11 +23497,11 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
23409
23497
  }), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({ id: string() }), _void(), { kind: "mutation" }), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
23410
23498
  addonId: string(),
23411
23499
  modelId: string(),
23412
- format: ModelFormatSchema$1
23500
+ format: ModelFormatSchema$2
23413
23501
  }), DownloadModelResultSchema, { kind: "mutation" }), method(object({
23414
23502
  addonId: string(),
23415
23503
  modelId: string(),
23416
- format: ModelFormatSchema$1
23504
+ format: ModelFormatSchema$2
23417
23505
  }), object({ success: literal(true) }), { kind: "mutation" }), method(object({
23418
23506
  steps: array(PipelineStepInputSchema).min(1),
23419
23507
  frame: FrameInputSchema.optional(),
@@ -23570,6 +23658,204 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
23570
23658
  filename: string().optional(),
23571
23659
  settings: record(string(), unknown()).optional()
23572
23660
  }), AudioTestResultSchema, { kind: "mutation" }), method(_void(), ConfigUISchemaNullableBridge);
23661
+ /**
23662
+ * The wire shapes of the Best settings plan and apply (D745), used by the
23663
+ * `pipeline-orchestrator` cap. The recommender's own types
23664
+ * (`recommend.ts`, `demand.ts`) are the TS face of the same data; these
23665
+ * schemas are what crosses the cap boundary.
23666
+ */
23667
+ var ModelFormatSchema$1 = _enum(MODEL_FORMATS);
23668
+ var HardwareClassIdSchema = _enum([
23669
+ "intel-core-ultra",
23670
+ "intel-n-series",
23671
+ "apple-m-base",
23672
+ "apple-m-pro",
23673
+ "unknown"
23674
+ ]);
23675
+ var AcceleratorKindSchema = _enum([
23676
+ "intel-npu",
23677
+ "intel-igpu",
23678
+ "x86-cpu",
23679
+ "arm-cpu",
23680
+ "apple-ane",
23681
+ "coral"
23682
+ ]);
23683
+ var RecommendationReasonSchema = discriminatedUnion("kind", [
23684
+ object({
23685
+ kind: literal("fits"),
23686
+ utilisation: number()
23687
+ }),
23688
+ object({
23689
+ kind: literal("tie-faster"),
23690
+ over: string(),
23691
+ recallDelta: number()
23692
+ }),
23693
+ object({
23694
+ kind: literal("stepped-down"),
23695
+ from: string(),
23696
+ to: string(),
23697
+ limitedBy: string()
23698
+ }),
23699
+ object({
23700
+ kind: literal("no-fit-lightest"),
23701
+ utilisation: number()
23702
+ }),
23703
+ object({
23704
+ kind: literal("derived-latency"),
23705
+ modelId: string()
23706
+ }),
23707
+ object({
23708
+ kind: literal("estimated-load"),
23709
+ observedForMs: number().nullable()
23710
+ }),
23711
+ object({ kind: literal("cpu-device") }),
23712
+ object({ kind: literal("coral-untouched") }),
23713
+ object({ kind: literal("device-disabled") }),
23714
+ object({ kind: literal("device-unavailable") }),
23715
+ object({ kind: literal("node-offline") }),
23716
+ object({ kind: literal("no-hardware-facts") }),
23717
+ object({
23718
+ kind: literal("no-measured-data"),
23719
+ hardwareClass: HardwareClassIdSchema
23720
+ }),
23721
+ object({
23722
+ kind: literal("no-family-build"),
23723
+ format: ModelFormatSchema$1
23724
+ })
23725
+ ]);
23726
+ var DeviceDemandSchema = object({
23727
+ nodeId: string(),
23728
+ deviceKey: string(),
23729
+ demandFps: number(),
23730
+ maxCameraFps: number(),
23731
+ alwaysOnCameras: number(),
23732
+ onMotionSessions: number(),
23733
+ onMotionSource: _enum([
23734
+ "observed-24h",
23735
+ "estimate",
23736
+ "none"
23737
+ ]),
23738
+ observedForMs: number().nullable()
23739
+ });
23740
+ var DeviceModelChoiceSchema = object({
23741
+ modelId: string(),
23742
+ p50Ms: number(),
23743
+ fps: number(),
23744
+ measured: boolean(),
23745
+ utilisation: number(),
23746
+ personRecall: number()
23747
+ });
23748
+ var DeviceRecommendationSchema = object({
23749
+ deviceKey: string(),
23750
+ accelerator: AcceleratorKindSchema.nullable(),
23751
+ enabled: boolean(),
23752
+ available: boolean(),
23753
+ demand: DeviceDemandSchema.nullable(),
23754
+ chosen: DeviceModelChoiceSchema.nullable(),
23755
+ reasons: array(RecommendationReasonSchema).readonly()
23756
+ });
23757
+ var NodeRecommendationSchema = object({
23758
+ nodeId: string(),
23759
+ reachable: boolean(),
23760
+ hardwareClass: HardwareClassIdSchema.nullable(),
23761
+ cpuModel: string().nullable(),
23762
+ skipped: boolean(),
23763
+ acceleratorModelId: string().nullable(),
23764
+ devices: array(DeviceRecommendationSchema).readonly(),
23765
+ reasons: array(RecommendationReasonSchema).readonly()
23766
+ });
23767
+ var ModelPinChangeSchema = object({
23768
+ stepId: string(),
23769
+ before: string().nullable(),
23770
+ after: string().nullable()
23771
+ });
23772
+ var NodeDeviceChangeSchema = object({
23773
+ nodeId: string(),
23774
+ deviceKey: string(),
23775
+ madeExplicit: boolean(),
23776
+ modelPins: array(ModelPinChangeSchema).readonly(),
23777
+ thresholds: array(object({
23778
+ stepId: string(),
23779
+ keys: array(string()).readonly()
23780
+ })).readonly()
23781
+ });
23782
+ var CameraOverrideClearSchema = object({
23783
+ deviceId: number(),
23784
+ source: _enum(["step-override", "wholesale"]),
23785
+ nodeId: string(),
23786
+ deviceKey: string().nullable(),
23787
+ stepId: string(),
23788
+ modelIdBefore: string().nullable(),
23789
+ keys: array(string()).readonly()
23790
+ });
23791
+ var DetectorStoreClearSchema = object({
23792
+ deviceId: number(),
23793
+ keys: array(string()).readonly()
23794
+ });
23795
+ var BestSettingsWarningSchema = discriminatedUnion("kind", [
23796
+ object({
23797
+ kind: literal("detector-store-cluster-wide"),
23798
+ skippedNodes: array(string()).readonly()
23799
+ }),
23800
+ object({
23801
+ kind: literal("detector-store-unreadable"),
23802
+ error: string()
23803
+ }),
23804
+ object({
23805
+ kind: literal("coral-enabled"),
23806
+ nodeId: string(),
23807
+ deviceKey: string()
23808
+ })
23809
+ ]);
23810
+ var BestSettingsOptionsSchema = object({
23811
+ /** Share of each accelerator's throughput kept free (0.3–0.5). */
23812
+ headroom: number().min(.3).max(.5).default(.4) });
23813
+ var BestSettingsPlanSchema = object({
23814
+ /** Hash of everything the apply will write — the apply refuses a different one. */
23815
+ planHash: string(),
23816
+ family: literal("yolov9"),
23817
+ headroom: number(),
23818
+ generatedAt: number(),
23819
+ nodes: array(NodeRecommendationSchema).readonly(),
23820
+ nodeChanges: array(NodeDeviceChangeSchema).readonly(),
23821
+ cameraClears: array(CameraOverrideClearSchema).readonly(),
23822
+ detectorStoreClears: array(DetectorStoreClearSchema).readonly(),
23823
+ warnings: array(BestSettingsWarningSchema).readonly()
23824
+ });
23825
+ var BestSettingsApplyInputSchema = object({
23826
+ planHash: string(),
23827
+ headroom: number().min(.3).max(.5).default(.4)
23828
+ });
23829
+ var BestSettingsPhaseResultSchema = object({
23830
+ phase: _enum([
23831
+ "download",
23832
+ "camera-overrides",
23833
+ "detector-thresholds",
23834
+ "node-models",
23835
+ "redispatch"
23836
+ ]),
23837
+ ok: boolean(),
23838
+ detail: string()
23839
+ });
23840
+ var BestSettingsApplyResultSchema = discriminatedUnion("kind", [
23841
+ object({
23842
+ kind: literal("applied"),
23843
+ planHash: string(),
23844
+ phases: array(BestSettingsPhaseResultSchema).readonly()
23845
+ }),
23846
+ object({
23847
+ kind: literal("aborted"),
23848
+ phases: array(BestSettingsPhaseResultSchema).readonly()
23849
+ }),
23850
+ object({
23851
+ kind: literal("stale"),
23852
+ plan: BestSettingsPlanSchema
23853
+ }),
23854
+ object({
23855
+ kind: literal("refused"),
23856
+ reason: _enum(["apply-in-progress"])
23857
+ })
23858
+ ]);
23573
23859
  object({
23574
23860
  activeCameras: number(),
23575
23861
  throttledCameras: number(),
@@ -25296,6 +25582,9 @@ method(object({
25296
25582
  }), {
25297
25583
  kind: "mutation",
25298
25584
  auth: "admin"
25585
+ }), method(BestSettingsOptionsSchema, BestSettingsPlanSchema, { auth: "admin" }), method(BestSettingsApplyInputSchema, BestSettingsApplyResultSchema, {
25586
+ kind: "mutation",
25587
+ auth: "admin"
25299
25588
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
25300
25589
  deviceId: number(),
25301
25590
  addonId: string(),
@@ -36343,6 +36632,16 @@ DeviceType.Camera, method(object({
36343
36632
  package: array(ZoneRuleSchema).readonly()
36344
36633
  });
36345
36634
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
36635
+ Object.freeze({
36636
+ person: .5,
36637
+ vehicle: .5,
36638
+ animal: .5
36639
+ });
36640
+ Object.freeze({
36641
+ person: .65,
36642
+ vehicle: .65,
36643
+ animal: .65
36644
+ });
36346
36645
  /**
36347
36646
  * Accessory device helpers — shared across drivers.
36348
36647
  *
@@ -40861,6 +41160,12 @@ Object.freeze({
40861
41160
  addonId: null,
40862
41161
  access: "delete"
40863
41162
  },
41163
+ "pipelineExecutor.clearModelBoundDeviceOverrides": {
41164
+ capName: "pipeline-executor",
41165
+ capScope: "system",
41166
+ addonId: null,
41167
+ access: "delete"
41168
+ },
40864
41169
  "pipelineExecutor.deleteModel": {
40865
41170
  capName: "pipeline-executor",
40866
41171
  capScope: "system",
@@ -41077,6 +41382,12 @@ Object.freeze({
41077
41382
  addonId: null,
41078
41383
  access: "view"
41079
41384
  },
41385
+ "pipelineOrchestrator.applyBestSettings": {
41386
+ capName: "pipeline-orchestrator",
41387
+ capScope: "system",
41388
+ addonId: null,
41389
+ access: "create"
41390
+ },
41080
41391
  "pipelineOrchestrator.applyDeviceSettingsPatch": {
41081
41392
  capName: "pipeline-orchestrator",
41082
41393
  capScope: "system",
@@ -41251,6 +41562,12 @@ Object.freeze({
41251
41562
  addonId: null,
41252
41563
  access: "create"
41253
41564
  },
41565
+ "pipelineOrchestrator.planBestSettings": {
41566
+ capName: "pipeline-orchestrator",
41567
+ capScope: "system",
41568
+ addonId: null,
41569
+ access: "view"
41570
+ },
41254
41571
  "pipelineOrchestrator.rebalance": {
41255
41572
  capName: "pipeline-orchestrator",
41256
41573
  capScope: "system",
@@ -46673,6 +46990,11 @@ Object.freeze({
46673
46990
  form: "single",
46674
46991
  optional: false
46675
46992
  }],
46993
+ "pipelineExecutor.clearModelBoundDeviceOverrides": [{
46994
+ name: "deviceIds",
46995
+ form: "array",
46996
+ optional: true
46997
+ }],
46676
46998
  "pipelineExecutor.runPipeline": [{
46677
46999
  name: "deviceId",
46678
47000
  form: "single",
@@ -48714,7 +49036,7 @@ var AgentUIAddon = class extends BaseAddon {
48714
49036
  capability: adminUiCapability,
48715
49037
  provider: {
48716
49038
  getStaticDir: async () => ({ staticDir: path.resolve(__dirname) }),
48717
- getVersion: async () => ({ version: "1.2.180" })
49039
+ getVersion: async () => ({ version: "1.2.182" })
48718
49040
  }
48719
49041
  }];
48720
49042
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-agent-ui",
3
- "version": "1.2.180",
3
+ "version": "1.2.182",
4
4
  "description": "Agent UI — lightweight status dashboard served by every agent node",
5
5
  "keywords": [
6
6
  "camstack",