camstack 1.2.44 → 1.2.45
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.
|
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
|
|
|
23633
23633
|
}
|
|
23634
23634
|
});
|
|
23635
23635
|
|
|
23636
|
-
// ../system/dist/dist-
|
|
23637
|
-
var
|
|
23638
|
-
"../system/dist/dist-
|
|
23636
|
+
// ../system/dist/dist-BNhvXrQk.js
|
|
23637
|
+
var require_dist_BNhvXrQk = __commonJS({
|
|
23638
|
+
"../system/dist/dist-BNhvXrQk.js"(exports) {
|
|
23639
23639
|
"use strict";
|
|
23640
23640
|
var zod = require_zod();
|
|
23641
23641
|
var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
|
|
@@ -34621,6 +34621,726 @@ var require_dist_D5Jhh8Vk = __commonJS({
|
|
|
34621
34621
|
getDescriptor: method(zod.z.void(), OauthIntegrationDescriptorSchema, { auth: "admin" })
|
|
34622
34622
|
}
|
|
34623
34623
|
};
|
|
34624
|
+
var NativeCropRefSchema = zod.z.object({
|
|
34625
|
+
/** Handle keying the retained native surface (node-pinned to its owner). */
|
|
34626
|
+
handle: FrameHandleSchema,
|
|
34627
|
+
/** The parent crop's padded/clamped rectangle in FRAME-space pixels. */
|
|
34628
|
+
cropFrameSpace: zod.z.object({
|
|
34629
|
+
x: zod.z.number(),
|
|
34630
|
+
y: zod.z.number(),
|
|
34631
|
+
w: zod.z.number(),
|
|
34632
|
+
h: zod.z.number()
|
|
34633
|
+
})
|
|
34634
|
+
});
|
|
34635
|
+
zod.z.object({
|
|
34636
|
+
crop: zod.z.object({
|
|
34637
|
+
left: zod.z.number(),
|
|
34638
|
+
top: zod.z.number(),
|
|
34639
|
+
width: zod.z.number().positive(),
|
|
34640
|
+
height: zod.z.number().positive()
|
|
34641
|
+
}).optional(),
|
|
34642
|
+
content: zod.z.object({
|
|
34643
|
+
width: zod.z.number().int().positive(),
|
|
34644
|
+
height: zod.z.number().int().positive()
|
|
34645
|
+
}),
|
|
34646
|
+
fit: zod.z.enum(["stretch", "contain"]),
|
|
34647
|
+
format: zod.z.enum([
|
|
34648
|
+
"rgb",
|
|
34649
|
+
"gray",
|
|
34650
|
+
"jpeg"
|
|
34651
|
+
])
|
|
34652
|
+
});
|
|
34653
|
+
var FrameRefSchema = zod.z.object({
|
|
34654
|
+
registryId: zod.z.string().min(1),
|
|
34655
|
+
id: zod.z.string().min(1),
|
|
34656
|
+
width: zod.z.number().int().positive(),
|
|
34657
|
+
height: zod.z.number().int().positive(),
|
|
34658
|
+
format: zod.z.enum(["rgb", "gray"]),
|
|
34659
|
+
timestamp: zod.z.number(),
|
|
34660
|
+
capturedAt: zod.z.number().optional()
|
|
34661
|
+
});
|
|
34662
|
+
var ModelFormatSchema$1 = zod.z.enum([
|
|
34663
|
+
"onnx",
|
|
34664
|
+
"coreml",
|
|
34665
|
+
"openvino",
|
|
34666
|
+
"tflite",
|
|
34667
|
+
"pt",
|
|
34668
|
+
"gguf"
|
|
34669
|
+
]);
|
|
34670
|
+
var PipelineSlotSchema = zod.z.enum([
|
|
34671
|
+
"detector",
|
|
34672
|
+
"cropper",
|
|
34673
|
+
"classifier",
|
|
34674
|
+
"refiner",
|
|
34675
|
+
"audio-classifier"
|
|
34676
|
+
]);
|
|
34677
|
+
var PipelineEngineChoiceSchema = zod.z.object({
|
|
34678
|
+
runtime: zod.z.enum(["node", "python"]),
|
|
34679
|
+
backend: zod.z.string(),
|
|
34680
|
+
format: ModelFormatSchema$1,
|
|
34681
|
+
device: zod.z.string().optional()
|
|
34682
|
+
});
|
|
34683
|
+
var EngineDeviceInfoSchema = zod.z.object({
|
|
34684
|
+
id: zod.z.string(),
|
|
34685
|
+
label: zod.z.string(),
|
|
34686
|
+
description: zod.z.string().optional()
|
|
34687
|
+
});
|
|
34688
|
+
var AvailableEngineSchema = zod.z.object({
|
|
34689
|
+
engine: PipelineEngineChoiceSchema,
|
|
34690
|
+
devices: zod.z.array(EngineDeviceInfoSchema).readonly(),
|
|
34691
|
+
defaultDevice: zod.z.string()
|
|
34692
|
+
});
|
|
34693
|
+
var PipelineDefaultStepSchema = zod.z.lazy(() => zod.z.object({
|
|
34694
|
+
addonId: zod.z.string(),
|
|
34695
|
+
addonName: zod.z.string(),
|
|
34696
|
+
slot: PipelineSlotSchema,
|
|
34697
|
+
inputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
34698
|
+
outputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
34699
|
+
enabled: zod.z.boolean(),
|
|
34700
|
+
modelId: zod.z.string(),
|
|
34701
|
+
children: zod.z.array(PipelineDefaultStepSchema).readonly(),
|
|
34702
|
+
group: zod.z.string().optional(),
|
|
34703
|
+
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
34704
|
+
}));
|
|
34705
|
+
var PipelineTemplateStepSchema = zod.z.lazy(() => zod.z.object({
|
|
34706
|
+
addonId: zod.z.string(),
|
|
34707
|
+
enabled: zod.z.boolean(),
|
|
34708
|
+
modelId: zod.z.string(),
|
|
34709
|
+
children: zod.z.array(PipelineTemplateStepSchema).readonly(),
|
|
34710
|
+
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
34711
|
+
}));
|
|
34712
|
+
var PipelineTemplateSchema$1 = zod.z.object({
|
|
34713
|
+
id: zod.z.string(),
|
|
34714
|
+
name: zod.z.string(),
|
|
34715
|
+
createdAt: zod.z.string(),
|
|
34716
|
+
updatedAt: zod.z.string(),
|
|
34717
|
+
engine: PipelineEngineChoiceSchema,
|
|
34718
|
+
steps: zod.z.array(PipelineTemplateStepSchema).readonly()
|
|
34719
|
+
});
|
|
34720
|
+
var PipelineModelOptionSchema = zod.z.object({
|
|
34721
|
+
id: zod.z.string(),
|
|
34722
|
+
name: zod.z.string(),
|
|
34723
|
+
formats: zod.z.record(zod.z.string(), zod.z.object({
|
|
34724
|
+
downloaded: zod.z.boolean(),
|
|
34725
|
+
sizeMB: zod.z.number()
|
|
34726
|
+
})),
|
|
34727
|
+
group: ModelVariantGroupSchema.optional(),
|
|
34728
|
+
legacy: zod.z.boolean().optional(),
|
|
34729
|
+
provider: ModelProviderIdSchema.optional()
|
|
34730
|
+
});
|
|
34731
|
+
var ConfigFieldBridge = zod.z.custom();
|
|
34732
|
+
var PipelineAddonSchemaSchema = zod.z.object({
|
|
34733
|
+
id: zod.z.string(),
|
|
34734
|
+
name: zod.z.string(),
|
|
34735
|
+
slot: PipelineSlotSchema,
|
|
34736
|
+
inputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
34737
|
+
outputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
34738
|
+
childSlots: zod.z.array(PipelineSlotSchema).readonly(),
|
|
34739
|
+
models: zod.z.array(PipelineModelOptionSchema).readonly(),
|
|
34740
|
+
defaultModelId: zod.z.string(),
|
|
34741
|
+
defaultModelIdByFormat: zod.z.record(zod.z.string(), zod.z.string()).optional(),
|
|
34742
|
+
enabledByDefault: zod.z.boolean().optional(),
|
|
34743
|
+
backfillIntoExistingOverrides: zod.z.boolean().optional(),
|
|
34744
|
+
defaultConfidence: zod.z.number(),
|
|
34745
|
+
group: zod.z.string().optional(),
|
|
34746
|
+
configSchema: zod.z.array(ConfigFieldBridge).readonly().optional()
|
|
34747
|
+
});
|
|
34748
|
+
var PipelineSlotSchemaSchema = zod.z.object({
|
|
34749
|
+
id: PipelineSlotSchema,
|
|
34750
|
+
label: zod.z.string(),
|
|
34751
|
+
priority: zod.z.number(),
|
|
34752
|
+
parentSlot: PipelineSlotSchema.nullable(),
|
|
34753
|
+
addons: zod.z.array(PipelineAddonSchemaSchema).readonly()
|
|
34754
|
+
});
|
|
34755
|
+
var PipelineSchemaSchema = zod.z.object({
|
|
34756
|
+
availableEngines: zod.z.array(AvailableEngineSchema).readonly(),
|
|
34757
|
+
selectedEngine: PipelineEngineChoiceSchema,
|
|
34758
|
+
slots: zod.z.array(PipelineSlotSchemaSchema).readonly()
|
|
34759
|
+
});
|
|
34760
|
+
var EngineProvisioningSchema = zod.z.object({
|
|
34761
|
+
runtimeId: zod.z.enum([
|
|
34762
|
+
"onnx",
|
|
34763
|
+
"openvino",
|
|
34764
|
+
"coreml",
|
|
34765
|
+
"edgetpu"
|
|
34766
|
+
]).nullable(),
|
|
34767
|
+
device: zod.z.string().nullable(),
|
|
34768
|
+
state: zod.z.enum([
|
|
34769
|
+
"idle",
|
|
34770
|
+
"installing",
|
|
34771
|
+
"verifying",
|
|
34772
|
+
"ready",
|
|
34773
|
+
"failed"
|
|
34774
|
+
]),
|
|
34775
|
+
progress: zod.z.number().optional(),
|
|
34776
|
+
error: zod.z.string().optional(),
|
|
34777
|
+
nextRetryAt: zod.z.number().optional(),
|
|
34778
|
+
/**
|
|
34779
|
+
* Gate A (config-correctness gate at engine change): human-readable
|
|
34780
|
+
* config issues surfaced EAGERLY when the node's engine changes — model
|
|
34781
|
+
* substitutions ("chose X, running Y") and zero-build steps ("no model
|
|
34782
|
+
* has a <format> build"). Additive/optional: informational only, never
|
|
34783
|
+
* enforced here — `assertEngineReady` (readiness) still gates inference.
|
|
34784
|
+
* Absent/empty when the node-default tree resolves cleanly.
|
|
34785
|
+
*/
|
|
34786
|
+
configIssues: zod.z.array(zod.z.string()).optional()
|
|
34787
|
+
});
|
|
34788
|
+
var PipelineStepInputSchema = zod.z.lazy(() => zod.z.object({
|
|
34789
|
+
addonId: zod.z.string(),
|
|
34790
|
+
modelId: zod.z.string().optional(),
|
|
34791
|
+
enabled: zod.z.boolean().default(true),
|
|
34792
|
+
children: zod.z.array(PipelineStepInputSchema).optional(),
|
|
34793
|
+
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
34794
|
+
jumpDeviceKey: zod.z.string().optional()
|
|
34795
|
+
}));
|
|
34796
|
+
var ModelSubstitutionSchema = zod.z.object({
|
|
34797
|
+
addonId: zod.z.string(),
|
|
34798
|
+
chosen: zod.z.string(),
|
|
34799
|
+
running: zod.z.string(),
|
|
34800
|
+
format: zod.z.string()
|
|
34801
|
+
});
|
|
34802
|
+
var PipelineValidationIssueSchema = zod.z.object({
|
|
34803
|
+
addonId: zod.z.string(),
|
|
34804
|
+
kind: zod.z.enum(["unknown-addon", "no-format-build"]),
|
|
34805
|
+
detail: zod.z.string()
|
|
34806
|
+
});
|
|
34807
|
+
var PipelineValidationResultSchema = zod.z.object({
|
|
34808
|
+
ok: zod.z.boolean(),
|
|
34809
|
+
issues: zod.z.array(PipelineValidationIssueSchema).readonly(),
|
|
34810
|
+
substitutions: zod.z.array(ModelSubstitutionSchema).readonly(),
|
|
34811
|
+
/** The node's `currentEngine.format` this validation ran against. */
|
|
34812
|
+
format: zod.z.string()
|
|
34813
|
+
});
|
|
34814
|
+
var ReferenceImageEntrySchema = zod.z.object({
|
|
34815
|
+
filename: zod.z.string(),
|
|
34816
|
+
stepIds: zod.z.array(zod.z.string()).readonly().optional()
|
|
34817
|
+
});
|
|
34818
|
+
var ReferenceImageBodySchema = zod.z.object({
|
|
34819
|
+
base64: zod.z.string(),
|
|
34820
|
+
filename: zod.z.string()
|
|
34821
|
+
});
|
|
34822
|
+
var ReferenceAudioEntrySchema = zod.z.object({
|
|
34823
|
+
filename: zod.z.string(),
|
|
34824
|
+
sizeKb: zod.z.number()
|
|
34825
|
+
});
|
|
34826
|
+
var ReferenceAudioBodySchema = zod.z.object({ base64: zod.z.string() });
|
|
34827
|
+
var AudioBackendSchema = zod.z.object({
|
|
34828
|
+
id: zod.z.string(),
|
|
34829
|
+
name: zod.z.string(),
|
|
34830
|
+
description: zod.z.string(),
|
|
34831
|
+
available: zod.z.boolean(),
|
|
34832
|
+
/**
|
|
34833
|
+
* Raw classifier labels this backend can emit (e.g. YAMNet's
|
|
34834
|
+
* 521-class set or Apple SoundAnalysis's 303-class set). Used by
|
|
34835
|
+
* the benchmark UI to populate the `enabledMicroClasses` filter
|
|
34836
|
+
* specific to the selected backend without a separate fetch.
|
|
34837
|
+
*/
|
|
34838
|
+
rawLabels: zod.z.array(zod.z.string()).readonly().optional()
|
|
34839
|
+
});
|
|
34840
|
+
var AudioCapabilitiesSchema = zod.z.object({
|
|
34841
|
+
activeBackend: zod.z.string(),
|
|
34842
|
+
availableBackends: zod.z.array(AudioBackendSchema).readonly(),
|
|
34843
|
+
sampleRate: zod.z.number(),
|
|
34844
|
+
chunkDurationMs: zod.z.number()
|
|
34845
|
+
});
|
|
34846
|
+
var DownloadModelResultSchema = zod.z.object({
|
|
34847
|
+
filePath: zod.z.string(),
|
|
34848
|
+
sizeMB: zod.z.number(),
|
|
34849
|
+
durationMs: zod.z.number()
|
|
34850
|
+
});
|
|
34851
|
+
var AudioTestResultSchema = zod.z.object({
|
|
34852
|
+
success: zod.z.boolean(),
|
|
34853
|
+
error: zod.z.string().optional(),
|
|
34854
|
+
frame: zod.z.custom().optional()
|
|
34855
|
+
});
|
|
34856
|
+
var PipelineConfigBridge = zod.z.custom();
|
|
34857
|
+
var ConfigUISchemaBridge = zod.z.custom();
|
|
34858
|
+
var ConfigUISchemaNullableBridge = zod.z.custom();
|
|
34859
|
+
var InferenceCapabilitiesBridge = zod.z.custom();
|
|
34860
|
+
var ModelAvailabilityListBridge = zod.z.custom();
|
|
34861
|
+
var PipelineRunResultBridge = zod.z.custom();
|
|
34862
|
+
var pipelineExecutorCapability = {
|
|
34863
|
+
name: "pipeline-executor",
|
|
34864
|
+
scope: "system",
|
|
34865
|
+
mode: "singleton",
|
|
34866
|
+
methods: {
|
|
34867
|
+
getAvailableEngines: method(zod.z.void(), zod.z.array(PipelineEngineChoiceSchema)),
|
|
34868
|
+
getSelectedEngine: method(zod.z.void(), PipelineEngineChoiceSchema),
|
|
34869
|
+
getDefaultSteps: method(PipelineEngineChoiceSchema, zod.z.array(PipelineDefaultStepSchema)),
|
|
34870
|
+
/**
|
|
34871
|
+
* Per-node detection-engine provisioning snapshot. Returns the live
|
|
34872
|
+
* state of the lazy runtime-provisioning machine on `nodeId`
|
|
34873
|
+
* (idle / installing / verifying / ready / failed). The UI pairs this
|
|
34874
|
+
* one-shot query with the `pipeline.engine-provisioning` live event
|
|
34875
|
+
* (emitted on every transition) to drive a per-node "engine ready?"
|
|
34876
|
+
* indicator without polling. Phase 2.
|
|
34877
|
+
*/
|
|
34878
|
+
getEngineProvisioning: method(zod.z.object({ nodeId: zod.z.string() }), EngineProvisioningSchema),
|
|
34879
|
+
getVideoPipelineSteps: method(zod.z.void(), zod.z.record(zod.z.string(), zod.z.object({
|
|
34880
|
+
modelId: zod.z.string(),
|
|
34881
|
+
settings: zod.z.record(zod.z.string(), zod.z.unknown()).readonly()
|
|
34882
|
+
}))),
|
|
34883
|
+
setVideoPipelineSteps: method(zod.z.object({ steps: zod.z.record(zod.z.string(), zod.z.object({
|
|
34884
|
+
modelId: zod.z.string(),
|
|
34885
|
+
settings: zod.z.record(zod.z.string(), zod.z.unknown()).readonly()
|
|
34886
|
+
})) }), zod.z.object({ success: zod.z.literal(true) }), {
|
|
34887
|
+
kind: "mutation",
|
|
34888
|
+
auth: "admin"
|
|
34889
|
+
}),
|
|
34890
|
+
/**
|
|
34891
|
+
* Clear THIS node's executor-side PER-DEVICE settings stores (the
|
|
34892
|
+
* per-camera step overrides the object-detection root reads via
|
|
34893
|
+
* `applyDeviceOverridesToTree`). `nodeId` is the ROUTING key — the
|
|
34894
|
+
* generated cap-router strips it (default `nodeIdMode: 'routing'`) and
|
|
34895
|
+
* dispatches to that node, so the provider method runs ON the target
|
|
34896
|
+
* node and receives no `nodeId`.
|
|
34897
|
+
*
|
|
34898
|
+
* This is the slimmed executor leg of the orchestrator's
|
|
34899
|
+
* `resetNodePipelineDefaults` flow (which owns the real reset: node
|
|
34900
|
+
* addonDefaults pins + per-camera orchestrator overrides). The legacy
|
|
34901
|
+
* `resetToDefault` — which reset a persisted global step-tree seed
|
|
34902
|
+
* nothing in the live per-camera path read — was removed together with
|
|
34903
|
+
* that seed.
|
|
34904
|
+
*/
|
|
34905
|
+
clearDeviceOverrides: method(zod.z.object({ nodeId: zod.z.string() }), zod.z.object({
|
|
34906
|
+
success: zod.z.literal(true),
|
|
34907
|
+
clearedDevices: zod.z.number()
|
|
34908
|
+
}), {
|
|
34909
|
+
kind: "mutation",
|
|
34910
|
+
auth: "admin"
|
|
34911
|
+
}),
|
|
34912
|
+
/**
|
|
34913
|
+
* Which of THIS node's inference devices the executor currently refuses,
|
|
34914
|
+
* and why. `nodeId` is the ROUTING key (stripped by the generated router).
|
|
34915
|
+
*
|
|
34916
|
+
* The channel that did not exist. Pool health was known only inside the
|
|
34917
|
+
* detection addon and was an input to no routing decision anywhere: the
|
|
34918
|
+
* per-dispatch capability gate is keyed on model FORMAT and so can never
|
|
34919
|
+
* separate `openvino:gpu` from `openvino:npu`, and the orchestrator's live
|
|
34920
|
+
* eligibility probe (`platformProbe.getCapabilities`) answers about
|
|
34921
|
+
* HARDWARE — which was present throughout. So when the hub's `openvino:gpu`
|
|
34922
|
+
* Python worker was SIGABRT'd by the Intel GPU plugin on 2026-08-25, the
|
|
34923
|
+
* balancer went on handing that dead pool cameras by rotation for 31 hours:
|
|
34924
|
+
* ~370 000 `PoolWorker[w0]: not initialized` lines, every frame lost.
|
|
34925
|
+
*
|
|
34926
|
+
* Read semantics the caller depends on, and which the provider guarantees:
|
|
34927
|
+
* this is a synchronous read of in-memory state. It never probes hardware,
|
|
34928
|
+
* never spawns a pool and never throws — an EMPTY `unhealthy` means "asked,
|
|
34929
|
+
* nothing is refused", which is what re-admits a device. A read that FAILS
|
|
34930
|
+
* (node offline, version skew) must therefore be distinguishable from an
|
|
34931
|
+
* empty answer, and it is: it rejects.
|
|
34932
|
+
*/
|
|
34933
|
+
getInferenceDeviceHealth: method(zod.z.object({ nodeId: zod.z.string() }), zod.z.object({ unhealthy: zod.z.array(zod.z.object({
|
|
34934
|
+
/** `<backend>:<device>`, e.g. `openvino:gpu`. */
|
|
34935
|
+
deviceKey: zod.z.string(),
|
|
34936
|
+
/**
|
|
34937
|
+
* `failed` — the per-device restart budget is exhausted; no pool
|
|
34938
|
+
* will be spawned until an operator re-arms it or the runner
|
|
34939
|
+
* respawns. `backoff` — under budget, waiting out the backoff (or
|
|
34940
|
+
* a cached pool observed dead and not yet condemned).
|
|
34941
|
+
*/
|
|
34942
|
+
state: zod.z.enum(["failed", "backoff"]),
|
|
34943
|
+
/** Epoch ms of the death that produced this state. */
|
|
34944
|
+
since: zod.z.number(),
|
|
34945
|
+
/** Pool deaths inside the current window. */
|
|
34946
|
+
deaths: zod.z.number(),
|
|
34947
|
+
/** The last death's message. */
|
|
34948
|
+
lastError: zod.z.string()
|
|
34949
|
+
})).readonly() })),
|
|
34950
|
+
/**
|
|
34951
|
+
* Re-arm a terminally `failed` inference device on `nodeId`: forget its
|
|
34952
|
+
* restart budget so the next dispatch builds a fresh pool.
|
|
34953
|
+
*
|
|
34954
|
+
* The terminal state is deliberate (the abort it bounds is deterministic —
|
|
34955
|
+
* an automatic probation would just respawn Python forever, more slowly),
|
|
34956
|
+
* and a terminal state an operator cannot leave is a silent fault. This is
|
|
34957
|
+
* the way out. `rearmed:false` means there was nothing to forget.
|
|
34958
|
+
*/
|
|
34959
|
+
rearmInferenceDevice: method(zod.z.object({
|
|
34960
|
+
nodeId: zod.z.string(),
|
|
34961
|
+
deviceKey: zod.z.string()
|
|
34962
|
+
}), zod.z.object({ rearmed: zod.z.boolean() }), {
|
|
34963
|
+
kind: "mutation",
|
|
34964
|
+
auth: "admin"
|
|
34965
|
+
}),
|
|
34966
|
+
getSchema: method(zod.z.void(), PipelineSchemaSchema),
|
|
34967
|
+
getGlobalSteps: method(zod.z.void(), zod.z.array(PipelineDefaultStepSchema).readonly().nullable()),
|
|
34968
|
+
getGlobalPipelineConfig: method(zod.z.void(), PipelineConfigBridge),
|
|
34969
|
+
getOrchestratorConfigSchema: method(zod.z.void(), ConfigUISchemaBridge),
|
|
34970
|
+
/**
|
|
34971
|
+
* Gate B (pre-init config-correctness gate). PURE COMPUTE against this
|
|
34972
|
+
* node's `currentEngine.format` — resolves `steps` the same way the
|
|
34973
|
+
* runtime dispatch path would, and reports what WOULD happen without
|
|
34974
|
+
* touching any node-global state. Called by the orchestrator at attach
|
|
34975
|
+
* time (`attachOn`), node-pinned to the TARGET node, so config problems
|
|
34976
|
+
* surface BEFORE `pipelineRunner.attachCamera` rather than at the first
|
|
34977
|
+
* per-frame resolve. `ok` is false iff `issues` is non-empty (both
|
|
34978
|
+
* `unknown-addon` and `no-format-build` are HARD issues); `substitutions`
|
|
34979
|
+
* is informational (a degraded-but-loadable model swap) and never
|
|
34980
|
+
* affects `ok`. Never throws.
|
|
34981
|
+
*/
|
|
34982
|
+
validatePipeline: method(zod.z.object({ steps: zod.z.array(PipelineStepInputSchema) }), PipelineValidationResultSchema),
|
|
34983
|
+
listTemplates: method(zod.z.void(), zod.z.array(PipelineTemplateSchema$1).readonly()),
|
|
34984
|
+
saveTemplate: method(zod.z.object({
|
|
34985
|
+
name: zod.z.string(),
|
|
34986
|
+
steps: zod.z.array(PipelineTemplateStepSchema).readonly(),
|
|
34987
|
+
engine: PipelineEngineChoiceSchema
|
|
34988
|
+
}), PipelineTemplateSchema$1, { kind: "mutation" }),
|
|
34989
|
+
updateTemplate: method(zod.z.object({
|
|
34990
|
+
id: zod.z.string(),
|
|
34991
|
+
name: zod.z.string().optional(),
|
|
34992
|
+
steps: zod.z.array(PipelineTemplateStepSchema).readonly().optional()
|
|
34993
|
+
}), PipelineTemplateSchema$1, { kind: "mutation" }),
|
|
34994
|
+
deleteTemplate: method(zod.z.object({ id: zod.z.string() }), zod.z.void(), { kind: "mutation" }),
|
|
34995
|
+
getCapabilities: method(zod.z.void(), InferenceCapabilitiesBridge),
|
|
34996
|
+
getAddonModels: method(zod.z.object({ addonId: zod.z.string() }), ModelAvailabilityListBridge),
|
|
34997
|
+
downloadModel: method(zod.z.object({
|
|
34998
|
+
addonId: zod.z.string(),
|
|
34999
|
+
modelId: zod.z.string(),
|
|
35000
|
+
format: ModelFormatSchema$1
|
|
35001
|
+
}), DownloadModelResultSchema, { kind: "mutation" }),
|
|
35002
|
+
deleteModel: method(zod.z.object({
|
|
35003
|
+
addonId: zod.z.string(),
|
|
35004
|
+
modelId: zod.z.string(),
|
|
35005
|
+
format: ModelFormatSchema$1
|
|
35006
|
+
}), zod.z.object({ success: zod.z.literal(true) }), { kind: "mutation" }),
|
|
35007
|
+
/**
|
|
35008
|
+
* Stateless single-frame execution. Callers (runner, benchmark) pass
|
|
35009
|
+
* the complete `engine` + `steps` tree; the executor holds no state
|
|
35010
|
+
* about cameras or saved pipelines.
|
|
35011
|
+
*
|
|
35012
|
+
* `engine` is optional during the migration window to preserve the
|
|
35013
|
+
* legacy call shape used by existing benchmark code; once all
|
|
35014
|
+
* callers pass it explicitly we make it required.
|
|
35015
|
+
*
|
|
35016
|
+
* Exactly one of `frame`, `frameRef`, `frameHandle`, `imageBase64`,
|
|
35017
|
+
* `referenceImage` must be provided:
|
|
35018
|
+
* - `frame`: runtime dispatch path (runner → decoded broker frame).
|
|
35019
|
+
* Carries the raw buffer, dimensions, and format; the executor
|
|
35020
|
+
* uses it directly without base64 round-tripping.
|
|
35021
|
+
* - `frameHandle` (CB5): a zero-pixel shm `FrameHandle` for the SAME
|
|
35022
|
+
* decoded frame. Both runner and executor are hub-local processes
|
|
35023
|
+
* sharing `/dev/shm`, so the executor maps the named segment and
|
|
35024
|
+
* reads the pixels back zero-copy — eliminating the ~1.2MB
|
|
35025
|
+
* re-serialisation over UDS/MsgPack the `frame` path pays per call.
|
|
35026
|
+
* High-risk: the FrameRing is a latest-wins seqlock with no
|
|
35027
|
+
* refcount, so a recycled slot yields a null read; the executor
|
|
35028
|
+
* then degrades to an empty result and the runner ships pixels via
|
|
35029
|
+
* `frame` as the fallback (queue-depth gated on the runner side).
|
|
35030
|
+
* - `imageBase64`: one-shot test path (benchmark ImageTab).
|
|
35031
|
+
* - `referenceImage`: named file from the reference-image store.
|
|
35032
|
+
*/
|
|
35033
|
+
runPipeline: method(zod.z.object({
|
|
35034
|
+
engine: PipelineEngineChoiceSchema.optional(),
|
|
35035
|
+
steps: zod.z.array(PipelineStepInputSchema).min(1),
|
|
35036
|
+
frame: FrameInputSchema.optional(),
|
|
35037
|
+
/**
|
|
35038
|
+
* Process-local lazy frame. Valid only when caller and provider resolve
|
|
35039
|
+
* in the same execution-group process; split/cross-node callers use
|
|
35040
|
+
* `frame`/`image` inline compatibility instead.
|
|
35041
|
+
*/
|
|
35042
|
+
frameRef: FrameRefSchema.optional(),
|
|
35043
|
+
/**
|
|
35044
|
+
* CB5 shm passthrough — a `FrameHandle` naming the same ring slot
|
|
35045
|
+
* the decoded pixels live in. One more member of the one-of
|
|
35046
|
+
* frame/frameHandle/image/imageBase64/referenceImage group.
|
|
35047
|
+
*/
|
|
35048
|
+
frameHandle: FrameHandleSchema.optional(),
|
|
35049
|
+
imageBase64: zod.z.string().optional(),
|
|
35050
|
+
/**
|
|
35051
|
+
* Binary JPEG bytes — preferred over `imageBase64` on internal
|
|
35052
|
+
* hops (hub → forked worker via Moleculer MsgPack) because it
|
|
35053
|
+
* skips the 33% base64 overhead + the per-call base64 decode on
|
|
35054
|
+
* the detection-pipeline worker. Callers can pass either; exactly
|
|
35055
|
+
* one of `frame`/`image`/`imageBase64`/`referenceImage` is required.
|
|
35056
|
+
*/
|
|
35057
|
+
image: zod.z.instanceof(Uint8Array).optional(),
|
|
35058
|
+
referenceImage: zod.z.string().optional(),
|
|
35059
|
+
deviceId: zod.z.number().optional(),
|
|
35060
|
+
sessionId: zod.z.string().optional(),
|
|
35061
|
+
/**
|
|
35062
|
+
* Execution plane. 'full' (default) runs the whole tree — benchmark,
|
|
35063
|
+
* reference-image, and detail-subtree calls. 'frame' is the live
|
|
35064
|
+
* per-frame dispatch: ONLY root-plane steps run; crop children
|
|
35065
|
+
* (inputClasses ≠ null) are skipped and served per-track via
|
|
35066
|
+
* pipelineRunner.runDetailSubtree (two-plane design).
|
|
35067
|
+
*/
|
|
35068
|
+
plane: zod.z.enum(["full", "frame"]).optional(),
|
|
35069
|
+
/**
|
|
35070
|
+
* Inference-device selector (Phase 2 multi-device). Format
|
|
35071
|
+
* `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
|
|
35072
|
+
* Omitted ⇒ the runner's default device (current single-engine
|
|
35073
|
+
* behaviour). Selects WHICH device pool of the node runs the call.
|
|
35074
|
+
*/
|
|
35075
|
+
deviceKey: zod.z.string().optional(),
|
|
35076
|
+
/**
|
|
35077
|
+
* Two-plane NATIVE child-crop reference. Set by `runDetailSubtree` ONLY
|
|
35078
|
+
* when the parent crop was resolved from the frame's retained NATIVE
|
|
35079
|
+
* surface (a frameHandle HIT). Lets the executor re-cut a LEAF crop
|
|
35080
|
+
* child's ROI (plate-ocr, face-embedding, leaf classifiers) at native
|
|
35081
|
+
* resolution from that surface — the SAME quality path faces already
|
|
35082
|
+
* had — instead of the downscaled parent tile. `handle` keys the native
|
|
35083
|
+
* surface (node-pinned to its owner); `cropFrameSpace` is the parent
|
|
35084
|
+
* crop's padded/clamped rectangle in FRAME-space pixels, used to compose
|
|
35085
|
+
* the executor's crop-normalized child ROI back into frame-normalized
|
|
35086
|
+
* coordinates. Auxiliary to the image source (`image`/`frame`/…), NOT one
|
|
35087
|
+
* of the mutually-exclusive image inputs. Absent ⇒ tile-crop children
|
|
35088
|
+
* (today's behaviour on the fallback path).
|
|
35089
|
+
*/
|
|
35090
|
+
nativeCropRef: NativeCropRefSchema.optional()
|
|
35091
|
+
}), PipelineRunResultBridge, { kind: "mutation" }),
|
|
35092
|
+
/**
|
|
35093
|
+
* Batched run — N raw frames packed into one cap call. The provider
|
|
35094
|
+
* routes the batch through `SharedInferencePool.inferBatch`
|
|
35095
|
+
* (`MSG_INFER_BATCH = 0x03`) so the IPC framing and JSON response
|
|
35096
|
+
* envelope cost is amortised N:1 vs N concurrent `runPipeline`
|
|
35097
|
+
* calls. Single root step + uniform model assumed; trees with crop
|
|
35098
|
+
* children fall back to sequential execution.
|
|
35099
|
+
*
|
|
35100
|
+
* Used by `scripts/bench-batch-style.mts` for batch benchmarking —
|
|
35101
|
+
* N frames in one call to amortise per-call IPC overhead.
|
|
35102
|
+
*/
|
|
35103
|
+
runPipelineBatch: method(zod.z.object({
|
|
35104
|
+
engine: PipelineEngineChoiceSchema.optional(),
|
|
35105
|
+
steps: zod.z.array(PipelineStepInputSchema).min(1),
|
|
35106
|
+
frames: zod.z.array(FrameInputSchema).min(1).max(255),
|
|
35107
|
+
deviceId: zod.z.number().optional(),
|
|
35108
|
+
sessionId: zod.z.string().optional(),
|
|
35109
|
+
/**
|
|
35110
|
+
* Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
|
|
35111
|
+
* the batch to the Python pool's bench preprocess cache
|
|
35112
|
+
* (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
|
|
35113
|
+
* preprocessed ONCE and every later inference is a pure-inference cache
|
|
35114
|
+
* hit — the sustained-throughput run measures inference, not
|
|
35115
|
+
* decode+preprocess+infer. Omitted/0 for live frames (all different →
|
|
35116
|
+
* full preprocess every call, correct). Fresh per sustained run;
|
|
35117
|
+
* released via `uncacheFrame`.
|
|
35118
|
+
*/
|
|
35119
|
+
frameId: zod.z.number().int().nonnegative().optional(),
|
|
35120
|
+
/** Inference-device selector (Phase 2 multi-device); see runPipeline. */
|
|
35121
|
+
deviceKey: zod.z.string().optional()
|
|
35122
|
+
}), zod.z.object({ results: zod.z.array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }),
|
|
35123
|
+
/**
|
|
35124
|
+
* Cache a raw frame inside the Python inference pool's memory.
|
|
35125
|
+
* Returns a numeric `frameId` that `inferCached` references —
|
|
35126
|
+
* subsequent calls send only 5 bytes through the pipe instead of
|
|
35127
|
+
* 1.2MB raw data, eliminating the pipe transfer bottleneck.
|
|
35128
|
+
*/
|
|
35129
|
+
cacheFrameInPool: method(zod.z.object({
|
|
35130
|
+
data: zod.z.instanceof(Uint8Array),
|
|
35131
|
+
width: zod.z.number().int().positive(),
|
|
35132
|
+
height: zod.z.number().int().positive(),
|
|
35133
|
+
format: zod.z.enum([
|
|
35134
|
+
"rgb",
|
|
35135
|
+
"bgr",
|
|
35136
|
+
"gray"
|
|
35137
|
+
])
|
|
35138
|
+
}), zod.z.object({
|
|
35139
|
+
frameId: zod.z.number(),
|
|
35140
|
+
width: zod.z.number(),
|
|
35141
|
+
height: zod.z.number()
|
|
35142
|
+
}), { kind: "mutation" }),
|
|
35143
|
+
/**
|
|
35144
|
+
* Run inference on a previously cached frame. Sends only 5 bytes
|
|
35145
|
+
* (model_idx + frameId) through the IPC pipe — eliminates the
|
|
35146
|
+
* ~35ms per-call overhead of transferring 1.2MB raw data.
|
|
35147
|
+
*/
|
|
35148
|
+
inferCached: method(zod.z.object({
|
|
35149
|
+
stepId: zod.z.string(),
|
|
35150
|
+
frameId: zod.z.number().int()
|
|
35151
|
+
}), zod.z.record(zod.z.string(), zod.z.unknown()), { kind: "mutation" }),
|
|
35152
|
+
/**
|
|
35153
|
+
* Release a cached frame from the Python pool's memory.
|
|
35154
|
+
*/
|
|
35155
|
+
uncacheFrame: method(zod.z.object({ frameId: zod.z.number().int() }), zod.z.void(), { kind: "mutation" }),
|
|
35156
|
+
/** Returns the effective pool tuning (resolved from user overrides + backend defaults). */
|
|
35157
|
+
getEffectiveTuning: method(zod.z.void(), zod.z.object({
|
|
35158
|
+
batchMode: zod.z.string(),
|
|
35159
|
+
windowMs: zod.z.number(),
|
|
35160
|
+
maxBatchSize: zod.z.number(),
|
|
35161
|
+
concurrency: zod.z.number()
|
|
35162
|
+
})),
|
|
35163
|
+
/**
|
|
35164
|
+
* List every EngineFactory currently loaded in this executor's RAM,
|
|
35165
|
+
* with the models resident and a coarse "in use" marker derived from
|
|
35166
|
+
* ongoing inference activity. Used by the Pipeline page Engines tab.
|
|
35167
|
+
*/
|
|
35168
|
+
listLoadedEngines: method(zod.z.void(), zod.z.array(zod.z.object({
|
|
35169
|
+
engineKey: zod.z.string(),
|
|
35170
|
+
engine: PipelineEngineChoiceSchema,
|
|
35171
|
+
modelsLoaded: zod.z.array(zod.z.string()).readonly(),
|
|
35172
|
+
inUseByCameras: zod.z.array(zod.z.number()).readonly(),
|
|
35173
|
+
/**
|
|
35174
|
+
* Origin of this resident factory.
|
|
35175
|
+
* - `runtime` — main camera-serving engine (no idle TTL).
|
|
35176
|
+
* - `warm-override` — benchmark/test override held in the warm
|
|
35177
|
+
* cache; auto-disposed after the idle TTL.
|
|
35178
|
+
* - `device-pool` — a concurrent per-device pool (Phase 2
|
|
35179
|
+
* multi-device, keyed by `deviceKey`) resolved
|
|
35180
|
+
* via `resolveDeviceFactory`. Runs alongside the
|
|
35181
|
+
* `runtime` engine on a DIFFERENT accelerator
|
|
35182
|
+
* (NPU / iGPU / Coral) — this is how the
|
|
35183
|
+
* Engines tab shows all pools running at once.
|
|
35184
|
+
*/
|
|
35185
|
+
kind: zod.z.enum([
|
|
35186
|
+
"runtime",
|
|
35187
|
+
"warm-override",
|
|
35188
|
+
"device-pool"
|
|
35189
|
+
]),
|
|
35190
|
+
/** Native pid of the underlying Python pool (null when no pool). */
|
|
35191
|
+
poolPid: zod.z.number().nullable(),
|
|
35192
|
+
/** ms since this factory was last used (null when not warm-tracked). */
|
|
35193
|
+
idleMs: zod.z.number().nullable(),
|
|
35194
|
+
/** Idle TTL after which `warm-override` factories self-evict (null when not applicable). */
|
|
35195
|
+
idleTtlMs: zod.z.number().nullable()
|
|
35196
|
+
})).readonly()),
|
|
35197
|
+
/** Warm up an engine without running a frame. No-op if already loaded. */
|
|
35198
|
+
spinEngine: method(zod.z.object({ engine: PipelineEngineChoiceSchema }), zod.z.object({ success: zod.z.literal(true) }), {
|
|
35199
|
+
kind: "mutation",
|
|
35200
|
+
auth: "admin"
|
|
35201
|
+
}),
|
|
35202
|
+
/**
|
|
35203
|
+
* Unload an engine from RAM. `force:true` unloads even when cameras
|
|
35204
|
+
* are actively using it (they re-spin on next frame). Default is
|
|
35205
|
+
* gated — returns `{success:false, reason}` when in use.
|
|
35206
|
+
*/
|
|
35207
|
+
killEngine: method(zod.z.object({
|
|
35208
|
+
engine: PipelineEngineChoiceSchema,
|
|
35209
|
+
force: zod.z.boolean().optional()
|
|
35210
|
+
}), zod.z.object({
|
|
35211
|
+
success: zod.z.boolean(),
|
|
35212
|
+
reason: zod.z.string().optional()
|
|
35213
|
+
}), {
|
|
35214
|
+
kind: "mutation",
|
|
35215
|
+
auth: "admin"
|
|
35216
|
+
}),
|
|
35217
|
+
listReferenceImages: method(zod.z.void(), zod.z.array(ReferenceImageEntrySchema).readonly()),
|
|
35218
|
+
getReferenceImage: method(zod.z.object({ filename: zod.z.string() }), ReferenceImageBodySchema.nullable()),
|
|
35219
|
+
getReferenceAudioFiles: method(zod.z.void(), zod.z.array(ReferenceAudioEntrySchema).readonly()),
|
|
35220
|
+
getReferenceAudio: method(zod.z.object({ filename: zod.z.string() }), ReferenceAudioBodySchema.nullable()),
|
|
35221
|
+
getAudioCapabilities: method(zod.z.void(), AudioCapabilitiesSchema),
|
|
35222
|
+
runAudioTest: method(zod.z.object({
|
|
35223
|
+
addonId: zod.z.string(),
|
|
35224
|
+
modelId: zod.z.string(),
|
|
35225
|
+
filename: zod.z.string().optional(),
|
|
35226
|
+
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
35227
|
+
}), AudioTestResultSchema, { kind: "mutation" }),
|
|
35228
|
+
getDetectionConfigSchema: method(zod.z.void(), ConfigUISchemaNullableBridge)
|
|
35229
|
+
}
|
|
35230
|
+
};
|
|
35231
|
+
var ZoneRuleModeEnum = zod.z.enum(["include", "exclude"]);
|
|
35232
|
+
var ZoneRuleSchema = zod.z.object({
|
|
35233
|
+
/** Stable rule id — survives edits, used by the UI for diffing. */
|
|
35234
|
+
id: zod.z.string(),
|
|
35235
|
+
/** Optional human-readable label rendered in the rule editor. */
|
|
35236
|
+
name: zod.z.string().optional(),
|
|
35237
|
+
/** Zones this rule targets. The rule's `mode` applies to ALL
|
|
35238
|
+
* listed zones (OR-set: a detection in any one of them counts).
|
|
35239
|
+
* At least one zone id required — a rule with no targets is a
|
|
35240
|
+
* configuration mistake and the form validator rejects it. */
|
|
35241
|
+
zoneIds: zod.z.array(zod.z.string()).min(1).readonly(),
|
|
35242
|
+
mode: ZoneRuleModeEnum,
|
|
35243
|
+
/**
|
|
35244
|
+
* Class names this rule applies to. Empty / undefined ⇒ rule
|
|
35245
|
+
* applies to every class. Class strings match the `macroClass`
|
|
35246
|
+
* field on detections (e.g. `person`, `car`, `dog`).
|
|
35247
|
+
*/
|
|
35248
|
+
classFilter: zod.z.array(zod.z.string()).readonly().optional(),
|
|
35249
|
+
/**
|
|
35250
|
+
* Minimum bbox/mask overlap (0–1) with any of the rule's zones
|
|
35251
|
+
* required to consider an entity "in the zone". Defaults to the
|
|
35252
|
+
* consumer's stage default when omitted. Kept for back-compat with
|
|
35253
|
+
* existing per-rule overrides; new operators pick the value via
|
|
35254
|
+
* `bboxInclusionPct` (operator-friendly 0–100). Whichever field is
|
|
35255
|
+
* set, the lower-level engine reads it as a 0–1 fraction.
|
|
35256
|
+
*/
|
|
35257
|
+
overlapThreshold: zod.z.number().min(0).max(1).optional(),
|
|
35258
|
+
/**
|
|
35259
|
+
* Operator-friendly version of `overlapThreshold` — the percentage
|
|
35260
|
+
* of the detection's bbox that must lie inside the zone for the
|
|
35261
|
+
* rule to match. Documented default is 85%; the engine substitutes
|
|
35262
|
+
* that when the field is omitted (kept optional so existing rules
|
|
35263
|
+
* stored without it stay valid).
|
|
35264
|
+
*
|
|
35265
|
+
* When BOTH `overlapThreshold` and `bboxInclusionPct` are set on a
|
|
35266
|
+
* rule, the engine prefers `bboxInclusionPct` because it's the
|
|
35267
|
+
* field exposed in the UI. Internally both feed the same gate.
|
|
35268
|
+
*/
|
|
35269
|
+
bboxInclusionPct: zod.z.number().min(0).max(100).optional(),
|
|
35270
|
+
/**
|
|
35271
|
+
* When `true` and a detection has a segmentation mask, use the
|
|
35272
|
+
* mask for overlap instead of the bbox. Detection-stage only;
|
|
35273
|
+
* motion rules ignore this field.
|
|
35274
|
+
*/
|
|
35275
|
+
preferMask: zod.z.boolean().optional(),
|
|
35276
|
+
/**
|
|
35277
|
+
* Soft-toggle: `false` disables the rule without deleting it.
|
|
35278
|
+
* Defaults to `true` so operators creating a rule via the UI
|
|
35279
|
+
* see it active immediately.
|
|
35280
|
+
*/
|
|
35281
|
+
enabled: zod.z.boolean().default(true)
|
|
35282
|
+
});
|
|
35283
|
+
zod.z.array(ZoneRuleSchema).readonly();
|
|
35284
|
+
var ZoneKindEnum = zod.z.enum(["polygon", "tripwire"]);
|
|
35285
|
+
var PolygonPointSchema = zod.z.object({
|
|
35286
|
+
x: zod.z.number(),
|
|
35287
|
+
y: zod.z.number()
|
|
35288
|
+
});
|
|
35289
|
+
var ZoneSchema = zod.z.object({
|
|
35290
|
+
id: zod.z.string(),
|
|
35291
|
+
name: zod.z.string(),
|
|
35292
|
+
kind: ZoneKindEnum.default("polygon"),
|
|
35293
|
+
/** Polygon vertices, fraction of frame (0–1). */
|
|
35294
|
+
polygon: zod.z.array(PolygonPointSchema).readonly(),
|
|
35295
|
+
/** Visual color for UI rendering. */
|
|
35296
|
+
color: zod.z.string().default("#3b82f6")
|
|
35297
|
+
});
|
|
35298
|
+
var zonesCapability = {
|
|
35299
|
+
name: "zones",
|
|
35300
|
+
scope: "device",
|
|
35301
|
+
mode: "singleton",
|
|
35302
|
+
deviceTypes: [DeviceType.Camera],
|
|
35303
|
+
methods: {
|
|
35304
|
+
listZones: method(zod.z.object({ deviceId: zod.z.number() }), zod.z.array(ZoneSchema).readonly()),
|
|
35305
|
+
addZone: method(zod.z.object({
|
|
35306
|
+
deviceId: zod.z.number(),
|
|
35307
|
+
zone: ZoneSchema
|
|
35308
|
+
}), zod.z.void(), {
|
|
35309
|
+
kind: "mutation",
|
|
35310
|
+
auth: "admin"
|
|
35311
|
+
}),
|
|
35312
|
+
removeZone: method(zod.z.object({
|
|
35313
|
+
deviceId: zod.z.number(),
|
|
35314
|
+
zoneId: zod.z.string()
|
|
35315
|
+
}), zod.z.void(), {
|
|
35316
|
+
kind: "mutation",
|
|
35317
|
+
auth: "admin"
|
|
35318
|
+
}),
|
|
35319
|
+
updateZone: method(zod.z.object({
|
|
35320
|
+
deviceId: zod.z.number(),
|
|
35321
|
+
zone: ZoneSchema
|
|
35322
|
+
}), zod.z.void(), {
|
|
35323
|
+
kind: "mutation",
|
|
35324
|
+
auth: "admin"
|
|
35325
|
+
})
|
|
35326
|
+
},
|
|
35327
|
+
/**
|
|
35328
|
+
* Runtime-state slice — the live zone catalogue mirrored by the
|
|
35329
|
+
* orchestrator on every CRUD mutation. Consumers read via
|
|
35330
|
+
* `device.state.zones.value` / `.watch(...)` without round-tripping
|
|
35331
|
+
* the cap, and the codegen DeviceProxy auto-wires the reactive
|
|
35332
|
+
* handle. Slice shape is `{ zones: Zone[] }` so future extensions
|
|
35333
|
+
* (e.g. zone groupings) can sit alongside the polygon list.
|
|
35334
|
+
*/
|
|
35335
|
+
runtimeState: zod.z.object({ zones: zod.z.array(ZoneSchema).readonly() }),
|
|
35336
|
+
/**
|
|
35337
|
+
* Runtime-state durability: **restored** — written only on operator mutation, so a camera that never had one has nothing to re-derive from. This is the slice `zone-mirror-hydration.ts` exists to paper over.
|
|
35338
|
+
*
|
|
35339
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
35340
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
35341
|
+
*/
|
|
35342
|
+
durability: "restored"
|
|
35343
|
+
};
|
|
34624
35344
|
var TrackStateSchema = zod.z.enum([
|
|
34625
35345
|
"new",
|
|
34626
35346
|
"entered",
|
|
@@ -35441,6 +36161,25 @@ var require_dist_D5Jhh8Vk = __commonJS({
|
|
|
35441
36161
|
/** Present when the pass ended by throwing. */
|
|
35442
36162
|
error: zod.z.string().nullable()
|
|
35443
36163
|
});
|
|
36164
|
+
var ReplayFrameInputSchema = zod.z.object({
|
|
36165
|
+
timestamp: zod.z.number(),
|
|
36166
|
+
frame: PipelineRunResultBridge
|
|
36167
|
+
});
|
|
36168
|
+
var ReplayTrackSchema = zod.z.object({
|
|
36169
|
+
className: zod.z.string(),
|
|
36170
|
+
firstSeenMs: zod.z.number(),
|
|
36171
|
+
lastSeenMs: zod.z.number(),
|
|
36172
|
+
/** Bbox of the track's FIRST matched detection, pixel-space in the clip's
|
|
36173
|
+
* frame — a representative box for the diff's `(className, window, IoU)`
|
|
36174
|
+
* pairing (`replay-diff.ts`). A replay does not need the full per-frame
|
|
36175
|
+
* trajectory production's `Track.positions` keeps. */
|
|
36176
|
+
bbox: BoundingBoxSchema,
|
|
36177
|
+
/** How many of the input frames this track matched a real detection on
|
|
36178
|
+
* (never a coasted/extrapolated frame) — the replay's own signal for "how
|
|
36179
|
+
* solid is this track", cheaper than re-deriving it from a trajectory. */
|
|
36180
|
+
framesMatched: zod.z.number().int()
|
|
36181
|
+
});
|
|
36182
|
+
var RunReplayFrameProcessorResultSchema = zod.z.object({ tracks: zod.z.array(ReplayTrackSchema).readonly() });
|
|
35444
36183
|
var pipelineAnalyticsCapability = {
|
|
35445
36184
|
name: "pipeline-analytics",
|
|
35446
36185
|
scope: "device",
|
|
@@ -35931,6 +36670,32 @@ var require_dist_D5Jhh8Vk = __commonJS({
|
|
|
35931
36670
|
kind: "mutation",
|
|
35932
36671
|
auth: "admin"
|
|
35933
36672
|
}),
|
|
36673
|
+
/**
|
|
36674
|
+
* The FrameProcessor pass of a replay run — see the `Replay` section
|
|
36675
|
+
* above this capability's definition for why this is not the
|
|
36676
|
+
* `processFrame` method this file's header says pipeline-analytics does
|
|
36677
|
+
* not have.
|
|
36678
|
+
*
|
|
36679
|
+
* Constructs a FRESH `FrameProcessor` for `(deviceId, source)`, feeds it
|
|
36680
|
+
* `frames` IN THE ORDER GIVEN (the caller is responsible for time
|
|
36681
|
+
* ordering — this method does not sort), and returns the tracks it
|
|
36682
|
+
* produced. Zero persistence: no `TrackStore`, no event bus, no media
|
|
36683
|
+
* capture. `zones` / `detectionRules` are the run's OWN zone set —
|
|
36684
|
+
* typically the camera's real zones plus an ephemeral overlay
|
|
36685
|
+
* (`addon-benchmark`'s `replay-plan.ts`), never read from or written to
|
|
36686
|
+
* the `zones` capability by this method itself.
|
|
36687
|
+
*/
|
|
36688
|
+
runReplayFrameProcessor: method(zod.z.object({
|
|
36689
|
+
deviceId: zod.z.number(),
|
|
36690
|
+
source: DetectionSourceSchema,
|
|
36691
|
+
zones: zod.z.array(ZoneSchema).readonly().optional(),
|
|
36692
|
+
detectionRules: zod.z.array(ZoneRuleSchema).readonly().optional(),
|
|
36693
|
+
zoneMembershipMinOverlap: zod.z.number().min(0).max(1).optional(),
|
|
36694
|
+
frames: zod.z.array(ReplayFrameInputSchema).min(1)
|
|
36695
|
+
}), RunReplayFrameProcessorResultSchema, {
|
|
36696
|
+
kind: "mutation",
|
|
36697
|
+
auth: "admin"
|
|
36698
|
+
}),
|
|
35934
36699
|
/** Every annotation on a track, oldest first. */
|
|
35935
36700
|
listRetrainAnnotations: method(zod.z.object({ trackId: zod.z.string() }), zod.z.array(RetrainAnnotationSchema).readonly(), {
|
|
35936
36701
|
kind: "query",
|
|
@@ -36097,559 +36862,6 @@ var require_dist_D5Jhh8Vk = __commonJS({
|
|
|
36097
36862
|
}) }
|
|
36098
36863
|
}
|
|
36099
36864
|
};
|
|
36100
|
-
var NativeCropRefSchema = zod.z.object({
|
|
36101
|
-
/** Handle keying the retained native surface (node-pinned to its owner). */
|
|
36102
|
-
handle: FrameHandleSchema,
|
|
36103
|
-
/** The parent crop's padded/clamped rectangle in FRAME-space pixels. */
|
|
36104
|
-
cropFrameSpace: zod.z.object({
|
|
36105
|
-
x: zod.z.number(),
|
|
36106
|
-
y: zod.z.number(),
|
|
36107
|
-
w: zod.z.number(),
|
|
36108
|
-
h: zod.z.number()
|
|
36109
|
-
})
|
|
36110
|
-
});
|
|
36111
|
-
zod.z.object({
|
|
36112
|
-
crop: zod.z.object({
|
|
36113
|
-
left: zod.z.number(),
|
|
36114
|
-
top: zod.z.number(),
|
|
36115
|
-
width: zod.z.number().positive(),
|
|
36116
|
-
height: zod.z.number().positive()
|
|
36117
|
-
}).optional(),
|
|
36118
|
-
content: zod.z.object({
|
|
36119
|
-
width: zod.z.number().int().positive(),
|
|
36120
|
-
height: zod.z.number().int().positive()
|
|
36121
|
-
}),
|
|
36122
|
-
fit: zod.z.enum(["stretch", "contain"]),
|
|
36123
|
-
format: zod.z.enum([
|
|
36124
|
-
"rgb",
|
|
36125
|
-
"gray",
|
|
36126
|
-
"jpeg"
|
|
36127
|
-
])
|
|
36128
|
-
});
|
|
36129
|
-
var FrameRefSchema = zod.z.object({
|
|
36130
|
-
registryId: zod.z.string().min(1),
|
|
36131
|
-
id: zod.z.string().min(1),
|
|
36132
|
-
width: zod.z.number().int().positive(),
|
|
36133
|
-
height: zod.z.number().int().positive(),
|
|
36134
|
-
format: zod.z.enum(["rgb", "gray"]),
|
|
36135
|
-
timestamp: zod.z.number(),
|
|
36136
|
-
capturedAt: zod.z.number().optional()
|
|
36137
|
-
});
|
|
36138
|
-
var ModelFormatSchema$1 = zod.z.enum([
|
|
36139
|
-
"onnx",
|
|
36140
|
-
"coreml",
|
|
36141
|
-
"openvino",
|
|
36142
|
-
"tflite",
|
|
36143
|
-
"pt",
|
|
36144
|
-
"gguf"
|
|
36145
|
-
]);
|
|
36146
|
-
var PipelineSlotSchema = zod.z.enum([
|
|
36147
|
-
"detector",
|
|
36148
|
-
"cropper",
|
|
36149
|
-
"classifier",
|
|
36150
|
-
"refiner",
|
|
36151
|
-
"audio-classifier"
|
|
36152
|
-
]);
|
|
36153
|
-
var PipelineEngineChoiceSchema = zod.z.object({
|
|
36154
|
-
runtime: zod.z.enum(["node", "python"]),
|
|
36155
|
-
backend: zod.z.string(),
|
|
36156
|
-
format: ModelFormatSchema$1,
|
|
36157
|
-
device: zod.z.string().optional()
|
|
36158
|
-
});
|
|
36159
|
-
var EngineDeviceInfoSchema = zod.z.object({
|
|
36160
|
-
id: zod.z.string(),
|
|
36161
|
-
label: zod.z.string(),
|
|
36162
|
-
description: zod.z.string().optional()
|
|
36163
|
-
});
|
|
36164
|
-
var AvailableEngineSchema = zod.z.object({
|
|
36165
|
-
engine: PipelineEngineChoiceSchema,
|
|
36166
|
-
devices: zod.z.array(EngineDeviceInfoSchema).readonly(),
|
|
36167
|
-
defaultDevice: zod.z.string()
|
|
36168
|
-
});
|
|
36169
|
-
var PipelineDefaultStepSchema = zod.z.lazy(() => zod.z.object({
|
|
36170
|
-
addonId: zod.z.string(),
|
|
36171
|
-
addonName: zod.z.string(),
|
|
36172
|
-
slot: PipelineSlotSchema,
|
|
36173
|
-
inputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
36174
|
-
outputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
36175
|
-
enabled: zod.z.boolean(),
|
|
36176
|
-
modelId: zod.z.string(),
|
|
36177
|
-
children: zod.z.array(PipelineDefaultStepSchema).readonly(),
|
|
36178
|
-
group: zod.z.string().optional(),
|
|
36179
|
-
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
36180
|
-
}));
|
|
36181
|
-
var PipelineTemplateStepSchema = zod.z.lazy(() => zod.z.object({
|
|
36182
|
-
addonId: zod.z.string(),
|
|
36183
|
-
enabled: zod.z.boolean(),
|
|
36184
|
-
modelId: zod.z.string(),
|
|
36185
|
-
children: zod.z.array(PipelineTemplateStepSchema).readonly(),
|
|
36186
|
-
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
36187
|
-
}));
|
|
36188
|
-
var PipelineTemplateSchema$1 = zod.z.object({
|
|
36189
|
-
id: zod.z.string(),
|
|
36190
|
-
name: zod.z.string(),
|
|
36191
|
-
createdAt: zod.z.string(),
|
|
36192
|
-
updatedAt: zod.z.string(),
|
|
36193
|
-
engine: PipelineEngineChoiceSchema,
|
|
36194
|
-
steps: zod.z.array(PipelineTemplateStepSchema).readonly()
|
|
36195
|
-
});
|
|
36196
|
-
var PipelineModelOptionSchema = zod.z.object({
|
|
36197
|
-
id: zod.z.string(),
|
|
36198
|
-
name: zod.z.string(),
|
|
36199
|
-
formats: zod.z.record(zod.z.string(), zod.z.object({
|
|
36200
|
-
downloaded: zod.z.boolean(),
|
|
36201
|
-
sizeMB: zod.z.number()
|
|
36202
|
-
})),
|
|
36203
|
-
group: ModelVariantGroupSchema.optional(),
|
|
36204
|
-
legacy: zod.z.boolean().optional(),
|
|
36205
|
-
provider: ModelProviderIdSchema.optional()
|
|
36206
|
-
});
|
|
36207
|
-
var ConfigFieldBridge = zod.z.custom();
|
|
36208
|
-
var PipelineAddonSchemaSchema = zod.z.object({
|
|
36209
|
-
id: zod.z.string(),
|
|
36210
|
-
name: zod.z.string(),
|
|
36211
|
-
slot: PipelineSlotSchema,
|
|
36212
|
-
inputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
36213
|
-
outputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
36214
|
-
childSlots: zod.z.array(PipelineSlotSchema).readonly(),
|
|
36215
|
-
models: zod.z.array(PipelineModelOptionSchema).readonly(),
|
|
36216
|
-
defaultModelId: zod.z.string(),
|
|
36217
|
-
defaultModelIdByFormat: zod.z.record(zod.z.string(), zod.z.string()).optional(),
|
|
36218
|
-
enabledByDefault: zod.z.boolean().optional(),
|
|
36219
|
-
backfillIntoExistingOverrides: zod.z.boolean().optional(),
|
|
36220
|
-
defaultConfidence: zod.z.number(),
|
|
36221
|
-
group: zod.z.string().optional(),
|
|
36222
|
-
configSchema: zod.z.array(ConfigFieldBridge).readonly().optional()
|
|
36223
|
-
});
|
|
36224
|
-
var PipelineSlotSchemaSchema = zod.z.object({
|
|
36225
|
-
id: PipelineSlotSchema,
|
|
36226
|
-
label: zod.z.string(),
|
|
36227
|
-
priority: zod.z.number(),
|
|
36228
|
-
parentSlot: PipelineSlotSchema.nullable(),
|
|
36229
|
-
addons: zod.z.array(PipelineAddonSchemaSchema).readonly()
|
|
36230
|
-
});
|
|
36231
|
-
var PipelineSchemaSchema = zod.z.object({
|
|
36232
|
-
availableEngines: zod.z.array(AvailableEngineSchema).readonly(),
|
|
36233
|
-
selectedEngine: PipelineEngineChoiceSchema,
|
|
36234
|
-
slots: zod.z.array(PipelineSlotSchemaSchema).readonly()
|
|
36235
|
-
});
|
|
36236
|
-
var EngineProvisioningSchema = zod.z.object({
|
|
36237
|
-
runtimeId: zod.z.enum([
|
|
36238
|
-
"onnx",
|
|
36239
|
-
"openvino",
|
|
36240
|
-
"coreml",
|
|
36241
|
-
"edgetpu"
|
|
36242
|
-
]).nullable(),
|
|
36243
|
-
device: zod.z.string().nullable(),
|
|
36244
|
-
state: zod.z.enum([
|
|
36245
|
-
"idle",
|
|
36246
|
-
"installing",
|
|
36247
|
-
"verifying",
|
|
36248
|
-
"ready",
|
|
36249
|
-
"failed"
|
|
36250
|
-
]),
|
|
36251
|
-
progress: zod.z.number().optional(),
|
|
36252
|
-
error: zod.z.string().optional(),
|
|
36253
|
-
nextRetryAt: zod.z.number().optional(),
|
|
36254
|
-
/**
|
|
36255
|
-
* Gate A (config-correctness gate at engine change): human-readable
|
|
36256
|
-
* config issues surfaced EAGERLY when the node's engine changes — model
|
|
36257
|
-
* substitutions ("chose X, running Y") and zero-build steps ("no model
|
|
36258
|
-
* has a <format> build"). Additive/optional: informational only, never
|
|
36259
|
-
* enforced here — `assertEngineReady` (readiness) still gates inference.
|
|
36260
|
-
* Absent/empty when the node-default tree resolves cleanly.
|
|
36261
|
-
*/
|
|
36262
|
-
configIssues: zod.z.array(zod.z.string()).optional()
|
|
36263
|
-
});
|
|
36264
|
-
var PipelineStepInputSchema = zod.z.lazy(() => zod.z.object({
|
|
36265
|
-
addonId: zod.z.string(),
|
|
36266
|
-
modelId: zod.z.string().optional(),
|
|
36267
|
-
enabled: zod.z.boolean().default(true),
|
|
36268
|
-
children: zod.z.array(PipelineStepInputSchema).optional(),
|
|
36269
|
-
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
36270
|
-
jumpDeviceKey: zod.z.string().optional()
|
|
36271
|
-
}));
|
|
36272
|
-
var ModelSubstitutionSchema = zod.z.object({
|
|
36273
|
-
addonId: zod.z.string(),
|
|
36274
|
-
chosen: zod.z.string(),
|
|
36275
|
-
running: zod.z.string(),
|
|
36276
|
-
format: zod.z.string()
|
|
36277
|
-
});
|
|
36278
|
-
var PipelineValidationIssueSchema = zod.z.object({
|
|
36279
|
-
addonId: zod.z.string(),
|
|
36280
|
-
kind: zod.z.enum(["unknown-addon", "no-format-build"]),
|
|
36281
|
-
detail: zod.z.string()
|
|
36282
|
-
});
|
|
36283
|
-
var PipelineValidationResultSchema = zod.z.object({
|
|
36284
|
-
ok: zod.z.boolean(),
|
|
36285
|
-
issues: zod.z.array(PipelineValidationIssueSchema).readonly(),
|
|
36286
|
-
substitutions: zod.z.array(ModelSubstitutionSchema).readonly(),
|
|
36287
|
-
/** The node's `currentEngine.format` this validation ran against. */
|
|
36288
|
-
format: zod.z.string()
|
|
36289
|
-
});
|
|
36290
|
-
var ReferenceImageEntrySchema = zod.z.object({
|
|
36291
|
-
filename: zod.z.string(),
|
|
36292
|
-
stepIds: zod.z.array(zod.z.string()).readonly().optional()
|
|
36293
|
-
});
|
|
36294
|
-
var ReferenceImageBodySchema = zod.z.object({
|
|
36295
|
-
base64: zod.z.string(),
|
|
36296
|
-
filename: zod.z.string()
|
|
36297
|
-
});
|
|
36298
|
-
var ReferenceAudioEntrySchema = zod.z.object({
|
|
36299
|
-
filename: zod.z.string(),
|
|
36300
|
-
sizeKb: zod.z.number()
|
|
36301
|
-
});
|
|
36302
|
-
var ReferenceAudioBodySchema = zod.z.object({ base64: zod.z.string() });
|
|
36303
|
-
var AudioBackendSchema = zod.z.object({
|
|
36304
|
-
id: zod.z.string(),
|
|
36305
|
-
name: zod.z.string(),
|
|
36306
|
-
description: zod.z.string(),
|
|
36307
|
-
available: zod.z.boolean(),
|
|
36308
|
-
/**
|
|
36309
|
-
* Raw classifier labels this backend can emit (e.g. YAMNet's
|
|
36310
|
-
* 521-class set or Apple SoundAnalysis's 303-class set). Used by
|
|
36311
|
-
* the benchmark UI to populate the `enabledMicroClasses` filter
|
|
36312
|
-
* specific to the selected backend without a separate fetch.
|
|
36313
|
-
*/
|
|
36314
|
-
rawLabels: zod.z.array(zod.z.string()).readonly().optional()
|
|
36315
|
-
});
|
|
36316
|
-
var AudioCapabilitiesSchema = zod.z.object({
|
|
36317
|
-
activeBackend: zod.z.string(),
|
|
36318
|
-
availableBackends: zod.z.array(AudioBackendSchema).readonly(),
|
|
36319
|
-
sampleRate: zod.z.number(),
|
|
36320
|
-
chunkDurationMs: zod.z.number()
|
|
36321
|
-
});
|
|
36322
|
-
var DownloadModelResultSchema = zod.z.object({
|
|
36323
|
-
filePath: zod.z.string(),
|
|
36324
|
-
sizeMB: zod.z.number(),
|
|
36325
|
-
durationMs: zod.z.number()
|
|
36326
|
-
});
|
|
36327
|
-
var AudioTestResultSchema = zod.z.object({
|
|
36328
|
-
success: zod.z.boolean(),
|
|
36329
|
-
error: zod.z.string().optional(),
|
|
36330
|
-
frame: zod.z.custom().optional()
|
|
36331
|
-
});
|
|
36332
|
-
var PipelineConfigBridge = zod.z.custom();
|
|
36333
|
-
var ConfigUISchemaBridge = zod.z.custom();
|
|
36334
|
-
var ConfigUISchemaNullableBridge = zod.z.custom();
|
|
36335
|
-
var InferenceCapabilitiesBridge = zod.z.custom();
|
|
36336
|
-
var ModelAvailabilityListBridge = zod.z.custom();
|
|
36337
|
-
var PipelineRunResultBridge = zod.z.custom();
|
|
36338
|
-
var pipelineExecutorCapability = {
|
|
36339
|
-
name: "pipeline-executor",
|
|
36340
|
-
scope: "system",
|
|
36341
|
-
mode: "singleton",
|
|
36342
|
-
methods: {
|
|
36343
|
-
getAvailableEngines: method(zod.z.void(), zod.z.array(PipelineEngineChoiceSchema)),
|
|
36344
|
-
getSelectedEngine: method(zod.z.void(), PipelineEngineChoiceSchema),
|
|
36345
|
-
getDefaultSteps: method(PipelineEngineChoiceSchema, zod.z.array(PipelineDefaultStepSchema)),
|
|
36346
|
-
/**
|
|
36347
|
-
* Per-node detection-engine provisioning snapshot. Returns the live
|
|
36348
|
-
* state of the lazy runtime-provisioning machine on `nodeId`
|
|
36349
|
-
* (idle / installing / verifying / ready / failed). The UI pairs this
|
|
36350
|
-
* one-shot query with the `pipeline.engine-provisioning` live event
|
|
36351
|
-
* (emitted on every transition) to drive a per-node "engine ready?"
|
|
36352
|
-
* indicator without polling. Phase 2.
|
|
36353
|
-
*/
|
|
36354
|
-
getEngineProvisioning: method(zod.z.object({ nodeId: zod.z.string() }), EngineProvisioningSchema),
|
|
36355
|
-
getVideoPipelineSteps: method(zod.z.void(), zod.z.record(zod.z.string(), zod.z.object({
|
|
36356
|
-
modelId: zod.z.string(),
|
|
36357
|
-
settings: zod.z.record(zod.z.string(), zod.z.unknown()).readonly()
|
|
36358
|
-
}))),
|
|
36359
|
-
setVideoPipelineSteps: method(zod.z.object({ steps: zod.z.record(zod.z.string(), zod.z.object({
|
|
36360
|
-
modelId: zod.z.string(),
|
|
36361
|
-
settings: zod.z.record(zod.z.string(), zod.z.unknown()).readonly()
|
|
36362
|
-
})) }), zod.z.object({ success: zod.z.literal(true) }), {
|
|
36363
|
-
kind: "mutation",
|
|
36364
|
-
auth: "admin"
|
|
36365
|
-
}),
|
|
36366
|
-
/**
|
|
36367
|
-
* Clear THIS node's executor-side PER-DEVICE settings stores (the
|
|
36368
|
-
* per-camera step overrides the object-detection root reads via
|
|
36369
|
-
* `applyDeviceOverridesToTree`). `nodeId` is the ROUTING key — the
|
|
36370
|
-
* generated cap-router strips it (default `nodeIdMode: 'routing'`) and
|
|
36371
|
-
* dispatches to that node, so the provider method runs ON the target
|
|
36372
|
-
* node and receives no `nodeId`.
|
|
36373
|
-
*
|
|
36374
|
-
* This is the slimmed executor leg of the orchestrator's
|
|
36375
|
-
* `resetNodePipelineDefaults` flow (which owns the real reset: node
|
|
36376
|
-
* addonDefaults pins + per-camera orchestrator overrides). The legacy
|
|
36377
|
-
* `resetToDefault` — which reset a persisted global step-tree seed
|
|
36378
|
-
* nothing in the live per-camera path read — was removed together with
|
|
36379
|
-
* that seed.
|
|
36380
|
-
*/
|
|
36381
|
-
clearDeviceOverrides: method(zod.z.object({ nodeId: zod.z.string() }), zod.z.object({
|
|
36382
|
-
success: zod.z.literal(true),
|
|
36383
|
-
clearedDevices: zod.z.number()
|
|
36384
|
-
}), {
|
|
36385
|
-
kind: "mutation",
|
|
36386
|
-
auth: "admin"
|
|
36387
|
-
}),
|
|
36388
|
-
getSchema: method(zod.z.void(), PipelineSchemaSchema),
|
|
36389
|
-
getGlobalSteps: method(zod.z.void(), zod.z.array(PipelineDefaultStepSchema).readonly().nullable()),
|
|
36390
|
-
getGlobalPipelineConfig: method(zod.z.void(), PipelineConfigBridge),
|
|
36391
|
-
getOrchestratorConfigSchema: method(zod.z.void(), ConfigUISchemaBridge),
|
|
36392
|
-
/**
|
|
36393
|
-
* Gate B (pre-init config-correctness gate). PURE COMPUTE against this
|
|
36394
|
-
* node's `currentEngine.format` — resolves `steps` the same way the
|
|
36395
|
-
* runtime dispatch path would, and reports what WOULD happen without
|
|
36396
|
-
* touching any node-global state. Called by the orchestrator at attach
|
|
36397
|
-
* time (`attachOn`), node-pinned to the TARGET node, so config problems
|
|
36398
|
-
* surface BEFORE `pipelineRunner.attachCamera` rather than at the first
|
|
36399
|
-
* per-frame resolve. `ok` is false iff `issues` is non-empty (both
|
|
36400
|
-
* `unknown-addon` and `no-format-build` are HARD issues); `substitutions`
|
|
36401
|
-
* is informational (a degraded-but-loadable model swap) and never
|
|
36402
|
-
* affects `ok`. Never throws.
|
|
36403
|
-
*/
|
|
36404
|
-
validatePipeline: method(zod.z.object({ steps: zod.z.array(PipelineStepInputSchema) }), PipelineValidationResultSchema),
|
|
36405
|
-
listTemplates: method(zod.z.void(), zod.z.array(PipelineTemplateSchema$1).readonly()),
|
|
36406
|
-
saveTemplate: method(zod.z.object({
|
|
36407
|
-
name: zod.z.string(),
|
|
36408
|
-
steps: zod.z.array(PipelineTemplateStepSchema).readonly(),
|
|
36409
|
-
engine: PipelineEngineChoiceSchema
|
|
36410
|
-
}), PipelineTemplateSchema$1, { kind: "mutation" }),
|
|
36411
|
-
updateTemplate: method(zod.z.object({
|
|
36412
|
-
id: zod.z.string(),
|
|
36413
|
-
name: zod.z.string().optional(),
|
|
36414
|
-
steps: zod.z.array(PipelineTemplateStepSchema).readonly().optional()
|
|
36415
|
-
}), PipelineTemplateSchema$1, { kind: "mutation" }),
|
|
36416
|
-
deleteTemplate: method(zod.z.object({ id: zod.z.string() }), zod.z.void(), { kind: "mutation" }),
|
|
36417
|
-
getCapabilities: method(zod.z.void(), InferenceCapabilitiesBridge),
|
|
36418
|
-
getAddonModels: method(zod.z.object({ addonId: zod.z.string() }), ModelAvailabilityListBridge),
|
|
36419
|
-
downloadModel: method(zod.z.object({
|
|
36420
|
-
addonId: zod.z.string(),
|
|
36421
|
-
modelId: zod.z.string(),
|
|
36422
|
-
format: ModelFormatSchema$1
|
|
36423
|
-
}), DownloadModelResultSchema, { kind: "mutation" }),
|
|
36424
|
-
deleteModel: method(zod.z.object({
|
|
36425
|
-
addonId: zod.z.string(),
|
|
36426
|
-
modelId: zod.z.string(),
|
|
36427
|
-
format: ModelFormatSchema$1
|
|
36428
|
-
}), zod.z.object({ success: zod.z.literal(true) }), { kind: "mutation" }),
|
|
36429
|
-
/**
|
|
36430
|
-
* Stateless single-frame execution. Callers (runner, benchmark) pass
|
|
36431
|
-
* the complete `engine` + `steps` tree; the executor holds no state
|
|
36432
|
-
* about cameras or saved pipelines.
|
|
36433
|
-
*
|
|
36434
|
-
* `engine` is optional during the migration window to preserve the
|
|
36435
|
-
* legacy call shape used by existing benchmark code; once all
|
|
36436
|
-
* callers pass it explicitly we make it required.
|
|
36437
|
-
*
|
|
36438
|
-
* Exactly one of `frame`, `frameRef`, `frameHandle`, `imageBase64`,
|
|
36439
|
-
* `referenceImage` must be provided:
|
|
36440
|
-
* - `frame`: runtime dispatch path (runner → decoded broker frame).
|
|
36441
|
-
* Carries the raw buffer, dimensions, and format; the executor
|
|
36442
|
-
* uses it directly without base64 round-tripping.
|
|
36443
|
-
* - `frameHandle` (CB5): a zero-pixel shm `FrameHandle` for the SAME
|
|
36444
|
-
* decoded frame. Both runner and executor are hub-local processes
|
|
36445
|
-
* sharing `/dev/shm`, so the executor maps the named segment and
|
|
36446
|
-
* reads the pixels back zero-copy — eliminating the ~1.2MB
|
|
36447
|
-
* re-serialisation over UDS/MsgPack the `frame` path pays per call.
|
|
36448
|
-
* High-risk: the FrameRing is a latest-wins seqlock with no
|
|
36449
|
-
* refcount, so a recycled slot yields a null read; the executor
|
|
36450
|
-
* then degrades to an empty result and the runner ships pixels via
|
|
36451
|
-
* `frame` as the fallback (queue-depth gated on the runner side).
|
|
36452
|
-
* - `imageBase64`: one-shot test path (benchmark ImageTab).
|
|
36453
|
-
* - `referenceImage`: named file from the reference-image store.
|
|
36454
|
-
*/
|
|
36455
|
-
runPipeline: method(zod.z.object({
|
|
36456
|
-
engine: PipelineEngineChoiceSchema.optional(),
|
|
36457
|
-
steps: zod.z.array(PipelineStepInputSchema).min(1),
|
|
36458
|
-
frame: FrameInputSchema.optional(),
|
|
36459
|
-
/**
|
|
36460
|
-
* Process-local lazy frame. Valid only when caller and provider resolve
|
|
36461
|
-
* in the same execution-group process; split/cross-node callers use
|
|
36462
|
-
* `frame`/`image` inline compatibility instead.
|
|
36463
|
-
*/
|
|
36464
|
-
frameRef: FrameRefSchema.optional(),
|
|
36465
|
-
/**
|
|
36466
|
-
* CB5 shm passthrough — a `FrameHandle` naming the same ring slot
|
|
36467
|
-
* the decoded pixels live in. One more member of the one-of
|
|
36468
|
-
* frame/frameHandle/image/imageBase64/referenceImage group.
|
|
36469
|
-
*/
|
|
36470
|
-
frameHandle: FrameHandleSchema.optional(),
|
|
36471
|
-
imageBase64: zod.z.string().optional(),
|
|
36472
|
-
/**
|
|
36473
|
-
* Binary JPEG bytes — preferred over `imageBase64` on internal
|
|
36474
|
-
* hops (hub → forked worker via Moleculer MsgPack) because it
|
|
36475
|
-
* skips the 33% base64 overhead + the per-call base64 decode on
|
|
36476
|
-
* the detection-pipeline worker. Callers can pass either; exactly
|
|
36477
|
-
* one of `frame`/`image`/`imageBase64`/`referenceImage` is required.
|
|
36478
|
-
*/
|
|
36479
|
-
image: zod.z.instanceof(Uint8Array).optional(),
|
|
36480
|
-
referenceImage: zod.z.string().optional(),
|
|
36481
|
-
deviceId: zod.z.number().optional(),
|
|
36482
|
-
sessionId: zod.z.string().optional(),
|
|
36483
|
-
/**
|
|
36484
|
-
* Execution plane. 'full' (default) runs the whole tree — benchmark,
|
|
36485
|
-
* reference-image, and detail-subtree calls. 'frame' is the live
|
|
36486
|
-
* per-frame dispatch: ONLY root-plane steps run; crop children
|
|
36487
|
-
* (inputClasses ≠ null) are skipped and served per-track via
|
|
36488
|
-
* pipelineRunner.runDetailSubtree (two-plane design).
|
|
36489
|
-
*/
|
|
36490
|
-
plane: zod.z.enum(["full", "frame"]).optional(),
|
|
36491
|
-
/**
|
|
36492
|
-
* Inference-device selector (Phase 2 multi-device). Format
|
|
36493
|
-
* `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
|
|
36494
|
-
* Omitted ⇒ the runner's default device (current single-engine
|
|
36495
|
-
* behaviour). Selects WHICH device pool of the node runs the call.
|
|
36496
|
-
*/
|
|
36497
|
-
deviceKey: zod.z.string().optional(),
|
|
36498
|
-
/**
|
|
36499
|
-
* Two-plane NATIVE child-crop reference. Set by `runDetailSubtree` ONLY
|
|
36500
|
-
* when the parent crop was resolved from the frame's retained NATIVE
|
|
36501
|
-
* surface (a frameHandle HIT). Lets the executor re-cut a LEAF crop
|
|
36502
|
-
* child's ROI (plate-ocr, face-embedding, leaf classifiers) at native
|
|
36503
|
-
* resolution from that surface — the SAME quality path faces already
|
|
36504
|
-
* had — instead of the downscaled parent tile. `handle` keys the native
|
|
36505
|
-
* surface (node-pinned to its owner); `cropFrameSpace` is the parent
|
|
36506
|
-
* crop's padded/clamped rectangle in FRAME-space pixels, used to compose
|
|
36507
|
-
* the executor's crop-normalized child ROI back into frame-normalized
|
|
36508
|
-
* coordinates. Auxiliary to the image source (`image`/`frame`/…), NOT one
|
|
36509
|
-
* of the mutually-exclusive image inputs. Absent ⇒ tile-crop children
|
|
36510
|
-
* (today's behaviour on the fallback path).
|
|
36511
|
-
*/
|
|
36512
|
-
nativeCropRef: NativeCropRefSchema.optional()
|
|
36513
|
-
}), PipelineRunResultBridge, { kind: "mutation" }),
|
|
36514
|
-
/**
|
|
36515
|
-
* Batched run — N raw frames packed into one cap call. The provider
|
|
36516
|
-
* routes the batch through `SharedInferencePool.inferBatch`
|
|
36517
|
-
* (`MSG_INFER_BATCH = 0x03`) so the IPC framing and JSON response
|
|
36518
|
-
* envelope cost is amortised N:1 vs N concurrent `runPipeline`
|
|
36519
|
-
* calls. Single root step + uniform model assumed; trees with crop
|
|
36520
|
-
* children fall back to sequential execution.
|
|
36521
|
-
*
|
|
36522
|
-
* Used by `scripts/bench-batch-style.mts` for batch benchmarking —
|
|
36523
|
-
* N frames in one call to amortise per-call IPC overhead.
|
|
36524
|
-
*/
|
|
36525
|
-
runPipelineBatch: method(zod.z.object({
|
|
36526
|
-
engine: PipelineEngineChoiceSchema.optional(),
|
|
36527
|
-
steps: zod.z.array(PipelineStepInputSchema).min(1),
|
|
36528
|
-
frames: zod.z.array(FrameInputSchema).min(1).max(255),
|
|
36529
|
-
deviceId: zod.z.number().optional(),
|
|
36530
|
-
sessionId: zod.z.string().optional(),
|
|
36531
|
-
/**
|
|
36532
|
-
* Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
|
|
36533
|
-
* the batch to the Python pool's bench preprocess cache
|
|
36534
|
-
* (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
|
|
36535
|
-
* preprocessed ONCE and every later inference is a pure-inference cache
|
|
36536
|
-
* hit — the sustained-throughput run measures inference, not
|
|
36537
|
-
* decode+preprocess+infer. Omitted/0 for live frames (all different →
|
|
36538
|
-
* full preprocess every call, correct). Fresh per sustained run;
|
|
36539
|
-
* released via `uncacheFrame`.
|
|
36540
|
-
*/
|
|
36541
|
-
frameId: zod.z.number().int().nonnegative().optional(),
|
|
36542
|
-
/** Inference-device selector (Phase 2 multi-device); see runPipeline. */
|
|
36543
|
-
deviceKey: zod.z.string().optional()
|
|
36544
|
-
}), zod.z.object({ results: zod.z.array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }),
|
|
36545
|
-
/**
|
|
36546
|
-
* Cache a raw frame inside the Python inference pool's memory.
|
|
36547
|
-
* Returns a numeric `frameId` that `inferCached` references —
|
|
36548
|
-
* subsequent calls send only 5 bytes through the pipe instead of
|
|
36549
|
-
* 1.2MB raw data, eliminating the pipe transfer bottleneck.
|
|
36550
|
-
*/
|
|
36551
|
-
cacheFrameInPool: method(zod.z.object({
|
|
36552
|
-
data: zod.z.instanceof(Uint8Array),
|
|
36553
|
-
width: zod.z.number().int().positive(),
|
|
36554
|
-
height: zod.z.number().int().positive(),
|
|
36555
|
-
format: zod.z.enum([
|
|
36556
|
-
"rgb",
|
|
36557
|
-
"bgr",
|
|
36558
|
-
"gray"
|
|
36559
|
-
])
|
|
36560
|
-
}), zod.z.object({
|
|
36561
|
-
frameId: zod.z.number(),
|
|
36562
|
-
width: zod.z.number(),
|
|
36563
|
-
height: zod.z.number()
|
|
36564
|
-
}), { kind: "mutation" }),
|
|
36565
|
-
/**
|
|
36566
|
-
* Run inference on a previously cached frame. Sends only 5 bytes
|
|
36567
|
-
* (model_idx + frameId) through the IPC pipe — eliminates the
|
|
36568
|
-
* ~35ms per-call overhead of transferring 1.2MB raw data.
|
|
36569
|
-
*/
|
|
36570
|
-
inferCached: method(zod.z.object({
|
|
36571
|
-
stepId: zod.z.string(),
|
|
36572
|
-
frameId: zod.z.number().int()
|
|
36573
|
-
}), zod.z.record(zod.z.string(), zod.z.unknown()), { kind: "mutation" }),
|
|
36574
|
-
/**
|
|
36575
|
-
* Release a cached frame from the Python pool's memory.
|
|
36576
|
-
*/
|
|
36577
|
-
uncacheFrame: method(zod.z.object({ frameId: zod.z.number().int() }), zod.z.void(), { kind: "mutation" }),
|
|
36578
|
-
/** Returns the effective pool tuning (resolved from user overrides + backend defaults). */
|
|
36579
|
-
getEffectiveTuning: method(zod.z.void(), zod.z.object({
|
|
36580
|
-
batchMode: zod.z.string(),
|
|
36581
|
-
windowMs: zod.z.number(),
|
|
36582
|
-
maxBatchSize: zod.z.number(),
|
|
36583
|
-
concurrency: zod.z.number()
|
|
36584
|
-
})),
|
|
36585
|
-
/**
|
|
36586
|
-
* List every EngineFactory currently loaded in this executor's RAM,
|
|
36587
|
-
* with the models resident and a coarse "in use" marker derived from
|
|
36588
|
-
* ongoing inference activity. Used by the Pipeline page Engines tab.
|
|
36589
|
-
*/
|
|
36590
|
-
listLoadedEngines: method(zod.z.void(), zod.z.array(zod.z.object({
|
|
36591
|
-
engineKey: zod.z.string(),
|
|
36592
|
-
engine: PipelineEngineChoiceSchema,
|
|
36593
|
-
modelsLoaded: zod.z.array(zod.z.string()).readonly(),
|
|
36594
|
-
inUseByCameras: zod.z.array(zod.z.number()).readonly(),
|
|
36595
|
-
/**
|
|
36596
|
-
* Origin of this resident factory.
|
|
36597
|
-
* - `runtime` — main camera-serving engine (no idle TTL).
|
|
36598
|
-
* - `warm-override` — benchmark/test override held in the warm
|
|
36599
|
-
* cache; auto-disposed after the idle TTL.
|
|
36600
|
-
* - `device-pool` — a concurrent per-device pool (Phase 2
|
|
36601
|
-
* multi-device, keyed by `deviceKey`) resolved
|
|
36602
|
-
* via `resolveDeviceFactory`. Runs alongside the
|
|
36603
|
-
* `runtime` engine on a DIFFERENT accelerator
|
|
36604
|
-
* (NPU / iGPU / Coral) — this is how the
|
|
36605
|
-
* Engines tab shows all pools running at once.
|
|
36606
|
-
*/
|
|
36607
|
-
kind: zod.z.enum([
|
|
36608
|
-
"runtime",
|
|
36609
|
-
"warm-override",
|
|
36610
|
-
"device-pool"
|
|
36611
|
-
]),
|
|
36612
|
-
/** Native pid of the underlying Python pool (null when no pool). */
|
|
36613
|
-
poolPid: zod.z.number().nullable(),
|
|
36614
|
-
/** ms since this factory was last used (null when not warm-tracked). */
|
|
36615
|
-
idleMs: zod.z.number().nullable(),
|
|
36616
|
-
/** Idle TTL after which `warm-override` factories self-evict (null when not applicable). */
|
|
36617
|
-
idleTtlMs: zod.z.number().nullable()
|
|
36618
|
-
})).readonly()),
|
|
36619
|
-
/** Warm up an engine without running a frame. No-op if already loaded. */
|
|
36620
|
-
spinEngine: method(zod.z.object({ engine: PipelineEngineChoiceSchema }), zod.z.object({ success: zod.z.literal(true) }), {
|
|
36621
|
-
kind: "mutation",
|
|
36622
|
-
auth: "admin"
|
|
36623
|
-
}),
|
|
36624
|
-
/**
|
|
36625
|
-
* Unload an engine from RAM. `force:true` unloads even when cameras
|
|
36626
|
-
* are actively using it (they re-spin on next frame). Default is
|
|
36627
|
-
* gated — returns `{success:false, reason}` when in use.
|
|
36628
|
-
*/
|
|
36629
|
-
killEngine: method(zod.z.object({
|
|
36630
|
-
engine: PipelineEngineChoiceSchema,
|
|
36631
|
-
force: zod.z.boolean().optional()
|
|
36632
|
-
}), zod.z.object({
|
|
36633
|
-
success: zod.z.boolean(),
|
|
36634
|
-
reason: zod.z.string().optional()
|
|
36635
|
-
}), {
|
|
36636
|
-
kind: "mutation",
|
|
36637
|
-
auth: "admin"
|
|
36638
|
-
}),
|
|
36639
|
-
listReferenceImages: method(zod.z.void(), zod.z.array(ReferenceImageEntrySchema).readonly()),
|
|
36640
|
-
getReferenceImage: method(zod.z.object({ filename: zod.z.string() }), ReferenceImageBodySchema.nullable()),
|
|
36641
|
-
getReferenceAudioFiles: method(zod.z.void(), zod.z.array(ReferenceAudioEntrySchema).readonly()),
|
|
36642
|
-
getReferenceAudio: method(zod.z.object({ filename: zod.z.string() }), ReferenceAudioBodySchema.nullable()),
|
|
36643
|
-
getAudioCapabilities: method(zod.z.void(), AudioCapabilitiesSchema),
|
|
36644
|
-
runAudioTest: method(zod.z.object({
|
|
36645
|
-
addonId: zod.z.string(),
|
|
36646
|
-
modelId: zod.z.string(),
|
|
36647
|
-
filename: zod.z.string().optional(),
|
|
36648
|
-
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
36649
|
-
}), AudioTestResultSchema, { kind: "mutation" }),
|
|
36650
|
-
getDetectionConfigSchema: method(zod.z.void(), ConfigUISchemaNullableBridge)
|
|
36651
|
-
}
|
|
36652
|
-
};
|
|
36653
36865
|
zod.z.object({
|
|
36654
36866
|
activeCameras: zod.z.number(),
|
|
36655
36867
|
throttledCameras: zod.z.number(),
|
|
@@ -36674,66 +36886,6 @@ var require_dist_D5Jhh8Vk = __commonJS({
|
|
|
36674
36886
|
])
|
|
36675
36887
|
});
|
|
36676
36888
|
var CameraMetricsWithDeviceIdSchema = CameraMetricsSchema.extend({ deviceId: zod.z.number() });
|
|
36677
|
-
var ZoneKindEnum = zod.z.enum(["polygon", "tripwire"]);
|
|
36678
|
-
var PolygonPointSchema = zod.z.object({
|
|
36679
|
-
x: zod.z.number(),
|
|
36680
|
-
y: zod.z.number()
|
|
36681
|
-
});
|
|
36682
|
-
var ZoneSchema = zod.z.object({
|
|
36683
|
-
id: zod.z.string(),
|
|
36684
|
-
name: zod.z.string(),
|
|
36685
|
-
kind: ZoneKindEnum.default("polygon"),
|
|
36686
|
-
/** Polygon vertices, fraction of frame (0–1). */
|
|
36687
|
-
polygon: zod.z.array(PolygonPointSchema).readonly(),
|
|
36688
|
-
/** Visual color for UI rendering. */
|
|
36689
|
-
color: zod.z.string().default("#3b82f6")
|
|
36690
|
-
});
|
|
36691
|
-
var zonesCapability = {
|
|
36692
|
-
name: "zones",
|
|
36693
|
-
scope: "device",
|
|
36694
|
-
mode: "singleton",
|
|
36695
|
-
deviceTypes: [DeviceType.Camera],
|
|
36696
|
-
methods: {
|
|
36697
|
-
listZones: method(zod.z.object({ deviceId: zod.z.number() }), zod.z.array(ZoneSchema).readonly()),
|
|
36698
|
-
addZone: method(zod.z.object({
|
|
36699
|
-
deviceId: zod.z.number(),
|
|
36700
|
-
zone: ZoneSchema
|
|
36701
|
-
}), zod.z.void(), {
|
|
36702
|
-
kind: "mutation",
|
|
36703
|
-
auth: "admin"
|
|
36704
|
-
}),
|
|
36705
|
-
removeZone: method(zod.z.object({
|
|
36706
|
-
deviceId: zod.z.number(),
|
|
36707
|
-
zoneId: zod.z.string()
|
|
36708
|
-
}), zod.z.void(), {
|
|
36709
|
-
kind: "mutation",
|
|
36710
|
-
auth: "admin"
|
|
36711
|
-
}),
|
|
36712
|
-
updateZone: method(zod.z.object({
|
|
36713
|
-
deviceId: zod.z.number(),
|
|
36714
|
-
zone: ZoneSchema
|
|
36715
|
-
}), zod.z.void(), {
|
|
36716
|
-
kind: "mutation",
|
|
36717
|
-
auth: "admin"
|
|
36718
|
-
})
|
|
36719
|
-
},
|
|
36720
|
-
/**
|
|
36721
|
-
* Runtime-state slice — the live zone catalogue mirrored by the
|
|
36722
|
-
* orchestrator on every CRUD mutation. Consumers read via
|
|
36723
|
-
* `device.state.zones.value` / `.watch(...)` without round-tripping
|
|
36724
|
-
* the cap, and the codegen DeviceProxy auto-wires the reactive
|
|
36725
|
-
* handle. Slice shape is `{ zones: Zone[] }` so future extensions
|
|
36726
|
-
* (e.g. zone groupings) can sit alongside the polygon list.
|
|
36727
|
-
*/
|
|
36728
|
-
runtimeState: zod.z.object({ zones: zod.z.array(ZoneSchema).readonly() }),
|
|
36729
|
-
/**
|
|
36730
|
-
* Runtime-state durability: **restored** — written only on operator mutation, so a camera that never had one has nothing to re-derive from. This is the slice `zone-mirror-hydration.ts` exists to paper over.
|
|
36731
|
-
*
|
|
36732
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
36733
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
36734
|
-
*/
|
|
36735
|
-
durability: "restored"
|
|
36736
|
-
};
|
|
36737
36889
|
var NativeCropBboxSchema = zod.z.object({
|
|
36738
36890
|
x: zod.z.number(),
|
|
36739
36891
|
y: zod.z.number(),
|
|
@@ -46167,59 +46319,6 @@ var require_dist_D5Jhh8Vk = __commonJS({
|
|
|
46167
46319
|
*/
|
|
46168
46320
|
durability: "session"
|
|
46169
46321
|
};
|
|
46170
|
-
var ZoneRuleModeEnum = zod.z.enum(["include", "exclude"]);
|
|
46171
|
-
var ZoneRuleSchema = zod.z.object({
|
|
46172
|
-
/** Stable rule id — survives edits, used by the UI for diffing. */
|
|
46173
|
-
id: zod.z.string(),
|
|
46174
|
-
/** Optional human-readable label rendered in the rule editor. */
|
|
46175
|
-
name: zod.z.string().optional(),
|
|
46176
|
-
/** Zones this rule targets. The rule's `mode` applies to ALL
|
|
46177
|
-
* listed zones (OR-set: a detection in any one of them counts).
|
|
46178
|
-
* At least one zone id required — a rule with no targets is a
|
|
46179
|
-
* configuration mistake and the form validator rejects it. */
|
|
46180
|
-
zoneIds: zod.z.array(zod.z.string()).min(1).readonly(),
|
|
46181
|
-
mode: ZoneRuleModeEnum,
|
|
46182
|
-
/**
|
|
46183
|
-
* Class names this rule applies to. Empty / undefined ⇒ rule
|
|
46184
|
-
* applies to every class. Class strings match the `macroClass`
|
|
46185
|
-
* field on detections (e.g. `person`, `car`, `dog`).
|
|
46186
|
-
*/
|
|
46187
|
-
classFilter: zod.z.array(zod.z.string()).readonly().optional(),
|
|
46188
|
-
/**
|
|
46189
|
-
* Minimum bbox/mask overlap (0–1) with any of the rule's zones
|
|
46190
|
-
* required to consider an entity "in the zone". Defaults to the
|
|
46191
|
-
* consumer's stage default when omitted. Kept for back-compat with
|
|
46192
|
-
* existing per-rule overrides; new operators pick the value via
|
|
46193
|
-
* `bboxInclusionPct` (operator-friendly 0–100). Whichever field is
|
|
46194
|
-
* set, the lower-level engine reads it as a 0–1 fraction.
|
|
46195
|
-
*/
|
|
46196
|
-
overlapThreshold: zod.z.number().min(0).max(1).optional(),
|
|
46197
|
-
/**
|
|
46198
|
-
* Operator-friendly version of `overlapThreshold` — the percentage
|
|
46199
|
-
* of the detection's bbox that must lie inside the zone for the
|
|
46200
|
-
* rule to match. Documented default is 85%; the engine substitutes
|
|
46201
|
-
* that when the field is omitted (kept optional so existing rules
|
|
46202
|
-
* stored without it stay valid).
|
|
46203
|
-
*
|
|
46204
|
-
* When BOTH `overlapThreshold` and `bboxInclusionPct` are set on a
|
|
46205
|
-
* rule, the engine prefers `bboxInclusionPct` because it's the
|
|
46206
|
-
* field exposed in the UI. Internally both feed the same gate.
|
|
46207
|
-
*/
|
|
46208
|
-
bboxInclusionPct: zod.z.number().min(0).max(100).optional(),
|
|
46209
|
-
/**
|
|
46210
|
-
* When `true` and a detection has a segmentation mask, use the
|
|
46211
|
-
* mask for overlap instead of the bbox. Detection-stage only;
|
|
46212
|
-
* motion rules ignore this field.
|
|
46213
|
-
*/
|
|
46214
|
-
preferMask: zod.z.boolean().optional(),
|
|
46215
|
-
/**
|
|
46216
|
-
* Soft-toggle: `false` disables the rule without deleting it.
|
|
46217
|
-
* Defaults to `true` so operators creating a rule via the UI
|
|
46218
|
-
* see it active immediately.
|
|
46219
|
-
*/
|
|
46220
|
-
enabled: zod.z.boolean().default(true)
|
|
46221
|
-
});
|
|
46222
|
-
zod.z.array(ZoneRuleSchema).readonly();
|
|
46223
46322
|
var ScriptRunnerStatusSchema = zod.z.object({
|
|
46224
46323
|
/** Whether the script is currently executing. */
|
|
46225
46324
|
isRunning: zod.z.boolean(),
|
|
@@ -51610,6 +51709,12 @@ var require_dist_D5Jhh8Vk = __commonJS({
|
|
|
51610
51709
|
addonId: null,
|
|
51611
51710
|
access: "create"
|
|
51612
51711
|
},
|
|
51712
|
+
"pipelineAnalytics.runReplayFrameProcessor": {
|
|
51713
|
+
capName: "pipeline-analytics",
|
|
51714
|
+
capScope: "device",
|
|
51715
|
+
addonId: null,
|
|
51716
|
+
access: "create"
|
|
51717
|
+
},
|
|
51613
51718
|
"pipelineAnalytics.saveRetrainAnnotations": {
|
|
51614
51719
|
capName: "pipeline-analytics",
|
|
51615
51720
|
capScope: "device",
|
|
@@ -51742,6 +51847,12 @@ var require_dist_D5Jhh8Vk = __commonJS({
|
|
|
51742
51847
|
addonId: null,
|
|
51743
51848
|
access: "view"
|
|
51744
51849
|
},
|
|
51850
|
+
"pipelineExecutor.getInferenceDeviceHealth": {
|
|
51851
|
+
capName: "pipeline-executor",
|
|
51852
|
+
capScope: "system",
|
|
51853
|
+
addonId: null,
|
|
51854
|
+
access: "view"
|
|
51855
|
+
},
|
|
51745
51856
|
"pipelineExecutor.getOrchestratorConfigSchema": {
|
|
51746
51857
|
capName: "pipeline-executor",
|
|
51747
51858
|
capScope: "system",
|
|
@@ -51814,6 +51925,12 @@ var require_dist_D5Jhh8Vk = __commonJS({
|
|
|
51814
51925
|
addonId: null,
|
|
51815
51926
|
access: "view"
|
|
51816
51927
|
},
|
|
51928
|
+
"pipelineExecutor.rearmInferenceDevice": {
|
|
51929
|
+
capName: "pipeline-executor",
|
|
51930
|
+
capScope: "system",
|
|
51931
|
+
addonId: null,
|
|
51932
|
+
access: "create"
|
|
51933
|
+
},
|
|
51817
51934
|
"pipelineExecutor.runAudioTest": {
|
|
51818
51935
|
capName: "pipeline-executor",
|
|
51819
51936
|
capScope: "system",
|
|
@@ -55062,6 +55179,11 @@ var require_dist_D5Jhh8Vk = __commonJS({
|
|
|
55062
55179
|
form: "single",
|
|
55063
55180
|
optional: false
|
|
55064
55181
|
}],
|
|
55182
|
+
"pipelineAnalytics.runReplayFrameProcessor": [{
|
|
55183
|
+
name: "deviceId",
|
|
55184
|
+
form: "single",
|
|
55185
|
+
optional: false
|
|
55186
|
+
}],
|
|
55065
55187
|
"pipelineAnalytics.saveRetrainAnnotations": [{
|
|
55066
55188
|
name: "deviceId",
|
|
55067
55189
|
form: "single",
|
|
@@ -57031,7 +57153,7 @@ var require_alerts_addon = __commonJS({
|
|
|
57031
57153
|
[Symbol.toStringTag]: { value: "Module" }
|
|
57032
57154
|
});
|
|
57033
57155
|
require_chunk_Cek0wNdY();
|
|
57034
|
-
var require_dist10 =
|
|
57156
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
57035
57157
|
function selectExpired(alerts, cutoffMs) {
|
|
57036
57158
|
return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
|
|
57037
57159
|
}
|
|
@@ -57850,7 +57972,7 @@ var require_console_logging = __commonJS({
|
|
|
57850
57972
|
[Symbol.toStringTag]: { value: "Module" }
|
|
57851
57973
|
});
|
|
57852
57974
|
require_chunk_Cek0wNdY();
|
|
57853
|
-
var require_dist10 =
|
|
57975
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
57854
57976
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
57855
57977
|
var LEVEL_RANK = {
|
|
57856
57978
|
debug: 0,
|
|
@@ -57944,7 +58066,7 @@ var require_core_blocks_addon = __commonJS({
|
|
|
57944
58066
|
"use strict";
|
|
57945
58067
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
57946
58068
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
57947
|
-
var require_dist10 =
|
|
58069
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
57948
58070
|
var node_crypto = __require("crypto");
|
|
57949
58071
|
var node_fs_promises = __require("fs/promises");
|
|
57950
58072
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -58841,11 +58963,11 @@ var require_core_blocks = __commonJS({
|
|
|
58841
58963
|
}
|
|
58842
58964
|
});
|
|
58843
58965
|
|
|
58844
|
-
// ../system/dist/retired-settings-keys-
|
|
58845
|
-
var
|
|
58846
|
-
"../system/dist/retired-settings-keys-
|
|
58966
|
+
// ../system/dist/retired-settings-keys-DVgdWTd7.js
|
|
58967
|
+
var require_retired_settings_keys_DVgdWTd7 = __commonJS({
|
|
58968
|
+
"../system/dist/retired-settings-keys-DVgdWTd7.js"(exports) {
|
|
58847
58969
|
"use strict";
|
|
58848
|
-
var require_dist10 =
|
|
58970
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
58849
58971
|
function settingsStoreIsAuthoritativeHere(env) {
|
|
58850
58972
|
const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
|
|
58851
58973
|
return raw === "" || raw === "hub";
|
|
@@ -60888,8 +61010,8 @@ var require_device_manager_addon = __commonJS({
|
|
|
60888
61010
|
[Symbol.toStringTag]: { value: "Module" }
|
|
60889
61011
|
});
|
|
60890
61012
|
require_chunk_Cek0wNdY();
|
|
60891
|
-
var require_dist10 =
|
|
60892
|
-
var require_retired_settings_keys =
|
|
61013
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
61014
|
+
var require_retired_settings_keys = require_retired_settings_keys_DVgdWTd7();
|
|
60893
61015
|
var node_crypto = __require("crypto");
|
|
60894
61016
|
var _camstack_types_node = require_node();
|
|
60895
61017
|
var JOB_HISTORY = 20;
|
|
@@ -61908,6 +62030,10 @@ var require_device_manager_addon = __commonJS({
|
|
|
61908
62030
|
device
|
|
61909
62031
|
};
|
|
61910
62032
|
}
|
|
62033
|
+
function extractCallerAddonId(input) {
|
|
62034
|
+
const raw = Reflect.get(input, "callerAddonId");
|
|
62035
|
+
return typeof raw === "string" && raw.length > 0 ? raw : void 0;
|
|
62036
|
+
}
|
|
61911
62037
|
async function listPersistedByAddon(pctx, input) {
|
|
61912
62038
|
const { addonId } = input;
|
|
61913
62039
|
return (await pctx.metaStore.rows.listByAddon(addonId)).map(({ meta: m }) => ({
|
|
@@ -61935,6 +62061,7 @@ var require_device_manager_addon = __commonJS({
|
|
|
61935
62061
|
async function listAll(pctx, input) {
|
|
61936
62062
|
const ownerFilter = Reflect.get(input, "addonId");
|
|
61937
62063
|
if (ownerFilter !== void 0 && (typeof ownerFilter !== "string" || ownerFilter.length === 0)) throw new Error(`deviceManager.listAll: addonId must be a non-empty string or be omitted \u2014 got ${JSON.stringify(ownerFilter)}. An owner filter that is present but empty is never widened to every device. On an addon context the id is \`ctx.id\`; there is no \`ctx.addonId\`.`);
|
|
62064
|
+
const callerAddonId = pctx.metaStore.rows.censusArmed ? extractCallerAddonId(input) : void 0;
|
|
61938
62065
|
const { addonId } = input;
|
|
61939
62066
|
const slim = input.projection === "slim";
|
|
61940
62067
|
const camerasOnly = input.isCamera === true;
|
|
@@ -61944,7 +62071,7 @@ var require_device_manager_addon = __commonJS({
|
|
|
61944
62071
|
const fleet = addonId ? await pctx.metaStore.rows.listByAddon(addonId) : await pctx.metaStore.rows.listFleet({
|
|
61945
62072
|
...input.deviceIds !== void 0 ? { deviceIds: input.deviceIds } : {},
|
|
61946
62073
|
slim
|
|
61947
|
-
});
|
|
62074
|
+
}, callerAddonId);
|
|
61948
62075
|
const rowById = /* @__PURE__ */ new Map();
|
|
61949
62076
|
for (const row of fleet) rowById.set(row.meta.id, row);
|
|
61950
62077
|
if (pctx.registry) {
|
|
@@ -62446,18 +62573,38 @@ var require_device_manager_addon = __commonJS({
|
|
|
62446
62573
|
manualIds
|
|
62447
62574
|
};
|
|
62448
62575
|
}
|
|
62576
|
+
function expandContainer(id, byId, byParent, visited, out) {
|
|
62577
|
+
if (visited.has(id)) return;
|
|
62578
|
+
const candidate = byId.get(id);
|
|
62579
|
+
if (!candidate) return;
|
|
62580
|
+
if (candidate.type !== require_dist10.DeviceType.Container) {
|
|
62581
|
+
out.add(id);
|
|
62582
|
+
return;
|
|
62583
|
+
}
|
|
62584
|
+
const nextVisited = new Set(visited);
|
|
62585
|
+
nextVisited.add(id);
|
|
62586
|
+
const children = byParent.get(id) ?? [];
|
|
62587
|
+
for (const child of children) expandContainer(child.id, byId, byParent, nextVisited, out);
|
|
62588
|
+
}
|
|
62449
62589
|
function resolveLinkedDeviceIds(params) {
|
|
62450
62590
|
const { selfId, selfLocation, config, candidates } = params;
|
|
62591
|
+
const byId = new Map(candidates.map((c) => [c.id, c]));
|
|
62592
|
+
const byParent = /* @__PURE__ */ new Map();
|
|
62593
|
+
for (const c of candidates) {
|
|
62594
|
+
if (c.parentDeviceId === null) continue;
|
|
62595
|
+
const siblings = byParent.get(c.parentDeviceId);
|
|
62596
|
+
if (siblings) siblings.push(c);
|
|
62597
|
+
else byParent.set(c.parentDeviceId, [c]);
|
|
62598
|
+
}
|
|
62451
62599
|
const ids = /* @__PURE__ */ new Set();
|
|
62452
|
-
|
|
62600
|
+
const expand = (id) => expandContainer(id, byId, byParent, /* @__PURE__ */ new Set(), ids);
|
|
62601
|
+
for (const c of candidates) if (c.parentDeviceId === selfId) expand(c.id);
|
|
62453
62602
|
if (config.mode === "auto") {
|
|
62454
|
-
if (selfLocation !== null && selfLocation.length > 0) {
|
|
62455
|
-
|
|
62603
|
+
if (selfLocation !== null && selfLocation.length > 0) for (const c of candidates) {
|
|
62604
|
+
if (c.type === require_dist10.DeviceType.Container) continue;
|
|
62605
|
+
if (c.location === selfLocation) ids.add(c.id);
|
|
62456
62606
|
}
|
|
62457
|
-
} else
|
|
62458
|
-
const known = new Set(candidates.map((c) => c.id));
|
|
62459
|
-
for (const id of config.manualIds) if (known.has(id)) ids.add(id);
|
|
62460
|
-
}
|
|
62607
|
+
} else for (const id of config.manualIds) if (byId.has(id)) expand(id);
|
|
62461
62608
|
ids.delete(selfId);
|
|
62462
62609
|
return [...ids];
|
|
62463
62610
|
}
|
|
@@ -62524,7 +62671,7 @@ var require_device_manager_addon = __commonJS({
|
|
|
62524
62671
|
if (!persisted || persisted.meta.type !== require_dist10.DeviceType.Camera) return null;
|
|
62525
62672
|
const [all, blob] = await Promise.all([listAll(pctx, LINK_CANDIDATE_PROJECTION), pctx.settings.readDeviceStore(deviceId)]);
|
|
62526
62673
|
const config = parseLinkedDevicesConfig(blob);
|
|
62527
|
-
const options = all.filter((d) => d.id !== deviceId).map((d) => ({
|
|
62674
|
+
const options = all.filter((d) => d.id !== deviceId && d.type !== require_dist10.DeviceType.Container).map((d) => ({
|
|
62528
62675
|
value: String(d.id),
|
|
62529
62676
|
label: d.location !== null ? `${d.name} (${d.location})` : d.name
|
|
62530
62677
|
}));
|
|
@@ -63528,11 +63675,42 @@ var require_device_manager_addon = __commonJS({
|
|
|
63528
63675
|
}
|
|
63529
63676
|
});
|
|
63530
63677
|
}
|
|
63678
|
+
async function collectDescendants(metaStore, rootId) {
|
|
63679
|
+
const out = [];
|
|
63680
|
+
const visited = /* @__PURE__ */ new Set([rootId]);
|
|
63681
|
+
const queue = [rootId];
|
|
63682
|
+
while (queue.length > 0) {
|
|
63683
|
+
const parentId = queue.shift();
|
|
63684
|
+
if (parentId === void 0) break;
|
|
63685
|
+
for (const row of await metaStore.rows.listByParent(parentId)) {
|
|
63686
|
+
if (visited.has(row.meta.id)) continue;
|
|
63687
|
+
visited.add(row.meta.id);
|
|
63688
|
+
out.push(row.meta);
|
|
63689
|
+
queue.push(row.meta.id);
|
|
63690
|
+
}
|
|
63691
|
+
}
|
|
63692
|
+
return out;
|
|
63693
|
+
}
|
|
63531
63694
|
async function setLocation(pctx, input) {
|
|
63532
63695
|
const { deviceId, location } = input;
|
|
63696
|
+
const cascaded = [];
|
|
63697
|
+
const failed = [];
|
|
63533
63698
|
await pctx.metaStore.withMetaWriteLock(async () => {
|
|
63534
|
-
|
|
63699
|
+
const persisted = await pctx.metaStore.resolvePersistedById(deviceId);
|
|
63700
|
+
if (!persisted) throw new Error(`[device-manager] setLocation: unknown device id=${deviceId}`);
|
|
63535
63701
|
await pctx.metaStore.rows.patch(deviceId, { location });
|
|
63702
|
+
if (persisted.meta.type === require_dist10.DeviceType.Container) {
|
|
63703
|
+
const descendants = await collectDescendants(pctx.metaStore, deviceId);
|
|
63704
|
+
for (const descendant of descendants) try {
|
|
63705
|
+
await pctx.metaStore.rows.patch(descendant.id, { location });
|
|
63706
|
+
cascaded.push(descendant.id);
|
|
63707
|
+
} catch (err) {
|
|
63708
|
+
failed.push({
|
|
63709
|
+
id: descendant.id,
|
|
63710
|
+
error: err
|
|
63711
|
+
});
|
|
63712
|
+
}
|
|
63713
|
+
}
|
|
63536
63714
|
});
|
|
63537
63715
|
pctx.host.ctx.eventBus.emit({
|
|
63538
63716
|
id: (0, node_crypto.randomUUID)(),
|
|
@@ -63548,6 +63726,36 @@ var require_device_manager_addon = __commonJS({
|
|
|
63548
63726
|
value: location
|
|
63549
63727
|
}
|
|
63550
63728
|
});
|
|
63729
|
+
for (const childId of cascaded) pctx.host.ctx.eventBus.emit({
|
|
63730
|
+
id: (0, node_crypto.randomUUID)(),
|
|
63731
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
63732
|
+
source: {
|
|
63733
|
+
type: "device",
|
|
63734
|
+
id: childId
|
|
63735
|
+
},
|
|
63736
|
+
category: require_dist10.EventCategory.DeviceMetaChanged,
|
|
63737
|
+
data: {
|
|
63738
|
+
deviceId: childId,
|
|
63739
|
+
field: "location",
|
|
63740
|
+
value: location
|
|
63741
|
+
}
|
|
63742
|
+
});
|
|
63743
|
+
if (cascaded.length > 0 || failed.length > 0) pctx.host.ctx.logger.info("setLocation: cascaded location to container descendants", {
|
|
63744
|
+
tags: { deviceId },
|
|
63745
|
+
meta: {
|
|
63746
|
+
location,
|
|
63747
|
+
updated: cascaded.length,
|
|
63748
|
+
failed: failed.length
|
|
63749
|
+
}
|
|
63750
|
+
});
|
|
63751
|
+
if (failed.length > 0) pctx.host.ctx.logger.error("setLocation: cascade partially failed \u2014 some descendants NOT aligned to the new location", {
|
|
63752
|
+
tags: { deviceId },
|
|
63753
|
+
meta: {
|
|
63754
|
+
location,
|
|
63755
|
+
failedIds: failed.map((f) => f.id),
|
|
63756
|
+
errors: failed.map((f) => f.error instanceof Error ? f.error.message : String(f.error))
|
|
63757
|
+
}
|
|
63758
|
+
});
|
|
63551
63759
|
}
|
|
63552
63760
|
async function setType(pctx, input) {
|
|
63553
63761
|
const { deviceId, type } = input;
|
|
@@ -64039,9 +64247,29 @@ var require_device_manager_addon = __commonJS({
|
|
|
64039
64247
|
* to it even if it lands after the close — otherwise the slow reads at the
|
|
64040
64248
|
* edge would be attributed to nobody, and the slow ones are the interesting
|
|
64041
64249
|
* ones.
|
|
64042
|
-
|
|
64043
|
-
|
|
64250
|
+
*
|
|
64251
|
+
* `callerAddonId`, when given, is formatted as the site VERBATIM instead of
|
|
64252
|
+
* walking the local stack. A call that arrived over the cap channel — a
|
|
64253
|
+
* forked addon's `ctx.api.deviceManager.listAll.query()`, routed through
|
|
64254
|
+
* `LocalChildRegistry` → `onUnownedCall` → `CapRouteResolver` — carries its
|
|
64255
|
+
* origin as DATA (the registered `childId` the parent captured off the UDS
|
|
64256
|
+
* connection), and no amount of stack depth would ever recover it: every
|
|
64257
|
+
* frame between the socket read and this call is the SAME generic
|
|
64258
|
+
* dispatcher code (`onUnownedCall`, `dispatch`, `invoke`) regardless of
|
|
64259
|
+
* which addon called — the 2026-08-25 boot census measured this directly,
|
|
64260
|
+
* five thousand calls landing on `listAll` with nothing nameable above it.
|
|
64261
|
+
*
|
|
64262
|
+
* `isOpen` is checked FIRST, before the id is even looked at — a caller
|
|
64263
|
+
* threading a (cheap, already-known) `callerAddonId` through on every
|
|
64264
|
+
* request, armed or not, must not pay for the template string when
|
|
64265
|
+
* disarmed. This is also why formatting lives HERE rather than at the call
|
|
64266
|
+
* site: `DeviceRowStore` passes the raw id through unconditionally, and
|
|
64267
|
+
* only this method — which already knows whether armed — decides whether
|
|
64268
|
+
* to spend anything on it.
|
|
64269
|
+
*/
|
|
64270
|
+
siteOf(callerAddonId, nowMs = Date.now()) {
|
|
64044
64271
|
if (!this.isOpen(nowMs)) return null;
|
|
64272
|
+
if (callerAddonId !== void 0) return `addon:${callerAddonId}`;
|
|
64045
64273
|
const holder = {};
|
|
64046
64274
|
Error.captureStackTrace(holder, this.siteOf);
|
|
64047
64275
|
return siteFromStack(holder.stack);
|
|
@@ -64329,6 +64557,16 @@ var require_device_manager_addon = __commonJS({
|
|
|
64329
64557
|
/** Call-site attribution for fleet reads. Armed only by
|
|
64330
64558
|
* `CAMSTACK_FLEET_READ_CENSUS_MS`; see `fleet-read-census.ts`. */
|
|
64331
64559
|
census;
|
|
64560
|
+
/**
|
|
64561
|
+
* Is the fleet-read census armed right now? Exposed so a caller ABOVE this
|
|
64562
|
+
* store (`device-queries.ts`) can skip extracting a caller identity off its
|
|
64563
|
+
* input entirely when nobody is measuring — "the boolean field read first"
|
|
64564
|
+
* pattern this repo already uses elsewhere to keep a diagnostic seam at
|
|
64565
|
+
* zero cost while disarmed.
|
|
64566
|
+
*/
|
|
64567
|
+
get censusArmed() {
|
|
64568
|
+
return this.census.armed;
|
|
64569
|
+
}
|
|
64332
64570
|
constructor(backend, logger, census) {
|
|
64333
64571
|
this.backend = backend;
|
|
64334
64572
|
this.logger = logger;
|
|
@@ -64377,15 +64615,23 @@ var require_device_manager_addon = __commonJS({
|
|
|
64377
64615
|
}
|
|
64378
64616
|
return decoded;
|
|
64379
64617
|
}
|
|
64380
|
-
/**
|
|
64381
|
-
|
|
64618
|
+
/**
|
|
64619
|
+
* Every device, ordered by numeric id.
|
|
64620
|
+
*
|
|
64621
|
+
* `callerAddonId`, when known, is the addon that ORIGINATED this call —
|
|
64622
|
+
* captured off the cap-channel envelope (`CapCallInput.callerAddonId`, set
|
|
64623
|
+
* by `LocalChildRegistry` from the registered `childId`), never guessed.
|
|
64624
|
+
* Passed straight to the census; a stack walk can never name it (see
|
|
64625
|
+
* `fleet-read-census.ts#siteOf`).
|
|
64626
|
+
*/
|
|
64627
|
+
async listAll(callerAddonId) {
|
|
64382
64628
|
return this.list({
|
|
64383
64629
|
orderBy: {
|
|
64384
64630
|
field: "deviceId",
|
|
64385
64631
|
direction: "asc"
|
|
64386
64632
|
},
|
|
64387
64633
|
limit: DEVICE_ROWS_FLEET_LIMIT
|
|
64388
|
-
});
|
|
64634
|
+
}, void 0, callerAddonId);
|
|
64389
64635
|
}
|
|
64390
64636
|
/**
|
|
64391
64637
|
* The fleet, read as narrowly as the question allows.
|
|
@@ -64402,8 +64648,10 @@ var require_device_manager_addon = __commonJS({
|
|
|
64402
64648
|
*
|
|
64403
64649
|
* `isCamera` is deliberately NOT one of them — see that constant's note and
|
|
64404
64650
|
* `device-row-store-filtered.spec.ts`.
|
|
64651
|
+
*
|
|
64652
|
+
* `callerAddonId` — see {@link listAll}'s doc; same meaning here.
|
|
64405
64653
|
*/
|
|
64406
|
-
async listFleet(opts) {
|
|
64654
|
+
async listFleet(opts, callerAddonId) {
|
|
64407
64655
|
if (opts.deviceIds !== void 0 && opts.deviceIds.length === 0) return [];
|
|
64408
64656
|
return this.list({
|
|
64409
64657
|
...opts.deviceIds !== void 0 ? { whereIn: { deviceId: [...new Set(opts.deviceIds)] } } : {},
|
|
@@ -64412,7 +64660,7 @@ var require_device_manager_addon = __commonJS({
|
|
|
64412
64660
|
direction: "asc"
|
|
64413
64661
|
},
|
|
64414
64662
|
limit: DEVICE_ROWS_FLEET_LIMIT
|
|
64415
|
-
}, opts.slim === true ? DEVICE_ROWS_SLIM_COLUMNS : void 0);
|
|
64663
|
+
}, opts.slim === true ? DEVICE_ROWS_SLIM_COLUMNS : void 0, callerAddonId);
|
|
64416
64664
|
}
|
|
64417
64665
|
/**
|
|
64418
64666
|
* Many devices, by numeric id, in ONE query.
|
|
@@ -64503,8 +64751,8 @@ var require_device_manager_addon = __commonJS({
|
|
|
64503
64751
|
await this.declare();
|
|
64504
64752
|
return this.backend.count({ collection: DEVICE_ROWS_COLLECTION });
|
|
64505
64753
|
}
|
|
64506
|
-
async list(filter, columns) {
|
|
64507
|
-
const site = this.census.siteOf();
|
|
64754
|
+
async list(filter, columns, callerAddonId) {
|
|
64755
|
+
const site = this.census.siteOf(callerAddonId);
|
|
64508
64756
|
await this.declare();
|
|
64509
64757
|
const records = await this.backend.query({
|
|
64510
64758
|
collection: DEVICE_ROWS_COLLECTION,
|
|
@@ -65432,7 +65680,7 @@ var require_hub_forwarder = __commonJS({
|
|
|
65432
65680
|
[Symbol.toStringTag]: { value: "Module" }
|
|
65433
65681
|
});
|
|
65434
65682
|
require_chunk_Cek0wNdY();
|
|
65435
|
-
var require_dist10 =
|
|
65683
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
65436
65684
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
65437
65685
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
65438
65686
|
var HubForwarderDestination = class {
|
|
@@ -65569,7 +65817,7 @@ var require_liveness_monitor_addon = __commonJS({
|
|
|
65569
65817
|
"use strict";
|
|
65570
65818
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
65571
65819
|
require_chunk_Cek0wNdY();
|
|
65572
|
-
var require_dist10 =
|
|
65820
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
65573
65821
|
var NO_DEVICES = "liveness:no-devices";
|
|
65574
65822
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
65575
65823
|
var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
|
|
@@ -65759,7 +66007,7 @@ var require_local_auth_addon = __commonJS({
|
|
|
65759
66007
|
[Symbol.toStringTag]: { value: "Module" }
|
|
65760
66008
|
});
|
|
65761
66009
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
65762
|
-
var require_dist10 =
|
|
66010
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
65763
66011
|
var node_crypto = __require("crypto");
|
|
65764
66012
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
65765
66013
|
var crypto$1 = __require("crypto");
|
|
@@ -73443,7 +73691,7 @@ var require_loki_logging = __commonJS({
|
|
|
73443
73691
|
[Symbol.toStringTag]: { value: "Module" }
|
|
73444
73692
|
});
|
|
73445
73693
|
require_chunk_Cek0wNdY();
|
|
73446
|
-
var require_dist10 =
|
|
73694
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
73447
73695
|
function sanitizeLabelName(raw) {
|
|
73448
73696
|
const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
|
|
73449
73697
|
return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
|
|
@@ -74008,7 +74256,7 @@ var require_native_metrics_addon = __commonJS({
|
|
|
74008
74256
|
[Symbol.toStringTag]: { value: "Module" }
|
|
74009
74257
|
});
|
|
74010
74258
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
74011
|
-
var require_dist10 =
|
|
74259
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
74012
74260
|
var node_child_process = __require("child_process");
|
|
74013
74261
|
var node_util = __require("util");
|
|
74014
74262
|
var node_os = __require("os");
|
|
@@ -74950,7 +75198,7 @@ var require_filesystem_storage_addon = __commonJS({
|
|
|
74950
75198
|
[Symbol.toStringTag]: { value: "Module" }
|
|
74951
75199
|
});
|
|
74952
75200
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
74953
|
-
var require_dist10 =
|
|
75201
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
74954
75202
|
var node_crypto = __require("crypto");
|
|
74955
75203
|
var node_fs_promises = __require("fs/promises");
|
|
74956
75204
|
var node_path = __require("path");
|
|
@@ -76066,8 +76314,8 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
76066
76314
|
[Symbol.toStringTag]: { value: "Module" }
|
|
76067
76315
|
});
|
|
76068
76316
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
76069
|
-
var require_dist10 =
|
|
76070
|
-
var require_retired_settings_keys =
|
|
76317
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
76318
|
+
var require_retired_settings_keys = require_retired_settings_keys_DVgdWTd7();
|
|
76071
76319
|
var node_crypto = __require("crypto");
|
|
76072
76320
|
var node_fs = __require("fs");
|
|
76073
76321
|
var node_module = __require("module");
|
|
@@ -78261,7 +78509,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
78261
78509
|
[Symbol.toStringTag]: { value: "Module" }
|
|
78262
78510
|
});
|
|
78263
78511
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
78264
|
-
var require_dist10 =
|
|
78512
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
78265
78513
|
var node_crypto = __require("crypto");
|
|
78266
78514
|
var node_fs_promises = __require("fs/promises");
|
|
78267
78515
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -80140,7 +80388,7 @@ var require_system_config_addon = __commonJS({
|
|
|
80140
80388
|
[Symbol.toStringTag]: { value: "Module" }
|
|
80141
80389
|
});
|
|
80142
80390
|
require_chunk_Cek0wNdY();
|
|
80143
|
-
var require_dist10 =
|
|
80391
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
80144
80392
|
var SECTION_TITLES = {
|
|
80145
80393
|
server: "Server",
|
|
80146
80394
|
auth: "Authentication"
|
|
@@ -98201,7 +98449,7 @@ var require_winston_logging = __commonJS({
|
|
|
98201
98449
|
[Symbol.toStringTag]: { value: "Module" }
|
|
98202
98450
|
});
|
|
98203
98451
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
98204
|
-
var require_dist10 =
|
|
98452
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
98205
98453
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
98206
98454
|
var node_path = __require("path");
|
|
98207
98455
|
node_path = require_chunk.__toESM(node_path);
|
|
@@ -100144,9 +100392,9 @@ var require_event_category_EY0GNjV9 = __commonJS({
|
|
|
100144
100392
|
}
|
|
100145
100393
|
});
|
|
100146
100394
|
|
|
100147
|
-
// ../types/dist/sleep-
|
|
100148
|
-
var
|
|
100149
|
-
"../types/dist/sleep-
|
|
100395
|
+
// ../types/dist/sleep-BCRrMlni.js
|
|
100396
|
+
var require_sleep_BCRrMlni = __commonJS({
|
|
100397
|
+
"../types/dist/sleep-BCRrMlni.js"(exports) {
|
|
100150
100398
|
"use strict";
|
|
100151
100399
|
var require_event_category = require_event_category_EY0GNjV9();
|
|
100152
100400
|
var zod = require_zod();
|
|
@@ -102746,6 +102994,7 @@ var require_sleep_DnbNfEhn = __commonJS({
|
|
|
102746
102994
|
deselectRetrainFrame: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "deselectRetrainFrame", "mutation", input),
|
|
102747
102995
|
getRetrainFrameImage: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getRetrainFrameImage", "query", input),
|
|
102748
102996
|
proposeRetrainAnnotations: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "proposeRetrainAnnotations", "mutation", input),
|
|
102997
|
+
runReplayFrameProcessor: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "runReplayFrameProcessor", "mutation", input),
|
|
102749
102998
|
listRetrainAnnotations: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "listRetrainAnnotations", "query", input),
|
|
102750
102999
|
saveRetrainAnnotations: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "saveRetrainAnnotations", "mutation", input),
|
|
102751
103000
|
completeRetrainTrack: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "completeRetrainTrack", "mutation", input),
|
|
@@ -103697,7 +103946,7 @@ var require_addon = __commonJS({
|
|
|
103697
103946
|
"use strict";
|
|
103698
103947
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
103699
103948
|
var require_event_category = require_event_category_EY0GNjV9();
|
|
103700
|
-
var require_sleep =
|
|
103949
|
+
var require_sleep = require_sleep_BCRrMlni();
|
|
103701
103950
|
var require_err_msg = require_err_msg_COpsHMw2();
|
|
103702
103951
|
var CAP_INPUT_DEFAULTS = Object.freeze({
|
|
103703
103952
|
"addons": { "getLogs": { "limit": 100 } },
|
|
@@ -110573,9 +110822,9 @@ var require_dist2 = __commonJS({
|
|
|
110573
110822
|
}
|
|
110574
110823
|
});
|
|
110575
110824
|
|
|
110576
|
-
// ../system/dist/manifest-python-deps-
|
|
110577
|
-
var
|
|
110578
|
-
"../system/dist/manifest-python-deps-
|
|
110825
|
+
// ../system/dist/manifest-python-deps-DBQarwp9.js
|
|
110826
|
+
var require_manifest_python_deps_DBQarwp9 = __commonJS({
|
|
110827
|
+
"../system/dist/manifest-python-deps-DBQarwp9.js"(exports) {
|
|
110579
110828
|
"use strict";
|
|
110580
110829
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
110581
110830
|
var node_crypto = __require("crypto");
|
|
@@ -114426,6 +114675,14 @@ var require_manifest_python_deps_Bu8H1_rg = __commonJS({
|
|
|
114426
114675
|
const raw = Reflect.get(args, "nodeId");
|
|
114427
114676
|
return typeof raw === "string" && raw.length > 0 ? raw : void 0;
|
|
114428
114677
|
}
|
|
114678
|
+
function withCallerAddonId(args, callerAddonId) {
|
|
114679
|
+
if (callerAddonId === void 0) return args;
|
|
114680
|
+
if (args === null || typeof args !== "object" || Array.isArray(args)) return args;
|
|
114681
|
+
return {
|
|
114682
|
+
...args,
|
|
114683
|
+
callerAddonId
|
|
114684
|
+
};
|
|
114685
|
+
}
|
|
114429
114686
|
var CapRouteResolver = class {
|
|
114430
114687
|
hubNodeId;
|
|
114431
114688
|
broker;
|
|
@@ -114493,10 +114750,20 @@ var require_manifest_python_deps_Bu8H1_rg = __commonJS({
|
|
|
114493
114750
|
* `hub-local-uds` caller that already knows the addonId (`buildCapCallFn`)
|
|
114494
114751
|
* talks to `LocalChildRegistry.callCapOnChild` directly rather than through
|
|
114495
114752
|
* `dispatch`.
|
|
114496
|
-
|
|
114497
|
-
|
|
114753
|
+
* @param callerAddonId Optional out-of-band CALLER-identity hint — the
|
|
114754
|
+
* addon that ORIGINATED the call, distinct from `addonId` above (which
|
|
114755
|
+
* names the resolved PROVIDER, not the caller). Set by
|
|
114756
|
+
* `onUnownedCall` from `CapCallInput.callerAddonId`
|
|
114757
|
+
* (`LocalChildRegistry` stamped it off the registered `childId`). Only
|
|
114758
|
+
* the `hub-in-process` branch consumes it — merged into `args` so a
|
|
114759
|
+
* diagnostic tool deep in that provider (e.g. device-manager's
|
|
114760
|
+
* fleet-read census) can read it without every provider method changing
|
|
114761
|
+
* signature, the same "extra field the provider destructures or
|
|
114762
|
+
* ignores" convention `nodeId` already uses on this path.
|
|
114763
|
+
*/
|
|
114764
|
+
async dispatch(route, method, args, addonId, callerAddonId) {
|
|
114498
114765
|
try {
|
|
114499
|
-
return await this.dispatchInner(route, method, args, addonId);
|
|
114766
|
+
return await this.dispatchInner(route, method, args, addonId, callerAddonId);
|
|
114500
114767
|
} catch (err) {
|
|
114501
114768
|
if (err instanceof CapRouteError) throw err;
|
|
114502
114769
|
const nodeId = this.routeNodeId(route);
|
|
@@ -114515,10 +114782,10 @@ var require_manifest_python_deps_Bu8H1_rg = __commonJS({
|
|
|
114515
114782
|
* Inner dispatch: may throw CapRouteError (validation failures) or arbitrary
|
|
114516
114783
|
* transport errors. The outer `dispatch` wraps non-CapRouteErrors.
|
|
114517
114784
|
*/
|
|
114518
|
-
async dispatchInner(route, method, args, addonId) {
|
|
114785
|
+
async dispatchInner(route, method, args, addonId, callerAddonId) {
|
|
114519
114786
|
switch (route.kind) {
|
|
114520
114787
|
case "hub-in-process":
|
|
114521
|
-
return route.ref.invoke(method, args);
|
|
114788
|
+
return route.ref.invoke(method, withCallerAddonId(args, callerAddonId));
|
|
114522
114789
|
case "hub-local-uds": {
|
|
114523
114790
|
const registry = this.hubLocalRegistry;
|
|
114524
114791
|
if (registry === null) throw new CapRouteError(route.capName, method, {
|
|
@@ -115052,7 +115319,8 @@ var require_manifest_python_deps_Bu8H1_rg = __commonJS({
|
|
|
115052
115319
|
args: out.args,
|
|
115053
115320
|
...out.deviceId !== void 0 ? { deviceId: out.deviceId } : {},
|
|
115054
115321
|
...out.nodeId !== void 0 ? { nodeId: out.nodeId } : {},
|
|
115055
|
-
...out.native === true ? { native: true } : {}
|
|
115322
|
+
...out.native === true ? { native: true } : {},
|
|
115323
|
+
...childId !== null ? { callerAddonId: childId } : {}
|
|
115056
115324
|
};
|
|
115057
115325
|
const pinnedNodeId = out.nodeId ?? extractNodeId(out.args);
|
|
115058
115326
|
const pinTargetsThisNode = pinnedNodeId !== void 0 && this.ownNodeId !== void 0 && pinnedNodeId === this.ownNodeId;
|
|
@@ -115546,7 +115814,7 @@ var require_manifest_python_deps_Bu8H1_rg = __commonJS({
|
|
|
115546
115814
|
...nodeId !== void 0 ? { nodeId } : {},
|
|
115547
115815
|
...deviceId !== void 0 ? { deviceId } : {}
|
|
115548
115816
|
});
|
|
115549
|
-
return await resolver.dispatch(route, input.method, input.args);
|
|
115817
|
+
return input.callerAddonId !== void 0 ? await resolver.dispatch(route, input.method, input.args, void 0, input.callerAddonId) : await resolver.dispatch(route, input.method, input.args);
|
|
115550
115818
|
} catch (err) {
|
|
115551
115819
|
if (!(err instanceof CapRouteError) || err.reason !== "no-provider") throw err;
|
|
115552
115820
|
}
|
|
@@ -121417,7 +121685,7 @@ var require_dist3 = __commonJS({
|
|
|
121417
121685
|
"use strict";
|
|
121418
121686
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
121419
121687
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
121420
|
-
var require_dist10 =
|
|
121688
|
+
var require_dist10 = require_dist_BNhvXrQk();
|
|
121421
121689
|
var require_builtins_alerts_alerts_addon = require_alerts_addon();
|
|
121422
121690
|
require_alerts();
|
|
121423
121691
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
@@ -121443,7 +121711,7 @@ var require_dist3 = __commonJS({
|
|
|
121443
121711
|
var require_builtins_winston_logging_index = require_winston_logging();
|
|
121444
121712
|
var require_file_data_plane = require_file_data_plane_DO8KbxCe();
|
|
121445
121713
|
var require_tls$1 = require_tls_u8QCJCFE();
|
|
121446
|
-
var require_manifest_python_deps =
|
|
121714
|
+
var require_manifest_python_deps = require_manifest_python_deps_DBQarwp9();
|
|
121447
121715
|
var require_resource_monitor = require_resource_monitor_CdnzxBLP();
|
|
121448
121716
|
var require_custom_action_registry = require_custom_action_registry_jY0NOZK8();
|
|
121449
121717
|
var zod = require_zod();
|
|
@@ -202065,7 +202333,7 @@ var require_dist4 = __commonJS({
|
|
|
202065
202333
|
"use strict";
|
|
202066
202334
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
202067
202335
|
var require_event_category = require_event_category_EY0GNjV9();
|
|
202068
|
-
var require_sleep =
|
|
202336
|
+
var require_sleep = require_sleep_BCRrMlni();
|
|
202069
202337
|
var require_canonical_hash = require_canonical_hash_DNV8S5ET();
|
|
202070
202338
|
var require_enums2 = require_enums();
|
|
202071
202339
|
var require_err_msg = require_err_msg_COpsHMw2();
|
|
@@ -213539,6 +213807,726 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
213539
213807
|
getDescriptor: require_sleep.method(zod.z.void(), OauthIntegrationDescriptorSchema, { auth: "admin" })
|
|
213540
213808
|
}
|
|
213541
213809
|
};
|
|
213810
|
+
var NativeCropRefSchema = zod.z.object({
|
|
213811
|
+
/** Handle keying the retained native surface (node-pinned to its owner). */
|
|
213812
|
+
handle: require_sleep.FrameHandleSchema,
|
|
213813
|
+
/** The parent crop's padded/clamped rectangle in FRAME-space pixels. */
|
|
213814
|
+
cropFrameSpace: zod.z.object({
|
|
213815
|
+
x: zod.z.number(),
|
|
213816
|
+
y: zod.z.number(),
|
|
213817
|
+
w: zod.z.number(),
|
|
213818
|
+
h: zod.z.number()
|
|
213819
|
+
})
|
|
213820
|
+
});
|
|
213821
|
+
zod.z.object({
|
|
213822
|
+
crop: zod.z.object({
|
|
213823
|
+
left: zod.z.number(),
|
|
213824
|
+
top: zod.z.number(),
|
|
213825
|
+
width: zod.z.number().positive(),
|
|
213826
|
+
height: zod.z.number().positive()
|
|
213827
|
+
}).optional(),
|
|
213828
|
+
content: zod.z.object({
|
|
213829
|
+
width: zod.z.number().int().positive(),
|
|
213830
|
+
height: zod.z.number().int().positive()
|
|
213831
|
+
}),
|
|
213832
|
+
fit: zod.z.enum(["stretch", "contain"]),
|
|
213833
|
+
format: zod.z.enum([
|
|
213834
|
+
"rgb",
|
|
213835
|
+
"gray",
|
|
213836
|
+
"jpeg"
|
|
213837
|
+
])
|
|
213838
|
+
});
|
|
213839
|
+
var FrameRefSchema = zod.z.object({
|
|
213840
|
+
registryId: zod.z.string().min(1),
|
|
213841
|
+
id: zod.z.string().min(1),
|
|
213842
|
+
width: zod.z.number().int().positive(),
|
|
213843
|
+
height: zod.z.number().int().positive(),
|
|
213844
|
+
format: zod.z.enum(["rgb", "gray"]),
|
|
213845
|
+
timestamp: zod.z.number(),
|
|
213846
|
+
capturedAt: zod.z.number().optional()
|
|
213847
|
+
});
|
|
213848
|
+
var ModelFormatSchema$1 = zod.z.enum([
|
|
213849
|
+
"onnx",
|
|
213850
|
+
"coreml",
|
|
213851
|
+
"openvino",
|
|
213852
|
+
"tflite",
|
|
213853
|
+
"pt",
|
|
213854
|
+
"gguf"
|
|
213855
|
+
]);
|
|
213856
|
+
var PipelineSlotSchema = zod.z.enum([
|
|
213857
|
+
"detector",
|
|
213858
|
+
"cropper",
|
|
213859
|
+
"classifier",
|
|
213860
|
+
"refiner",
|
|
213861
|
+
"audio-classifier"
|
|
213862
|
+
]);
|
|
213863
|
+
var PipelineEngineChoiceSchema = zod.z.object({
|
|
213864
|
+
runtime: zod.z.enum(["node", "python"]),
|
|
213865
|
+
backend: zod.z.string(),
|
|
213866
|
+
format: ModelFormatSchema$1,
|
|
213867
|
+
device: zod.z.string().optional()
|
|
213868
|
+
});
|
|
213869
|
+
var EngineDeviceInfoSchema = zod.z.object({
|
|
213870
|
+
id: zod.z.string(),
|
|
213871
|
+
label: zod.z.string(),
|
|
213872
|
+
description: zod.z.string().optional()
|
|
213873
|
+
});
|
|
213874
|
+
var AvailableEngineSchema = zod.z.object({
|
|
213875
|
+
engine: PipelineEngineChoiceSchema,
|
|
213876
|
+
devices: zod.z.array(EngineDeviceInfoSchema).readonly(),
|
|
213877
|
+
defaultDevice: zod.z.string()
|
|
213878
|
+
});
|
|
213879
|
+
var PipelineDefaultStepSchema = zod.z.lazy(() => zod.z.object({
|
|
213880
|
+
addonId: zod.z.string(),
|
|
213881
|
+
addonName: zod.z.string(),
|
|
213882
|
+
slot: PipelineSlotSchema,
|
|
213883
|
+
inputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
213884
|
+
outputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
213885
|
+
enabled: zod.z.boolean(),
|
|
213886
|
+
modelId: zod.z.string(),
|
|
213887
|
+
children: zod.z.array(PipelineDefaultStepSchema).readonly(),
|
|
213888
|
+
group: zod.z.string().optional(),
|
|
213889
|
+
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
213890
|
+
}));
|
|
213891
|
+
var PipelineTemplateStepSchema = zod.z.lazy(() => zod.z.object({
|
|
213892
|
+
addonId: zod.z.string(),
|
|
213893
|
+
enabled: zod.z.boolean(),
|
|
213894
|
+
modelId: zod.z.string(),
|
|
213895
|
+
children: zod.z.array(PipelineTemplateStepSchema).readonly(),
|
|
213896
|
+
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
213897
|
+
}));
|
|
213898
|
+
var PipelineTemplateSchema$1 = zod.z.object({
|
|
213899
|
+
id: zod.z.string(),
|
|
213900
|
+
name: zod.z.string(),
|
|
213901
|
+
createdAt: zod.z.string(),
|
|
213902
|
+
updatedAt: zod.z.string(),
|
|
213903
|
+
engine: PipelineEngineChoiceSchema,
|
|
213904
|
+
steps: zod.z.array(PipelineTemplateStepSchema).readonly()
|
|
213905
|
+
});
|
|
213906
|
+
var PipelineModelOptionSchema = zod.z.object({
|
|
213907
|
+
id: zod.z.string(),
|
|
213908
|
+
name: zod.z.string(),
|
|
213909
|
+
formats: zod.z.record(zod.z.string(), zod.z.object({
|
|
213910
|
+
downloaded: zod.z.boolean(),
|
|
213911
|
+
sizeMB: zod.z.number()
|
|
213912
|
+
})),
|
|
213913
|
+
group: ModelVariantGroupSchema.optional(),
|
|
213914
|
+
legacy: zod.z.boolean().optional(),
|
|
213915
|
+
provider: ModelProviderIdSchema.optional()
|
|
213916
|
+
});
|
|
213917
|
+
var ConfigFieldBridge = zod.z.custom();
|
|
213918
|
+
var PipelineAddonSchemaSchema = zod.z.object({
|
|
213919
|
+
id: zod.z.string(),
|
|
213920
|
+
name: zod.z.string(),
|
|
213921
|
+
slot: PipelineSlotSchema,
|
|
213922
|
+
inputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
213923
|
+
outputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
213924
|
+
childSlots: zod.z.array(PipelineSlotSchema).readonly(),
|
|
213925
|
+
models: zod.z.array(PipelineModelOptionSchema).readonly(),
|
|
213926
|
+
defaultModelId: zod.z.string(),
|
|
213927
|
+
defaultModelIdByFormat: zod.z.record(zod.z.string(), zod.z.string()).optional(),
|
|
213928
|
+
enabledByDefault: zod.z.boolean().optional(),
|
|
213929
|
+
backfillIntoExistingOverrides: zod.z.boolean().optional(),
|
|
213930
|
+
defaultConfidence: zod.z.number(),
|
|
213931
|
+
group: zod.z.string().optional(),
|
|
213932
|
+
configSchema: zod.z.array(ConfigFieldBridge).readonly().optional()
|
|
213933
|
+
});
|
|
213934
|
+
var PipelineSlotSchemaSchema = zod.z.object({
|
|
213935
|
+
id: PipelineSlotSchema,
|
|
213936
|
+
label: zod.z.string(),
|
|
213937
|
+
priority: zod.z.number(),
|
|
213938
|
+
parentSlot: PipelineSlotSchema.nullable(),
|
|
213939
|
+
addons: zod.z.array(PipelineAddonSchemaSchema).readonly()
|
|
213940
|
+
});
|
|
213941
|
+
var PipelineSchemaSchema = zod.z.object({
|
|
213942
|
+
availableEngines: zod.z.array(AvailableEngineSchema).readonly(),
|
|
213943
|
+
selectedEngine: PipelineEngineChoiceSchema,
|
|
213944
|
+
slots: zod.z.array(PipelineSlotSchemaSchema).readonly()
|
|
213945
|
+
});
|
|
213946
|
+
var EngineProvisioningSchema = zod.z.object({
|
|
213947
|
+
runtimeId: zod.z.enum([
|
|
213948
|
+
"onnx",
|
|
213949
|
+
"openvino",
|
|
213950
|
+
"coreml",
|
|
213951
|
+
"edgetpu"
|
|
213952
|
+
]).nullable(),
|
|
213953
|
+
device: zod.z.string().nullable(),
|
|
213954
|
+
state: zod.z.enum([
|
|
213955
|
+
"idle",
|
|
213956
|
+
"installing",
|
|
213957
|
+
"verifying",
|
|
213958
|
+
"ready",
|
|
213959
|
+
"failed"
|
|
213960
|
+
]),
|
|
213961
|
+
progress: zod.z.number().optional(),
|
|
213962
|
+
error: zod.z.string().optional(),
|
|
213963
|
+
nextRetryAt: zod.z.number().optional(),
|
|
213964
|
+
/**
|
|
213965
|
+
* Gate A (config-correctness gate at engine change): human-readable
|
|
213966
|
+
* config issues surfaced EAGERLY when the node's engine changes — model
|
|
213967
|
+
* substitutions ("chose X, running Y") and zero-build steps ("no model
|
|
213968
|
+
* has a <format> build"). Additive/optional: informational only, never
|
|
213969
|
+
* enforced here — `assertEngineReady` (readiness) still gates inference.
|
|
213970
|
+
* Absent/empty when the node-default tree resolves cleanly.
|
|
213971
|
+
*/
|
|
213972
|
+
configIssues: zod.z.array(zod.z.string()).optional()
|
|
213973
|
+
});
|
|
213974
|
+
var PipelineStepInputSchema = zod.z.lazy(() => zod.z.object({
|
|
213975
|
+
addonId: zod.z.string(),
|
|
213976
|
+
modelId: zod.z.string().optional(),
|
|
213977
|
+
enabled: zod.z.boolean().default(true),
|
|
213978
|
+
children: zod.z.array(PipelineStepInputSchema).optional(),
|
|
213979
|
+
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
213980
|
+
jumpDeviceKey: zod.z.string().optional()
|
|
213981
|
+
}));
|
|
213982
|
+
var ModelSubstitutionSchema = zod.z.object({
|
|
213983
|
+
addonId: zod.z.string(),
|
|
213984
|
+
chosen: zod.z.string(),
|
|
213985
|
+
running: zod.z.string(),
|
|
213986
|
+
format: zod.z.string()
|
|
213987
|
+
});
|
|
213988
|
+
var PipelineValidationIssueSchema = zod.z.object({
|
|
213989
|
+
addonId: zod.z.string(),
|
|
213990
|
+
kind: zod.z.enum(["unknown-addon", "no-format-build"]),
|
|
213991
|
+
detail: zod.z.string()
|
|
213992
|
+
});
|
|
213993
|
+
var PipelineValidationResultSchema = zod.z.object({
|
|
213994
|
+
ok: zod.z.boolean(),
|
|
213995
|
+
issues: zod.z.array(PipelineValidationIssueSchema).readonly(),
|
|
213996
|
+
substitutions: zod.z.array(ModelSubstitutionSchema).readonly(),
|
|
213997
|
+
/** The node's `currentEngine.format` this validation ran against. */
|
|
213998
|
+
format: zod.z.string()
|
|
213999
|
+
});
|
|
214000
|
+
var ReferenceImageEntrySchema = zod.z.object({
|
|
214001
|
+
filename: zod.z.string(),
|
|
214002
|
+
stepIds: zod.z.array(zod.z.string()).readonly().optional()
|
|
214003
|
+
});
|
|
214004
|
+
var ReferenceImageBodySchema = zod.z.object({
|
|
214005
|
+
base64: zod.z.string(),
|
|
214006
|
+
filename: zod.z.string()
|
|
214007
|
+
});
|
|
214008
|
+
var ReferenceAudioEntrySchema = zod.z.object({
|
|
214009
|
+
filename: zod.z.string(),
|
|
214010
|
+
sizeKb: zod.z.number()
|
|
214011
|
+
});
|
|
214012
|
+
var ReferenceAudioBodySchema = zod.z.object({ base64: zod.z.string() });
|
|
214013
|
+
var AudioBackendSchema = zod.z.object({
|
|
214014
|
+
id: zod.z.string(),
|
|
214015
|
+
name: zod.z.string(),
|
|
214016
|
+
description: zod.z.string(),
|
|
214017
|
+
available: zod.z.boolean(),
|
|
214018
|
+
/**
|
|
214019
|
+
* Raw classifier labels this backend can emit (e.g. YAMNet's
|
|
214020
|
+
* 521-class set or Apple SoundAnalysis's 303-class set). Used by
|
|
214021
|
+
* the benchmark UI to populate the `enabledMicroClasses` filter
|
|
214022
|
+
* specific to the selected backend without a separate fetch.
|
|
214023
|
+
*/
|
|
214024
|
+
rawLabels: zod.z.array(zod.z.string()).readonly().optional()
|
|
214025
|
+
});
|
|
214026
|
+
var AudioCapabilitiesSchema = zod.z.object({
|
|
214027
|
+
activeBackend: zod.z.string(),
|
|
214028
|
+
availableBackends: zod.z.array(AudioBackendSchema).readonly(),
|
|
214029
|
+
sampleRate: zod.z.number(),
|
|
214030
|
+
chunkDurationMs: zod.z.number()
|
|
214031
|
+
});
|
|
214032
|
+
var DownloadModelResultSchema = zod.z.object({
|
|
214033
|
+
filePath: zod.z.string(),
|
|
214034
|
+
sizeMB: zod.z.number(),
|
|
214035
|
+
durationMs: zod.z.number()
|
|
214036
|
+
});
|
|
214037
|
+
var AudioTestResultSchema = zod.z.object({
|
|
214038
|
+
success: zod.z.boolean(),
|
|
214039
|
+
error: zod.z.string().optional(),
|
|
214040
|
+
frame: zod.z.custom().optional()
|
|
214041
|
+
});
|
|
214042
|
+
var PipelineConfigBridge = zod.z.custom();
|
|
214043
|
+
var ConfigUISchemaBridge = zod.z.custom();
|
|
214044
|
+
var ConfigUISchemaNullableBridge = zod.z.custom();
|
|
214045
|
+
var InferenceCapabilitiesBridge = zod.z.custom();
|
|
214046
|
+
var ModelAvailabilityListBridge = zod.z.custom();
|
|
214047
|
+
var PipelineRunResultBridge = zod.z.custom();
|
|
214048
|
+
var pipelineExecutorCapability = {
|
|
214049
|
+
name: "pipeline-executor",
|
|
214050
|
+
scope: "system",
|
|
214051
|
+
mode: "singleton",
|
|
214052
|
+
methods: {
|
|
214053
|
+
getAvailableEngines: require_sleep.method(zod.z.void(), zod.z.array(PipelineEngineChoiceSchema)),
|
|
214054
|
+
getSelectedEngine: require_sleep.method(zod.z.void(), PipelineEngineChoiceSchema),
|
|
214055
|
+
getDefaultSteps: require_sleep.method(PipelineEngineChoiceSchema, zod.z.array(PipelineDefaultStepSchema)),
|
|
214056
|
+
/**
|
|
214057
|
+
* Per-node detection-engine provisioning snapshot. Returns the live
|
|
214058
|
+
* state of the lazy runtime-provisioning machine on `nodeId`
|
|
214059
|
+
* (idle / installing / verifying / ready / failed). The UI pairs this
|
|
214060
|
+
* one-shot query with the `pipeline.engine-provisioning` live event
|
|
214061
|
+
* (emitted on every transition) to drive a per-node "engine ready?"
|
|
214062
|
+
* indicator without polling. Phase 2.
|
|
214063
|
+
*/
|
|
214064
|
+
getEngineProvisioning: require_sleep.method(zod.z.object({ nodeId: zod.z.string() }), EngineProvisioningSchema),
|
|
214065
|
+
getVideoPipelineSteps: require_sleep.method(zod.z.void(), zod.z.record(zod.z.string(), zod.z.object({
|
|
214066
|
+
modelId: zod.z.string(),
|
|
214067
|
+
settings: zod.z.record(zod.z.string(), zod.z.unknown()).readonly()
|
|
214068
|
+
}))),
|
|
214069
|
+
setVideoPipelineSteps: require_sleep.method(zod.z.object({ steps: zod.z.record(zod.z.string(), zod.z.object({
|
|
214070
|
+
modelId: zod.z.string(),
|
|
214071
|
+
settings: zod.z.record(zod.z.string(), zod.z.unknown()).readonly()
|
|
214072
|
+
})) }), zod.z.object({ success: zod.z.literal(true) }), {
|
|
214073
|
+
kind: "mutation",
|
|
214074
|
+
auth: "admin"
|
|
214075
|
+
}),
|
|
214076
|
+
/**
|
|
214077
|
+
* Clear THIS node's executor-side PER-DEVICE settings stores (the
|
|
214078
|
+
* per-camera step overrides the object-detection root reads via
|
|
214079
|
+
* `applyDeviceOverridesToTree`). `nodeId` is the ROUTING key — the
|
|
214080
|
+
* generated cap-router strips it (default `nodeIdMode: 'routing'`) and
|
|
214081
|
+
* dispatches to that node, so the provider method runs ON the target
|
|
214082
|
+
* node and receives no `nodeId`.
|
|
214083
|
+
*
|
|
214084
|
+
* This is the slimmed executor leg of the orchestrator's
|
|
214085
|
+
* `resetNodePipelineDefaults` flow (which owns the real reset: node
|
|
214086
|
+
* addonDefaults pins + per-camera orchestrator overrides). The legacy
|
|
214087
|
+
* `resetToDefault` — which reset a persisted global step-tree seed
|
|
214088
|
+
* nothing in the live per-camera path read — was removed together with
|
|
214089
|
+
* that seed.
|
|
214090
|
+
*/
|
|
214091
|
+
clearDeviceOverrides: require_sleep.method(zod.z.object({ nodeId: zod.z.string() }), zod.z.object({
|
|
214092
|
+
success: zod.z.literal(true),
|
|
214093
|
+
clearedDevices: zod.z.number()
|
|
214094
|
+
}), {
|
|
214095
|
+
kind: "mutation",
|
|
214096
|
+
auth: "admin"
|
|
214097
|
+
}),
|
|
214098
|
+
/**
|
|
214099
|
+
* Which of THIS node's inference devices the executor currently refuses,
|
|
214100
|
+
* and why. `nodeId` is the ROUTING key (stripped by the generated router).
|
|
214101
|
+
*
|
|
214102
|
+
* The channel that did not exist. Pool health was known only inside the
|
|
214103
|
+
* detection addon and was an input to no routing decision anywhere: the
|
|
214104
|
+
* per-dispatch capability gate is keyed on model FORMAT and so can never
|
|
214105
|
+
* separate `openvino:gpu` from `openvino:npu`, and the orchestrator's live
|
|
214106
|
+
* eligibility probe (`platformProbe.getCapabilities`) answers about
|
|
214107
|
+
* HARDWARE — which was present throughout. So when the hub's `openvino:gpu`
|
|
214108
|
+
* Python worker was SIGABRT'd by the Intel GPU plugin on 2026-08-25, the
|
|
214109
|
+
* balancer went on handing that dead pool cameras by rotation for 31 hours:
|
|
214110
|
+
* ~370 000 `PoolWorker[w0]: not initialized` lines, every frame lost.
|
|
214111
|
+
*
|
|
214112
|
+
* Read semantics the caller depends on, and which the provider guarantees:
|
|
214113
|
+
* this is a synchronous read of in-memory state. It never probes hardware,
|
|
214114
|
+
* never spawns a pool and never throws — an EMPTY `unhealthy` means "asked,
|
|
214115
|
+
* nothing is refused", which is what re-admits a device. A read that FAILS
|
|
214116
|
+
* (node offline, version skew) must therefore be distinguishable from an
|
|
214117
|
+
* empty answer, and it is: it rejects.
|
|
214118
|
+
*/
|
|
214119
|
+
getInferenceDeviceHealth: require_sleep.method(zod.z.object({ nodeId: zod.z.string() }), zod.z.object({ unhealthy: zod.z.array(zod.z.object({
|
|
214120
|
+
/** `<backend>:<device>`, e.g. `openvino:gpu`. */
|
|
214121
|
+
deviceKey: zod.z.string(),
|
|
214122
|
+
/**
|
|
214123
|
+
* `failed` — the per-device restart budget is exhausted; no pool
|
|
214124
|
+
* will be spawned until an operator re-arms it or the runner
|
|
214125
|
+
* respawns. `backoff` — under budget, waiting out the backoff (or
|
|
214126
|
+
* a cached pool observed dead and not yet condemned).
|
|
214127
|
+
*/
|
|
214128
|
+
state: zod.z.enum(["failed", "backoff"]),
|
|
214129
|
+
/** Epoch ms of the death that produced this state. */
|
|
214130
|
+
since: zod.z.number(),
|
|
214131
|
+
/** Pool deaths inside the current window. */
|
|
214132
|
+
deaths: zod.z.number(),
|
|
214133
|
+
/** The last death's message. */
|
|
214134
|
+
lastError: zod.z.string()
|
|
214135
|
+
})).readonly() })),
|
|
214136
|
+
/**
|
|
214137
|
+
* Re-arm a terminally `failed` inference device on `nodeId`: forget its
|
|
214138
|
+
* restart budget so the next dispatch builds a fresh pool.
|
|
214139
|
+
*
|
|
214140
|
+
* The terminal state is deliberate (the abort it bounds is deterministic —
|
|
214141
|
+
* an automatic probation would just respawn Python forever, more slowly),
|
|
214142
|
+
* and a terminal state an operator cannot leave is a silent fault. This is
|
|
214143
|
+
* the way out. `rearmed:false` means there was nothing to forget.
|
|
214144
|
+
*/
|
|
214145
|
+
rearmInferenceDevice: require_sleep.method(zod.z.object({
|
|
214146
|
+
nodeId: zod.z.string(),
|
|
214147
|
+
deviceKey: zod.z.string()
|
|
214148
|
+
}), zod.z.object({ rearmed: zod.z.boolean() }), {
|
|
214149
|
+
kind: "mutation",
|
|
214150
|
+
auth: "admin"
|
|
214151
|
+
}),
|
|
214152
|
+
getSchema: require_sleep.method(zod.z.void(), PipelineSchemaSchema),
|
|
214153
|
+
getGlobalSteps: require_sleep.method(zod.z.void(), zod.z.array(PipelineDefaultStepSchema).readonly().nullable()),
|
|
214154
|
+
getGlobalPipelineConfig: require_sleep.method(zod.z.void(), PipelineConfigBridge),
|
|
214155
|
+
getOrchestratorConfigSchema: require_sleep.method(zod.z.void(), ConfigUISchemaBridge),
|
|
214156
|
+
/**
|
|
214157
|
+
* Gate B (pre-init config-correctness gate). PURE COMPUTE against this
|
|
214158
|
+
* node's `currentEngine.format` — resolves `steps` the same way the
|
|
214159
|
+
* runtime dispatch path would, and reports what WOULD happen without
|
|
214160
|
+
* touching any node-global state. Called by the orchestrator at attach
|
|
214161
|
+
* time (`attachOn`), node-pinned to the TARGET node, so config problems
|
|
214162
|
+
* surface BEFORE `pipelineRunner.attachCamera` rather than at the first
|
|
214163
|
+
* per-frame resolve. `ok` is false iff `issues` is non-empty (both
|
|
214164
|
+
* `unknown-addon` and `no-format-build` are HARD issues); `substitutions`
|
|
214165
|
+
* is informational (a degraded-but-loadable model swap) and never
|
|
214166
|
+
* affects `ok`. Never throws.
|
|
214167
|
+
*/
|
|
214168
|
+
validatePipeline: require_sleep.method(zod.z.object({ steps: zod.z.array(PipelineStepInputSchema) }), PipelineValidationResultSchema),
|
|
214169
|
+
listTemplates: require_sleep.method(zod.z.void(), zod.z.array(PipelineTemplateSchema$1).readonly()),
|
|
214170
|
+
saveTemplate: require_sleep.method(zod.z.object({
|
|
214171
|
+
name: zod.z.string(),
|
|
214172
|
+
steps: zod.z.array(PipelineTemplateStepSchema).readonly(),
|
|
214173
|
+
engine: PipelineEngineChoiceSchema
|
|
214174
|
+
}), PipelineTemplateSchema$1, { kind: "mutation" }),
|
|
214175
|
+
updateTemplate: require_sleep.method(zod.z.object({
|
|
214176
|
+
id: zod.z.string(),
|
|
214177
|
+
name: zod.z.string().optional(),
|
|
214178
|
+
steps: zod.z.array(PipelineTemplateStepSchema).readonly().optional()
|
|
214179
|
+
}), PipelineTemplateSchema$1, { kind: "mutation" }),
|
|
214180
|
+
deleteTemplate: require_sleep.method(zod.z.object({ id: zod.z.string() }), zod.z.void(), { kind: "mutation" }),
|
|
214181
|
+
getCapabilities: require_sleep.method(zod.z.void(), InferenceCapabilitiesBridge),
|
|
214182
|
+
getAddonModels: require_sleep.method(zod.z.object({ addonId: zod.z.string() }), ModelAvailabilityListBridge),
|
|
214183
|
+
downloadModel: require_sleep.method(zod.z.object({
|
|
214184
|
+
addonId: zod.z.string(),
|
|
214185
|
+
modelId: zod.z.string(),
|
|
214186
|
+
format: ModelFormatSchema$1
|
|
214187
|
+
}), DownloadModelResultSchema, { kind: "mutation" }),
|
|
214188
|
+
deleteModel: require_sleep.method(zod.z.object({
|
|
214189
|
+
addonId: zod.z.string(),
|
|
214190
|
+
modelId: zod.z.string(),
|
|
214191
|
+
format: ModelFormatSchema$1
|
|
214192
|
+
}), zod.z.object({ success: zod.z.literal(true) }), { kind: "mutation" }),
|
|
214193
|
+
/**
|
|
214194
|
+
* Stateless single-frame execution. Callers (runner, benchmark) pass
|
|
214195
|
+
* the complete `engine` + `steps` tree; the executor holds no state
|
|
214196
|
+
* about cameras or saved pipelines.
|
|
214197
|
+
*
|
|
214198
|
+
* `engine` is optional during the migration window to preserve the
|
|
214199
|
+
* legacy call shape used by existing benchmark code; once all
|
|
214200
|
+
* callers pass it explicitly we make it required.
|
|
214201
|
+
*
|
|
214202
|
+
* Exactly one of `frame`, `frameRef`, `frameHandle`, `imageBase64`,
|
|
214203
|
+
* `referenceImage` must be provided:
|
|
214204
|
+
* - `frame`: runtime dispatch path (runner → decoded broker frame).
|
|
214205
|
+
* Carries the raw buffer, dimensions, and format; the executor
|
|
214206
|
+
* uses it directly without base64 round-tripping.
|
|
214207
|
+
* - `frameHandle` (CB5): a zero-pixel shm `FrameHandle` for the SAME
|
|
214208
|
+
* decoded frame. Both runner and executor are hub-local processes
|
|
214209
|
+
* sharing `/dev/shm`, so the executor maps the named segment and
|
|
214210
|
+
* reads the pixels back zero-copy — eliminating the ~1.2MB
|
|
214211
|
+
* re-serialisation over UDS/MsgPack the `frame` path pays per call.
|
|
214212
|
+
* High-risk: the FrameRing is a latest-wins seqlock with no
|
|
214213
|
+
* refcount, so a recycled slot yields a null read; the executor
|
|
214214
|
+
* then degrades to an empty result and the runner ships pixels via
|
|
214215
|
+
* `frame` as the fallback (queue-depth gated on the runner side).
|
|
214216
|
+
* - `imageBase64`: one-shot test path (benchmark ImageTab).
|
|
214217
|
+
* - `referenceImage`: named file from the reference-image store.
|
|
214218
|
+
*/
|
|
214219
|
+
runPipeline: require_sleep.method(zod.z.object({
|
|
214220
|
+
engine: PipelineEngineChoiceSchema.optional(),
|
|
214221
|
+
steps: zod.z.array(PipelineStepInputSchema).min(1),
|
|
214222
|
+
frame: FrameInputSchema.optional(),
|
|
214223
|
+
/**
|
|
214224
|
+
* Process-local lazy frame. Valid only when caller and provider resolve
|
|
214225
|
+
* in the same execution-group process; split/cross-node callers use
|
|
214226
|
+
* `frame`/`image` inline compatibility instead.
|
|
214227
|
+
*/
|
|
214228
|
+
frameRef: FrameRefSchema.optional(),
|
|
214229
|
+
/**
|
|
214230
|
+
* CB5 shm passthrough — a `FrameHandle` naming the same ring slot
|
|
214231
|
+
* the decoded pixels live in. One more member of the one-of
|
|
214232
|
+
* frame/frameHandle/image/imageBase64/referenceImage group.
|
|
214233
|
+
*/
|
|
214234
|
+
frameHandle: require_sleep.FrameHandleSchema.optional(),
|
|
214235
|
+
imageBase64: zod.z.string().optional(),
|
|
214236
|
+
/**
|
|
214237
|
+
* Binary JPEG bytes — preferred over `imageBase64` on internal
|
|
214238
|
+
* hops (hub → forked worker via Moleculer MsgPack) because it
|
|
214239
|
+
* skips the 33% base64 overhead + the per-call base64 decode on
|
|
214240
|
+
* the detection-pipeline worker. Callers can pass either; exactly
|
|
214241
|
+
* one of `frame`/`image`/`imageBase64`/`referenceImage` is required.
|
|
214242
|
+
*/
|
|
214243
|
+
image: zod.z.instanceof(Uint8Array).optional(),
|
|
214244
|
+
referenceImage: zod.z.string().optional(),
|
|
214245
|
+
deviceId: zod.z.number().optional(),
|
|
214246
|
+
sessionId: zod.z.string().optional(),
|
|
214247
|
+
/**
|
|
214248
|
+
* Execution plane. 'full' (default) runs the whole tree — benchmark,
|
|
214249
|
+
* reference-image, and detail-subtree calls. 'frame' is the live
|
|
214250
|
+
* per-frame dispatch: ONLY root-plane steps run; crop children
|
|
214251
|
+
* (inputClasses ≠ null) are skipped and served per-track via
|
|
214252
|
+
* pipelineRunner.runDetailSubtree (two-plane design).
|
|
214253
|
+
*/
|
|
214254
|
+
plane: zod.z.enum(["full", "frame"]).optional(),
|
|
214255
|
+
/**
|
|
214256
|
+
* Inference-device selector (Phase 2 multi-device). Format
|
|
214257
|
+
* `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
|
|
214258
|
+
* Omitted ⇒ the runner's default device (current single-engine
|
|
214259
|
+
* behaviour). Selects WHICH device pool of the node runs the call.
|
|
214260
|
+
*/
|
|
214261
|
+
deviceKey: zod.z.string().optional(),
|
|
214262
|
+
/**
|
|
214263
|
+
* Two-plane NATIVE child-crop reference. Set by `runDetailSubtree` ONLY
|
|
214264
|
+
* when the parent crop was resolved from the frame's retained NATIVE
|
|
214265
|
+
* surface (a frameHandle HIT). Lets the executor re-cut a LEAF crop
|
|
214266
|
+
* child's ROI (plate-ocr, face-embedding, leaf classifiers) at native
|
|
214267
|
+
* resolution from that surface — the SAME quality path faces already
|
|
214268
|
+
* had — instead of the downscaled parent tile. `handle` keys the native
|
|
214269
|
+
* surface (node-pinned to its owner); `cropFrameSpace` is the parent
|
|
214270
|
+
* crop's padded/clamped rectangle in FRAME-space pixels, used to compose
|
|
214271
|
+
* the executor's crop-normalized child ROI back into frame-normalized
|
|
214272
|
+
* coordinates. Auxiliary to the image source (`image`/`frame`/…), NOT one
|
|
214273
|
+
* of the mutually-exclusive image inputs. Absent ⇒ tile-crop children
|
|
214274
|
+
* (today's behaviour on the fallback path).
|
|
214275
|
+
*/
|
|
214276
|
+
nativeCropRef: NativeCropRefSchema.optional()
|
|
214277
|
+
}), PipelineRunResultBridge, { kind: "mutation" }),
|
|
214278
|
+
/**
|
|
214279
|
+
* Batched run — N raw frames packed into one cap call. The provider
|
|
214280
|
+
* routes the batch through `SharedInferencePool.inferBatch`
|
|
214281
|
+
* (`MSG_INFER_BATCH = 0x03`) so the IPC framing and JSON response
|
|
214282
|
+
* envelope cost is amortised N:1 vs N concurrent `runPipeline`
|
|
214283
|
+
* calls. Single root step + uniform model assumed; trees with crop
|
|
214284
|
+
* children fall back to sequential execution.
|
|
214285
|
+
*
|
|
214286
|
+
* Used by `scripts/bench-batch-style.mts` for batch benchmarking —
|
|
214287
|
+
* N frames in one call to amortise per-call IPC overhead.
|
|
214288
|
+
*/
|
|
214289
|
+
runPipelineBatch: require_sleep.method(zod.z.object({
|
|
214290
|
+
engine: PipelineEngineChoiceSchema.optional(),
|
|
214291
|
+
steps: zod.z.array(PipelineStepInputSchema).min(1),
|
|
214292
|
+
frames: zod.z.array(FrameInputSchema).min(1).max(255),
|
|
214293
|
+
deviceId: zod.z.number().optional(),
|
|
214294
|
+
sessionId: zod.z.string().optional(),
|
|
214295
|
+
/**
|
|
214296
|
+
* Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
|
|
214297
|
+
* the batch to the Python pool's bench preprocess cache
|
|
214298
|
+
* (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
|
|
214299
|
+
* preprocessed ONCE and every later inference is a pure-inference cache
|
|
214300
|
+
* hit — the sustained-throughput run measures inference, not
|
|
214301
|
+
* decode+preprocess+infer. Omitted/0 for live frames (all different →
|
|
214302
|
+
* full preprocess every call, correct). Fresh per sustained run;
|
|
214303
|
+
* released via `uncacheFrame`.
|
|
214304
|
+
*/
|
|
214305
|
+
frameId: zod.z.number().int().nonnegative().optional(),
|
|
214306
|
+
/** Inference-device selector (Phase 2 multi-device); see runPipeline. */
|
|
214307
|
+
deviceKey: zod.z.string().optional()
|
|
214308
|
+
}), zod.z.object({ results: zod.z.array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }),
|
|
214309
|
+
/**
|
|
214310
|
+
* Cache a raw frame inside the Python inference pool's memory.
|
|
214311
|
+
* Returns a numeric `frameId` that `inferCached` references —
|
|
214312
|
+
* subsequent calls send only 5 bytes through the pipe instead of
|
|
214313
|
+
* 1.2MB raw data, eliminating the pipe transfer bottleneck.
|
|
214314
|
+
*/
|
|
214315
|
+
cacheFrameInPool: require_sleep.method(zod.z.object({
|
|
214316
|
+
data: zod.z.instanceof(Uint8Array),
|
|
214317
|
+
width: zod.z.number().int().positive(),
|
|
214318
|
+
height: zod.z.number().int().positive(),
|
|
214319
|
+
format: zod.z.enum([
|
|
214320
|
+
"rgb",
|
|
214321
|
+
"bgr",
|
|
214322
|
+
"gray"
|
|
214323
|
+
])
|
|
214324
|
+
}), zod.z.object({
|
|
214325
|
+
frameId: zod.z.number(),
|
|
214326
|
+
width: zod.z.number(),
|
|
214327
|
+
height: zod.z.number()
|
|
214328
|
+
}), { kind: "mutation" }),
|
|
214329
|
+
/**
|
|
214330
|
+
* Run inference on a previously cached frame. Sends only 5 bytes
|
|
214331
|
+
* (model_idx + frameId) through the IPC pipe — eliminates the
|
|
214332
|
+
* ~35ms per-call overhead of transferring 1.2MB raw data.
|
|
214333
|
+
*/
|
|
214334
|
+
inferCached: require_sleep.method(zod.z.object({
|
|
214335
|
+
stepId: zod.z.string(),
|
|
214336
|
+
frameId: zod.z.number().int()
|
|
214337
|
+
}), zod.z.record(zod.z.string(), zod.z.unknown()), { kind: "mutation" }),
|
|
214338
|
+
/**
|
|
214339
|
+
* Release a cached frame from the Python pool's memory.
|
|
214340
|
+
*/
|
|
214341
|
+
uncacheFrame: require_sleep.method(zod.z.object({ frameId: zod.z.number().int() }), zod.z.void(), { kind: "mutation" }),
|
|
214342
|
+
/** Returns the effective pool tuning (resolved from user overrides + backend defaults). */
|
|
214343
|
+
getEffectiveTuning: require_sleep.method(zod.z.void(), zod.z.object({
|
|
214344
|
+
batchMode: zod.z.string(),
|
|
214345
|
+
windowMs: zod.z.number(),
|
|
214346
|
+
maxBatchSize: zod.z.number(),
|
|
214347
|
+
concurrency: zod.z.number()
|
|
214348
|
+
})),
|
|
214349
|
+
/**
|
|
214350
|
+
* List every EngineFactory currently loaded in this executor's RAM,
|
|
214351
|
+
* with the models resident and a coarse "in use" marker derived from
|
|
214352
|
+
* ongoing inference activity. Used by the Pipeline page Engines tab.
|
|
214353
|
+
*/
|
|
214354
|
+
listLoadedEngines: require_sleep.method(zod.z.void(), zod.z.array(zod.z.object({
|
|
214355
|
+
engineKey: zod.z.string(),
|
|
214356
|
+
engine: PipelineEngineChoiceSchema,
|
|
214357
|
+
modelsLoaded: zod.z.array(zod.z.string()).readonly(),
|
|
214358
|
+
inUseByCameras: zod.z.array(zod.z.number()).readonly(),
|
|
214359
|
+
/**
|
|
214360
|
+
* Origin of this resident factory.
|
|
214361
|
+
* - `runtime` — main camera-serving engine (no idle TTL).
|
|
214362
|
+
* - `warm-override` — benchmark/test override held in the warm
|
|
214363
|
+
* cache; auto-disposed after the idle TTL.
|
|
214364
|
+
* - `device-pool` — a concurrent per-device pool (Phase 2
|
|
214365
|
+
* multi-device, keyed by `deviceKey`) resolved
|
|
214366
|
+
* via `resolveDeviceFactory`. Runs alongside the
|
|
214367
|
+
* `runtime` engine on a DIFFERENT accelerator
|
|
214368
|
+
* (NPU / iGPU / Coral) — this is how the
|
|
214369
|
+
* Engines tab shows all pools running at once.
|
|
214370
|
+
*/
|
|
214371
|
+
kind: zod.z.enum([
|
|
214372
|
+
"runtime",
|
|
214373
|
+
"warm-override",
|
|
214374
|
+
"device-pool"
|
|
214375
|
+
]),
|
|
214376
|
+
/** Native pid of the underlying Python pool (null when no pool). */
|
|
214377
|
+
poolPid: zod.z.number().nullable(),
|
|
214378
|
+
/** ms since this factory was last used (null when not warm-tracked). */
|
|
214379
|
+
idleMs: zod.z.number().nullable(),
|
|
214380
|
+
/** Idle TTL after which `warm-override` factories self-evict (null when not applicable). */
|
|
214381
|
+
idleTtlMs: zod.z.number().nullable()
|
|
214382
|
+
})).readonly()),
|
|
214383
|
+
/** Warm up an engine without running a frame. No-op if already loaded. */
|
|
214384
|
+
spinEngine: require_sleep.method(zod.z.object({ engine: PipelineEngineChoiceSchema }), zod.z.object({ success: zod.z.literal(true) }), {
|
|
214385
|
+
kind: "mutation",
|
|
214386
|
+
auth: "admin"
|
|
214387
|
+
}),
|
|
214388
|
+
/**
|
|
214389
|
+
* Unload an engine from RAM. `force:true` unloads even when cameras
|
|
214390
|
+
* are actively using it (they re-spin on next frame). Default is
|
|
214391
|
+
* gated — returns `{success:false, reason}` when in use.
|
|
214392
|
+
*/
|
|
214393
|
+
killEngine: require_sleep.method(zod.z.object({
|
|
214394
|
+
engine: PipelineEngineChoiceSchema,
|
|
214395
|
+
force: zod.z.boolean().optional()
|
|
214396
|
+
}), zod.z.object({
|
|
214397
|
+
success: zod.z.boolean(),
|
|
214398
|
+
reason: zod.z.string().optional()
|
|
214399
|
+
}), {
|
|
214400
|
+
kind: "mutation",
|
|
214401
|
+
auth: "admin"
|
|
214402
|
+
}),
|
|
214403
|
+
listReferenceImages: require_sleep.method(zod.z.void(), zod.z.array(ReferenceImageEntrySchema).readonly()),
|
|
214404
|
+
getReferenceImage: require_sleep.method(zod.z.object({ filename: zod.z.string() }), ReferenceImageBodySchema.nullable()),
|
|
214405
|
+
getReferenceAudioFiles: require_sleep.method(zod.z.void(), zod.z.array(ReferenceAudioEntrySchema).readonly()),
|
|
214406
|
+
getReferenceAudio: require_sleep.method(zod.z.object({ filename: zod.z.string() }), ReferenceAudioBodySchema.nullable()),
|
|
214407
|
+
getAudioCapabilities: require_sleep.method(zod.z.void(), AudioCapabilitiesSchema),
|
|
214408
|
+
runAudioTest: require_sleep.method(zod.z.object({
|
|
214409
|
+
addonId: zod.z.string(),
|
|
214410
|
+
modelId: zod.z.string(),
|
|
214411
|
+
filename: zod.z.string().optional(),
|
|
214412
|
+
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
214413
|
+
}), AudioTestResultSchema, { kind: "mutation" }),
|
|
214414
|
+
getDetectionConfigSchema: require_sleep.method(zod.z.void(), ConfigUISchemaNullableBridge)
|
|
214415
|
+
}
|
|
214416
|
+
};
|
|
214417
|
+
var ZoneRuleModeEnum = zod.z.enum(["include", "exclude"]);
|
|
214418
|
+
var ZoneRuleSchema = zod.z.object({
|
|
214419
|
+
/** Stable rule id — survives edits, used by the UI for diffing. */
|
|
214420
|
+
id: zod.z.string(),
|
|
214421
|
+
/** Optional human-readable label rendered in the rule editor. */
|
|
214422
|
+
name: zod.z.string().optional(),
|
|
214423
|
+
/** Zones this rule targets. The rule's `mode` applies to ALL
|
|
214424
|
+
* listed zones (OR-set: a detection in any one of them counts).
|
|
214425
|
+
* At least one zone id required — a rule with no targets is a
|
|
214426
|
+
* configuration mistake and the form validator rejects it. */
|
|
214427
|
+
zoneIds: zod.z.array(zod.z.string()).min(1).readonly(),
|
|
214428
|
+
mode: ZoneRuleModeEnum,
|
|
214429
|
+
/**
|
|
214430
|
+
* Class names this rule applies to. Empty / undefined ⇒ rule
|
|
214431
|
+
* applies to every class. Class strings match the `macroClass`
|
|
214432
|
+
* field on detections (e.g. `person`, `car`, `dog`).
|
|
214433
|
+
*/
|
|
214434
|
+
classFilter: zod.z.array(zod.z.string()).readonly().optional(),
|
|
214435
|
+
/**
|
|
214436
|
+
* Minimum bbox/mask overlap (0–1) with any of the rule's zones
|
|
214437
|
+
* required to consider an entity "in the zone". Defaults to the
|
|
214438
|
+
* consumer's stage default when omitted. Kept for back-compat with
|
|
214439
|
+
* existing per-rule overrides; new operators pick the value via
|
|
214440
|
+
* `bboxInclusionPct` (operator-friendly 0–100). Whichever field is
|
|
214441
|
+
* set, the lower-level engine reads it as a 0–1 fraction.
|
|
214442
|
+
*/
|
|
214443
|
+
overlapThreshold: zod.z.number().min(0).max(1).optional(),
|
|
214444
|
+
/**
|
|
214445
|
+
* Operator-friendly version of `overlapThreshold` — the percentage
|
|
214446
|
+
* of the detection's bbox that must lie inside the zone for the
|
|
214447
|
+
* rule to match. Documented default is 85%; the engine substitutes
|
|
214448
|
+
* that when the field is omitted (kept optional so existing rules
|
|
214449
|
+
* stored without it stay valid).
|
|
214450
|
+
*
|
|
214451
|
+
* When BOTH `overlapThreshold` and `bboxInclusionPct` are set on a
|
|
214452
|
+
* rule, the engine prefers `bboxInclusionPct` because it's the
|
|
214453
|
+
* field exposed in the UI. Internally both feed the same gate.
|
|
214454
|
+
*/
|
|
214455
|
+
bboxInclusionPct: zod.z.number().min(0).max(100).optional(),
|
|
214456
|
+
/**
|
|
214457
|
+
* When `true` and a detection has a segmentation mask, use the
|
|
214458
|
+
* mask for overlap instead of the bbox. Detection-stage only;
|
|
214459
|
+
* motion rules ignore this field.
|
|
214460
|
+
*/
|
|
214461
|
+
preferMask: zod.z.boolean().optional(),
|
|
214462
|
+
/**
|
|
214463
|
+
* Soft-toggle: `false` disables the rule without deleting it.
|
|
214464
|
+
* Defaults to `true` so operators creating a rule via the UI
|
|
214465
|
+
* see it active immediately.
|
|
214466
|
+
*/
|
|
214467
|
+
enabled: zod.z.boolean().default(true)
|
|
214468
|
+
});
|
|
214469
|
+
var ZoneRulesArraySchema = zod.z.array(ZoneRuleSchema).readonly();
|
|
214470
|
+
var ZoneKindEnum = zod.z.enum(["polygon", "tripwire"]);
|
|
214471
|
+
var PolygonPointSchema = zod.z.object({
|
|
214472
|
+
x: zod.z.number(),
|
|
214473
|
+
y: zod.z.number()
|
|
214474
|
+
});
|
|
214475
|
+
var ZoneSchema = zod.z.object({
|
|
214476
|
+
id: zod.z.string(),
|
|
214477
|
+
name: zod.z.string(),
|
|
214478
|
+
kind: ZoneKindEnum.default("polygon"),
|
|
214479
|
+
/** Polygon vertices, fraction of frame (0–1). */
|
|
214480
|
+
polygon: zod.z.array(PolygonPointSchema).readonly(),
|
|
214481
|
+
/** Visual color for UI rendering. */
|
|
214482
|
+
color: zod.z.string().default("#3b82f6")
|
|
214483
|
+
});
|
|
214484
|
+
var zonesCapability = {
|
|
214485
|
+
name: "zones",
|
|
214486
|
+
scope: "device",
|
|
214487
|
+
mode: "singleton",
|
|
214488
|
+
deviceTypes: [require_sleep.DeviceType.Camera],
|
|
214489
|
+
methods: {
|
|
214490
|
+
listZones: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), zod.z.array(ZoneSchema).readonly()),
|
|
214491
|
+
addZone: require_sleep.method(zod.z.object({
|
|
214492
|
+
deviceId: zod.z.number(),
|
|
214493
|
+
zone: ZoneSchema
|
|
214494
|
+
}), zod.z.void(), {
|
|
214495
|
+
kind: "mutation",
|
|
214496
|
+
auth: "admin"
|
|
214497
|
+
}),
|
|
214498
|
+
removeZone: require_sleep.method(zod.z.object({
|
|
214499
|
+
deviceId: zod.z.number(),
|
|
214500
|
+
zoneId: zod.z.string()
|
|
214501
|
+
}), zod.z.void(), {
|
|
214502
|
+
kind: "mutation",
|
|
214503
|
+
auth: "admin"
|
|
214504
|
+
}),
|
|
214505
|
+
updateZone: require_sleep.method(zod.z.object({
|
|
214506
|
+
deviceId: zod.z.number(),
|
|
214507
|
+
zone: ZoneSchema
|
|
214508
|
+
}), zod.z.void(), {
|
|
214509
|
+
kind: "mutation",
|
|
214510
|
+
auth: "admin"
|
|
214511
|
+
})
|
|
214512
|
+
},
|
|
214513
|
+
/**
|
|
214514
|
+
* Runtime-state slice — the live zone catalogue mirrored by the
|
|
214515
|
+
* orchestrator on every CRUD mutation. Consumers read via
|
|
214516
|
+
* `device.state.zones.value` / `.watch(...)` without round-tripping
|
|
214517
|
+
* the cap, and the codegen DeviceProxy auto-wires the reactive
|
|
214518
|
+
* handle. Slice shape is `{ zones: Zone[] }` so future extensions
|
|
214519
|
+
* (e.g. zone groupings) can sit alongside the polygon list.
|
|
214520
|
+
*/
|
|
214521
|
+
runtimeState: zod.z.object({ zones: zod.z.array(ZoneSchema).readonly() }),
|
|
214522
|
+
/**
|
|
214523
|
+
* Runtime-state durability: **restored** — written only on operator mutation, so a camera that never had one has nothing to re-derive from. This is the slice `zone-mirror-hydration.ts` exists to paper over.
|
|
214524
|
+
*
|
|
214525
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
214526
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
214527
|
+
*/
|
|
214528
|
+
durability: "restored"
|
|
214529
|
+
};
|
|
213542
214530
|
var TrackStateSchema = zod.z.enum([
|
|
213543
214531
|
"new",
|
|
213544
214532
|
"entered",
|
|
@@ -214359,6 +215347,25 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
214359
215347
|
/** Present when the pass ended by throwing. */
|
|
214360
215348
|
error: zod.z.string().nullable()
|
|
214361
215349
|
});
|
|
215350
|
+
var ReplayFrameInputSchema = zod.z.object({
|
|
215351
|
+
timestamp: zod.z.number(),
|
|
215352
|
+
frame: PipelineRunResultBridge
|
|
215353
|
+
});
|
|
215354
|
+
var ReplayTrackSchema = zod.z.object({
|
|
215355
|
+
className: zod.z.string(),
|
|
215356
|
+
firstSeenMs: zod.z.number(),
|
|
215357
|
+
lastSeenMs: zod.z.number(),
|
|
215358
|
+
/** Bbox of the track's FIRST matched detection, pixel-space in the clip's
|
|
215359
|
+
* frame — a representative box for the diff's `(className, window, IoU)`
|
|
215360
|
+
* pairing (`replay-diff.ts`). A replay does not need the full per-frame
|
|
215361
|
+
* trajectory production's `Track.positions` keeps. */
|
|
215362
|
+
bbox: BoundingBoxSchema,
|
|
215363
|
+
/** How many of the input frames this track matched a real detection on
|
|
215364
|
+
* (never a coasted/extrapolated frame) — the replay's own signal for "how
|
|
215365
|
+
* solid is this track", cheaper than re-deriving it from a trajectory. */
|
|
215366
|
+
framesMatched: zod.z.number().int()
|
|
215367
|
+
});
|
|
215368
|
+
var RunReplayFrameProcessorResultSchema = zod.z.object({ tracks: zod.z.array(ReplayTrackSchema).readonly() });
|
|
214362
215369
|
var pipelineAnalyticsCapability = {
|
|
214363
215370
|
name: "pipeline-analytics",
|
|
214364
215371
|
scope: "device",
|
|
@@ -214849,6 +215856,32 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
214849
215856
|
kind: "mutation",
|
|
214850
215857
|
auth: "admin"
|
|
214851
215858
|
}),
|
|
215859
|
+
/**
|
|
215860
|
+
* The FrameProcessor pass of a replay run — see the `Replay` section
|
|
215861
|
+
* above this capability's definition for why this is not the
|
|
215862
|
+
* `processFrame` method this file's header says pipeline-analytics does
|
|
215863
|
+
* not have.
|
|
215864
|
+
*
|
|
215865
|
+
* Constructs a FRESH `FrameProcessor` for `(deviceId, source)`, feeds it
|
|
215866
|
+
* `frames` IN THE ORDER GIVEN (the caller is responsible for time
|
|
215867
|
+
* ordering — this method does not sort), and returns the tracks it
|
|
215868
|
+
* produced. Zero persistence: no `TrackStore`, no event bus, no media
|
|
215869
|
+
* capture. `zones` / `detectionRules` are the run's OWN zone set —
|
|
215870
|
+
* typically the camera's real zones plus an ephemeral overlay
|
|
215871
|
+
* (`addon-benchmark`'s `replay-plan.ts`), never read from or written to
|
|
215872
|
+
* the `zones` capability by this method itself.
|
|
215873
|
+
*/
|
|
215874
|
+
runReplayFrameProcessor: require_sleep.method(zod.z.object({
|
|
215875
|
+
deviceId: zod.z.number(),
|
|
215876
|
+
source: DetectionSourceSchema,
|
|
215877
|
+
zones: zod.z.array(ZoneSchema).readonly().optional(),
|
|
215878
|
+
detectionRules: zod.z.array(ZoneRuleSchema).readonly().optional(),
|
|
215879
|
+
zoneMembershipMinOverlap: zod.z.number().min(0).max(1).optional(),
|
|
215880
|
+
frames: zod.z.array(ReplayFrameInputSchema).min(1)
|
|
215881
|
+
}), RunReplayFrameProcessorResultSchema, {
|
|
215882
|
+
kind: "mutation",
|
|
215883
|
+
auth: "admin"
|
|
215884
|
+
}),
|
|
214852
215885
|
/** Every annotation on a track, oldest first. */
|
|
214853
215886
|
listRetrainAnnotations: require_sleep.method(zod.z.object({ trackId: zod.z.string() }), zod.z.array(RetrainAnnotationSchema).readonly(), {
|
|
214854
215887
|
kind: "query",
|
|
@@ -215015,559 +216048,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
215015
216048
|
}) }
|
|
215016
216049
|
}
|
|
215017
216050
|
};
|
|
215018
|
-
var NativeCropRefSchema = zod.z.object({
|
|
215019
|
-
/** Handle keying the retained native surface (node-pinned to its owner). */
|
|
215020
|
-
handle: require_sleep.FrameHandleSchema,
|
|
215021
|
-
/** The parent crop's padded/clamped rectangle in FRAME-space pixels. */
|
|
215022
|
-
cropFrameSpace: zod.z.object({
|
|
215023
|
-
x: zod.z.number(),
|
|
215024
|
-
y: zod.z.number(),
|
|
215025
|
-
w: zod.z.number(),
|
|
215026
|
-
h: zod.z.number()
|
|
215027
|
-
})
|
|
215028
|
-
});
|
|
215029
|
-
zod.z.object({
|
|
215030
|
-
crop: zod.z.object({
|
|
215031
|
-
left: zod.z.number(),
|
|
215032
|
-
top: zod.z.number(),
|
|
215033
|
-
width: zod.z.number().positive(),
|
|
215034
|
-
height: zod.z.number().positive()
|
|
215035
|
-
}).optional(),
|
|
215036
|
-
content: zod.z.object({
|
|
215037
|
-
width: zod.z.number().int().positive(),
|
|
215038
|
-
height: zod.z.number().int().positive()
|
|
215039
|
-
}),
|
|
215040
|
-
fit: zod.z.enum(["stretch", "contain"]),
|
|
215041
|
-
format: zod.z.enum([
|
|
215042
|
-
"rgb",
|
|
215043
|
-
"gray",
|
|
215044
|
-
"jpeg"
|
|
215045
|
-
])
|
|
215046
|
-
});
|
|
215047
|
-
var FrameRefSchema = zod.z.object({
|
|
215048
|
-
registryId: zod.z.string().min(1),
|
|
215049
|
-
id: zod.z.string().min(1),
|
|
215050
|
-
width: zod.z.number().int().positive(),
|
|
215051
|
-
height: zod.z.number().int().positive(),
|
|
215052
|
-
format: zod.z.enum(["rgb", "gray"]),
|
|
215053
|
-
timestamp: zod.z.number(),
|
|
215054
|
-
capturedAt: zod.z.number().optional()
|
|
215055
|
-
});
|
|
215056
|
-
var ModelFormatSchema$1 = zod.z.enum([
|
|
215057
|
-
"onnx",
|
|
215058
|
-
"coreml",
|
|
215059
|
-
"openvino",
|
|
215060
|
-
"tflite",
|
|
215061
|
-
"pt",
|
|
215062
|
-
"gguf"
|
|
215063
|
-
]);
|
|
215064
|
-
var PipelineSlotSchema = zod.z.enum([
|
|
215065
|
-
"detector",
|
|
215066
|
-
"cropper",
|
|
215067
|
-
"classifier",
|
|
215068
|
-
"refiner",
|
|
215069
|
-
"audio-classifier"
|
|
215070
|
-
]);
|
|
215071
|
-
var PipelineEngineChoiceSchema = zod.z.object({
|
|
215072
|
-
runtime: zod.z.enum(["node", "python"]),
|
|
215073
|
-
backend: zod.z.string(),
|
|
215074
|
-
format: ModelFormatSchema$1,
|
|
215075
|
-
device: zod.z.string().optional()
|
|
215076
|
-
});
|
|
215077
|
-
var EngineDeviceInfoSchema = zod.z.object({
|
|
215078
|
-
id: zod.z.string(),
|
|
215079
|
-
label: zod.z.string(),
|
|
215080
|
-
description: zod.z.string().optional()
|
|
215081
|
-
});
|
|
215082
|
-
var AvailableEngineSchema = zod.z.object({
|
|
215083
|
-
engine: PipelineEngineChoiceSchema,
|
|
215084
|
-
devices: zod.z.array(EngineDeviceInfoSchema).readonly(),
|
|
215085
|
-
defaultDevice: zod.z.string()
|
|
215086
|
-
});
|
|
215087
|
-
var PipelineDefaultStepSchema = zod.z.lazy(() => zod.z.object({
|
|
215088
|
-
addonId: zod.z.string(),
|
|
215089
|
-
addonName: zod.z.string(),
|
|
215090
|
-
slot: PipelineSlotSchema,
|
|
215091
|
-
inputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
215092
|
-
outputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
215093
|
-
enabled: zod.z.boolean(),
|
|
215094
|
-
modelId: zod.z.string(),
|
|
215095
|
-
children: zod.z.array(PipelineDefaultStepSchema).readonly(),
|
|
215096
|
-
group: zod.z.string().optional(),
|
|
215097
|
-
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
215098
|
-
}));
|
|
215099
|
-
var PipelineTemplateStepSchema = zod.z.lazy(() => zod.z.object({
|
|
215100
|
-
addonId: zod.z.string(),
|
|
215101
|
-
enabled: zod.z.boolean(),
|
|
215102
|
-
modelId: zod.z.string(),
|
|
215103
|
-
children: zod.z.array(PipelineTemplateStepSchema).readonly(),
|
|
215104
|
-
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
215105
|
-
}));
|
|
215106
|
-
var PipelineTemplateSchema$1 = zod.z.object({
|
|
215107
|
-
id: zod.z.string(),
|
|
215108
|
-
name: zod.z.string(),
|
|
215109
|
-
createdAt: zod.z.string(),
|
|
215110
|
-
updatedAt: zod.z.string(),
|
|
215111
|
-
engine: PipelineEngineChoiceSchema,
|
|
215112
|
-
steps: zod.z.array(PipelineTemplateStepSchema).readonly()
|
|
215113
|
-
});
|
|
215114
|
-
var PipelineModelOptionSchema = zod.z.object({
|
|
215115
|
-
id: zod.z.string(),
|
|
215116
|
-
name: zod.z.string(),
|
|
215117
|
-
formats: zod.z.record(zod.z.string(), zod.z.object({
|
|
215118
|
-
downloaded: zod.z.boolean(),
|
|
215119
|
-
sizeMB: zod.z.number()
|
|
215120
|
-
})),
|
|
215121
|
-
group: ModelVariantGroupSchema.optional(),
|
|
215122
|
-
legacy: zod.z.boolean().optional(),
|
|
215123
|
-
provider: ModelProviderIdSchema.optional()
|
|
215124
|
-
});
|
|
215125
|
-
var ConfigFieldBridge = zod.z.custom();
|
|
215126
|
-
var PipelineAddonSchemaSchema = zod.z.object({
|
|
215127
|
-
id: zod.z.string(),
|
|
215128
|
-
name: zod.z.string(),
|
|
215129
|
-
slot: PipelineSlotSchema,
|
|
215130
|
-
inputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
215131
|
-
outputClasses: zod.z.array(zod.z.string()).readonly(),
|
|
215132
|
-
childSlots: zod.z.array(PipelineSlotSchema).readonly(),
|
|
215133
|
-
models: zod.z.array(PipelineModelOptionSchema).readonly(),
|
|
215134
|
-
defaultModelId: zod.z.string(),
|
|
215135
|
-
defaultModelIdByFormat: zod.z.record(zod.z.string(), zod.z.string()).optional(),
|
|
215136
|
-
enabledByDefault: zod.z.boolean().optional(),
|
|
215137
|
-
backfillIntoExistingOverrides: zod.z.boolean().optional(),
|
|
215138
|
-
defaultConfidence: zod.z.number(),
|
|
215139
|
-
group: zod.z.string().optional(),
|
|
215140
|
-
configSchema: zod.z.array(ConfigFieldBridge).readonly().optional()
|
|
215141
|
-
});
|
|
215142
|
-
var PipelineSlotSchemaSchema = zod.z.object({
|
|
215143
|
-
id: PipelineSlotSchema,
|
|
215144
|
-
label: zod.z.string(),
|
|
215145
|
-
priority: zod.z.number(),
|
|
215146
|
-
parentSlot: PipelineSlotSchema.nullable(),
|
|
215147
|
-
addons: zod.z.array(PipelineAddonSchemaSchema).readonly()
|
|
215148
|
-
});
|
|
215149
|
-
var PipelineSchemaSchema = zod.z.object({
|
|
215150
|
-
availableEngines: zod.z.array(AvailableEngineSchema).readonly(),
|
|
215151
|
-
selectedEngine: PipelineEngineChoiceSchema,
|
|
215152
|
-
slots: zod.z.array(PipelineSlotSchemaSchema).readonly()
|
|
215153
|
-
});
|
|
215154
|
-
var EngineProvisioningSchema = zod.z.object({
|
|
215155
|
-
runtimeId: zod.z.enum([
|
|
215156
|
-
"onnx",
|
|
215157
|
-
"openvino",
|
|
215158
|
-
"coreml",
|
|
215159
|
-
"edgetpu"
|
|
215160
|
-
]).nullable(),
|
|
215161
|
-
device: zod.z.string().nullable(),
|
|
215162
|
-
state: zod.z.enum([
|
|
215163
|
-
"idle",
|
|
215164
|
-
"installing",
|
|
215165
|
-
"verifying",
|
|
215166
|
-
"ready",
|
|
215167
|
-
"failed"
|
|
215168
|
-
]),
|
|
215169
|
-
progress: zod.z.number().optional(),
|
|
215170
|
-
error: zod.z.string().optional(),
|
|
215171
|
-
nextRetryAt: zod.z.number().optional(),
|
|
215172
|
-
/**
|
|
215173
|
-
* Gate A (config-correctness gate at engine change): human-readable
|
|
215174
|
-
* config issues surfaced EAGERLY when the node's engine changes — model
|
|
215175
|
-
* substitutions ("chose X, running Y") and zero-build steps ("no model
|
|
215176
|
-
* has a <format> build"). Additive/optional: informational only, never
|
|
215177
|
-
* enforced here — `assertEngineReady` (readiness) still gates inference.
|
|
215178
|
-
* Absent/empty when the node-default tree resolves cleanly.
|
|
215179
|
-
*/
|
|
215180
|
-
configIssues: zod.z.array(zod.z.string()).optional()
|
|
215181
|
-
});
|
|
215182
|
-
var PipelineStepInputSchema = zod.z.lazy(() => zod.z.object({
|
|
215183
|
-
addonId: zod.z.string(),
|
|
215184
|
-
modelId: zod.z.string().optional(),
|
|
215185
|
-
enabled: zod.z.boolean().default(true),
|
|
215186
|
-
children: zod.z.array(PipelineStepInputSchema).optional(),
|
|
215187
|
-
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
215188
|
-
jumpDeviceKey: zod.z.string().optional()
|
|
215189
|
-
}));
|
|
215190
|
-
var ModelSubstitutionSchema = zod.z.object({
|
|
215191
|
-
addonId: zod.z.string(),
|
|
215192
|
-
chosen: zod.z.string(),
|
|
215193
|
-
running: zod.z.string(),
|
|
215194
|
-
format: zod.z.string()
|
|
215195
|
-
});
|
|
215196
|
-
var PipelineValidationIssueSchema = zod.z.object({
|
|
215197
|
-
addonId: zod.z.string(),
|
|
215198
|
-
kind: zod.z.enum(["unknown-addon", "no-format-build"]),
|
|
215199
|
-
detail: zod.z.string()
|
|
215200
|
-
});
|
|
215201
|
-
var PipelineValidationResultSchema = zod.z.object({
|
|
215202
|
-
ok: zod.z.boolean(),
|
|
215203
|
-
issues: zod.z.array(PipelineValidationIssueSchema).readonly(),
|
|
215204
|
-
substitutions: zod.z.array(ModelSubstitutionSchema).readonly(),
|
|
215205
|
-
/** The node's `currentEngine.format` this validation ran against. */
|
|
215206
|
-
format: zod.z.string()
|
|
215207
|
-
});
|
|
215208
|
-
var ReferenceImageEntrySchema = zod.z.object({
|
|
215209
|
-
filename: zod.z.string(),
|
|
215210
|
-
stepIds: zod.z.array(zod.z.string()).readonly().optional()
|
|
215211
|
-
});
|
|
215212
|
-
var ReferenceImageBodySchema = zod.z.object({
|
|
215213
|
-
base64: zod.z.string(),
|
|
215214
|
-
filename: zod.z.string()
|
|
215215
|
-
});
|
|
215216
|
-
var ReferenceAudioEntrySchema = zod.z.object({
|
|
215217
|
-
filename: zod.z.string(),
|
|
215218
|
-
sizeKb: zod.z.number()
|
|
215219
|
-
});
|
|
215220
|
-
var ReferenceAudioBodySchema = zod.z.object({ base64: zod.z.string() });
|
|
215221
|
-
var AudioBackendSchema = zod.z.object({
|
|
215222
|
-
id: zod.z.string(),
|
|
215223
|
-
name: zod.z.string(),
|
|
215224
|
-
description: zod.z.string(),
|
|
215225
|
-
available: zod.z.boolean(),
|
|
215226
|
-
/**
|
|
215227
|
-
* Raw classifier labels this backend can emit (e.g. YAMNet's
|
|
215228
|
-
* 521-class set or Apple SoundAnalysis's 303-class set). Used by
|
|
215229
|
-
* the benchmark UI to populate the `enabledMicroClasses` filter
|
|
215230
|
-
* specific to the selected backend without a separate fetch.
|
|
215231
|
-
*/
|
|
215232
|
-
rawLabels: zod.z.array(zod.z.string()).readonly().optional()
|
|
215233
|
-
});
|
|
215234
|
-
var AudioCapabilitiesSchema = zod.z.object({
|
|
215235
|
-
activeBackend: zod.z.string(),
|
|
215236
|
-
availableBackends: zod.z.array(AudioBackendSchema).readonly(),
|
|
215237
|
-
sampleRate: zod.z.number(),
|
|
215238
|
-
chunkDurationMs: zod.z.number()
|
|
215239
|
-
});
|
|
215240
|
-
var DownloadModelResultSchema = zod.z.object({
|
|
215241
|
-
filePath: zod.z.string(),
|
|
215242
|
-
sizeMB: zod.z.number(),
|
|
215243
|
-
durationMs: zod.z.number()
|
|
215244
|
-
});
|
|
215245
|
-
var AudioTestResultSchema = zod.z.object({
|
|
215246
|
-
success: zod.z.boolean(),
|
|
215247
|
-
error: zod.z.string().optional(),
|
|
215248
|
-
frame: zod.z.custom().optional()
|
|
215249
|
-
});
|
|
215250
|
-
var PipelineConfigBridge = zod.z.custom();
|
|
215251
|
-
var ConfigUISchemaBridge = zod.z.custom();
|
|
215252
|
-
var ConfigUISchemaNullableBridge = zod.z.custom();
|
|
215253
|
-
var InferenceCapabilitiesBridge = zod.z.custom();
|
|
215254
|
-
var ModelAvailabilityListBridge = zod.z.custom();
|
|
215255
|
-
var PipelineRunResultBridge = zod.z.custom();
|
|
215256
|
-
var pipelineExecutorCapability = {
|
|
215257
|
-
name: "pipeline-executor",
|
|
215258
|
-
scope: "system",
|
|
215259
|
-
mode: "singleton",
|
|
215260
|
-
methods: {
|
|
215261
|
-
getAvailableEngines: require_sleep.method(zod.z.void(), zod.z.array(PipelineEngineChoiceSchema)),
|
|
215262
|
-
getSelectedEngine: require_sleep.method(zod.z.void(), PipelineEngineChoiceSchema),
|
|
215263
|
-
getDefaultSteps: require_sleep.method(PipelineEngineChoiceSchema, zod.z.array(PipelineDefaultStepSchema)),
|
|
215264
|
-
/**
|
|
215265
|
-
* Per-node detection-engine provisioning snapshot. Returns the live
|
|
215266
|
-
* state of the lazy runtime-provisioning machine on `nodeId`
|
|
215267
|
-
* (idle / installing / verifying / ready / failed). The UI pairs this
|
|
215268
|
-
* one-shot query with the `pipeline.engine-provisioning` live event
|
|
215269
|
-
* (emitted on every transition) to drive a per-node "engine ready?"
|
|
215270
|
-
* indicator without polling. Phase 2.
|
|
215271
|
-
*/
|
|
215272
|
-
getEngineProvisioning: require_sleep.method(zod.z.object({ nodeId: zod.z.string() }), EngineProvisioningSchema),
|
|
215273
|
-
getVideoPipelineSteps: require_sleep.method(zod.z.void(), zod.z.record(zod.z.string(), zod.z.object({
|
|
215274
|
-
modelId: zod.z.string(),
|
|
215275
|
-
settings: zod.z.record(zod.z.string(), zod.z.unknown()).readonly()
|
|
215276
|
-
}))),
|
|
215277
|
-
setVideoPipelineSteps: require_sleep.method(zod.z.object({ steps: zod.z.record(zod.z.string(), zod.z.object({
|
|
215278
|
-
modelId: zod.z.string(),
|
|
215279
|
-
settings: zod.z.record(zod.z.string(), zod.z.unknown()).readonly()
|
|
215280
|
-
})) }), zod.z.object({ success: zod.z.literal(true) }), {
|
|
215281
|
-
kind: "mutation",
|
|
215282
|
-
auth: "admin"
|
|
215283
|
-
}),
|
|
215284
|
-
/**
|
|
215285
|
-
* Clear THIS node's executor-side PER-DEVICE settings stores (the
|
|
215286
|
-
* per-camera step overrides the object-detection root reads via
|
|
215287
|
-
* `applyDeviceOverridesToTree`). `nodeId` is the ROUTING key — the
|
|
215288
|
-
* generated cap-router strips it (default `nodeIdMode: 'routing'`) and
|
|
215289
|
-
* dispatches to that node, so the provider method runs ON the target
|
|
215290
|
-
* node and receives no `nodeId`.
|
|
215291
|
-
*
|
|
215292
|
-
* This is the slimmed executor leg of the orchestrator's
|
|
215293
|
-
* `resetNodePipelineDefaults` flow (which owns the real reset: node
|
|
215294
|
-
* addonDefaults pins + per-camera orchestrator overrides). The legacy
|
|
215295
|
-
* `resetToDefault` — which reset a persisted global step-tree seed
|
|
215296
|
-
* nothing in the live per-camera path read — was removed together with
|
|
215297
|
-
* that seed.
|
|
215298
|
-
*/
|
|
215299
|
-
clearDeviceOverrides: require_sleep.method(zod.z.object({ nodeId: zod.z.string() }), zod.z.object({
|
|
215300
|
-
success: zod.z.literal(true),
|
|
215301
|
-
clearedDevices: zod.z.number()
|
|
215302
|
-
}), {
|
|
215303
|
-
kind: "mutation",
|
|
215304
|
-
auth: "admin"
|
|
215305
|
-
}),
|
|
215306
|
-
getSchema: require_sleep.method(zod.z.void(), PipelineSchemaSchema),
|
|
215307
|
-
getGlobalSteps: require_sleep.method(zod.z.void(), zod.z.array(PipelineDefaultStepSchema).readonly().nullable()),
|
|
215308
|
-
getGlobalPipelineConfig: require_sleep.method(zod.z.void(), PipelineConfigBridge),
|
|
215309
|
-
getOrchestratorConfigSchema: require_sleep.method(zod.z.void(), ConfigUISchemaBridge),
|
|
215310
|
-
/**
|
|
215311
|
-
* Gate B (pre-init config-correctness gate). PURE COMPUTE against this
|
|
215312
|
-
* node's `currentEngine.format` — resolves `steps` the same way the
|
|
215313
|
-
* runtime dispatch path would, and reports what WOULD happen without
|
|
215314
|
-
* touching any node-global state. Called by the orchestrator at attach
|
|
215315
|
-
* time (`attachOn`), node-pinned to the TARGET node, so config problems
|
|
215316
|
-
* surface BEFORE `pipelineRunner.attachCamera` rather than at the first
|
|
215317
|
-
* per-frame resolve. `ok` is false iff `issues` is non-empty (both
|
|
215318
|
-
* `unknown-addon` and `no-format-build` are HARD issues); `substitutions`
|
|
215319
|
-
* is informational (a degraded-but-loadable model swap) and never
|
|
215320
|
-
* affects `ok`. Never throws.
|
|
215321
|
-
*/
|
|
215322
|
-
validatePipeline: require_sleep.method(zod.z.object({ steps: zod.z.array(PipelineStepInputSchema) }), PipelineValidationResultSchema),
|
|
215323
|
-
listTemplates: require_sleep.method(zod.z.void(), zod.z.array(PipelineTemplateSchema$1).readonly()),
|
|
215324
|
-
saveTemplate: require_sleep.method(zod.z.object({
|
|
215325
|
-
name: zod.z.string(),
|
|
215326
|
-
steps: zod.z.array(PipelineTemplateStepSchema).readonly(),
|
|
215327
|
-
engine: PipelineEngineChoiceSchema
|
|
215328
|
-
}), PipelineTemplateSchema$1, { kind: "mutation" }),
|
|
215329
|
-
updateTemplate: require_sleep.method(zod.z.object({
|
|
215330
|
-
id: zod.z.string(),
|
|
215331
|
-
name: zod.z.string().optional(),
|
|
215332
|
-
steps: zod.z.array(PipelineTemplateStepSchema).readonly().optional()
|
|
215333
|
-
}), PipelineTemplateSchema$1, { kind: "mutation" }),
|
|
215334
|
-
deleteTemplate: require_sleep.method(zod.z.object({ id: zod.z.string() }), zod.z.void(), { kind: "mutation" }),
|
|
215335
|
-
getCapabilities: require_sleep.method(zod.z.void(), InferenceCapabilitiesBridge),
|
|
215336
|
-
getAddonModels: require_sleep.method(zod.z.object({ addonId: zod.z.string() }), ModelAvailabilityListBridge),
|
|
215337
|
-
downloadModel: require_sleep.method(zod.z.object({
|
|
215338
|
-
addonId: zod.z.string(),
|
|
215339
|
-
modelId: zod.z.string(),
|
|
215340
|
-
format: ModelFormatSchema$1
|
|
215341
|
-
}), DownloadModelResultSchema, { kind: "mutation" }),
|
|
215342
|
-
deleteModel: require_sleep.method(zod.z.object({
|
|
215343
|
-
addonId: zod.z.string(),
|
|
215344
|
-
modelId: zod.z.string(),
|
|
215345
|
-
format: ModelFormatSchema$1
|
|
215346
|
-
}), zod.z.object({ success: zod.z.literal(true) }), { kind: "mutation" }),
|
|
215347
|
-
/**
|
|
215348
|
-
* Stateless single-frame execution. Callers (runner, benchmark) pass
|
|
215349
|
-
* the complete `engine` + `steps` tree; the executor holds no state
|
|
215350
|
-
* about cameras or saved pipelines.
|
|
215351
|
-
*
|
|
215352
|
-
* `engine` is optional during the migration window to preserve the
|
|
215353
|
-
* legacy call shape used by existing benchmark code; once all
|
|
215354
|
-
* callers pass it explicitly we make it required.
|
|
215355
|
-
*
|
|
215356
|
-
* Exactly one of `frame`, `frameRef`, `frameHandle`, `imageBase64`,
|
|
215357
|
-
* `referenceImage` must be provided:
|
|
215358
|
-
* - `frame`: runtime dispatch path (runner → decoded broker frame).
|
|
215359
|
-
* Carries the raw buffer, dimensions, and format; the executor
|
|
215360
|
-
* uses it directly without base64 round-tripping.
|
|
215361
|
-
* - `frameHandle` (CB5): a zero-pixel shm `FrameHandle` for the SAME
|
|
215362
|
-
* decoded frame. Both runner and executor are hub-local processes
|
|
215363
|
-
* sharing `/dev/shm`, so the executor maps the named segment and
|
|
215364
|
-
* reads the pixels back zero-copy — eliminating the ~1.2MB
|
|
215365
|
-
* re-serialisation over UDS/MsgPack the `frame` path pays per call.
|
|
215366
|
-
* High-risk: the FrameRing is a latest-wins seqlock with no
|
|
215367
|
-
* refcount, so a recycled slot yields a null read; the executor
|
|
215368
|
-
* then degrades to an empty result and the runner ships pixels via
|
|
215369
|
-
* `frame` as the fallback (queue-depth gated on the runner side).
|
|
215370
|
-
* - `imageBase64`: one-shot test path (benchmark ImageTab).
|
|
215371
|
-
* - `referenceImage`: named file from the reference-image store.
|
|
215372
|
-
*/
|
|
215373
|
-
runPipeline: require_sleep.method(zod.z.object({
|
|
215374
|
-
engine: PipelineEngineChoiceSchema.optional(),
|
|
215375
|
-
steps: zod.z.array(PipelineStepInputSchema).min(1),
|
|
215376
|
-
frame: FrameInputSchema.optional(),
|
|
215377
|
-
/**
|
|
215378
|
-
* Process-local lazy frame. Valid only when caller and provider resolve
|
|
215379
|
-
* in the same execution-group process; split/cross-node callers use
|
|
215380
|
-
* `frame`/`image` inline compatibility instead.
|
|
215381
|
-
*/
|
|
215382
|
-
frameRef: FrameRefSchema.optional(),
|
|
215383
|
-
/**
|
|
215384
|
-
* CB5 shm passthrough — a `FrameHandle` naming the same ring slot
|
|
215385
|
-
* the decoded pixels live in. One more member of the one-of
|
|
215386
|
-
* frame/frameHandle/image/imageBase64/referenceImage group.
|
|
215387
|
-
*/
|
|
215388
|
-
frameHandle: require_sleep.FrameHandleSchema.optional(),
|
|
215389
|
-
imageBase64: zod.z.string().optional(),
|
|
215390
|
-
/**
|
|
215391
|
-
* Binary JPEG bytes — preferred over `imageBase64` on internal
|
|
215392
|
-
* hops (hub → forked worker via Moleculer MsgPack) because it
|
|
215393
|
-
* skips the 33% base64 overhead + the per-call base64 decode on
|
|
215394
|
-
* the detection-pipeline worker. Callers can pass either; exactly
|
|
215395
|
-
* one of `frame`/`image`/`imageBase64`/`referenceImage` is required.
|
|
215396
|
-
*/
|
|
215397
|
-
image: zod.z.instanceof(Uint8Array).optional(),
|
|
215398
|
-
referenceImage: zod.z.string().optional(),
|
|
215399
|
-
deviceId: zod.z.number().optional(),
|
|
215400
|
-
sessionId: zod.z.string().optional(),
|
|
215401
|
-
/**
|
|
215402
|
-
* Execution plane. 'full' (default) runs the whole tree — benchmark,
|
|
215403
|
-
* reference-image, and detail-subtree calls. 'frame' is the live
|
|
215404
|
-
* per-frame dispatch: ONLY root-plane steps run; crop children
|
|
215405
|
-
* (inputClasses ≠ null) are skipped and served per-track via
|
|
215406
|
-
* pipelineRunner.runDetailSubtree (two-plane design).
|
|
215407
|
-
*/
|
|
215408
|
-
plane: zod.z.enum(["full", "frame"]).optional(),
|
|
215409
|
-
/**
|
|
215410
|
-
* Inference-device selector (Phase 2 multi-device). Format
|
|
215411
|
-
* `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
|
|
215412
|
-
* Omitted ⇒ the runner's default device (current single-engine
|
|
215413
|
-
* behaviour). Selects WHICH device pool of the node runs the call.
|
|
215414
|
-
*/
|
|
215415
|
-
deviceKey: zod.z.string().optional(),
|
|
215416
|
-
/**
|
|
215417
|
-
* Two-plane NATIVE child-crop reference. Set by `runDetailSubtree` ONLY
|
|
215418
|
-
* when the parent crop was resolved from the frame's retained NATIVE
|
|
215419
|
-
* surface (a frameHandle HIT). Lets the executor re-cut a LEAF crop
|
|
215420
|
-
* child's ROI (plate-ocr, face-embedding, leaf classifiers) at native
|
|
215421
|
-
* resolution from that surface — the SAME quality path faces already
|
|
215422
|
-
* had — instead of the downscaled parent tile. `handle` keys the native
|
|
215423
|
-
* surface (node-pinned to its owner); `cropFrameSpace` is the parent
|
|
215424
|
-
* crop's padded/clamped rectangle in FRAME-space pixels, used to compose
|
|
215425
|
-
* the executor's crop-normalized child ROI back into frame-normalized
|
|
215426
|
-
* coordinates. Auxiliary to the image source (`image`/`frame`/…), NOT one
|
|
215427
|
-
* of the mutually-exclusive image inputs. Absent ⇒ tile-crop children
|
|
215428
|
-
* (today's behaviour on the fallback path).
|
|
215429
|
-
*/
|
|
215430
|
-
nativeCropRef: NativeCropRefSchema.optional()
|
|
215431
|
-
}), PipelineRunResultBridge, { kind: "mutation" }),
|
|
215432
|
-
/**
|
|
215433
|
-
* Batched run — N raw frames packed into one cap call. The provider
|
|
215434
|
-
* routes the batch through `SharedInferencePool.inferBatch`
|
|
215435
|
-
* (`MSG_INFER_BATCH = 0x03`) so the IPC framing and JSON response
|
|
215436
|
-
* envelope cost is amortised N:1 vs N concurrent `runPipeline`
|
|
215437
|
-
* calls. Single root step + uniform model assumed; trees with crop
|
|
215438
|
-
* children fall back to sequential execution.
|
|
215439
|
-
*
|
|
215440
|
-
* Used by `scripts/bench-batch-style.mts` for batch benchmarking —
|
|
215441
|
-
* N frames in one call to amortise per-call IPC overhead.
|
|
215442
|
-
*/
|
|
215443
|
-
runPipelineBatch: require_sleep.method(zod.z.object({
|
|
215444
|
-
engine: PipelineEngineChoiceSchema.optional(),
|
|
215445
|
-
steps: zod.z.array(PipelineStepInputSchema).min(1),
|
|
215446
|
-
frames: zod.z.array(FrameInputSchema).min(1).max(255),
|
|
215447
|
-
deviceId: zod.z.number().optional(),
|
|
215448
|
-
sessionId: zod.z.string().optional(),
|
|
215449
|
-
/**
|
|
215450
|
-
* Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
|
|
215451
|
-
* the batch to the Python pool's bench preprocess cache
|
|
215452
|
-
* (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
|
|
215453
|
-
* preprocessed ONCE and every later inference is a pure-inference cache
|
|
215454
|
-
* hit — the sustained-throughput run measures inference, not
|
|
215455
|
-
* decode+preprocess+infer. Omitted/0 for live frames (all different →
|
|
215456
|
-
* full preprocess every call, correct). Fresh per sustained run;
|
|
215457
|
-
* released via `uncacheFrame`.
|
|
215458
|
-
*/
|
|
215459
|
-
frameId: zod.z.number().int().nonnegative().optional(),
|
|
215460
|
-
/** Inference-device selector (Phase 2 multi-device); see runPipeline. */
|
|
215461
|
-
deviceKey: zod.z.string().optional()
|
|
215462
|
-
}), zod.z.object({ results: zod.z.array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }),
|
|
215463
|
-
/**
|
|
215464
|
-
* Cache a raw frame inside the Python inference pool's memory.
|
|
215465
|
-
* Returns a numeric `frameId` that `inferCached` references —
|
|
215466
|
-
* subsequent calls send only 5 bytes through the pipe instead of
|
|
215467
|
-
* 1.2MB raw data, eliminating the pipe transfer bottleneck.
|
|
215468
|
-
*/
|
|
215469
|
-
cacheFrameInPool: require_sleep.method(zod.z.object({
|
|
215470
|
-
data: zod.z.instanceof(Uint8Array),
|
|
215471
|
-
width: zod.z.number().int().positive(),
|
|
215472
|
-
height: zod.z.number().int().positive(),
|
|
215473
|
-
format: zod.z.enum([
|
|
215474
|
-
"rgb",
|
|
215475
|
-
"bgr",
|
|
215476
|
-
"gray"
|
|
215477
|
-
])
|
|
215478
|
-
}), zod.z.object({
|
|
215479
|
-
frameId: zod.z.number(),
|
|
215480
|
-
width: zod.z.number(),
|
|
215481
|
-
height: zod.z.number()
|
|
215482
|
-
}), { kind: "mutation" }),
|
|
215483
|
-
/**
|
|
215484
|
-
* Run inference on a previously cached frame. Sends only 5 bytes
|
|
215485
|
-
* (model_idx + frameId) through the IPC pipe — eliminates the
|
|
215486
|
-
* ~35ms per-call overhead of transferring 1.2MB raw data.
|
|
215487
|
-
*/
|
|
215488
|
-
inferCached: require_sleep.method(zod.z.object({
|
|
215489
|
-
stepId: zod.z.string(),
|
|
215490
|
-
frameId: zod.z.number().int()
|
|
215491
|
-
}), zod.z.record(zod.z.string(), zod.z.unknown()), { kind: "mutation" }),
|
|
215492
|
-
/**
|
|
215493
|
-
* Release a cached frame from the Python pool's memory.
|
|
215494
|
-
*/
|
|
215495
|
-
uncacheFrame: require_sleep.method(zod.z.object({ frameId: zod.z.number().int() }), zod.z.void(), { kind: "mutation" }),
|
|
215496
|
-
/** Returns the effective pool tuning (resolved from user overrides + backend defaults). */
|
|
215497
|
-
getEffectiveTuning: require_sleep.method(zod.z.void(), zod.z.object({
|
|
215498
|
-
batchMode: zod.z.string(),
|
|
215499
|
-
windowMs: zod.z.number(),
|
|
215500
|
-
maxBatchSize: zod.z.number(),
|
|
215501
|
-
concurrency: zod.z.number()
|
|
215502
|
-
})),
|
|
215503
|
-
/**
|
|
215504
|
-
* List every EngineFactory currently loaded in this executor's RAM,
|
|
215505
|
-
* with the models resident and a coarse "in use" marker derived from
|
|
215506
|
-
* ongoing inference activity. Used by the Pipeline page Engines tab.
|
|
215507
|
-
*/
|
|
215508
|
-
listLoadedEngines: require_sleep.method(zod.z.void(), zod.z.array(zod.z.object({
|
|
215509
|
-
engineKey: zod.z.string(),
|
|
215510
|
-
engine: PipelineEngineChoiceSchema,
|
|
215511
|
-
modelsLoaded: zod.z.array(zod.z.string()).readonly(),
|
|
215512
|
-
inUseByCameras: zod.z.array(zod.z.number()).readonly(),
|
|
215513
|
-
/**
|
|
215514
|
-
* Origin of this resident factory.
|
|
215515
|
-
* - `runtime` — main camera-serving engine (no idle TTL).
|
|
215516
|
-
* - `warm-override` — benchmark/test override held in the warm
|
|
215517
|
-
* cache; auto-disposed after the idle TTL.
|
|
215518
|
-
* - `device-pool` — a concurrent per-device pool (Phase 2
|
|
215519
|
-
* multi-device, keyed by `deviceKey`) resolved
|
|
215520
|
-
* via `resolveDeviceFactory`. Runs alongside the
|
|
215521
|
-
* `runtime` engine on a DIFFERENT accelerator
|
|
215522
|
-
* (NPU / iGPU / Coral) — this is how the
|
|
215523
|
-
* Engines tab shows all pools running at once.
|
|
215524
|
-
*/
|
|
215525
|
-
kind: zod.z.enum([
|
|
215526
|
-
"runtime",
|
|
215527
|
-
"warm-override",
|
|
215528
|
-
"device-pool"
|
|
215529
|
-
]),
|
|
215530
|
-
/** Native pid of the underlying Python pool (null when no pool). */
|
|
215531
|
-
poolPid: zod.z.number().nullable(),
|
|
215532
|
-
/** ms since this factory was last used (null when not warm-tracked). */
|
|
215533
|
-
idleMs: zod.z.number().nullable(),
|
|
215534
|
-
/** Idle TTL after which `warm-override` factories self-evict (null when not applicable). */
|
|
215535
|
-
idleTtlMs: zod.z.number().nullable()
|
|
215536
|
-
})).readonly()),
|
|
215537
|
-
/** Warm up an engine without running a frame. No-op if already loaded. */
|
|
215538
|
-
spinEngine: require_sleep.method(zod.z.object({ engine: PipelineEngineChoiceSchema }), zod.z.object({ success: zod.z.literal(true) }), {
|
|
215539
|
-
kind: "mutation",
|
|
215540
|
-
auth: "admin"
|
|
215541
|
-
}),
|
|
215542
|
-
/**
|
|
215543
|
-
* Unload an engine from RAM. `force:true` unloads even when cameras
|
|
215544
|
-
* are actively using it (they re-spin on next frame). Default is
|
|
215545
|
-
* gated — returns `{success:false, reason}` when in use.
|
|
215546
|
-
*/
|
|
215547
|
-
killEngine: require_sleep.method(zod.z.object({
|
|
215548
|
-
engine: PipelineEngineChoiceSchema,
|
|
215549
|
-
force: zod.z.boolean().optional()
|
|
215550
|
-
}), zod.z.object({
|
|
215551
|
-
success: zod.z.boolean(),
|
|
215552
|
-
reason: zod.z.string().optional()
|
|
215553
|
-
}), {
|
|
215554
|
-
kind: "mutation",
|
|
215555
|
-
auth: "admin"
|
|
215556
|
-
}),
|
|
215557
|
-
listReferenceImages: require_sleep.method(zod.z.void(), zod.z.array(ReferenceImageEntrySchema).readonly()),
|
|
215558
|
-
getReferenceImage: require_sleep.method(zod.z.object({ filename: zod.z.string() }), ReferenceImageBodySchema.nullable()),
|
|
215559
|
-
getReferenceAudioFiles: require_sleep.method(zod.z.void(), zod.z.array(ReferenceAudioEntrySchema).readonly()),
|
|
215560
|
-
getReferenceAudio: require_sleep.method(zod.z.object({ filename: zod.z.string() }), ReferenceAudioBodySchema.nullable()),
|
|
215561
|
-
getAudioCapabilities: require_sleep.method(zod.z.void(), AudioCapabilitiesSchema),
|
|
215562
|
-
runAudioTest: require_sleep.method(zod.z.object({
|
|
215563
|
-
addonId: zod.z.string(),
|
|
215564
|
-
modelId: zod.z.string(),
|
|
215565
|
-
filename: zod.z.string().optional(),
|
|
215566
|
-
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
215567
|
-
}), AudioTestResultSchema, { kind: "mutation" }),
|
|
215568
|
-
getDetectionConfigSchema: require_sleep.method(zod.z.void(), ConfigUISchemaNullableBridge)
|
|
215569
|
-
}
|
|
215570
|
-
};
|
|
215571
216051
|
var OrchestratorMetricsSchema = zod.z.object({
|
|
215572
216052
|
activeCameras: zod.z.number(),
|
|
215573
216053
|
throttledCameras: zod.z.number(),
|
|
@@ -215592,66 +216072,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
215592
216072
|
])
|
|
215593
216073
|
});
|
|
215594
216074
|
var CameraMetricsWithDeviceIdSchema = CameraMetricsSchema.extend({ deviceId: zod.z.number() });
|
|
215595
|
-
var ZoneKindEnum = zod.z.enum(["polygon", "tripwire"]);
|
|
215596
|
-
var PolygonPointSchema = zod.z.object({
|
|
215597
|
-
x: zod.z.number(),
|
|
215598
|
-
y: zod.z.number()
|
|
215599
|
-
});
|
|
215600
|
-
var ZoneSchema = zod.z.object({
|
|
215601
|
-
id: zod.z.string(),
|
|
215602
|
-
name: zod.z.string(),
|
|
215603
|
-
kind: ZoneKindEnum.default("polygon"),
|
|
215604
|
-
/** Polygon vertices, fraction of frame (0–1). */
|
|
215605
|
-
polygon: zod.z.array(PolygonPointSchema).readonly(),
|
|
215606
|
-
/** Visual color for UI rendering. */
|
|
215607
|
-
color: zod.z.string().default("#3b82f6")
|
|
215608
|
-
});
|
|
215609
|
-
var zonesCapability = {
|
|
215610
|
-
name: "zones",
|
|
215611
|
-
scope: "device",
|
|
215612
|
-
mode: "singleton",
|
|
215613
|
-
deviceTypes: [require_sleep.DeviceType.Camera],
|
|
215614
|
-
methods: {
|
|
215615
|
-
listZones: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), zod.z.array(ZoneSchema).readonly()),
|
|
215616
|
-
addZone: require_sleep.method(zod.z.object({
|
|
215617
|
-
deviceId: zod.z.number(),
|
|
215618
|
-
zone: ZoneSchema
|
|
215619
|
-
}), zod.z.void(), {
|
|
215620
|
-
kind: "mutation",
|
|
215621
|
-
auth: "admin"
|
|
215622
|
-
}),
|
|
215623
|
-
removeZone: require_sleep.method(zod.z.object({
|
|
215624
|
-
deviceId: zod.z.number(),
|
|
215625
|
-
zoneId: zod.z.string()
|
|
215626
|
-
}), zod.z.void(), {
|
|
215627
|
-
kind: "mutation",
|
|
215628
|
-
auth: "admin"
|
|
215629
|
-
}),
|
|
215630
|
-
updateZone: require_sleep.method(zod.z.object({
|
|
215631
|
-
deviceId: zod.z.number(),
|
|
215632
|
-
zone: ZoneSchema
|
|
215633
|
-
}), zod.z.void(), {
|
|
215634
|
-
kind: "mutation",
|
|
215635
|
-
auth: "admin"
|
|
215636
|
-
})
|
|
215637
|
-
},
|
|
215638
|
-
/**
|
|
215639
|
-
* Runtime-state slice — the live zone catalogue mirrored by the
|
|
215640
|
-
* orchestrator on every CRUD mutation. Consumers read via
|
|
215641
|
-
* `device.state.zones.value` / `.watch(...)` without round-tripping
|
|
215642
|
-
* the cap, and the codegen DeviceProxy auto-wires the reactive
|
|
215643
|
-
* handle. Slice shape is `{ zones: Zone[] }` so future extensions
|
|
215644
|
-
* (e.g. zone groupings) can sit alongside the polygon list.
|
|
215645
|
-
*/
|
|
215646
|
-
runtimeState: zod.z.object({ zones: zod.z.array(ZoneSchema).readonly() }),
|
|
215647
|
-
/**
|
|
215648
|
-
* Runtime-state durability: **restored** — written only on operator mutation, so a camera that never had one has nothing to re-derive from. This is the slice `zone-mirror-hydration.ts` exists to paper over.
|
|
215649
|
-
*
|
|
215650
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
215651
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
215652
|
-
*/
|
|
215653
|
-
durability: "restored"
|
|
215654
|
-
};
|
|
215655
216075
|
var NativeCropBboxSchema = zod.z.object({
|
|
215656
216076
|
x: zod.z.number(),
|
|
215657
216077
|
y: zod.z.number(),
|
|
@@ -225275,59 +225695,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
225275
225695
|
*/
|
|
225276
225696
|
durability: "session"
|
|
225277
225697
|
};
|
|
225278
|
-
var ZoneRuleModeEnum = zod.z.enum(["include", "exclude"]);
|
|
225279
|
-
var ZoneRuleSchema = zod.z.object({
|
|
225280
|
-
/** Stable rule id — survives edits, used by the UI for diffing. */
|
|
225281
|
-
id: zod.z.string(),
|
|
225282
|
-
/** Optional human-readable label rendered in the rule editor. */
|
|
225283
|
-
name: zod.z.string().optional(),
|
|
225284
|
-
/** Zones this rule targets. The rule's `mode` applies to ALL
|
|
225285
|
-
* listed zones (OR-set: a detection in any one of them counts).
|
|
225286
|
-
* At least one zone id required — a rule with no targets is a
|
|
225287
|
-
* configuration mistake and the form validator rejects it. */
|
|
225288
|
-
zoneIds: zod.z.array(zod.z.string()).min(1).readonly(),
|
|
225289
|
-
mode: ZoneRuleModeEnum,
|
|
225290
|
-
/**
|
|
225291
|
-
* Class names this rule applies to. Empty / undefined ⇒ rule
|
|
225292
|
-
* applies to every class. Class strings match the `macroClass`
|
|
225293
|
-
* field on detections (e.g. `person`, `car`, `dog`).
|
|
225294
|
-
*/
|
|
225295
|
-
classFilter: zod.z.array(zod.z.string()).readonly().optional(),
|
|
225296
|
-
/**
|
|
225297
|
-
* Minimum bbox/mask overlap (0–1) with any of the rule's zones
|
|
225298
|
-
* required to consider an entity "in the zone". Defaults to the
|
|
225299
|
-
* consumer's stage default when omitted. Kept for back-compat with
|
|
225300
|
-
* existing per-rule overrides; new operators pick the value via
|
|
225301
|
-
* `bboxInclusionPct` (operator-friendly 0–100). Whichever field is
|
|
225302
|
-
* set, the lower-level engine reads it as a 0–1 fraction.
|
|
225303
|
-
*/
|
|
225304
|
-
overlapThreshold: zod.z.number().min(0).max(1).optional(),
|
|
225305
|
-
/**
|
|
225306
|
-
* Operator-friendly version of `overlapThreshold` — the percentage
|
|
225307
|
-
* of the detection's bbox that must lie inside the zone for the
|
|
225308
|
-
* rule to match. Documented default is 85%; the engine substitutes
|
|
225309
|
-
* that when the field is omitted (kept optional so existing rules
|
|
225310
|
-
* stored without it stay valid).
|
|
225311
|
-
*
|
|
225312
|
-
* When BOTH `overlapThreshold` and `bboxInclusionPct` are set on a
|
|
225313
|
-
* rule, the engine prefers `bboxInclusionPct` because it's the
|
|
225314
|
-
* field exposed in the UI. Internally both feed the same gate.
|
|
225315
|
-
*/
|
|
225316
|
-
bboxInclusionPct: zod.z.number().min(0).max(100).optional(),
|
|
225317
|
-
/**
|
|
225318
|
-
* When `true` and a detection has a segmentation mask, use the
|
|
225319
|
-
* mask for overlap instead of the bbox. Detection-stage only;
|
|
225320
|
-
* motion rules ignore this field.
|
|
225321
|
-
*/
|
|
225322
|
-
preferMask: zod.z.boolean().optional(),
|
|
225323
|
-
/**
|
|
225324
|
-
* Soft-toggle: `false` disables the rule without deleting it.
|
|
225325
|
-
* Defaults to `true` so operators creating a rule via the UI
|
|
225326
|
-
* see it active immediately.
|
|
225327
|
-
*/
|
|
225328
|
-
enabled: zod.z.boolean().default(true)
|
|
225329
|
-
});
|
|
225330
|
-
var ZoneRulesArraySchema = zod.z.array(ZoneRuleSchema).readonly();
|
|
225331
225698
|
var ScriptRunnerStatusSchema = zod.z.object({
|
|
225332
225699
|
/** Whether the script is currently executing. */
|
|
225333
225700
|
isRunning: zod.z.boolean(),
|
|
@@ -233620,6 +233987,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
233620
233987
|
addonId: null,
|
|
233621
233988
|
access: "create"
|
|
233622
233989
|
},
|
|
233990
|
+
"pipelineAnalytics.runReplayFrameProcessor": {
|
|
233991
|
+
capName: "pipeline-analytics",
|
|
233992
|
+
capScope: "device",
|
|
233993
|
+
addonId: null,
|
|
233994
|
+
access: "create"
|
|
233995
|
+
},
|
|
233623
233996
|
"pipelineAnalytics.saveRetrainAnnotations": {
|
|
233624
233997
|
capName: "pipeline-analytics",
|
|
233625
233998
|
capScope: "device",
|
|
@@ -233752,6 +234125,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
233752
234125
|
addonId: null,
|
|
233753
234126
|
access: "view"
|
|
233754
234127
|
},
|
|
234128
|
+
"pipelineExecutor.getInferenceDeviceHealth": {
|
|
234129
|
+
capName: "pipeline-executor",
|
|
234130
|
+
capScope: "system",
|
|
234131
|
+
addonId: null,
|
|
234132
|
+
access: "view"
|
|
234133
|
+
},
|
|
233755
234134
|
"pipelineExecutor.getOrchestratorConfigSchema": {
|
|
233756
234135
|
capName: "pipeline-executor",
|
|
233757
234136
|
capScope: "system",
|
|
@@ -233824,6 +234203,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
233824
234203
|
addonId: null,
|
|
233825
234204
|
access: "view"
|
|
233826
234205
|
},
|
|
234206
|
+
"pipelineExecutor.rearmInferenceDevice": {
|
|
234207
|
+
capName: "pipeline-executor",
|
|
234208
|
+
capScope: "system",
|
|
234209
|
+
addonId: null,
|
|
234210
|
+
access: "create"
|
|
234211
|
+
},
|
|
233827
234212
|
"pipelineExecutor.runAudioTest": {
|
|
233828
234213
|
capName: "pipeline-executor",
|
|
233829
234214
|
capScope: "system",
|
|
@@ -237324,6 +237709,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
237324
237709
|
form: "single",
|
|
237325
237710
|
optional: false
|
|
237326
237711
|
}],
|
|
237712
|
+
"pipelineAnalytics.runReplayFrameProcessor": [{
|
|
237713
|
+
name: "deviceId",
|
|
237714
|
+
form: "single",
|
|
237715
|
+
optional: false
|
|
237716
|
+
}],
|
|
237327
237717
|
"pipelineAnalytics.saveRetrainAnnotations": [{
|
|
237328
237718
|
name: "deviceId",
|
|
237329
237719
|
form: "single",
|
|
@@ -238900,6 +239290,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
238900
239290
|
getVideoPipelineSteps: (input) => dispatch("pipelineExecutor", "getVideoPipelineSteps", "query", input),
|
|
238901
239291
|
setVideoPipelineSteps: (input) => dispatch("pipelineExecutor", "setVideoPipelineSteps", "mutation", input),
|
|
238902
239292
|
clearDeviceOverrides: (input) => dispatch("pipelineExecutor", "clearDeviceOverrides", "mutation", input),
|
|
239293
|
+
getInferenceDeviceHealth: (input) => dispatch("pipelineExecutor", "getInferenceDeviceHealth", "query", input),
|
|
239294
|
+
rearmInferenceDevice: (input) => dispatch("pipelineExecutor", "rearmInferenceDevice", "mutation", input),
|
|
238903
239295
|
getSchema: (input) => dispatch("pipelineExecutor", "getSchema", "query", input),
|
|
238904
239296
|
getGlobalSteps: (input) => dispatch("pipelineExecutor", "getGlobalSteps", "query", input),
|
|
238905
239297
|
getGlobalPipelineConfig: (input) => dispatch("pipelineExecutor", "getGlobalPipelineConfig", "query", input),
|