@camstack/addon-terminal 0.1.33 → 0.1.35
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.
- package/dist/addon.js +939 -693
- package/dist/addon.mjs +939 -693
- package/package.json +1 -1
package/dist/addon.mjs
CHANGED
|
@@ -6698,7 +6698,7 @@ function method(input, output, options) {
|
|
|
6698
6698
|
input,
|
|
6699
6699
|
output,
|
|
6700
6700
|
kind: options?.kind ?? "query",
|
|
6701
|
-
auth: options
|
|
6701
|
+
...options?.auth !== void 0 ? { auth: options.auth } : {},
|
|
6702
6702
|
...options?.access !== void 0 ? { access: options.access } : {},
|
|
6703
6703
|
...options?.caller !== void 0 ? { caller: options.caller } : {},
|
|
6704
6704
|
timeoutMs: options?.timeoutMs
|
|
@@ -6722,7 +6722,7 @@ function event(data) {
|
|
|
6722
6722
|
}
|
|
6723
6723
|
var StaticDirOutputSchema$1 = object({ staticDir: string() });
|
|
6724
6724
|
var VersionOutputSchema$1 = object({ version: string() });
|
|
6725
|
-
method(_void(), StaticDirOutputSchema$1), method(_void(), VersionOutputSchema$1);
|
|
6725
|
+
method(_void(), StaticDirOutputSchema$1, { auth: "admin" }), method(_void(), VersionOutputSchema$1, { auth: "admin" });
|
|
6726
6726
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
6727
6727
|
DeviceType["Camera"] = "camera";
|
|
6728
6728
|
DeviceType["Hub"] = "hub";
|
|
@@ -7043,7 +7043,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
7043
7043
|
}({});
|
|
7044
7044
|
var StaticDirOutputSchema = object({ staticDir: string() });
|
|
7045
7045
|
var VersionOutputSchema = object({ version: string() });
|
|
7046
|
-
method(_void(), StaticDirOutputSchema), method(_void(), VersionOutputSchema);
|
|
7046
|
+
method(_void(), StaticDirOutputSchema, { auth: "admin" }), method(_void(), VersionOutputSchema, { auth: "admin" });
|
|
7047
7047
|
/**
|
|
7048
7048
|
* device-ops — device-scoped cap that unifies the per-IDevice operations
|
|
7049
7049
|
* previously routed through the `.device-ops` Moleculer bridge service.
|
|
@@ -7677,24 +7677,6 @@ var RecordingRetentionSchema = object({
|
|
|
7677
7677
|
maxSizeGb: number().min(0).optional()
|
|
7678
7678
|
});
|
|
7679
7679
|
/**
|
|
7680
|
-
* Scrub-thumbnail fidelity preset — the single per-camera selector bundling the
|
|
7681
|
-
* sprite tile RESOLUTION + JPEG QUALITY the recorder packs timeline-scrub
|
|
7682
|
-
* previews at. Five graduated steps; absent on a config = `standard` (the
|
|
7683
|
-
* shipped default, matching `sheet-geometry`/`sheet-composer`).
|
|
7684
|
-
*
|
|
7685
|
-
* Existing sheets are IMMUTABLE — a changed preset applies to NEW windows only.
|
|
7686
|
-
* Each window's index sidecar carries its own tile dims, so a camera whose
|
|
7687
|
-
* preset changed over time renders every historical window at the dims it was
|
|
7688
|
-
* written with.
|
|
7689
|
-
*/
|
|
7690
|
-
var ScrubThumbnailPresetSchema = _enum([
|
|
7691
|
-
"minimal",
|
|
7692
|
-
"low",
|
|
7693
|
-
"standard",
|
|
7694
|
-
"high",
|
|
7695
|
-
"max"
|
|
7696
|
-
]);
|
|
7697
|
-
/**
|
|
7698
7680
|
* The full per-camera recording intent — the wire shape of a RecordingTarget.
|
|
7699
7681
|
*
|
|
7700
7682
|
* `bands` is the ONLY authored recording intent: what to record, when, and on
|
|
@@ -7702,7 +7684,11 @@ var ScrubThumbnailPresetSchema = _enum([
|
|
|
7702
7684
|
* other field is a storage knob (profiles, segment length, retention, scrub).
|
|
7703
7685
|
*
|
|
7704
7686
|
* STRICT on purpose: the legacy authoring surface (`schedule`/`schedules`/
|
|
7705
|
-
* `triggers`/`preBufferSec`/`postBufferSec`/`rules`) was retired 2026-07-30
|
|
7687
|
+
* `triggers`/`preBufferSec`/`postBufferSec`/`rules`) was retired 2026-07-30,
|
|
7688
|
+
* and `scrubThumbnails` — a five-step fidelity knob for a sprite tier that was
|
|
7689
|
+
* deleted on 2026-07-24 and had ZERO consumers in the recorder — on 2026-08-25
|
|
7690
|
+
* (D62: a switch that writes a store nobody reads is worse than no switch).
|
|
7691
|
+
* Stored rows keep loading: the READ schema is `.strip()` (config-store.ts).
|
|
7706
7692
|
* A stale caller must fail loudly — silently stripping its legacy intent would
|
|
7707
7693
|
* persist a band-less config, i.e. silently stop recording the camera.
|
|
7708
7694
|
*/
|
|
@@ -7725,14 +7711,7 @@ var RecordingConfigSchema = object({
|
|
|
7725
7711
|
* "off" is the absence of a covering band, never a band value.
|
|
7726
7712
|
*/
|
|
7727
7713
|
bands: array(RecordingBandSchema).default([]),
|
|
7728
|
-
retention: RecordingRetentionSchema.optional()
|
|
7729
|
-
/**
|
|
7730
|
-
* Per-camera scrub-thumbnail fidelity preset (resolution + JPEG quality for
|
|
7731
|
-
* timeline-scrub sprite previews). Absent = `standard`. Applies to NEW
|
|
7732
|
-
* windows only — existing sheets are immutable, and each window's index
|
|
7733
|
-
* carries its own tile dims so mixed-preset history renders correctly.
|
|
7734
|
-
*/
|
|
7735
|
-
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7714
|
+
retention: RecordingRetentionSchema.optional()
|
|
7736
7715
|
}).strict();
|
|
7737
7716
|
/**
|
|
7738
7717
|
* Entity-relocation job state (storage entity-routing spec, Phase 4).
|
|
@@ -7808,10 +7787,11 @@ var RelocateFootageInputSchema = object({
|
|
|
7808
7787
|
* `RecordingConfig.enabled` or camera wrapper bindings. */
|
|
7809
7788
|
var StorageMigrationLeaseInputSchema = object({ leaseId: string().min(1) });
|
|
7810
7789
|
var StorageMigrationFootageMoveInputSchema = RelocateFootageInputSchema.extend({ leaseId: string().min(1) });
|
|
7811
|
-
var
|
|
7790
|
+
var RelocateMediaInputSchema = object({
|
|
7812
7791
|
toLocationId: string(),
|
|
7813
7792
|
throttleMbps: number().min(1).max(1e3).optional()
|
|
7814
|
-
})
|
|
7793
|
+
});
|
|
7794
|
+
var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: string().min(1) });
|
|
7815
7795
|
/** The independently selectable logical storage classes. `recordings`
|
|
7816
7796
|
* encompasses the high and mid segment profiles; `recordingsLow` is low
|
|
7817
7797
|
* segments; `eventMedia` is post-analysis blobs. */
|
|
@@ -8106,7 +8086,26 @@ var LabelDefinitionSchema = object({
|
|
|
8106
8086
|
description: string().optional(),
|
|
8107
8087
|
icon: string().optional()
|
|
8108
8088
|
});
|
|
8109
|
-
|
|
8089
|
+
/**
|
|
8090
|
+
* Wire schema for a per-model CATALOG classMap override
|
|
8091
|
+
* (`ModelCatalogEntry.classMap` / `ModelConvertMetadata.classMap`) —
|
|
8092
|
+
* restricted to {@link CLASS_MAP_MACRO_TARGETS}, the only macros the
|
|
8093
|
+
* detection pipeline executor actually routes.
|
|
8094
|
+
*
|
|
8095
|
+
* This is deliberately a DIFFERENT, narrower shape than the general-purpose
|
|
8096
|
+
* `ClassMapDefinition` interface above (e.g. `IDetectionAddon.getClassMap()`
|
|
8097
|
+
* and the audio `YAMNET_TO_MACRO` catalog both use macro targets outside this
|
|
8098
|
+
* enum) — the two used to share the name `ClassMapDefinition`/
|
|
8099
|
+
* `ClassMapDefinitionSchema`, which made the schema-type-twin guard
|
|
8100
|
+
* (`scripts/check-schema-type-twins.ts`) flag them as a duplicated shape. They
|
|
8101
|
+
* are not: it is two different concepts colliding on a name. Keep this type
|
|
8102
|
+
* under its own name rather than reusing `ClassMapDefinition` — reusing it
|
|
8103
|
+
* would either narrow every `ClassMapDefinition` consumer to the four
|
|
8104
|
+
* detection macros (breaking `YAMNET_TO_MACRO`) or drop the validation this
|
|
8105
|
+
* schema exists for (see the "rejects a classMap whose target is not a
|
|
8106
|
+
* detection macro" test in `model-catalog-schema.test.ts`).
|
|
8107
|
+
*/
|
|
8108
|
+
var DetectionCatalogClassMapSchema = object({
|
|
8110
8109
|
mapping: record(string(), _enum([
|
|
8111
8110
|
"person",
|
|
8112
8111
|
"vehicle",
|
|
@@ -8311,7 +8310,7 @@ var ModelCatalogEntrySchema = object({
|
|
|
8311
8310
|
* applies (Frigate / COCO public catalog). Set on a custom model whose raw
|
|
8312
8311
|
* labels already ARE the CamStack macros (Scrypted identity map).
|
|
8313
8312
|
*/
|
|
8314
|
-
classMap:
|
|
8313
|
+
classMap: DetectionCatalogClassMapSchema.optional()
|
|
8315
8314
|
});
|
|
8316
8315
|
var ConvertTargetSchema = discriminatedUnion("format", [object({
|
|
8317
8316
|
format: literal("openvino"),
|
|
@@ -8341,7 +8340,7 @@ var ModelConvertMetadataSchema = object({
|
|
|
8341
8340
|
"segmentation"
|
|
8342
8341
|
]),
|
|
8343
8342
|
faceAlignment: boolean().optional(),
|
|
8344
|
-
classMap:
|
|
8343
|
+
classMap: DetectionCatalogClassMapSchema.optional()
|
|
8345
8344
|
});
|
|
8346
8345
|
var ConvertResultSchema = object({
|
|
8347
8346
|
entry: ModelCatalogEntrySchema,
|
|
@@ -9204,7 +9203,7 @@ var AddonPageDeclarationSchema = object({
|
|
|
9204
9203
|
/** Display label for a CUSTOM `section` id (ignored for well-known ids). */
|
|
9205
9204
|
sectionLabel: string().optional()
|
|
9206
9205
|
});
|
|
9207
|
-
method(_void(), array(AddonPageDeclarationSchema).readonly());
|
|
9206
|
+
method(_void(), array(AddonPageDeclarationSchema).readonly(), { auth: "admin" });
|
|
9208
9207
|
var AddonHttpRouteSchema = object({
|
|
9209
9208
|
method: _enum([
|
|
9210
9209
|
"GET",
|
|
@@ -9439,7 +9438,7 @@ var WidgetMetadataSchema = object({
|
|
|
9439
9438
|
defaultColumns: number().int().min(1).max(12).default(6),
|
|
9440
9439
|
defaultRows: number().int().min(1).max(12).default(1)
|
|
9441
9440
|
});
|
|
9442
|
-
method(_void(), array(WidgetMetadataSchema).readonly());
|
|
9441
|
+
method(_void(), array(WidgetMetadataSchema).readonly(), { auth: "admin" });
|
|
9443
9442
|
/**
|
|
9444
9443
|
* `addon-widgets` — system-scoped singleton aggregator cap. Public-facing
|
|
9445
9444
|
* surface that admin-ui consumes through `useAddonWidgetsListWidgets()`.
|
|
@@ -11063,7 +11062,7 @@ var CustomModelDescriptorSchema = object({
|
|
|
11063
11062
|
stepId: string(),
|
|
11064
11063
|
entry: ModelCatalogEntrySchema
|
|
11065
11064
|
});
|
|
11066
|
-
method(_void(), array(CustomModelDescriptorSchema).readonly());
|
|
11065
|
+
method(_void(), array(CustomModelDescriptorSchema).readonly(), { auth: "admin" });
|
|
11067
11066
|
/**
|
|
11068
11067
|
* Query filter for settings-store collections.
|
|
11069
11068
|
*/
|
|
@@ -11150,7 +11149,8 @@ method(object({
|
|
|
11150
11149
|
}), _void(), { kind: "mutation" }), method(object({
|
|
11151
11150
|
namespace: string().optional(),
|
|
11152
11151
|
collection: string(),
|
|
11153
|
-
filter: QueryFilterSchema.optional()
|
|
11152
|
+
filter: QueryFilterSchema.optional(),
|
|
11153
|
+
columns: array(string()).readonly().optional()
|
|
11154
11154
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
11155
11155
|
namespace: string().optional(),
|
|
11156
11156
|
collection: string(),
|
|
@@ -11213,46 +11213,87 @@ var EngineInfoSchema = object({
|
|
|
11213
11213
|
kind: _enum(["relational", "vector"]),
|
|
11214
11214
|
displayName: string()
|
|
11215
11215
|
});
|
|
11216
|
-
method(_void(), EngineInfoSchema), method(object({
|
|
11216
|
+
method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
11217
11217
|
namespace: string().optional(),
|
|
11218
11218
|
collection: string(),
|
|
11219
11219
|
key: string()
|
|
11220
|
-
}), unknown()), method(object({
|
|
11220
|
+
}), unknown(), { auth: "admin" }), method(object({
|
|
11221
11221
|
namespace: string().optional(),
|
|
11222
11222
|
collection: string(),
|
|
11223
11223
|
key: string(),
|
|
11224
11224
|
value: unknown()
|
|
11225
|
-
}), _void(), {
|
|
11225
|
+
}), _void(), {
|
|
11226
|
+
kind: "mutation",
|
|
11227
|
+
auth: "admin"
|
|
11228
|
+
}), method(object({
|
|
11226
11229
|
namespace: string().optional(),
|
|
11227
11230
|
collection: string(),
|
|
11228
|
-
filter: QueryFilterSchema.optional()
|
|
11229
|
-
|
|
11231
|
+
filter: QueryFilterSchema.optional(),
|
|
11232
|
+
/**
|
|
11233
|
+
* SQL-level column projection — MUST mirror `settings-store.query`.
|
|
11234
|
+
*
|
|
11235
|
+
* ⚠ An earlier version of this comment blamed Zod stripping, and that
|
|
11236
|
+
* was wrong — corrected 2026-08-26 after the hop map
|
|
11237
|
+
* (`docs/design/2026-08-26-mappa-hop-argomenti.md`) traced the path.
|
|
11238
|
+
* There is **no Zod parse at all** between the door and the engine: the
|
|
11239
|
+
* dispatcher forwards the payload verbatim and UDS carries it whole. A
|
|
11240
|
+
* field declared here reaches `SqliteSettingsBackend` either way.
|
|
11241
|
+
*
|
|
11242
|
+
* What actually lost `columns` was the THIRD declaration of this shape:
|
|
11243
|
+
* `SettingsQueryInput` in `interfaces/storage.ts`, a hand-written TS
|
|
11244
|
+
* interface the engine destructures from. The field existed on both
|
|
11245
|
+
* schemas and the engine still never read it, because nothing checks a
|
|
11246
|
+
* registered provider against `InferProvider<cap>` —
|
|
11247
|
+
* `ProviderRegistration.provider` is typed `object`.
|
|
11248
|
+
*
|
|
11249
|
+
* It is declared here anyway, and must stay in step with
|
|
11250
|
+
* `settings-store.query`: a caller reading only the cap definitions has
|
|
11251
|
+
* to be able to see that this call carries a projection.
|
|
11252
|
+
* `data-door-schema-parity.spec.ts` keeps the two aligned.
|
|
11253
|
+
*/
|
|
11254
|
+
columns: array(string()).readonly().optional()
|
|
11255
|
+
}), array(SettingsRecordSchema).readonly(), { auth: "admin" }), method(object({
|
|
11230
11256
|
namespace: string().optional(),
|
|
11231
11257
|
collection: string(),
|
|
11232
11258
|
record: SettingsRecordSchema
|
|
11233
|
-
}), _void(), {
|
|
11259
|
+
}), _void(), {
|
|
11260
|
+
kind: "mutation",
|
|
11261
|
+
auth: "admin"
|
|
11262
|
+
}), method(object({
|
|
11234
11263
|
namespace: string().optional(),
|
|
11235
11264
|
collection: string(),
|
|
11236
11265
|
id: string(),
|
|
11237
11266
|
data: record(string(), unknown())
|
|
11238
|
-
}), _void(), {
|
|
11267
|
+
}), _void(), {
|
|
11268
|
+
kind: "mutation",
|
|
11269
|
+
auth: "admin"
|
|
11270
|
+
}), method(object({
|
|
11239
11271
|
namespace: string().optional(),
|
|
11240
11272
|
collection: string(),
|
|
11241
11273
|
key: string()
|
|
11242
|
-
}), _void(), {
|
|
11274
|
+
}), _void(), {
|
|
11275
|
+
kind: "mutation",
|
|
11276
|
+
auth: "admin"
|
|
11277
|
+
}), method(object({
|
|
11243
11278
|
namespace: string().optional(),
|
|
11244
11279
|
collection: string(),
|
|
11245
11280
|
filter: MutationFilterSchema
|
|
11246
|
-
}), object({ deleted: number().int() }), {
|
|
11281
|
+
}), object({ deleted: number().int() }), {
|
|
11282
|
+
kind: "mutation",
|
|
11283
|
+
auth: "admin"
|
|
11284
|
+
}), method(object({
|
|
11247
11285
|
namespace: string().optional(),
|
|
11248
11286
|
collection: string(),
|
|
11249
11287
|
filter: MutationFilterSchema,
|
|
11250
11288
|
data: record(string(), unknown())
|
|
11251
|
-
}), object({ updated: number().int() }), {
|
|
11289
|
+
}), object({ updated: number().int() }), {
|
|
11290
|
+
kind: "mutation",
|
|
11291
|
+
auth: "admin"
|
|
11292
|
+
}), method(object({
|
|
11252
11293
|
namespace: string().optional(),
|
|
11253
11294
|
collection: string(),
|
|
11254
11295
|
filter: QueryFilterSchema.optional()
|
|
11255
|
-
}), number()), method(object({
|
|
11296
|
+
}), number(), { auth: "admin" }), method(object({
|
|
11256
11297
|
namespace: string().optional(),
|
|
11257
11298
|
collection: string(),
|
|
11258
11299
|
field: string(),
|
|
@@ -11262,15 +11303,18 @@ method(_void(), EngineInfoSchema), method(object({
|
|
|
11262
11303
|
}), array(object({
|
|
11263
11304
|
bucket: number().int(),
|
|
11264
11305
|
count: number().int()
|
|
11265
|
-
})).readonly()), method(object({
|
|
11306
|
+
})).readonly(), { auth: "admin" }), method(object({
|
|
11266
11307
|
namespace: string().optional(),
|
|
11267
11308
|
collection: string()
|
|
11268
|
-
}), boolean()), method(object({
|
|
11309
|
+
}), boolean(), { auth: "admin" }), method(object({
|
|
11269
11310
|
namespace: string().optional(),
|
|
11270
11311
|
collection: string(),
|
|
11271
11312
|
columns: array(CollectionColumnSchema).readonly(),
|
|
11272
11313
|
indexes: array(CollectionIndexSchema).readonly().optional()
|
|
11273
|
-
}), _void(), {
|
|
11314
|
+
}), _void(), {
|
|
11315
|
+
kind: "mutation",
|
|
11316
|
+
auth: "admin"
|
|
11317
|
+
});
|
|
11274
11318
|
/**
|
|
11275
11319
|
* shm ring usage stats for a `frameSink: 'shm'` decoder session —
|
|
11276
11320
|
* exposed via `decoder.getShmStats` so downstream consumers can
|
|
@@ -12505,7 +12549,7 @@ method(object({
|
|
|
12505
12549
|
crop: _instanceof(Uint8Array),
|
|
12506
12550
|
width: number(),
|
|
12507
12551
|
height: number()
|
|
12508
|
-
}), EmbeddingResultSchema), method(object({ text: string() }), EmbeddingResultSchema), method(_void(), EmbeddingInfoSchema);
|
|
12552
|
+
}), EmbeddingResultSchema, { auth: "admin" }), method(object({ text: string() }), EmbeddingResultSchema, { auth: "admin" }), method(_void(), EmbeddingInfoSchema, { auth: "admin" });
|
|
12509
12553
|
/**
|
|
12510
12554
|
* filesystem-browse — per-node capability for browsing the node's local
|
|
12511
12555
|
* filesystem. Reads are unconfined (whole filesystem, from `/` down); WRITES
|
|
@@ -12798,19 +12842,22 @@ method(LlmGenerateBaseInputSchema.extend({
|
|
|
12798
12842
|
runtime: ManagedRuntimeConfigSchema,
|
|
12799
12843
|
/** The managed profile's timeout, threaded by the hub provider. */
|
|
12800
12844
|
timeoutMs: number().int().positive().optional()
|
|
12801
|
-
}), LlmGenerateResultSchema, {
|
|
12845
|
+
}), LlmGenerateResultSchema, {
|
|
12846
|
+
kind: "mutation",
|
|
12847
|
+
auth: "admin"
|
|
12848
|
+
}), method(object({ runtime: ManagedRuntimeConfigSchema }), LlmRuntimeStatusSchema, {
|
|
12802
12849
|
kind: "mutation",
|
|
12803
12850
|
auth: "admin"
|
|
12804
12851
|
}), method(object({}), _void(), {
|
|
12805
12852
|
kind: "mutation",
|
|
12806
12853
|
auth: "admin"
|
|
12807
|
-
}), method(object({}), LlmRuntimeStatusSchema), method(object({ model: ManagedModelRefSchema }), _void(), {
|
|
12854
|
+
}), method(object({}), LlmRuntimeStatusSchema, { auth: "admin" }), method(object({ model: ManagedModelRefSchema }), _void(), {
|
|
12808
12855
|
kind: "mutation",
|
|
12809
12856
|
auth: "admin"
|
|
12810
12857
|
}), method(object({ file: string() }), _void(), {
|
|
12811
12858
|
kind: "mutation",
|
|
12812
12859
|
auth: "admin"
|
|
12813
|
-
}), method(object({}), array(LlmNodeModelSchema)), method(object({}), LlmRuntimeDiskUsageSchema);
|
|
12860
|
+
}), method(object({}), array(LlmNodeModelSchema), { auth: "admin" }), method(object({}), LlmRuntimeDiskUsageSchema, { auth: "admin" });
|
|
12814
12861
|
/**
|
|
12815
12862
|
* `llm` — consumer-facing LLM surface (spec §1-§3). Collection-mode: array
|
|
12816
12863
|
* methods concat-fan across providers; single-row methods route to ONE
|
|
@@ -16321,7 +16368,647 @@ var OauthIntegrationDescriptorSchema = object({
|
|
|
16321
16368
|
*/
|
|
16322
16369
|
refreshTokenTtlSec: union([number().int().positive(), literal("never")]).optional()
|
|
16323
16370
|
});
|
|
16324
|
-
method(_void(), OauthIntegrationDescriptorSchema);
|
|
16371
|
+
method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" });
|
|
16372
|
+
/**
|
|
16373
|
+
* Reference to the frame's retained NATIVE surface + the parent crop's placement
|
|
16374
|
+
* within the frame, so the executor can re-cut a leaf child ROI at native
|
|
16375
|
+
* resolution on the detail plane. See the `runPipeline` `nativeCropRef` field.
|
|
16376
|
+
*/
|
|
16377
|
+
var NativeCropRefSchema = object({
|
|
16378
|
+
/** Handle keying the retained native surface (node-pinned to its owner). */
|
|
16379
|
+
handle: FrameHandleSchema,
|
|
16380
|
+
/** The parent crop's padded/clamped rectangle in FRAME-space pixels. */
|
|
16381
|
+
cropFrameSpace: object({
|
|
16382
|
+
x: number(),
|
|
16383
|
+
y: number(),
|
|
16384
|
+
w: number(),
|
|
16385
|
+
h: number()
|
|
16386
|
+
})
|
|
16387
|
+
});
|
|
16388
|
+
object({
|
|
16389
|
+
crop: object({
|
|
16390
|
+
left: number(),
|
|
16391
|
+
top: number(),
|
|
16392
|
+
width: number().positive(),
|
|
16393
|
+
height: number().positive()
|
|
16394
|
+
}).optional(),
|
|
16395
|
+
content: object({
|
|
16396
|
+
width: number().int().positive(),
|
|
16397
|
+
height: number().int().positive()
|
|
16398
|
+
}),
|
|
16399
|
+
fit: _enum(["stretch", "contain"]),
|
|
16400
|
+
format: _enum([
|
|
16401
|
+
"rgb",
|
|
16402
|
+
"gray",
|
|
16403
|
+
"jpeg"
|
|
16404
|
+
])
|
|
16405
|
+
});
|
|
16406
|
+
/**
|
|
16407
|
+
* Process-local frame identity. It is serializable so it can ride an in-process
|
|
16408
|
+
* capability call, but `registryId` deliberately prevents resolution in any
|
|
16409
|
+
* other process or execution group.
|
|
16410
|
+
*/
|
|
16411
|
+
var FrameRefSchema = object({
|
|
16412
|
+
registryId: string().min(1),
|
|
16413
|
+
id: string().min(1),
|
|
16414
|
+
width: number().int().positive(),
|
|
16415
|
+
height: number().int().positive(),
|
|
16416
|
+
format: _enum(["rgb", "gray"]),
|
|
16417
|
+
timestamp: number(),
|
|
16418
|
+
capturedAt: number().optional()
|
|
16419
|
+
});
|
|
16420
|
+
var ModelFormatSchema$1 = _enum([
|
|
16421
|
+
"onnx",
|
|
16422
|
+
"coreml",
|
|
16423
|
+
"openvino",
|
|
16424
|
+
"tflite",
|
|
16425
|
+
"pt",
|
|
16426
|
+
"gguf"
|
|
16427
|
+
]);
|
|
16428
|
+
var PipelineSlotSchema = _enum([
|
|
16429
|
+
"detector",
|
|
16430
|
+
"cropper",
|
|
16431
|
+
"classifier",
|
|
16432
|
+
"refiner",
|
|
16433
|
+
"audio-classifier"
|
|
16434
|
+
]);
|
|
16435
|
+
var PipelineEngineChoiceSchema = object({
|
|
16436
|
+
runtime: _enum(["node", "python"]),
|
|
16437
|
+
backend: string(),
|
|
16438
|
+
format: ModelFormatSchema$1,
|
|
16439
|
+
device: string().optional()
|
|
16440
|
+
});
|
|
16441
|
+
var AvailableEngineSchema = object({
|
|
16442
|
+
engine: PipelineEngineChoiceSchema,
|
|
16443
|
+
devices: array(object({
|
|
16444
|
+
id: string(),
|
|
16445
|
+
label: string(),
|
|
16446
|
+
description: string().optional()
|
|
16447
|
+
})).readonly(),
|
|
16448
|
+
defaultDevice: string()
|
|
16449
|
+
});
|
|
16450
|
+
var PipelineDefaultStepSchema = lazy(() => object({
|
|
16451
|
+
addonId: string(),
|
|
16452
|
+
addonName: string(),
|
|
16453
|
+
slot: PipelineSlotSchema,
|
|
16454
|
+
inputClasses: array(string()).readonly(),
|
|
16455
|
+
outputClasses: array(string()).readonly(),
|
|
16456
|
+
enabled: boolean(),
|
|
16457
|
+
modelId: string(),
|
|
16458
|
+
children: array(PipelineDefaultStepSchema).readonly(),
|
|
16459
|
+
group: string().optional(),
|
|
16460
|
+
settings: record(string(), unknown()).optional()
|
|
16461
|
+
}));
|
|
16462
|
+
var PipelineTemplateStepSchema = lazy(() => object({
|
|
16463
|
+
addonId: string(),
|
|
16464
|
+
enabled: boolean(),
|
|
16465
|
+
modelId: string(),
|
|
16466
|
+
children: array(PipelineTemplateStepSchema).readonly(),
|
|
16467
|
+
settings: record(string(), unknown()).optional()
|
|
16468
|
+
}));
|
|
16469
|
+
var PipelineTemplateSchema$1 = object({
|
|
16470
|
+
id: string(),
|
|
16471
|
+
name: string(),
|
|
16472
|
+
createdAt: string(),
|
|
16473
|
+
updatedAt: string(),
|
|
16474
|
+
engine: PipelineEngineChoiceSchema,
|
|
16475
|
+
steps: array(PipelineTemplateStepSchema).readonly()
|
|
16476
|
+
});
|
|
16477
|
+
var PipelineModelOptionSchema = object({
|
|
16478
|
+
id: string(),
|
|
16479
|
+
name: string(),
|
|
16480
|
+
formats: record(string(), object({
|
|
16481
|
+
downloaded: boolean(),
|
|
16482
|
+
sizeMB: number()
|
|
16483
|
+
})),
|
|
16484
|
+
group: ModelVariantGroupSchema.optional(),
|
|
16485
|
+
legacy: boolean().optional(),
|
|
16486
|
+
provider: ModelProviderIdSchema.optional()
|
|
16487
|
+
});
|
|
16488
|
+
var ConfigFieldBridge = custom();
|
|
16489
|
+
var PipelineAddonSchemaSchema = object({
|
|
16490
|
+
id: string(),
|
|
16491
|
+
name: string(),
|
|
16492
|
+
slot: PipelineSlotSchema,
|
|
16493
|
+
inputClasses: array(string()).readonly(),
|
|
16494
|
+
outputClasses: array(string()).readonly(),
|
|
16495
|
+
childSlots: array(PipelineSlotSchema).readonly(),
|
|
16496
|
+
models: array(PipelineModelOptionSchema).readonly(),
|
|
16497
|
+
defaultModelId: string(),
|
|
16498
|
+
defaultModelIdByFormat: record(string(), string()).optional(),
|
|
16499
|
+
enabledByDefault: boolean().optional(),
|
|
16500
|
+
backfillIntoExistingOverrides: boolean().optional(),
|
|
16501
|
+
defaultConfidence: number(),
|
|
16502
|
+
group: string().optional(),
|
|
16503
|
+
configSchema: array(ConfigFieldBridge).readonly().optional()
|
|
16504
|
+
});
|
|
16505
|
+
var PipelineSlotSchemaSchema = object({
|
|
16506
|
+
id: PipelineSlotSchema,
|
|
16507
|
+
label: string(),
|
|
16508
|
+
priority: number(),
|
|
16509
|
+
parentSlot: PipelineSlotSchema.nullable(),
|
|
16510
|
+
addons: array(PipelineAddonSchemaSchema).readonly()
|
|
16511
|
+
});
|
|
16512
|
+
var PipelineSchemaSchema = object({
|
|
16513
|
+
availableEngines: array(AvailableEngineSchema).readonly(),
|
|
16514
|
+
selectedEngine: PipelineEngineChoiceSchema,
|
|
16515
|
+
slots: array(PipelineSlotSchemaSchema).readonly()
|
|
16516
|
+
});
|
|
16517
|
+
var EngineProvisioningSchema = object({
|
|
16518
|
+
runtimeId: _enum([
|
|
16519
|
+
"onnx",
|
|
16520
|
+
"openvino",
|
|
16521
|
+
"coreml",
|
|
16522
|
+
"edgetpu"
|
|
16523
|
+
]).nullable(),
|
|
16524
|
+
device: string().nullable(),
|
|
16525
|
+
state: _enum([
|
|
16526
|
+
"idle",
|
|
16527
|
+
"installing",
|
|
16528
|
+
"verifying",
|
|
16529
|
+
"ready",
|
|
16530
|
+
"failed"
|
|
16531
|
+
]),
|
|
16532
|
+
progress: number().optional(),
|
|
16533
|
+
error: string().optional(),
|
|
16534
|
+
nextRetryAt: number().optional(),
|
|
16535
|
+
/**
|
|
16536
|
+
* Gate A (config-correctness gate at engine change): human-readable
|
|
16537
|
+
* config issues surfaced EAGERLY when the node's engine changes — model
|
|
16538
|
+
* substitutions ("chose X, running Y") and zero-build steps ("no model
|
|
16539
|
+
* has a <format> build"). Additive/optional: informational only, never
|
|
16540
|
+
* enforced here — `assertEngineReady` (readiness) still gates inference.
|
|
16541
|
+
* Absent/empty when the node-default tree resolves cleanly.
|
|
16542
|
+
*/
|
|
16543
|
+
configIssues: array(string()).optional()
|
|
16544
|
+
});
|
|
16545
|
+
var PipelineStepInputSchema = lazy(() => object({
|
|
16546
|
+
addonId: string(),
|
|
16547
|
+
modelId: string().optional(),
|
|
16548
|
+
enabled: boolean().default(true),
|
|
16549
|
+
children: array(PipelineStepInputSchema).optional(),
|
|
16550
|
+
settings: record(string(), unknown()).optional(),
|
|
16551
|
+
jumpDeviceKey: string().optional()
|
|
16552
|
+
}));
|
|
16553
|
+
var ModelSubstitutionSchema = object({
|
|
16554
|
+
addonId: string(),
|
|
16555
|
+
chosen: string(),
|
|
16556
|
+
running: string(),
|
|
16557
|
+
format: string()
|
|
16558
|
+
});
|
|
16559
|
+
var PipelineValidationIssueSchema = object({
|
|
16560
|
+
addonId: string(),
|
|
16561
|
+
kind: _enum(["unknown-addon", "no-format-build"]),
|
|
16562
|
+
detail: string()
|
|
16563
|
+
});
|
|
16564
|
+
var PipelineValidationResultSchema = object({
|
|
16565
|
+
ok: boolean(),
|
|
16566
|
+
issues: array(PipelineValidationIssueSchema).readonly(),
|
|
16567
|
+
substitutions: array(ModelSubstitutionSchema).readonly(),
|
|
16568
|
+
/** The node's `currentEngine.format` this validation ran against. */
|
|
16569
|
+
format: string()
|
|
16570
|
+
});
|
|
16571
|
+
var ReferenceImageEntrySchema = object({
|
|
16572
|
+
filename: string(),
|
|
16573
|
+
stepIds: array(string()).readonly().optional()
|
|
16574
|
+
});
|
|
16575
|
+
var ReferenceImageBodySchema = object({
|
|
16576
|
+
base64: string(),
|
|
16577
|
+
filename: string()
|
|
16578
|
+
});
|
|
16579
|
+
var ReferenceAudioEntrySchema = object({
|
|
16580
|
+
filename: string(),
|
|
16581
|
+
sizeKb: number()
|
|
16582
|
+
});
|
|
16583
|
+
var ReferenceAudioBodySchema = object({ base64: string() });
|
|
16584
|
+
var AudioBackendSchema = object({
|
|
16585
|
+
id: string(),
|
|
16586
|
+
name: string(),
|
|
16587
|
+
description: string(),
|
|
16588
|
+
available: boolean(),
|
|
16589
|
+
/**
|
|
16590
|
+
* Raw classifier labels this backend can emit (e.g. YAMNet's
|
|
16591
|
+
* 521-class set or Apple SoundAnalysis's 303-class set). Used by
|
|
16592
|
+
* the benchmark UI to populate the `enabledMicroClasses` filter
|
|
16593
|
+
* specific to the selected backend without a separate fetch.
|
|
16594
|
+
*/
|
|
16595
|
+
rawLabels: array(string()).readonly().optional()
|
|
16596
|
+
});
|
|
16597
|
+
var AudioCapabilitiesSchema = object({
|
|
16598
|
+
activeBackend: string(),
|
|
16599
|
+
availableBackends: array(AudioBackendSchema).readonly(),
|
|
16600
|
+
sampleRate: number(),
|
|
16601
|
+
chunkDurationMs: number()
|
|
16602
|
+
});
|
|
16603
|
+
var DownloadModelResultSchema = object({
|
|
16604
|
+
filePath: string(),
|
|
16605
|
+
sizeMB: number(),
|
|
16606
|
+
durationMs: number()
|
|
16607
|
+
});
|
|
16608
|
+
/**
|
|
16609
|
+
* Wrapper carrying a single test run's result. Replaces the legacy
|
|
16610
|
+
* ad-hoc `{labels: [{className, originalClass, score}]}` shape with the
|
|
16611
|
+
* canonical `AudioResult` from the Phase 6 output rework: one
|
|
16612
|
+
* `AudioDetection` per class above `minScore`, top-N candidates in
|
|
16613
|
+
* `debug.alternateLabels['audio-classifier']`, per-source timings in
|
|
16614
|
+
* `debug.stepTimings`. The outer `success`/`error` fields stay so the
|
|
16615
|
+
* benchmark UI can still report a clean failure when the classifier
|
|
16616
|
+
* cap isn't available.
|
|
16617
|
+
*/
|
|
16618
|
+
var AudioTestResultSchema = object({
|
|
16619
|
+
success: boolean(),
|
|
16620
|
+
error: string().optional(),
|
|
16621
|
+
frame: custom().optional()
|
|
16622
|
+
});
|
|
16623
|
+
var PipelineConfigBridge = custom();
|
|
16624
|
+
var ConfigUISchemaBridge = custom();
|
|
16625
|
+
var ConfigUISchemaNullableBridge = custom();
|
|
16626
|
+
var InferenceCapabilitiesBridge = custom();
|
|
16627
|
+
var ModelAvailabilityListBridge = custom();
|
|
16628
|
+
var PipelineRunResultBridge = custom();
|
|
16629
|
+
method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
|
|
16630
|
+
modelId: string(),
|
|
16631
|
+
settings: record(string(), unknown()).readonly()
|
|
16632
|
+
}))), method(object({ steps: record(string(), object({
|
|
16633
|
+
modelId: string(),
|
|
16634
|
+
settings: record(string(), unknown()).readonly()
|
|
16635
|
+
})) }), object({ success: literal(true) }), {
|
|
16636
|
+
kind: "mutation",
|
|
16637
|
+
auth: "admin"
|
|
16638
|
+
}), method(object({ nodeId: string() }), object({
|
|
16639
|
+
success: literal(true),
|
|
16640
|
+
clearedDevices: number()
|
|
16641
|
+
}), {
|
|
16642
|
+
kind: "mutation",
|
|
16643
|
+
auth: "admin"
|
|
16644
|
+
}), method(object({ nodeId: string() }), object({ unhealthy: array(object({
|
|
16645
|
+
/** `<backend>:<device>`, e.g. `openvino:gpu`. */
|
|
16646
|
+
deviceKey: string(),
|
|
16647
|
+
/**
|
|
16648
|
+
* `failed` — the per-device restart budget is exhausted; no pool
|
|
16649
|
+
* will be spawned until an operator re-arms it or the runner
|
|
16650
|
+
* respawns. `backoff` — under budget, waiting out the backoff (or
|
|
16651
|
+
* a cached pool observed dead and not yet condemned).
|
|
16652
|
+
*/
|
|
16653
|
+
state: _enum(["failed", "backoff"]),
|
|
16654
|
+
/** Epoch ms of the death that produced this state. */
|
|
16655
|
+
since: number(),
|
|
16656
|
+
/** Pool deaths inside the current window. */
|
|
16657
|
+
deaths: number(),
|
|
16658
|
+
/** The last death's message. */
|
|
16659
|
+
lastError: string()
|
|
16660
|
+
})).readonly() })), method(object({
|
|
16661
|
+
nodeId: string(),
|
|
16662
|
+
deviceKey: string()
|
|
16663
|
+
}), object({ rearmed: boolean() }), {
|
|
16664
|
+
kind: "mutation",
|
|
16665
|
+
auth: "admin"
|
|
16666
|
+
}), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({ steps: array(PipelineStepInputSchema) }), PipelineValidationResultSchema), method(_void(), array(PipelineTemplateSchema$1).readonly()), method(object({
|
|
16667
|
+
name: string(),
|
|
16668
|
+
steps: array(PipelineTemplateStepSchema).readonly(),
|
|
16669
|
+
engine: PipelineEngineChoiceSchema
|
|
16670
|
+
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({
|
|
16671
|
+
id: string(),
|
|
16672
|
+
name: string().optional(),
|
|
16673
|
+
steps: array(PipelineTemplateStepSchema).readonly().optional()
|
|
16674
|
+
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({ id: string() }), _void(), { kind: "mutation" }), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
|
|
16675
|
+
addonId: string(),
|
|
16676
|
+
modelId: string(),
|
|
16677
|
+
format: ModelFormatSchema$1
|
|
16678
|
+
}), DownloadModelResultSchema, { kind: "mutation" }), method(object({
|
|
16679
|
+
addonId: string(),
|
|
16680
|
+
modelId: string(),
|
|
16681
|
+
format: ModelFormatSchema$1
|
|
16682
|
+
}), object({ success: literal(true) }), { kind: "mutation" }), method(object({
|
|
16683
|
+
engine: PipelineEngineChoiceSchema.optional(),
|
|
16684
|
+
steps: array(PipelineStepInputSchema).min(1),
|
|
16685
|
+
frame: FrameInputSchema.optional(),
|
|
16686
|
+
/**
|
|
16687
|
+
* Process-local lazy frame. Valid only when caller and provider resolve
|
|
16688
|
+
* in the same execution-group process; split/cross-node callers use
|
|
16689
|
+
* `frame`/`image` inline compatibility instead.
|
|
16690
|
+
*/
|
|
16691
|
+
frameRef: FrameRefSchema.optional(),
|
|
16692
|
+
/**
|
|
16693
|
+
* CB5 shm passthrough — a `FrameHandle` naming the same ring slot
|
|
16694
|
+
* the decoded pixels live in. One more member of the one-of
|
|
16695
|
+
* frame/frameHandle/image/imageBase64/referenceImage group.
|
|
16696
|
+
*/
|
|
16697
|
+
frameHandle: FrameHandleSchema.optional(),
|
|
16698
|
+
imageBase64: string().optional(),
|
|
16699
|
+
/**
|
|
16700
|
+
* Binary JPEG bytes — preferred over `imageBase64` on internal
|
|
16701
|
+
* hops (hub → forked worker via Moleculer MsgPack) because it
|
|
16702
|
+
* skips the 33% base64 overhead + the per-call base64 decode on
|
|
16703
|
+
* the detection-pipeline worker. Callers can pass either; exactly
|
|
16704
|
+
* one of `frame`/`image`/`imageBase64`/`referenceImage` is required.
|
|
16705
|
+
*/
|
|
16706
|
+
image: _instanceof(Uint8Array).optional(),
|
|
16707
|
+
referenceImage: string().optional(),
|
|
16708
|
+
deviceId: number().optional(),
|
|
16709
|
+
sessionId: string().optional(),
|
|
16710
|
+
/**
|
|
16711
|
+
* Execution plane. 'full' (default) runs the whole tree — benchmark,
|
|
16712
|
+
* reference-image, and detail-subtree calls. 'frame' is the live
|
|
16713
|
+
* per-frame dispatch: ONLY root-plane steps run; crop children
|
|
16714
|
+
* (inputClasses ≠ null) are skipped and served per-track via
|
|
16715
|
+
* pipelineRunner.runDetailSubtree (two-plane design).
|
|
16716
|
+
*/
|
|
16717
|
+
plane: _enum(["full", "frame"]).optional(),
|
|
16718
|
+
/**
|
|
16719
|
+
* Inference-device selector (Phase 2 multi-device). Format
|
|
16720
|
+
* `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
|
|
16721
|
+
* Omitted ⇒ the runner's default device (current single-engine
|
|
16722
|
+
* behaviour). Selects WHICH device pool of the node runs the call.
|
|
16723
|
+
*/
|
|
16724
|
+
deviceKey: string().optional(),
|
|
16725
|
+
/**
|
|
16726
|
+
* Two-plane NATIVE child-crop reference. Set by `runDetailSubtree` ONLY
|
|
16727
|
+
* when the parent crop was resolved from the frame's retained NATIVE
|
|
16728
|
+
* surface (a frameHandle HIT). Lets the executor re-cut a LEAF crop
|
|
16729
|
+
* child's ROI (plate-ocr, face-embedding, leaf classifiers) at native
|
|
16730
|
+
* resolution from that surface — the SAME quality path faces already
|
|
16731
|
+
* had — instead of the downscaled parent tile. `handle` keys the native
|
|
16732
|
+
* surface (node-pinned to its owner); `cropFrameSpace` is the parent
|
|
16733
|
+
* crop's padded/clamped rectangle in FRAME-space pixels, used to compose
|
|
16734
|
+
* the executor's crop-normalized child ROI back into frame-normalized
|
|
16735
|
+
* coordinates. Auxiliary to the image source (`image`/`frame`/…), NOT one
|
|
16736
|
+
* of the mutually-exclusive image inputs. Absent ⇒ tile-crop children
|
|
16737
|
+
* (today's behaviour on the fallback path).
|
|
16738
|
+
*/
|
|
16739
|
+
nativeCropRef: NativeCropRefSchema.optional()
|
|
16740
|
+
}), PipelineRunResultBridge, { kind: "mutation" }), method(object({
|
|
16741
|
+
engine: PipelineEngineChoiceSchema.optional(),
|
|
16742
|
+
steps: array(PipelineStepInputSchema).min(1),
|
|
16743
|
+
frames: array(FrameInputSchema).min(1).max(255),
|
|
16744
|
+
deviceId: number().optional(),
|
|
16745
|
+
sessionId: string().optional(),
|
|
16746
|
+
/**
|
|
16747
|
+
* Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
|
|
16748
|
+
* the batch to the Python pool's bench preprocess cache
|
|
16749
|
+
* (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
|
|
16750
|
+
* preprocessed ONCE and every later inference is a pure-inference cache
|
|
16751
|
+
* hit — the sustained-throughput run measures inference, not
|
|
16752
|
+
* decode+preprocess+infer. Omitted/0 for live frames (all different →
|
|
16753
|
+
* full preprocess every call, correct). Fresh per sustained run;
|
|
16754
|
+
* released via `uncacheFrame`.
|
|
16755
|
+
*/
|
|
16756
|
+
frameId: number().int().nonnegative().optional(),
|
|
16757
|
+
/** Inference-device selector (Phase 2 multi-device); see runPipeline. */
|
|
16758
|
+
deviceKey: string().optional()
|
|
16759
|
+
}), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
|
|
16760
|
+
data: _instanceof(Uint8Array),
|
|
16761
|
+
width: number().int().positive(),
|
|
16762
|
+
height: number().int().positive(),
|
|
16763
|
+
format: _enum([
|
|
16764
|
+
"rgb",
|
|
16765
|
+
"bgr",
|
|
16766
|
+
"gray"
|
|
16767
|
+
])
|
|
16768
|
+
}), object({
|
|
16769
|
+
frameId: number(),
|
|
16770
|
+
width: number(),
|
|
16771
|
+
height: number()
|
|
16772
|
+
}), { kind: "mutation" }), method(object({
|
|
16773
|
+
stepId: string(),
|
|
16774
|
+
frameId: number().int()
|
|
16775
|
+
}), record(string(), unknown()), { kind: "mutation" }), method(object({ frameId: number().int() }), _void(), { kind: "mutation" }), method(_void(), object({
|
|
16776
|
+
batchMode: string(),
|
|
16777
|
+
windowMs: number(),
|
|
16778
|
+
maxBatchSize: number(),
|
|
16779
|
+
concurrency: number()
|
|
16780
|
+
})), method(_void(), array(object({
|
|
16781
|
+
engineKey: string(),
|
|
16782
|
+
engine: PipelineEngineChoiceSchema,
|
|
16783
|
+
modelsLoaded: array(string()).readonly(),
|
|
16784
|
+
inUseByCameras: array(number()).readonly(),
|
|
16785
|
+
/**
|
|
16786
|
+
* Origin of this resident factory.
|
|
16787
|
+
* - `runtime` — main camera-serving engine (no idle TTL).
|
|
16788
|
+
* - `warm-override` — benchmark/test override held in the warm
|
|
16789
|
+
* cache; auto-disposed after the idle TTL.
|
|
16790
|
+
* - `device-pool` — a concurrent per-device pool (Phase 2
|
|
16791
|
+
* multi-device, keyed by `deviceKey`) resolved
|
|
16792
|
+
* via `resolveDeviceFactory`. Runs alongside the
|
|
16793
|
+
* `runtime` engine on a DIFFERENT accelerator
|
|
16794
|
+
* (NPU / iGPU / Coral) — this is how the
|
|
16795
|
+
* Engines tab shows all pools running at once.
|
|
16796
|
+
*/
|
|
16797
|
+
kind: _enum([
|
|
16798
|
+
"runtime",
|
|
16799
|
+
"warm-override",
|
|
16800
|
+
"device-pool"
|
|
16801
|
+
]),
|
|
16802
|
+
/** Native pid of the underlying Python pool (null when no pool). */
|
|
16803
|
+
poolPid: number().nullable(),
|
|
16804
|
+
/** ms since this factory was last used (null when not warm-tracked). */
|
|
16805
|
+
idleMs: number().nullable(),
|
|
16806
|
+
/** Idle TTL after which `warm-override` factories self-evict (null when not applicable). */
|
|
16807
|
+
idleTtlMs: number().nullable()
|
|
16808
|
+
})).readonly()), method(object({ engine: PipelineEngineChoiceSchema }), object({ success: literal(true) }), {
|
|
16809
|
+
kind: "mutation",
|
|
16810
|
+
auth: "admin"
|
|
16811
|
+
}), method(object({
|
|
16812
|
+
engine: PipelineEngineChoiceSchema,
|
|
16813
|
+
force: boolean().optional()
|
|
16814
|
+
}), object({
|
|
16815
|
+
success: boolean(),
|
|
16816
|
+
reason: string().optional()
|
|
16817
|
+
}), {
|
|
16818
|
+
kind: "mutation",
|
|
16819
|
+
auth: "admin"
|
|
16820
|
+
}), method(_void(), array(ReferenceImageEntrySchema).readonly()), method(object({ filename: string() }), ReferenceImageBodySchema.nullable()), method(_void(), array(ReferenceAudioEntrySchema).readonly()), method(object({ filename: string() }), ReferenceAudioBodySchema.nullable()), method(_void(), AudioCapabilitiesSchema), method(object({
|
|
16821
|
+
addonId: string(),
|
|
16822
|
+
modelId: string(),
|
|
16823
|
+
filename: string().optional(),
|
|
16824
|
+
settings: record(string(), unknown()).optional()
|
|
16825
|
+
}), AudioTestResultSchema, { kind: "mutation" }), method(_void(), ConfigUISchemaNullableBridge);
|
|
16826
|
+
/**
|
|
16827
|
+
* Per-stage gating mode applied to the zones a rule references.
|
|
16828
|
+
*
|
|
16829
|
+
* - `include`: the rule contributes to a **whitelist** for its stage.
|
|
16830
|
+
* When at least one `include` rule fires for a stage, only entities
|
|
16831
|
+
* inside one of those zones pass that stage.
|
|
16832
|
+
* - `exclude`: the rule contributes to a **blacklist** for its stage.
|
|
16833
|
+
* Entities inside one of those zones are dropped at that stage.
|
|
16834
|
+
*
|
|
16835
|
+
* `monitor`-style observation (count without filtering) is not a rule
|
|
16836
|
+
* mode — zones without any matching rule are observed naturally by
|
|
16837
|
+
* `zone-analytics` (live snapshot + history), so an "I just want to
|
|
16838
|
+
* count, not filter" use case needs no rule at all.
|
|
16839
|
+
*/
|
|
16840
|
+
var ZoneRuleModeEnum = _enum(["include", "exclude"]);
|
|
16841
|
+
/**
|
|
16842
|
+
* Per-consumer rule that references existing zones (geometry) and
|
|
16843
|
+
* defines how a specific pipeline stage should treat them. Each
|
|
16844
|
+
* consumer addon owns its own `ZoneRule[]` array in its per-device
|
|
16845
|
+
* settings:
|
|
16846
|
+
*
|
|
16847
|
+
* - `addon-motion-wasm` → `motionZoneRules: ZoneRule[]` (motion stage)
|
|
16848
|
+
* - `addon-detection-pipeline` → `detectionZoneRules: ZoneRule[]` (detection stage)
|
|
16849
|
+
* - future: notification rules, audio gating, etc.
|
|
16850
|
+
*
|
|
16851
|
+
* One rule applies to N zones (`zoneIds[]`) so the operator can
|
|
16852
|
+
* express "ignore motion in ALL of {garden, street}" with a single
|
|
16853
|
+
* rule. `classFilter` narrows the rule to specific object classes —
|
|
16854
|
+
* "drop person detections in the street, but keep cars" is one
|
|
16855
|
+
* `exclude` rule with `classFilter: ['person']`.
|
|
16856
|
+
*
|
|
16857
|
+
* `enabled` is a soft toggle — the operator can keep the rule
|
|
16858
|
+
* configured but inert without deleting it.
|
|
16859
|
+
*/
|
|
16860
|
+
var ZoneRuleSchema = object({
|
|
16861
|
+
/** Stable rule id — survives edits, used by the UI for diffing. */
|
|
16862
|
+
id: string(),
|
|
16863
|
+
/** Optional human-readable label rendered in the rule editor. */
|
|
16864
|
+
name: string().optional(),
|
|
16865
|
+
/** Zones this rule targets. The rule's `mode` applies to ALL
|
|
16866
|
+
* listed zones (OR-set: a detection in any one of them counts).
|
|
16867
|
+
* At least one zone id required — a rule with no targets is a
|
|
16868
|
+
* configuration mistake and the form validator rejects it. */
|
|
16869
|
+
zoneIds: array(string()).min(1).readonly(),
|
|
16870
|
+
mode: ZoneRuleModeEnum,
|
|
16871
|
+
/**
|
|
16872
|
+
* Class names this rule applies to. Empty / undefined ⇒ rule
|
|
16873
|
+
* applies to every class. Class strings match the `macroClass`
|
|
16874
|
+
* field on detections (e.g. `person`, `car`, `dog`).
|
|
16875
|
+
*/
|
|
16876
|
+
classFilter: array(string()).readonly().optional(),
|
|
16877
|
+
/**
|
|
16878
|
+
* Minimum bbox/mask overlap (0–1) with any of the rule's zones
|
|
16879
|
+
* required to consider an entity "in the zone". Defaults to the
|
|
16880
|
+
* consumer's stage default when omitted. Kept for back-compat with
|
|
16881
|
+
* existing per-rule overrides; new operators pick the value via
|
|
16882
|
+
* `bboxInclusionPct` (operator-friendly 0–100). Whichever field is
|
|
16883
|
+
* set, the lower-level engine reads it as a 0–1 fraction.
|
|
16884
|
+
*/
|
|
16885
|
+
overlapThreshold: number().min(0).max(1).optional(),
|
|
16886
|
+
/**
|
|
16887
|
+
* Operator-friendly version of `overlapThreshold` — the percentage
|
|
16888
|
+
* of the detection's bbox that must lie inside the zone for the
|
|
16889
|
+
* rule to match. Documented default is 85%; the engine substitutes
|
|
16890
|
+
* that when the field is omitted (kept optional so existing rules
|
|
16891
|
+
* stored without it stay valid).
|
|
16892
|
+
*
|
|
16893
|
+
* When BOTH `overlapThreshold` and `bboxInclusionPct` are set on a
|
|
16894
|
+
* rule, the engine prefers `bboxInclusionPct` because it's the
|
|
16895
|
+
* field exposed in the UI. Internally both feed the same gate.
|
|
16896
|
+
*/
|
|
16897
|
+
bboxInclusionPct: number().min(0).max(100).optional(),
|
|
16898
|
+
/**
|
|
16899
|
+
* When `true` and a detection has a segmentation mask, use the
|
|
16900
|
+
* mask for overlap instead of the bbox. Detection-stage only;
|
|
16901
|
+
* motion rules ignore this field.
|
|
16902
|
+
*/
|
|
16903
|
+
preferMask: boolean().optional(),
|
|
16904
|
+
/**
|
|
16905
|
+
* Soft-toggle: `false` disables the rule without deleting it.
|
|
16906
|
+
* Defaults to `true` so operators creating a rule via the UI
|
|
16907
|
+
* see it active immediately.
|
|
16908
|
+
*/
|
|
16909
|
+
enabled: boolean().default(true)
|
|
16910
|
+
});
|
|
16911
|
+
array(ZoneRuleSchema).readonly();
|
|
16912
|
+
/**
|
|
16913
|
+
* Zone — pure geometry + identity. NO filtering behaviour.
|
|
16914
|
+
*
|
|
16915
|
+
* Zones describe **where** in the frame the operator wants to flag
|
|
16916
|
+
* something; consumer-owned {@link ZoneRule} arrays describe **how**
|
|
16917
|
+
* each pipeline stage uses them. Splitting the two means a single
|
|
16918
|
+
* polygon "Driveway" can simultaneously back a motion-exclude rule,
|
|
16919
|
+
* a detection-include rule on `['car']`, and an occupancy aggregate
|
|
16920
|
+
* — without three duplicated polygons.
|
|
16921
|
+
*
|
|
16922
|
+
* Owned by the orchestrator addon (provider) and mirrored into the
|
|
16923
|
+
* `zones` device-state slice on every mutation. Consumers
|
|
16924
|
+
* (motion-wasm, pipeline-executor, analytics, admin UI) read either
|
|
16925
|
+
* via `api.zones.listZones` (one-shot) or via `dev.state.zones` (live
|
|
16926
|
+
* mirror with `onChanged`).
|
|
16927
|
+
*
|
|
16928
|
+
* Coordinates are normalised fractions of the frame (0–1) so zones
|
|
16929
|
+
* survive resolution changes and stream profile switches.
|
|
16930
|
+
*
|
|
16931
|
+
* `kind` discriminates between full polygons (closed regions used
|
|
16932
|
+
* for intrusion / occupancy filters) and tripwires (open 2-point
|
|
16933
|
+
* line segments used for cross events). Onboard / firmware-reported
|
|
16934
|
+
* zones (Reolink, ONVIF) are out of scope for now — see the deferred
|
|
16935
|
+
* task list.
|
|
16936
|
+
*/
|
|
16937
|
+
var ZoneKindEnum = _enum(["polygon", "tripwire"]);
|
|
16938
|
+
/** Polygon vertex in fraction-of-frame coordinates (0–1). */
|
|
16939
|
+
var PolygonPointSchema = object({
|
|
16940
|
+
x: number(),
|
|
16941
|
+
y: number()
|
|
16942
|
+
});
|
|
16943
|
+
/** A camera detection zone — pure geometry/identity. */
|
|
16944
|
+
var ZoneSchema = object({
|
|
16945
|
+
id: string(),
|
|
16946
|
+
name: string(),
|
|
16947
|
+
kind: ZoneKindEnum.default("polygon"),
|
|
16948
|
+
/** Polygon vertices, fraction of frame (0–1). */
|
|
16949
|
+
polygon: array(PolygonPointSchema).readonly(),
|
|
16950
|
+
/** Visual color for UI rendering. */
|
|
16951
|
+
color: string().default("#3b82f6")
|
|
16952
|
+
});
|
|
16953
|
+
/**
|
|
16954
|
+
* Zones capability — per-camera CRUD over polygon detection zones.
|
|
16955
|
+
*
|
|
16956
|
+
* Provider lives in `addon-pipeline-orchestrator` (hub-only). Persists
|
|
16957
|
+
* to per-device settings and mirrors into the `zones` device-state
|
|
16958
|
+
* slice on every mutation, so downstream consumers can subscribe via
|
|
16959
|
+
* `dev.state.zones.onChanged`.
|
|
16960
|
+
*
|
|
16961
|
+
* The cap surface only handles geometry + identity; filtering
|
|
16962
|
+
* behaviour (per-class, include/exclude, threshold) lives in the
|
|
16963
|
+
* consumer addons' rule arrays — see `ZoneRuleSchema` exported from
|
|
16964
|
+
* `capabilities/schemas/zone-rule.js`.
|
|
16965
|
+
*/
|
|
16966
|
+
var zonesCapability = {
|
|
16967
|
+
name: "zones",
|
|
16968
|
+
scope: "device",
|
|
16969
|
+
mode: "singleton",
|
|
16970
|
+
deviceTypes: [DeviceType.Camera],
|
|
16971
|
+
methods: {
|
|
16972
|
+
listZones: method(object({ deviceId: number() }), array(ZoneSchema).readonly()),
|
|
16973
|
+
addZone: method(object({
|
|
16974
|
+
deviceId: number(),
|
|
16975
|
+
zone: ZoneSchema
|
|
16976
|
+
}), _void(), {
|
|
16977
|
+
kind: "mutation",
|
|
16978
|
+
auth: "admin"
|
|
16979
|
+
}),
|
|
16980
|
+
removeZone: method(object({
|
|
16981
|
+
deviceId: number(),
|
|
16982
|
+
zoneId: string()
|
|
16983
|
+
}), _void(), {
|
|
16984
|
+
kind: "mutation",
|
|
16985
|
+
auth: "admin"
|
|
16986
|
+
}),
|
|
16987
|
+
updateZone: method(object({
|
|
16988
|
+
deviceId: number(),
|
|
16989
|
+
zone: ZoneSchema
|
|
16990
|
+
}), _void(), {
|
|
16991
|
+
kind: "mutation",
|
|
16992
|
+
auth: "admin"
|
|
16993
|
+
})
|
|
16994
|
+
},
|
|
16995
|
+
/**
|
|
16996
|
+
* Runtime-state slice — the live zone catalogue mirrored by the
|
|
16997
|
+
* orchestrator on every CRUD mutation. Consumers read via
|
|
16998
|
+
* `device.state.zones.value` / `.watch(...)` without round-tripping
|
|
16999
|
+
* the cap, and the codegen DeviceProxy auto-wires the reactive
|
|
17000
|
+
* handle. Slice shape is `{ zones: Zone[] }` so future extensions
|
|
17001
|
+
* (e.g. zone groupings) can sit alongside the polygon list.
|
|
17002
|
+
*/
|
|
17003
|
+
runtimeState: object({ zones: array(ZoneSchema).readonly() }),
|
|
17004
|
+
/**
|
|
17005
|
+
* 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.
|
|
17006
|
+
*
|
|
17007
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
17008
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
17009
|
+
*/
|
|
17010
|
+
durability: "restored"
|
|
17011
|
+
};
|
|
16325
17012
|
/**
|
|
16326
17013
|
* pipeline-analytics — device-scoped wrapper cap. Refines raw
|
|
16327
17014
|
* per-frame detections emitted by the pipeline runner into tracked
|
|
@@ -17411,6 +18098,24 @@ var RebuildStatusSchema = object({
|
|
|
17411
18098
|
/** Present when the pass ended by throwing. */
|
|
17412
18099
|
error: string().nullable()
|
|
17413
18100
|
});
|
|
18101
|
+
var ReplayFrameInputSchema = object({
|
|
18102
|
+
timestamp: number(),
|
|
18103
|
+
frame: PipelineRunResultBridge
|
|
18104
|
+
});
|
|
18105
|
+
var RunReplayFrameProcessorResultSchema = object({ tracks: array(object({
|
|
18106
|
+
className: string(),
|
|
18107
|
+
firstSeenMs: number(),
|
|
18108
|
+
lastSeenMs: number(),
|
|
18109
|
+
/** Bbox of the track's FIRST matched detection, pixel-space in the clip's
|
|
18110
|
+
* frame — a representative box for the diff's `(className, window, IoU)`
|
|
18111
|
+
* pairing (`replay-diff.ts`). A replay does not need the full per-frame
|
|
18112
|
+
* trajectory production's `Track.positions` keeps. */
|
|
18113
|
+
bbox: BoundingBoxSchema,
|
|
18114
|
+
/** How many of the input frames this track matched a real detection on
|
|
18115
|
+
* (never a coasted/extrapolated frame) — the replay's own signal for "how
|
|
18116
|
+
* solid is this track", cheaper than re-deriving it from a trajectory. */
|
|
18117
|
+
framesMatched: number().int()
|
|
18118
|
+
})).readonly() });
|
|
17414
18119
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
17415
18120
|
deviceId: number(),
|
|
17416
18121
|
trackId: string()
|
|
@@ -17516,6 +18221,15 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17516
18221
|
}), method(object({ jobId: string() }), RelocateJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
17517
18222
|
kind: "mutation",
|
|
17518
18223
|
auth: "admin"
|
|
18224
|
+
}), method(RelocateMediaInputSchema, object({ jobId: string() }), {
|
|
18225
|
+
kind: "mutation",
|
|
18226
|
+
auth: "admin"
|
|
18227
|
+
}), method(object({}), array(RelocateJobSchema).readonly(), {
|
|
18228
|
+
kind: "query",
|
|
18229
|
+
auth: "admin"
|
|
18230
|
+
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
18231
|
+
kind: "mutation",
|
|
18232
|
+
auth: "admin"
|
|
17519
18233
|
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
17520
18234
|
kind: "query",
|
|
17521
18235
|
auth: "admin"
|
|
@@ -17572,6 +18286,16 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17572
18286
|
}), RetrainAssistResultSchema, {
|
|
17573
18287
|
kind: "mutation",
|
|
17574
18288
|
auth: "admin"
|
|
18289
|
+
}), method(object({
|
|
18290
|
+
deviceId: number(),
|
|
18291
|
+
source: DetectionSourceSchema,
|
|
18292
|
+
zones: array(ZoneSchema).readonly().optional(),
|
|
18293
|
+
detectionRules: array(ZoneRuleSchema).readonly().optional(),
|
|
18294
|
+
zoneMembershipMinOverlap: number().min(0).max(1).optional(),
|
|
18295
|
+
frames: array(ReplayFrameInputSchema).min(1)
|
|
18296
|
+
}), RunReplayFrameProcessorResultSchema, {
|
|
18297
|
+
kind: "mutation",
|
|
18298
|
+
auth: "admin"
|
|
17575
18299
|
}), method(object({ trackId: string() }), array(RetrainAnnotationSchema).readonly(), {
|
|
17576
18300
|
kind: "query",
|
|
17577
18301
|
auth: "admin"
|
|
@@ -17636,433 +18360,6 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17636
18360
|
eventId: string(),
|
|
17637
18361
|
timestamp: number()
|
|
17638
18362
|
});
|
|
17639
|
-
/**
|
|
17640
|
-
* Reference to the frame's retained NATIVE surface + the parent crop's placement
|
|
17641
|
-
* within the frame, so the executor can re-cut a leaf child ROI at native
|
|
17642
|
-
* resolution on the detail plane. See the `runPipeline` `nativeCropRef` field.
|
|
17643
|
-
*/
|
|
17644
|
-
var NativeCropRefSchema = object({
|
|
17645
|
-
/** Handle keying the retained native surface (node-pinned to its owner). */
|
|
17646
|
-
handle: FrameHandleSchema,
|
|
17647
|
-
/** The parent crop's padded/clamped rectangle in FRAME-space pixels. */
|
|
17648
|
-
cropFrameSpace: object({
|
|
17649
|
-
x: number(),
|
|
17650
|
-
y: number(),
|
|
17651
|
-
w: number(),
|
|
17652
|
-
h: number()
|
|
17653
|
-
})
|
|
17654
|
-
});
|
|
17655
|
-
object({
|
|
17656
|
-
crop: object({
|
|
17657
|
-
left: number(),
|
|
17658
|
-
top: number(),
|
|
17659
|
-
width: number().positive(),
|
|
17660
|
-
height: number().positive()
|
|
17661
|
-
}).optional(),
|
|
17662
|
-
content: object({
|
|
17663
|
-
width: number().int().positive(),
|
|
17664
|
-
height: number().int().positive()
|
|
17665
|
-
}),
|
|
17666
|
-
fit: _enum(["stretch", "contain"]),
|
|
17667
|
-
format: _enum([
|
|
17668
|
-
"rgb",
|
|
17669
|
-
"gray",
|
|
17670
|
-
"jpeg"
|
|
17671
|
-
])
|
|
17672
|
-
});
|
|
17673
|
-
var FrameRefSchema = object({
|
|
17674
|
-
registryId: string().min(1),
|
|
17675
|
-
id: string().min(1),
|
|
17676
|
-
width: number().int().positive(),
|
|
17677
|
-
height: number().int().positive(),
|
|
17678
|
-
format: _enum(["rgb", "gray"]),
|
|
17679
|
-
timestamp: number(),
|
|
17680
|
-
capturedAt: number().optional()
|
|
17681
|
-
});
|
|
17682
|
-
var ModelFormatSchema$1 = _enum([
|
|
17683
|
-
"onnx",
|
|
17684
|
-
"coreml",
|
|
17685
|
-
"openvino",
|
|
17686
|
-
"tflite",
|
|
17687
|
-
"pt",
|
|
17688
|
-
"gguf"
|
|
17689
|
-
]);
|
|
17690
|
-
var PipelineSlotSchema = _enum([
|
|
17691
|
-
"detector",
|
|
17692
|
-
"cropper",
|
|
17693
|
-
"classifier",
|
|
17694
|
-
"refiner",
|
|
17695
|
-
"audio-classifier"
|
|
17696
|
-
]);
|
|
17697
|
-
var PipelineEngineChoiceSchema = object({
|
|
17698
|
-
runtime: _enum(["node", "python"]),
|
|
17699
|
-
backend: string(),
|
|
17700
|
-
format: ModelFormatSchema$1,
|
|
17701
|
-
device: string().optional()
|
|
17702
|
-
});
|
|
17703
|
-
var AvailableEngineSchema = object({
|
|
17704
|
-
engine: PipelineEngineChoiceSchema,
|
|
17705
|
-
devices: array(object({
|
|
17706
|
-
id: string(),
|
|
17707
|
-
label: string(),
|
|
17708
|
-
description: string().optional()
|
|
17709
|
-
})).readonly(),
|
|
17710
|
-
defaultDevice: string()
|
|
17711
|
-
});
|
|
17712
|
-
var PipelineDefaultStepSchema = lazy(() => object({
|
|
17713
|
-
addonId: string(),
|
|
17714
|
-
addonName: string(),
|
|
17715
|
-
slot: PipelineSlotSchema,
|
|
17716
|
-
inputClasses: array(string()).readonly(),
|
|
17717
|
-
outputClasses: array(string()).readonly(),
|
|
17718
|
-
enabled: boolean(),
|
|
17719
|
-
modelId: string(),
|
|
17720
|
-
children: array(PipelineDefaultStepSchema).readonly(),
|
|
17721
|
-
group: string().optional(),
|
|
17722
|
-
settings: record(string(), unknown()).optional()
|
|
17723
|
-
}));
|
|
17724
|
-
var PipelineTemplateStepSchema = lazy(() => object({
|
|
17725
|
-
addonId: string(),
|
|
17726
|
-
enabled: boolean(),
|
|
17727
|
-
modelId: string(),
|
|
17728
|
-
children: array(PipelineTemplateStepSchema).readonly(),
|
|
17729
|
-
settings: record(string(), unknown()).optional()
|
|
17730
|
-
}));
|
|
17731
|
-
var PipelineTemplateSchema$1 = object({
|
|
17732
|
-
id: string(),
|
|
17733
|
-
name: string(),
|
|
17734
|
-
createdAt: string(),
|
|
17735
|
-
updatedAt: string(),
|
|
17736
|
-
engine: PipelineEngineChoiceSchema,
|
|
17737
|
-
steps: array(PipelineTemplateStepSchema).readonly()
|
|
17738
|
-
});
|
|
17739
|
-
var PipelineModelOptionSchema = object({
|
|
17740
|
-
id: string(),
|
|
17741
|
-
name: string(),
|
|
17742
|
-
formats: record(string(), object({
|
|
17743
|
-
downloaded: boolean(),
|
|
17744
|
-
sizeMB: number()
|
|
17745
|
-
})),
|
|
17746
|
-
group: ModelVariantGroupSchema.optional(),
|
|
17747
|
-
legacy: boolean().optional(),
|
|
17748
|
-
provider: ModelProviderIdSchema.optional()
|
|
17749
|
-
});
|
|
17750
|
-
var ConfigFieldBridge = custom();
|
|
17751
|
-
var PipelineAddonSchemaSchema = object({
|
|
17752
|
-
id: string(),
|
|
17753
|
-
name: string(),
|
|
17754
|
-
slot: PipelineSlotSchema,
|
|
17755
|
-
inputClasses: array(string()).readonly(),
|
|
17756
|
-
outputClasses: array(string()).readonly(),
|
|
17757
|
-
childSlots: array(PipelineSlotSchema).readonly(),
|
|
17758
|
-
models: array(PipelineModelOptionSchema).readonly(),
|
|
17759
|
-
defaultModelId: string(),
|
|
17760
|
-
defaultModelIdByFormat: record(string(), string()).optional(),
|
|
17761
|
-
enabledByDefault: boolean().optional(),
|
|
17762
|
-
backfillIntoExistingOverrides: boolean().optional(),
|
|
17763
|
-
defaultConfidence: number(),
|
|
17764
|
-
group: string().optional(),
|
|
17765
|
-
configSchema: array(ConfigFieldBridge).readonly().optional()
|
|
17766
|
-
});
|
|
17767
|
-
var PipelineSlotSchemaSchema = object({
|
|
17768
|
-
id: PipelineSlotSchema,
|
|
17769
|
-
label: string(),
|
|
17770
|
-
priority: number(),
|
|
17771
|
-
parentSlot: PipelineSlotSchema.nullable(),
|
|
17772
|
-
addons: array(PipelineAddonSchemaSchema).readonly()
|
|
17773
|
-
});
|
|
17774
|
-
var PipelineSchemaSchema = object({
|
|
17775
|
-
availableEngines: array(AvailableEngineSchema).readonly(),
|
|
17776
|
-
selectedEngine: PipelineEngineChoiceSchema,
|
|
17777
|
-
slots: array(PipelineSlotSchemaSchema).readonly()
|
|
17778
|
-
});
|
|
17779
|
-
var EngineProvisioningSchema = object({
|
|
17780
|
-
runtimeId: _enum([
|
|
17781
|
-
"onnx",
|
|
17782
|
-
"openvino",
|
|
17783
|
-
"coreml",
|
|
17784
|
-
"edgetpu"
|
|
17785
|
-
]).nullable(),
|
|
17786
|
-
device: string().nullable(),
|
|
17787
|
-
state: _enum([
|
|
17788
|
-
"idle",
|
|
17789
|
-
"installing",
|
|
17790
|
-
"verifying",
|
|
17791
|
-
"ready",
|
|
17792
|
-
"failed"
|
|
17793
|
-
]),
|
|
17794
|
-
progress: number().optional(),
|
|
17795
|
-
error: string().optional(),
|
|
17796
|
-
nextRetryAt: number().optional(),
|
|
17797
|
-
/**
|
|
17798
|
-
* Gate A (config-correctness gate at engine change): human-readable
|
|
17799
|
-
* config issues surfaced EAGERLY when the node's engine changes — model
|
|
17800
|
-
* substitutions ("chose X, running Y") and zero-build steps ("no model
|
|
17801
|
-
* has a <format> build"). Additive/optional: informational only, never
|
|
17802
|
-
* enforced here — `assertEngineReady` (readiness) still gates inference.
|
|
17803
|
-
* Absent/empty when the node-default tree resolves cleanly.
|
|
17804
|
-
*/
|
|
17805
|
-
configIssues: array(string()).optional()
|
|
17806
|
-
});
|
|
17807
|
-
var PipelineStepInputSchema = lazy(() => object({
|
|
17808
|
-
addonId: string(),
|
|
17809
|
-
modelId: string().optional(),
|
|
17810
|
-
enabled: boolean().default(true),
|
|
17811
|
-
children: array(PipelineStepInputSchema).optional(),
|
|
17812
|
-
settings: record(string(), unknown()).optional(),
|
|
17813
|
-
jumpDeviceKey: string().optional()
|
|
17814
|
-
}));
|
|
17815
|
-
var ModelSubstitutionSchema = object({
|
|
17816
|
-
addonId: string(),
|
|
17817
|
-
chosen: string(),
|
|
17818
|
-
running: string(),
|
|
17819
|
-
format: string()
|
|
17820
|
-
});
|
|
17821
|
-
var PipelineValidationIssueSchema = object({
|
|
17822
|
-
addonId: string(),
|
|
17823
|
-
kind: _enum(["unknown-addon", "no-format-build"]),
|
|
17824
|
-
detail: string()
|
|
17825
|
-
});
|
|
17826
|
-
var PipelineValidationResultSchema = object({
|
|
17827
|
-
ok: boolean(),
|
|
17828
|
-
issues: array(PipelineValidationIssueSchema).readonly(),
|
|
17829
|
-
substitutions: array(ModelSubstitutionSchema).readonly(),
|
|
17830
|
-
/** The node's `currentEngine.format` this validation ran against. */
|
|
17831
|
-
format: string()
|
|
17832
|
-
});
|
|
17833
|
-
var ReferenceImageEntrySchema = object({
|
|
17834
|
-
filename: string(),
|
|
17835
|
-
stepIds: array(string()).readonly().optional()
|
|
17836
|
-
});
|
|
17837
|
-
var ReferenceImageBodySchema = object({
|
|
17838
|
-
base64: string(),
|
|
17839
|
-
filename: string()
|
|
17840
|
-
});
|
|
17841
|
-
var ReferenceAudioEntrySchema = object({
|
|
17842
|
-
filename: string(),
|
|
17843
|
-
sizeKb: number()
|
|
17844
|
-
});
|
|
17845
|
-
var ReferenceAudioBodySchema = object({ base64: string() });
|
|
17846
|
-
var AudioBackendSchema = object({
|
|
17847
|
-
id: string(),
|
|
17848
|
-
name: string(),
|
|
17849
|
-
description: string(),
|
|
17850
|
-
available: boolean(),
|
|
17851
|
-
/**
|
|
17852
|
-
* Raw classifier labels this backend can emit (e.g. YAMNet's
|
|
17853
|
-
* 521-class set or Apple SoundAnalysis's 303-class set). Used by
|
|
17854
|
-
* the benchmark UI to populate the `enabledMicroClasses` filter
|
|
17855
|
-
* specific to the selected backend without a separate fetch.
|
|
17856
|
-
*/
|
|
17857
|
-
rawLabels: array(string()).readonly().optional()
|
|
17858
|
-
});
|
|
17859
|
-
var AudioCapabilitiesSchema = object({
|
|
17860
|
-
activeBackend: string(),
|
|
17861
|
-
availableBackends: array(AudioBackendSchema).readonly(),
|
|
17862
|
-
sampleRate: number(),
|
|
17863
|
-
chunkDurationMs: number()
|
|
17864
|
-
});
|
|
17865
|
-
var DownloadModelResultSchema = object({
|
|
17866
|
-
filePath: string(),
|
|
17867
|
-
sizeMB: number(),
|
|
17868
|
-
durationMs: number()
|
|
17869
|
-
});
|
|
17870
|
-
/**
|
|
17871
|
-
* Wrapper carrying a single test run's result. Replaces the legacy
|
|
17872
|
-
* ad-hoc `{labels: [{className, originalClass, score}]}` shape with the
|
|
17873
|
-
* canonical `AudioResult` from the Phase 6 output rework: one
|
|
17874
|
-
* `AudioDetection` per class above `minScore`, top-N candidates in
|
|
17875
|
-
* `debug.alternateLabels['audio-classifier']`, per-source timings in
|
|
17876
|
-
* `debug.stepTimings`. The outer `success`/`error` fields stay so the
|
|
17877
|
-
* benchmark UI can still report a clean failure when the classifier
|
|
17878
|
-
* cap isn't available.
|
|
17879
|
-
*/
|
|
17880
|
-
var AudioTestResultSchema = object({
|
|
17881
|
-
success: boolean(),
|
|
17882
|
-
error: string().optional(),
|
|
17883
|
-
frame: custom().optional()
|
|
17884
|
-
});
|
|
17885
|
-
var PipelineConfigBridge = custom();
|
|
17886
|
-
var ConfigUISchemaBridge = custom();
|
|
17887
|
-
var ConfigUISchemaNullableBridge = custom();
|
|
17888
|
-
var InferenceCapabilitiesBridge = custom();
|
|
17889
|
-
var ModelAvailabilityListBridge = custom();
|
|
17890
|
-
var PipelineRunResultBridge = custom();
|
|
17891
|
-
method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
|
|
17892
|
-
modelId: string(),
|
|
17893
|
-
settings: record(string(), unknown()).readonly()
|
|
17894
|
-
}))), method(object({ steps: record(string(), object({
|
|
17895
|
-
modelId: string(),
|
|
17896
|
-
settings: record(string(), unknown()).readonly()
|
|
17897
|
-
})) }), object({ success: literal(true) }), {
|
|
17898
|
-
kind: "mutation",
|
|
17899
|
-
auth: "admin"
|
|
17900
|
-
}), method(object({ nodeId: string() }), object({
|
|
17901
|
-
success: literal(true),
|
|
17902
|
-
clearedDevices: number()
|
|
17903
|
-
}), {
|
|
17904
|
-
kind: "mutation",
|
|
17905
|
-
auth: "admin"
|
|
17906
|
-
}), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({ steps: array(PipelineStepInputSchema) }), PipelineValidationResultSchema), method(_void(), array(PipelineTemplateSchema$1).readonly()), method(object({
|
|
17907
|
-
name: string(),
|
|
17908
|
-
steps: array(PipelineTemplateStepSchema).readonly(),
|
|
17909
|
-
engine: PipelineEngineChoiceSchema
|
|
17910
|
-
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({
|
|
17911
|
-
id: string(),
|
|
17912
|
-
name: string().optional(),
|
|
17913
|
-
steps: array(PipelineTemplateStepSchema).readonly().optional()
|
|
17914
|
-
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({ id: string() }), _void(), { kind: "mutation" }), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
|
|
17915
|
-
addonId: string(),
|
|
17916
|
-
modelId: string(),
|
|
17917
|
-
format: ModelFormatSchema$1
|
|
17918
|
-
}), DownloadModelResultSchema, { kind: "mutation" }), method(object({
|
|
17919
|
-
addonId: string(),
|
|
17920
|
-
modelId: string(),
|
|
17921
|
-
format: ModelFormatSchema$1
|
|
17922
|
-
}), object({ success: literal(true) }), { kind: "mutation" }), method(object({
|
|
17923
|
-
engine: PipelineEngineChoiceSchema.optional(),
|
|
17924
|
-
steps: array(PipelineStepInputSchema).min(1),
|
|
17925
|
-
frame: FrameInputSchema.optional(),
|
|
17926
|
-
/**
|
|
17927
|
-
* Process-local lazy frame. Valid only when caller and provider resolve
|
|
17928
|
-
* in the same execution-group process; split/cross-node callers use
|
|
17929
|
-
* `frame`/`image` inline compatibility instead.
|
|
17930
|
-
*/
|
|
17931
|
-
frameRef: FrameRefSchema.optional(),
|
|
17932
|
-
/**
|
|
17933
|
-
* CB5 shm passthrough — a `FrameHandle` naming the same ring slot
|
|
17934
|
-
* the decoded pixels live in. One more member of the one-of
|
|
17935
|
-
* frame/frameHandle/image/imageBase64/referenceImage group.
|
|
17936
|
-
*/
|
|
17937
|
-
frameHandle: FrameHandleSchema.optional(),
|
|
17938
|
-
imageBase64: string().optional(),
|
|
17939
|
-
/**
|
|
17940
|
-
* Binary JPEG bytes — preferred over `imageBase64` on internal
|
|
17941
|
-
* hops (hub → forked worker via Moleculer MsgPack) because it
|
|
17942
|
-
* skips the 33% base64 overhead + the per-call base64 decode on
|
|
17943
|
-
* the detection-pipeline worker. Callers can pass either; exactly
|
|
17944
|
-
* one of `frame`/`image`/`imageBase64`/`referenceImage` is required.
|
|
17945
|
-
*/
|
|
17946
|
-
image: _instanceof(Uint8Array).optional(),
|
|
17947
|
-
referenceImage: string().optional(),
|
|
17948
|
-
deviceId: number().optional(),
|
|
17949
|
-
sessionId: string().optional(),
|
|
17950
|
-
/**
|
|
17951
|
-
* Execution plane. 'full' (default) runs the whole tree — benchmark,
|
|
17952
|
-
* reference-image, and detail-subtree calls. 'frame' is the live
|
|
17953
|
-
* per-frame dispatch: ONLY root-plane steps run; crop children
|
|
17954
|
-
* (inputClasses ≠ null) are skipped and served per-track via
|
|
17955
|
-
* pipelineRunner.runDetailSubtree (two-plane design).
|
|
17956
|
-
*/
|
|
17957
|
-
plane: _enum(["full", "frame"]).optional(),
|
|
17958
|
-
/**
|
|
17959
|
-
* Inference-device selector (Phase 2 multi-device). Format
|
|
17960
|
-
* `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
|
|
17961
|
-
* Omitted ⇒ the runner's default device (current single-engine
|
|
17962
|
-
* behaviour). Selects WHICH device pool of the node runs the call.
|
|
17963
|
-
*/
|
|
17964
|
-
deviceKey: string().optional(),
|
|
17965
|
-
/**
|
|
17966
|
-
* Two-plane NATIVE child-crop reference. Set by `runDetailSubtree` ONLY
|
|
17967
|
-
* when the parent crop was resolved from the frame's retained NATIVE
|
|
17968
|
-
* surface (a frameHandle HIT). Lets the executor re-cut a LEAF crop
|
|
17969
|
-
* child's ROI (plate-ocr, face-embedding, leaf classifiers) at native
|
|
17970
|
-
* resolution from that surface — the SAME quality path faces already
|
|
17971
|
-
* had — instead of the downscaled parent tile. `handle` keys the native
|
|
17972
|
-
* surface (node-pinned to its owner); `cropFrameSpace` is the parent
|
|
17973
|
-
* crop's padded/clamped rectangle in FRAME-space pixels, used to compose
|
|
17974
|
-
* the executor's crop-normalized child ROI back into frame-normalized
|
|
17975
|
-
* coordinates. Auxiliary to the image source (`image`/`frame`/…), NOT one
|
|
17976
|
-
* of the mutually-exclusive image inputs. Absent ⇒ tile-crop children
|
|
17977
|
-
* (today's behaviour on the fallback path).
|
|
17978
|
-
*/
|
|
17979
|
-
nativeCropRef: NativeCropRefSchema.optional()
|
|
17980
|
-
}), PipelineRunResultBridge, { kind: "mutation" }), method(object({
|
|
17981
|
-
engine: PipelineEngineChoiceSchema.optional(),
|
|
17982
|
-
steps: array(PipelineStepInputSchema).min(1),
|
|
17983
|
-
frames: array(FrameInputSchema).min(1).max(255),
|
|
17984
|
-
deviceId: number().optional(),
|
|
17985
|
-
sessionId: string().optional(),
|
|
17986
|
-
/**
|
|
17987
|
-
* Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
|
|
17988
|
-
* the batch to the Python pool's bench preprocess cache
|
|
17989
|
-
* (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
|
|
17990
|
-
* preprocessed ONCE and every later inference is a pure-inference cache
|
|
17991
|
-
* hit — the sustained-throughput run measures inference, not
|
|
17992
|
-
* decode+preprocess+infer. Omitted/0 for live frames (all different →
|
|
17993
|
-
* full preprocess every call, correct). Fresh per sustained run;
|
|
17994
|
-
* released via `uncacheFrame`.
|
|
17995
|
-
*/
|
|
17996
|
-
frameId: number().int().nonnegative().optional(),
|
|
17997
|
-
/** Inference-device selector (Phase 2 multi-device); see runPipeline. */
|
|
17998
|
-
deviceKey: string().optional()
|
|
17999
|
-
}), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
|
|
18000
|
-
data: _instanceof(Uint8Array),
|
|
18001
|
-
width: number().int().positive(),
|
|
18002
|
-
height: number().int().positive(),
|
|
18003
|
-
format: _enum([
|
|
18004
|
-
"rgb",
|
|
18005
|
-
"bgr",
|
|
18006
|
-
"gray"
|
|
18007
|
-
])
|
|
18008
|
-
}), object({
|
|
18009
|
-
frameId: number(),
|
|
18010
|
-
width: number(),
|
|
18011
|
-
height: number()
|
|
18012
|
-
}), { kind: "mutation" }), method(object({
|
|
18013
|
-
stepId: string(),
|
|
18014
|
-
frameId: number().int()
|
|
18015
|
-
}), record(string(), unknown()), { kind: "mutation" }), method(object({ frameId: number().int() }), _void(), { kind: "mutation" }), method(_void(), object({
|
|
18016
|
-
batchMode: string(),
|
|
18017
|
-
windowMs: number(),
|
|
18018
|
-
maxBatchSize: number(),
|
|
18019
|
-
concurrency: number()
|
|
18020
|
-
})), method(_void(), array(object({
|
|
18021
|
-
engineKey: string(),
|
|
18022
|
-
engine: PipelineEngineChoiceSchema,
|
|
18023
|
-
modelsLoaded: array(string()).readonly(),
|
|
18024
|
-
inUseByCameras: array(number()).readonly(),
|
|
18025
|
-
/**
|
|
18026
|
-
* Origin of this resident factory.
|
|
18027
|
-
* - `runtime` — main camera-serving engine (no idle TTL).
|
|
18028
|
-
* - `warm-override` — benchmark/test override held in the warm
|
|
18029
|
-
* cache; auto-disposed after the idle TTL.
|
|
18030
|
-
* - `device-pool` — a concurrent per-device pool (Phase 2
|
|
18031
|
-
* multi-device, keyed by `deviceKey`) resolved
|
|
18032
|
-
* via `resolveDeviceFactory`. Runs alongside the
|
|
18033
|
-
* `runtime` engine on a DIFFERENT accelerator
|
|
18034
|
-
* (NPU / iGPU / Coral) — this is how the
|
|
18035
|
-
* Engines tab shows all pools running at once.
|
|
18036
|
-
*/
|
|
18037
|
-
kind: _enum([
|
|
18038
|
-
"runtime",
|
|
18039
|
-
"warm-override",
|
|
18040
|
-
"device-pool"
|
|
18041
|
-
]),
|
|
18042
|
-
/** Native pid of the underlying Python pool (null when no pool). */
|
|
18043
|
-
poolPid: number().nullable(),
|
|
18044
|
-
/** ms since this factory was last used (null when not warm-tracked). */
|
|
18045
|
-
idleMs: number().nullable(),
|
|
18046
|
-
/** Idle TTL after which `warm-override` factories self-evict (null when not applicable). */
|
|
18047
|
-
idleTtlMs: number().nullable()
|
|
18048
|
-
})).readonly()), method(object({ engine: PipelineEngineChoiceSchema }), object({ success: literal(true) }), {
|
|
18049
|
-
kind: "mutation",
|
|
18050
|
-
auth: "admin"
|
|
18051
|
-
}), method(object({
|
|
18052
|
-
engine: PipelineEngineChoiceSchema,
|
|
18053
|
-
force: boolean().optional()
|
|
18054
|
-
}), object({
|
|
18055
|
-
success: boolean(),
|
|
18056
|
-
reason: string().optional()
|
|
18057
|
-
}), {
|
|
18058
|
-
kind: "mutation",
|
|
18059
|
-
auth: "admin"
|
|
18060
|
-
}), method(_void(), array(ReferenceImageEntrySchema).readonly()), method(object({ filename: string() }), ReferenceImageBodySchema.nullable()), method(_void(), array(ReferenceAudioEntrySchema).readonly()), method(object({ filename: string() }), ReferenceAudioBodySchema.nullable()), method(_void(), AudioCapabilitiesSchema), method(object({
|
|
18061
|
-
addonId: string(),
|
|
18062
|
-
modelId: string(),
|
|
18063
|
-
filename: string().optional(),
|
|
18064
|
-
settings: record(string(), unknown()).optional()
|
|
18065
|
-
}), AudioTestResultSchema, { kind: "mutation" }), method(_void(), ConfigUISchemaNullableBridge);
|
|
18066
18363
|
object({
|
|
18067
18364
|
activeCameras: number(),
|
|
18068
18365
|
throttledCameras: number(),
|
|
@@ -18088,106 +18385,6 @@ var CameraMetricsSchema = object({
|
|
|
18088
18385
|
});
|
|
18089
18386
|
var CameraMetricsWithDeviceIdSchema = CameraMetricsSchema.extend({ deviceId: number() });
|
|
18090
18387
|
/**
|
|
18091
|
-
* Zone — pure geometry + identity. NO filtering behaviour.
|
|
18092
|
-
*
|
|
18093
|
-
* Zones describe **where** in the frame the operator wants to flag
|
|
18094
|
-
* something; consumer-owned {@link ZoneRule} arrays describe **how**
|
|
18095
|
-
* each pipeline stage uses them. Splitting the two means a single
|
|
18096
|
-
* polygon "Driveway" can simultaneously back a motion-exclude rule,
|
|
18097
|
-
* a detection-include rule on `['car']`, and an occupancy aggregate
|
|
18098
|
-
* — without three duplicated polygons.
|
|
18099
|
-
*
|
|
18100
|
-
* Owned by the orchestrator addon (provider) and mirrored into the
|
|
18101
|
-
* `zones` device-state slice on every mutation. Consumers
|
|
18102
|
-
* (motion-wasm, pipeline-executor, analytics, admin UI) read either
|
|
18103
|
-
* via `api.zones.listZones` (one-shot) or via `dev.state.zones` (live
|
|
18104
|
-
* mirror with `onChanged`).
|
|
18105
|
-
*
|
|
18106
|
-
* Coordinates are normalised fractions of the frame (0–1) so zones
|
|
18107
|
-
* survive resolution changes and stream profile switches.
|
|
18108
|
-
*
|
|
18109
|
-
* `kind` discriminates between full polygons (closed regions used
|
|
18110
|
-
* for intrusion / occupancy filters) and tripwires (open 2-point
|
|
18111
|
-
* line segments used for cross events). Onboard / firmware-reported
|
|
18112
|
-
* zones (Reolink, ONVIF) are out of scope for now — see the deferred
|
|
18113
|
-
* task list.
|
|
18114
|
-
*/
|
|
18115
|
-
var ZoneKindEnum = _enum(["polygon", "tripwire"]);
|
|
18116
|
-
/** Polygon vertex in fraction-of-frame coordinates (0–1). */
|
|
18117
|
-
var PolygonPointSchema = object({
|
|
18118
|
-
x: number(),
|
|
18119
|
-
y: number()
|
|
18120
|
-
});
|
|
18121
|
-
/** A camera detection zone — pure geometry/identity. */
|
|
18122
|
-
var ZoneSchema = object({
|
|
18123
|
-
id: string(),
|
|
18124
|
-
name: string(),
|
|
18125
|
-
kind: ZoneKindEnum.default("polygon"),
|
|
18126
|
-
/** Polygon vertices, fraction of frame (0–1). */
|
|
18127
|
-
polygon: array(PolygonPointSchema).readonly(),
|
|
18128
|
-
/** Visual color for UI rendering. */
|
|
18129
|
-
color: string().default("#3b82f6")
|
|
18130
|
-
});
|
|
18131
|
-
/**
|
|
18132
|
-
* Zones capability — per-camera CRUD over polygon detection zones.
|
|
18133
|
-
*
|
|
18134
|
-
* Provider lives in `addon-pipeline-orchestrator` (hub-only). Persists
|
|
18135
|
-
* to per-device settings and mirrors into the `zones` device-state
|
|
18136
|
-
* slice on every mutation, so downstream consumers can subscribe via
|
|
18137
|
-
* `dev.state.zones.onChanged`.
|
|
18138
|
-
*
|
|
18139
|
-
* The cap surface only handles geometry + identity; filtering
|
|
18140
|
-
* behaviour (per-class, include/exclude, threshold) lives in the
|
|
18141
|
-
* consumer addons' rule arrays — see `ZoneRuleSchema` exported from
|
|
18142
|
-
* `capabilities/schemas/zone-rule.js`.
|
|
18143
|
-
*/
|
|
18144
|
-
var zonesCapability = {
|
|
18145
|
-
name: "zones",
|
|
18146
|
-
scope: "device",
|
|
18147
|
-
mode: "singleton",
|
|
18148
|
-
deviceTypes: [DeviceType.Camera],
|
|
18149
|
-
methods: {
|
|
18150
|
-
listZones: method(object({ deviceId: number() }), array(ZoneSchema).readonly()),
|
|
18151
|
-
addZone: method(object({
|
|
18152
|
-
deviceId: number(),
|
|
18153
|
-
zone: ZoneSchema
|
|
18154
|
-
}), _void(), {
|
|
18155
|
-
kind: "mutation",
|
|
18156
|
-
auth: "admin"
|
|
18157
|
-
}),
|
|
18158
|
-
removeZone: method(object({
|
|
18159
|
-
deviceId: number(),
|
|
18160
|
-
zoneId: string()
|
|
18161
|
-
}), _void(), {
|
|
18162
|
-
kind: "mutation",
|
|
18163
|
-
auth: "admin"
|
|
18164
|
-
}),
|
|
18165
|
-
updateZone: method(object({
|
|
18166
|
-
deviceId: number(),
|
|
18167
|
-
zone: ZoneSchema
|
|
18168
|
-
}), _void(), {
|
|
18169
|
-
kind: "mutation",
|
|
18170
|
-
auth: "admin"
|
|
18171
|
-
})
|
|
18172
|
-
},
|
|
18173
|
-
/**
|
|
18174
|
-
* Runtime-state slice — the live zone catalogue mirrored by the
|
|
18175
|
-
* orchestrator on every CRUD mutation. Consumers read via
|
|
18176
|
-
* `device.state.zones.value` / `.watch(...)` without round-tripping
|
|
18177
|
-
* the cap, and the codegen DeviceProxy auto-wires the reactive
|
|
18178
|
-
* handle. Slice shape is `{ zones: Zone[] }` so future extensions
|
|
18179
|
-
* (e.g. zone groupings) can sit alongside the polygon list.
|
|
18180
|
-
*/
|
|
18181
|
-
runtimeState: object({ zones: array(ZoneSchema).readonly() }),
|
|
18182
|
-
/**
|
|
18183
|
-
* 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.
|
|
18184
|
-
*
|
|
18185
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
18186
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
18187
|
-
*/
|
|
18188
|
-
durability: "restored"
|
|
18189
|
-
};
|
|
18190
|
-
/**
|
|
18191
18388
|
* A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
|
|
18192
18389
|
* decode worker resolves it against the RETAINED native frame's real pixel dims,
|
|
18193
18390
|
* so the caller supplies only the detection-res bbox divided by the detection
|
|
@@ -19979,7 +20176,7 @@ method(object({
|
|
|
19979
20176
|
* linking rather than produce an eternal token.
|
|
19980
20177
|
*/
|
|
19981
20178
|
ttlSec: union([number().int().positive(), literal("never")]).optional()
|
|
19982
|
-
}), object({ token: string() })), method(object({ token: string() }), SsoBridgeClaimsSchema.nullable());
|
|
20179
|
+
}), object({ token: string() }), { auth: "admin" }), method(object({ token: string() }), SsoBridgeClaimsSchema.nullable(), { auth: "admin" });
|
|
19983
20180
|
var ProviderListEntrySchema = discriminatedUnion("shouldSaveDiskSpace", [object({
|
|
19984
20181
|
providerId: string().min(1),
|
|
19985
20182
|
displayName: string().min(1),
|
|
@@ -20074,10 +20271,13 @@ var EvictResultSchema = object({
|
|
|
20074
20271
|
/** True when the provider has nothing left it is willing to drop on this location. */
|
|
20075
20272
|
exhausted: boolean()
|
|
20076
20273
|
});
|
|
20077
|
-
method(object({ locationId: string() }), EvictableUsageSchema), method(object({
|
|
20274
|
+
method(object({ locationId: string() }), EvictableUsageSchema, { auth: "admin" }), method(object({
|
|
20078
20275
|
locationId: string(),
|
|
20079
20276
|
targetBytes: number().int().positive()
|
|
20080
|
-
}), EvictResultSchema, {
|
|
20277
|
+
}), EvictResultSchema, {
|
|
20278
|
+
kind: "mutation",
|
|
20279
|
+
auth: "admin"
|
|
20280
|
+
});
|
|
20081
20281
|
method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin" }), method(StorageMigrationInputSchema, object({ jobId: string() }), {
|
|
20082
20282
|
kind: "mutation",
|
|
20083
20283
|
auth: "admin"
|
|
@@ -20137,26 +20337,50 @@ var ReadChunkInputSchema = object({
|
|
|
20137
20337
|
length: number()
|
|
20138
20338
|
});
|
|
20139
20339
|
var EndDownloadInputSchema = object({ downloadId: string() });
|
|
20140
|
-
method(_void(), ProviderInfoSchema), method(object({ config: record(string(), unknown()) }), TestLocationResultSchema, { auth: "admin" }), method(object({
|
|
20340
|
+
method(_void(), ProviderInfoSchema, { auth: "admin" }), method(object({ config: record(string(), unknown()) }), TestLocationResultSchema, { auth: "admin" }), method(object({
|
|
20141
20341
|
location: StorageLocationSchema,
|
|
20142
20342
|
relativePath: string()
|
|
20143
|
-
}), string()), method(object({
|
|
20343
|
+
}), string(), { auth: "admin" }), method(object({
|
|
20144
20344
|
location: StorageLocationSchema,
|
|
20145
20345
|
relativePath: string(),
|
|
20146
20346
|
data: _instanceof(Uint8Array)
|
|
20147
|
-
}), _void(), {
|
|
20347
|
+
}), _void(), {
|
|
20348
|
+
kind: "mutation",
|
|
20349
|
+
auth: "admin"
|
|
20350
|
+
}), method(object({
|
|
20148
20351
|
location: StorageLocationSchema,
|
|
20149
20352
|
relativePath: string()
|
|
20150
|
-
}), _instanceof(Uint8Array)), method(object({
|
|
20353
|
+
}), _instanceof(Uint8Array), { auth: "admin" }), method(object({
|
|
20151
20354
|
location: StorageLocationSchema,
|
|
20152
20355
|
relativePath: string()
|
|
20153
|
-
}), boolean()), method(object({
|
|
20356
|
+
}), boolean(), { auth: "admin" }), method(object({
|
|
20154
20357
|
location: StorageLocationSchema,
|
|
20155
20358
|
prefix: string().optional()
|
|
20156
|
-
}), array(string()).readonly()), method(object({
|
|
20359
|
+
}), array(string()).readonly(), { auth: "admin" }), method(object({
|
|
20157
20360
|
location: StorageLocationSchema,
|
|
20158
20361
|
relativePath: string()
|
|
20159
|
-
}), _void(), {
|
|
20362
|
+
}), _void(), {
|
|
20363
|
+
kind: "mutation",
|
|
20364
|
+
auth: "admin"
|
|
20365
|
+
}), method(object({ location: StorageLocationSchema }), number().nullable(), { auth: "admin" }), method(BeginUploadInputSchema, BeginUploadResultSchema, {
|
|
20366
|
+
kind: "mutation",
|
|
20367
|
+
auth: "admin"
|
|
20368
|
+
}), method(WriteChunkInputSchema, _void(), {
|
|
20369
|
+
kind: "mutation",
|
|
20370
|
+
auth: "admin"
|
|
20371
|
+
}), method(FinalizeUploadInputSchema, _void(), {
|
|
20372
|
+
kind: "mutation",
|
|
20373
|
+
auth: "admin"
|
|
20374
|
+
}), method(AbortUploadInputSchema, _void(), {
|
|
20375
|
+
kind: "mutation",
|
|
20376
|
+
auth: "admin"
|
|
20377
|
+
}), method(BeginDownloadInputSchema, BeginDownloadResultSchema, {
|
|
20378
|
+
kind: "mutation",
|
|
20379
|
+
auth: "admin"
|
|
20380
|
+
}), method(ReadChunkInputSchema, _instanceof(Uint8Array), { auth: "admin" }), method(EndDownloadInputSchema, _void(), {
|
|
20381
|
+
kind: "mutation",
|
|
20382
|
+
auth: "admin"
|
|
20383
|
+
});
|
|
20160
20384
|
/** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
|
|
20161
20385
|
var ProfileSettingsSchemaBridge = unknown().nullable();
|
|
20162
20386
|
var ProfileSettingsBagSchema = record(string(), unknown());
|
|
@@ -20458,7 +20682,8 @@ method(object({
|
|
|
20458
20682
|
access: "create"
|
|
20459
20683
|
}), method(object({ userId: string().optional() }), object({ optionsJSON: record(string(), unknown()) }), {
|
|
20460
20684
|
kind: "mutation",
|
|
20461
|
-
access: "view"
|
|
20685
|
+
access: "view",
|
|
20686
|
+
auth: "admin"
|
|
20462
20687
|
}), method(object({
|
|
20463
20688
|
/** Required — the user the assertion belongs to (verified). */
|
|
20464
20689
|
userId: string(),
|
|
@@ -20466,10 +20691,12 @@ method(object({
|
|
|
20466
20691
|
response: record(string(), unknown())
|
|
20467
20692
|
}), object({ verified: boolean() }), {
|
|
20468
20693
|
kind: "mutation",
|
|
20469
|
-
access: "view"
|
|
20694
|
+
access: "view",
|
|
20695
|
+
auth: "admin"
|
|
20470
20696
|
}), method(object({}), object({ optionsJSON: record(string(), unknown()) }), {
|
|
20471
20697
|
kind: "mutation",
|
|
20472
|
-
access: "view"
|
|
20698
|
+
access: "view",
|
|
20699
|
+
auth: "admin"
|
|
20473
20700
|
}), method(object({
|
|
20474
20701
|
/** AuthenticationResponseJSON from the browser. */
|
|
20475
20702
|
response: record(string(), unknown()) }), object({
|
|
@@ -20477,7 +20704,8 @@ response: record(string(), unknown()) }), object({
|
|
|
20477
20704
|
userId: string().nullable()
|
|
20478
20705
|
}), {
|
|
20479
20706
|
kind: "mutation",
|
|
20480
|
-
access: "view"
|
|
20707
|
+
access: "view",
|
|
20708
|
+
auth: "admin"
|
|
20481
20709
|
}), method(object({ userId: string() }), array(PasskeySummarySchema), { auth: "admin" }), method(object({
|
|
20482
20710
|
userId: string(),
|
|
20483
20711
|
credentialId: string()
|
|
@@ -20649,7 +20877,19 @@ var VectorStatsResultSchema = object({
|
|
|
20649
20877
|
/** False when the backend ranks approximately. */
|
|
20650
20878
|
exact: boolean()
|
|
20651
20879
|
});
|
|
20652
|
-
method(VectorDeclareIndexInputSchema, _void(), {
|
|
20880
|
+
method(VectorDeclareIndexInputSchema, _void(), {
|
|
20881
|
+
kind: "mutation",
|
|
20882
|
+
auth: "admin"
|
|
20883
|
+
}), method(VectorUpsertInputSchema, VectorUpsertResultSchema, {
|
|
20884
|
+
kind: "mutation",
|
|
20885
|
+
auth: "admin"
|
|
20886
|
+
}), method(VectorQueryInputSchema, VectorQueryResultSchema, { auth: "admin" }), method(VectorGetInputSchema, VectorGetResultSchema, { auth: "admin" }), method(VectorDeleteInputSchema, VectorDeleteResultSchema, {
|
|
20887
|
+
kind: "mutation",
|
|
20888
|
+
auth: "admin"
|
|
20889
|
+
}), method(VectorDeleteByFilterInputSchema, VectorDeleteResultSchema, {
|
|
20890
|
+
kind: "mutation",
|
|
20891
|
+
auth: "admin"
|
|
20892
|
+
}), method(VectorStatsInputSchema, VectorStatsResultSchema, { auth: "admin" });
|
|
20653
20893
|
var ClipSchema = object({
|
|
20654
20894
|
/** Opaque, provider-namespaced id. The default provider encodes the time
|
|
20655
20895
|
* window so `getClipPlayback` is self-contained (no event re-query). */
|
|
@@ -23102,7 +23342,27 @@ var MediaFileLiteSchema$1 = object({
|
|
|
23102
23342
|
sizeBytes: number(),
|
|
23103
23343
|
timestamp: number()
|
|
23104
23344
|
});
|
|
23105
|
-
method(
|
|
23345
|
+
method(object({
|
|
23346
|
+
/**
|
|
23347
|
+
* Inline {@link IdentitySchema.coverBase64} on every row.
|
|
23348
|
+
*
|
|
23349
|
+
* Default `false`, the same inversion `listRecentFaces` and
|
|
23350
|
+
* `listPlates` took on 2026-08-25 (see `include-crops-default.ts` for
|
|
23351
|
+
* why the burden belongs on the caller that WANTS the bytes). Measured
|
|
23352
|
+
* on the live hub the same day: four identities cost 40,979 B with the
|
|
23353
|
+
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
23354
|
+
* four times and the viewer holds at `staleTime: 30_000`.
|
|
23355
|
+
*
|
|
23356
|
+
* Nothing loses its avatar: `coverMediaKey` is already on every row and
|
|
23357
|
+
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
23358
|
+
*
|
|
23359
|
+
* **This is an INPUT field, so it does not reach the addon until the
|
|
23360
|
+
* next train** — the hub router validates cap inputs against its own
|
|
23361
|
+
* compiled Zod and strips a key it does not know. Until then the
|
|
23362
|
+
* provider sees `undefined`, which resolves to `false`: the cheap shape
|
|
23363
|
+
* is what ships, and the opt-in becomes reachable when the train lands.
|
|
23364
|
+
*/
|
|
23365
|
+
includeCrops: boolean().optional() }).optional(), array(IdentitySchema).readonly()), method(object({ name: string().min(1) }), IdentitySchema, {
|
|
23106
23366
|
kind: "mutation",
|
|
23107
23367
|
auth: "admin"
|
|
23108
23368
|
}), method(object({
|
|
@@ -25992,8 +26252,10 @@ var PlateInfoSchema = object({
|
|
|
25992
26252
|
keyFrameMediaKey: string().optional(),
|
|
25993
26253
|
base64: string().optional(),
|
|
25994
26254
|
/**
|
|
25995
|
-
* Same crop as a data-plane URL
|
|
25996
|
-
* never inlines JPEG; `listPlates`
|
|
26255
|
+
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
26256
|
+
* crop. `getPlateByTrack` returns this and never inlines JPEG; `listPlates`
|
|
26257
|
+
* and `searchPlates` inline the crop only when their `includeCrops` input is
|
|
26258
|
+
* left at its `true` default.
|
|
25997
26259
|
*/
|
|
25998
26260
|
cropUrl: string().optional()
|
|
25999
26261
|
});
|
|
@@ -26013,14 +26275,34 @@ var PlateClusterSchema = object({
|
|
|
26013
26275
|
});
|
|
26014
26276
|
method(object({
|
|
26015
26277
|
deviceId: number().int().optional(),
|
|
26016
|
-
limit: number().int().positive().optional()
|
|
26278
|
+
limit: number().int().positive().optional(),
|
|
26279
|
+
/**
|
|
26280
|
+
* Inline the base64 crop on every row. Default `true` — the existing
|
|
26281
|
+
* behaviour, kept so no caller breaks.
|
|
26282
|
+
*
|
|
26283
|
+
* Set `false` once the caller renders {@link PlateInfo.cropUrl}.
|
|
26284
|
+
* Measured on the live hub at the 500 rows the Plates view asks for:
|
|
26285
|
+
* 879,403 B and 27.7 s with the crops inline, against a few KiB of
|
|
26286
|
+
* metadata without them — and the browser then caches the images.
|
|
26287
|
+
*
|
|
26288
|
+
* This is the plate twin of `faceGallery.listRecentFaces`'s option;
|
|
26289
|
+
* plates were the one gallery list left without it.
|
|
26290
|
+
*
|
|
26291
|
+
* **This is an INPUT field, so it does not reach the addon until the
|
|
26292
|
+
* next train.** The hub router validates cap inputs against its own
|
|
26293
|
+
* compiled Zod and strips a key it does not know. Until the train
|
|
26294
|
+
* ships, sending `false` is harmless and keeps the crops inline.
|
|
26295
|
+
*/
|
|
26296
|
+
includeCrops: boolean().optional()
|
|
26017
26297
|
}).optional(), array(PlateInfoSchema).readonly()), method(object({
|
|
26018
26298
|
deviceId: number().int(),
|
|
26019
26299
|
trackId: string()
|
|
26020
26300
|
}), PlateInfoSchema.nullable()), method(object({ plateId: string() }), array(MediaFileLiteSchema).readonly()), method(object({
|
|
26021
26301
|
text: string().min(1),
|
|
26022
26302
|
maxDistance: number().int().min(0).optional(),
|
|
26023
|
-
limit: number().int().positive().optional()
|
|
26303
|
+
limit: number().int().positive().optional(),
|
|
26304
|
+
/** See `listPlates.includeCrops`. Default `true`. */
|
|
26305
|
+
includeCrops: boolean().optional()
|
|
26024
26306
|
}), array(PlateInfoSchema).readonly()), method(object({
|
|
26025
26307
|
maxDistance: number().int().min(0).optional(),
|
|
26026
26308
|
minClusterSize: number().int().min(2).optional(),
|
|
@@ -26034,7 +26316,13 @@ method(object({
|
|
|
26034
26316
|
}), method(object({ plateId: string() }), _void(), {
|
|
26035
26317
|
kind: "mutation",
|
|
26036
26318
|
auth: "admin"
|
|
26037
|
-
}), method(
|
|
26319
|
+
}), method(object({
|
|
26320
|
+
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
26321
|
+
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
26322
|
+
* option; `coverMediaKey` + the `event-media` plane carry the picture.
|
|
26323
|
+
* INPUT field: stripped by the hub router until the train ships, which
|
|
26324
|
+
* resolves to `false` and is exactly the intended default. */
|
|
26325
|
+
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
26038
26326
|
kind: "mutation",
|
|
26039
26327
|
auth: "admin"
|
|
26040
26328
|
}), method(object({
|
|
@@ -27555,92 +27843,6 @@ var sceneMonitorCapability = {
|
|
|
27555
27843
|
durability: "session"
|
|
27556
27844
|
};
|
|
27557
27845
|
/**
|
|
27558
|
-
* Per-stage gating mode applied to the zones a rule references.
|
|
27559
|
-
*
|
|
27560
|
-
* - `include`: the rule contributes to a **whitelist** for its stage.
|
|
27561
|
-
* When at least one `include` rule fires for a stage, only entities
|
|
27562
|
-
* inside one of those zones pass that stage.
|
|
27563
|
-
* - `exclude`: the rule contributes to a **blacklist** for its stage.
|
|
27564
|
-
* Entities inside one of those zones are dropped at that stage.
|
|
27565
|
-
*
|
|
27566
|
-
* `monitor`-style observation (count without filtering) is not a rule
|
|
27567
|
-
* mode — zones without any matching rule are observed naturally by
|
|
27568
|
-
* `zone-analytics` (live snapshot + history), so an "I just want to
|
|
27569
|
-
* count, not filter" use case needs no rule at all.
|
|
27570
|
-
*/
|
|
27571
|
-
var ZoneRuleModeEnum = _enum(["include", "exclude"]);
|
|
27572
|
-
/**
|
|
27573
|
-
* Per-consumer rule that references existing zones (geometry) and
|
|
27574
|
-
* defines how a specific pipeline stage should treat them. Each
|
|
27575
|
-
* consumer addon owns its own `ZoneRule[]` array in its per-device
|
|
27576
|
-
* settings:
|
|
27577
|
-
*
|
|
27578
|
-
* - `addon-motion-wasm` → `motionZoneRules: ZoneRule[]` (motion stage)
|
|
27579
|
-
* - `addon-detection-pipeline` → `detectionZoneRules: ZoneRule[]` (detection stage)
|
|
27580
|
-
* - future: notification rules, audio gating, etc.
|
|
27581
|
-
*
|
|
27582
|
-
* One rule applies to N zones (`zoneIds[]`) so the operator can
|
|
27583
|
-
* express "ignore motion in ALL of {garden, street}" with a single
|
|
27584
|
-
* rule. `classFilter` narrows the rule to specific object classes —
|
|
27585
|
-
* "drop person detections in the street, but keep cars" is one
|
|
27586
|
-
* `exclude` rule with `classFilter: ['person']`.
|
|
27587
|
-
*
|
|
27588
|
-
* `enabled` is a soft toggle — the operator can keep the rule
|
|
27589
|
-
* configured but inert without deleting it.
|
|
27590
|
-
*/
|
|
27591
|
-
var ZoneRuleSchema = object({
|
|
27592
|
-
/** Stable rule id — survives edits, used by the UI for diffing. */
|
|
27593
|
-
id: string(),
|
|
27594
|
-
/** Optional human-readable label rendered in the rule editor. */
|
|
27595
|
-
name: string().optional(),
|
|
27596
|
-
/** Zones this rule targets. The rule's `mode` applies to ALL
|
|
27597
|
-
* listed zones (OR-set: a detection in any one of them counts).
|
|
27598
|
-
* At least one zone id required — a rule with no targets is a
|
|
27599
|
-
* configuration mistake and the form validator rejects it. */
|
|
27600
|
-
zoneIds: array(string()).min(1).readonly(),
|
|
27601
|
-
mode: ZoneRuleModeEnum,
|
|
27602
|
-
/**
|
|
27603
|
-
* Class names this rule applies to. Empty / undefined ⇒ rule
|
|
27604
|
-
* applies to every class. Class strings match the `macroClass`
|
|
27605
|
-
* field on detections (e.g. `person`, `car`, `dog`).
|
|
27606
|
-
*/
|
|
27607
|
-
classFilter: array(string()).readonly().optional(),
|
|
27608
|
-
/**
|
|
27609
|
-
* Minimum bbox/mask overlap (0–1) with any of the rule's zones
|
|
27610
|
-
* required to consider an entity "in the zone". Defaults to the
|
|
27611
|
-
* consumer's stage default when omitted. Kept for back-compat with
|
|
27612
|
-
* existing per-rule overrides; new operators pick the value via
|
|
27613
|
-
* `bboxInclusionPct` (operator-friendly 0–100). Whichever field is
|
|
27614
|
-
* set, the lower-level engine reads it as a 0–1 fraction.
|
|
27615
|
-
*/
|
|
27616
|
-
overlapThreshold: number().min(0).max(1).optional(),
|
|
27617
|
-
/**
|
|
27618
|
-
* Operator-friendly version of `overlapThreshold` — the percentage
|
|
27619
|
-
* of the detection's bbox that must lie inside the zone for the
|
|
27620
|
-
* rule to match. Documented default is 85%; the engine substitutes
|
|
27621
|
-
* that when the field is omitted (kept optional so existing rules
|
|
27622
|
-
* stored without it stay valid).
|
|
27623
|
-
*
|
|
27624
|
-
* When BOTH `overlapThreshold` and `bboxInclusionPct` are set on a
|
|
27625
|
-
* rule, the engine prefers `bboxInclusionPct` because it's the
|
|
27626
|
-
* field exposed in the UI. Internally both feed the same gate.
|
|
27627
|
-
*/
|
|
27628
|
-
bboxInclusionPct: number().min(0).max(100).optional(),
|
|
27629
|
-
/**
|
|
27630
|
-
* When `true` and a detection has a segmentation mask, use the
|
|
27631
|
-
* mask for overlap instead of the bbox. Detection-stage only;
|
|
27632
|
-
* motion rules ignore this field.
|
|
27633
|
-
*/
|
|
27634
|
-
preferMask: boolean().optional(),
|
|
27635
|
-
/**
|
|
27636
|
-
* Soft-toggle: `false` disables the rule without deleting it.
|
|
27637
|
-
* Defaults to `true` so operators creating a rule via the UI
|
|
27638
|
-
* see it active immediately.
|
|
27639
|
-
*/
|
|
27640
|
-
enabled: boolean().default(true)
|
|
27641
|
-
});
|
|
27642
|
-
array(ZoneRuleSchema).readonly();
|
|
27643
|
-
/**
|
|
27644
27846
|
* Script-runner cap. Models HA `script.*` entities on
|
|
27645
27847
|
* `DeviceType.Script`. A Script is a pre-recorded action sequence
|
|
27646
27848
|
* that can be invoked imperatively — optionally with a variables
|
|
@@ -33293,6 +33495,12 @@ Object.freeze({
|
|
|
33293
33495
|
addonId: null,
|
|
33294
33496
|
access: "create"
|
|
33295
33497
|
},
|
|
33498
|
+
"pipelineAnalytics.cancelRelocateMedia": {
|
|
33499
|
+
capName: "pipeline-analytics",
|
|
33500
|
+
capScope: "device",
|
|
33501
|
+
addonId: null,
|
|
33502
|
+
access: "create"
|
|
33503
|
+
},
|
|
33296
33504
|
"pipelineAnalytics.cancelStorageMigrationMove": {
|
|
33297
33505
|
capName: "pipeline-analytics",
|
|
33298
33506
|
capScope: "device",
|
|
@@ -33467,6 +33675,12 @@ Object.freeze({
|
|
|
33467
33675
|
addonId: null,
|
|
33468
33676
|
access: "view"
|
|
33469
33677
|
},
|
|
33678
|
+
"pipelineAnalytics.listRelocateMediaJobs": {
|
|
33679
|
+
capName: "pipeline-analytics",
|
|
33680
|
+
capScope: "device",
|
|
33681
|
+
addonId: null,
|
|
33682
|
+
access: "view"
|
|
33683
|
+
},
|
|
33470
33684
|
"pipelineAnalytics.listRetrainAnnotations": {
|
|
33471
33685
|
capName: "pipeline-analytics",
|
|
33472
33686
|
capScope: "device",
|
|
@@ -33545,6 +33759,12 @@ Object.freeze({
|
|
|
33545
33759
|
addonId: null,
|
|
33546
33760
|
access: "create"
|
|
33547
33761
|
},
|
|
33762
|
+
"pipelineAnalytics.relocateMedia": {
|
|
33763
|
+
capName: "pipeline-analytics",
|
|
33764
|
+
capScope: "device",
|
|
33765
|
+
addonId: null,
|
|
33766
|
+
access: "create"
|
|
33767
|
+
},
|
|
33548
33768
|
"pipelineAnalytics.restageRetrainTrack": {
|
|
33549
33769
|
capName: "pipeline-analytics",
|
|
33550
33770
|
capScope: "device",
|
|
@@ -33557,6 +33777,12 @@ Object.freeze({
|
|
|
33557
33777
|
addonId: null,
|
|
33558
33778
|
access: "create"
|
|
33559
33779
|
},
|
|
33780
|
+
"pipelineAnalytics.runReplayFrameProcessor": {
|
|
33781
|
+
capName: "pipeline-analytics",
|
|
33782
|
+
capScope: "device",
|
|
33783
|
+
addonId: null,
|
|
33784
|
+
access: "create"
|
|
33785
|
+
},
|
|
33560
33786
|
"pipelineAnalytics.saveRetrainAnnotations": {
|
|
33561
33787
|
capName: "pipeline-analytics",
|
|
33562
33788
|
capScope: "device",
|
|
@@ -33689,6 +33915,12 @@ Object.freeze({
|
|
|
33689
33915
|
addonId: null,
|
|
33690
33916
|
access: "view"
|
|
33691
33917
|
},
|
|
33918
|
+
"pipelineExecutor.getInferenceDeviceHealth": {
|
|
33919
|
+
capName: "pipeline-executor",
|
|
33920
|
+
capScope: "system",
|
|
33921
|
+
addonId: null,
|
|
33922
|
+
access: "view"
|
|
33923
|
+
},
|
|
33692
33924
|
"pipelineExecutor.getOrchestratorConfigSchema": {
|
|
33693
33925
|
capName: "pipeline-executor",
|
|
33694
33926
|
capScope: "system",
|
|
@@ -33761,6 +33993,12 @@ Object.freeze({
|
|
|
33761
33993
|
addonId: null,
|
|
33762
33994
|
access: "view"
|
|
33763
33995
|
},
|
|
33996
|
+
"pipelineExecutor.rearmInferenceDevice": {
|
|
33997
|
+
capName: "pipeline-executor",
|
|
33998
|
+
capScope: "system",
|
|
33999
|
+
addonId: null,
|
|
34000
|
+
access: "create"
|
|
34001
|
+
},
|
|
33764
34002
|
"pipelineExecutor.runAudioTest": {
|
|
33765
34003
|
capName: "pipeline-executor",
|
|
33766
34004
|
capScope: "system",
|
|
@@ -37009,6 +37247,11 @@ Object.freeze({
|
|
|
37009
37247
|
form: "single",
|
|
37010
37248
|
optional: false
|
|
37011
37249
|
}],
|
|
37250
|
+
"pipelineAnalytics.runReplayFrameProcessor": [{
|
|
37251
|
+
name: "deviceId",
|
|
37252
|
+
form: "single",
|
|
37253
|
+
optional: false
|
|
37254
|
+
}],
|
|
37012
37255
|
"pipelineAnalytics.saveRetrainAnnotations": [{
|
|
37013
37256
|
name: "deviceId",
|
|
37014
37257
|
form: "single",
|
|
@@ -44408,7 +44651,10 @@ function sanitizeProfileSettings(profileId, raw) {
|
|
|
44408
44651
|
showContainers: true,
|
|
44409
44652
|
showSensors: true
|
|
44410
44653
|
};
|
|
44411
|
-
for (const plugin of GLANCES_PLUGINS)
|
|
44654
|
+
for (const plugin of GLANCES_PLUGINS) {
|
|
44655
|
+
const value = bag[plugin.key];
|
|
44656
|
+
if (typeof value === "boolean") out[plugin.key] = value;
|
|
44657
|
+
}
|
|
44412
44658
|
return out;
|
|
44413
44659
|
}
|
|
44414
44660
|
function profileSettingsToArgs(profileId, settings) {
|