@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.js
CHANGED
|
@@ -6721,7 +6721,7 @@ function method(input, output, options) {
|
|
|
6721
6721
|
input,
|
|
6722
6722
|
output,
|
|
6723
6723
|
kind: options?.kind ?? "query",
|
|
6724
|
-
auth: options
|
|
6724
|
+
...options?.auth !== void 0 ? { auth: options.auth } : {},
|
|
6725
6725
|
...options?.access !== void 0 ? { access: options.access } : {},
|
|
6726
6726
|
...options?.caller !== void 0 ? { caller: options.caller } : {},
|
|
6727
6727
|
timeoutMs: options?.timeoutMs
|
|
@@ -6745,7 +6745,7 @@ function event(data) {
|
|
|
6745
6745
|
}
|
|
6746
6746
|
var StaticDirOutputSchema$1 = object({ staticDir: string() });
|
|
6747
6747
|
var VersionOutputSchema$1 = object({ version: string() });
|
|
6748
|
-
method(_void(), StaticDirOutputSchema$1), method(_void(), VersionOutputSchema$1);
|
|
6748
|
+
method(_void(), StaticDirOutputSchema$1, { auth: "admin" }), method(_void(), VersionOutputSchema$1, { auth: "admin" });
|
|
6749
6749
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
6750
6750
|
DeviceType["Camera"] = "camera";
|
|
6751
6751
|
DeviceType["Hub"] = "hub";
|
|
@@ -7066,7 +7066,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
7066
7066
|
}({});
|
|
7067
7067
|
var StaticDirOutputSchema = object({ staticDir: string() });
|
|
7068
7068
|
var VersionOutputSchema = object({ version: string() });
|
|
7069
|
-
method(_void(), StaticDirOutputSchema), method(_void(), VersionOutputSchema);
|
|
7069
|
+
method(_void(), StaticDirOutputSchema, { auth: "admin" }), method(_void(), VersionOutputSchema, { auth: "admin" });
|
|
7070
7070
|
/**
|
|
7071
7071
|
* device-ops — device-scoped cap that unifies the per-IDevice operations
|
|
7072
7072
|
* previously routed through the `.device-ops` Moleculer bridge service.
|
|
@@ -7700,24 +7700,6 @@ var RecordingRetentionSchema = object({
|
|
|
7700
7700
|
maxSizeGb: number().min(0).optional()
|
|
7701
7701
|
});
|
|
7702
7702
|
/**
|
|
7703
|
-
* Scrub-thumbnail fidelity preset — the single per-camera selector bundling the
|
|
7704
|
-
* sprite tile RESOLUTION + JPEG QUALITY the recorder packs timeline-scrub
|
|
7705
|
-
* previews at. Five graduated steps; absent on a config = `standard` (the
|
|
7706
|
-
* shipped default, matching `sheet-geometry`/`sheet-composer`).
|
|
7707
|
-
*
|
|
7708
|
-
* Existing sheets are IMMUTABLE — a changed preset applies to NEW windows only.
|
|
7709
|
-
* Each window's index sidecar carries its own tile dims, so a camera whose
|
|
7710
|
-
* preset changed over time renders every historical window at the dims it was
|
|
7711
|
-
* written with.
|
|
7712
|
-
*/
|
|
7713
|
-
var ScrubThumbnailPresetSchema = _enum([
|
|
7714
|
-
"minimal",
|
|
7715
|
-
"low",
|
|
7716
|
-
"standard",
|
|
7717
|
-
"high",
|
|
7718
|
-
"max"
|
|
7719
|
-
]);
|
|
7720
|
-
/**
|
|
7721
7703
|
* The full per-camera recording intent — the wire shape of a RecordingTarget.
|
|
7722
7704
|
*
|
|
7723
7705
|
* `bands` is the ONLY authored recording intent: what to record, when, and on
|
|
@@ -7725,7 +7707,11 @@ var ScrubThumbnailPresetSchema = _enum([
|
|
|
7725
7707
|
* other field is a storage knob (profiles, segment length, retention, scrub).
|
|
7726
7708
|
*
|
|
7727
7709
|
* STRICT on purpose: the legacy authoring surface (`schedule`/`schedules`/
|
|
7728
|
-
* `triggers`/`preBufferSec`/`postBufferSec`/`rules`) was retired 2026-07-30
|
|
7710
|
+
* `triggers`/`preBufferSec`/`postBufferSec`/`rules`) was retired 2026-07-30,
|
|
7711
|
+
* and `scrubThumbnails` — a five-step fidelity knob for a sprite tier that was
|
|
7712
|
+
* deleted on 2026-07-24 and had ZERO consumers in the recorder — on 2026-08-25
|
|
7713
|
+
* (D62: a switch that writes a store nobody reads is worse than no switch).
|
|
7714
|
+
* Stored rows keep loading: the READ schema is `.strip()` (config-store.ts).
|
|
7729
7715
|
* A stale caller must fail loudly — silently stripping its legacy intent would
|
|
7730
7716
|
* persist a band-less config, i.e. silently stop recording the camera.
|
|
7731
7717
|
*/
|
|
@@ -7748,14 +7734,7 @@ var RecordingConfigSchema = object({
|
|
|
7748
7734
|
* "off" is the absence of a covering band, never a band value.
|
|
7749
7735
|
*/
|
|
7750
7736
|
bands: array(RecordingBandSchema).default([]),
|
|
7751
|
-
retention: RecordingRetentionSchema.optional()
|
|
7752
|
-
/**
|
|
7753
|
-
* Per-camera scrub-thumbnail fidelity preset (resolution + JPEG quality for
|
|
7754
|
-
* timeline-scrub sprite previews). Absent = `standard`. Applies to NEW
|
|
7755
|
-
* windows only — existing sheets are immutable, and each window's index
|
|
7756
|
-
* carries its own tile dims so mixed-preset history renders correctly.
|
|
7757
|
-
*/
|
|
7758
|
-
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7737
|
+
retention: RecordingRetentionSchema.optional()
|
|
7759
7738
|
}).strict();
|
|
7760
7739
|
/**
|
|
7761
7740
|
* Entity-relocation job state (storage entity-routing spec, Phase 4).
|
|
@@ -7831,10 +7810,11 @@ var RelocateFootageInputSchema = object({
|
|
|
7831
7810
|
* `RecordingConfig.enabled` or camera wrapper bindings. */
|
|
7832
7811
|
var StorageMigrationLeaseInputSchema = object({ leaseId: string().min(1) });
|
|
7833
7812
|
var StorageMigrationFootageMoveInputSchema = RelocateFootageInputSchema.extend({ leaseId: string().min(1) });
|
|
7834
|
-
var
|
|
7813
|
+
var RelocateMediaInputSchema = object({
|
|
7835
7814
|
toLocationId: string(),
|
|
7836
7815
|
throttleMbps: number().min(1).max(1e3).optional()
|
|
7837
|
-
})
|
|
7816
|
+
});
|
|
7817
|
+
var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: string().min(1) });
|
|
7838
7818
|
/** The independently selectable logical storage classes. `recordings`
|
|
7839
7819
|
* encompasses the high and mid segment profiles; `recordingsLow` is low
|
|
7840
7820
|
* segments; `eventMedia` is post-analysis blobs. */
|
|
@@ -8129,7 +8109,26 @@ var LabelDefinitionSchema = object({
|
|
|
8129
8109
|
description: string().optional(),
|
|
8130
8110
|
icon: string().optional()
|
|
8131
8111
|
});
|
|
8132
|
-
|
|
8112
|
+
/**
|
|
8113
|
+
* Wire schema for a per-model CATALOG classMap override
|
|
8114
|
+
* (`ModelCatalogEntry.classMap` / `ModelConvertMetadata.classMap`) —
|
|
8115
|
+
* restricted to {@link CLASS_MAP_MACRO_TARGETS}, the only macros the
|
|
8116
|
+
* detection pipeline executor actually routes.
|
|
8117
|
+
*
|
|
8118
|
+
* This is deliberately a DIFFERENT, narrower shape than the general-purpose
|
|
8119
|
+
* `ClassMapDefinition` interface above (e.g. `IDetectionAddon.getClassMap()`
|
|
8120
|
+
* and the audio `YAMNET_TO_MACRO` catalog both use macro targets outside this
|
|
8121
|
+
* enum) — the two used to share the name `ClassMapDefinition`/
|
|
8122
|
+
* `ClassMapDefinitionSchema`, which made the schema-type-twin guard
|
|
8123
|
+
* (`scripts/check-schema-type-twins.ts`) flag them as a duplicated shape. They
|
|
8124
|
+
* are not: it is two different concepts colliding on a name. Keep this type
|
|
8125
|
+
* under its own name rather than reusing `ClassMapDefinition` — reusing it
|
|
8126
|
+
* would either narrow every `ClassMapDefinition` consumer to the four
|
|
8127
|
+
* detection macros (breaking `YAMNET_TO_MACRO`) or drop the validation this
|
|
8128
|
+
* schema exists for (see the "rejects a classMap whose target is not a
|
|
8129
|
+
* detection macro" test in `model-catalog-schema.test.ts`).
|
|
8130
|
+
*/
|
|
8131
|
+
var DetectionCatalogClassMapSchema = object({
|
|
8133
8132
|
mapping: record(string(), _enum([
|
|
8134
8133
|
"person",
|
|
8135
8134
|
"vehicle",
|
|
@@ -8334,7 +8333,7 @@ var ModelCatalogEntrySchema = object({
|
|
|
8334
8333
|
* applies (Frigate / COCO public catalog). Set on a custom model whose raw
|
|
8335
8334
|
* labels already ARE the CamStack macros (Scrypted identity map).
|
|
8336
8335
|
*/
|
|
8337
|
-
classMap:
|
|
8336
|
+
classMap: DetectionCatalogClassMapSchema.optional()
|
|
8338
8337
|
});
|
|
8339
8338
|
var ConvertTargetSchema = discriminatedUnion("format", [object({
|
|
8340
8339
|
format: literal("openvino"),
|
|
@@ -8364,7 +8363,7 @@ var ModelConvertMetadataSchema = object({
|
|
|
8364
8363
|
"segmentation"
|
|
8365
8364
|
]),
|
|
8366
8365
|
faceAlignment: boolean().optional(),
|
|
8367
|
-
classMap:
|
|
8366
|
+
classMap: DetectionCatalogClassMapSchema.optional()
|
|
8368
8367
|
});
|
|
8369
8368
|
var ConvertResultSchema = object({
|
|
8370
8369
|
entry: ModelCatalogEntrySchema,
|
|
@@ -9227,7 +9226,7 @@ var AddonPageDeclarationSchema = object({
|
|
|
9227
9226
|
/** Display label for a CUSTOM `section` id (ignored for well-known ids). */
|
|
9228
9227
|
sectionLabel: string().optional()
|
|
9229
9228
|
});
|
|
9230
|
-
method(_void(), array(AddonPageDeclarationSchema).readonly());
|
|
9229
|
+
method(_void(), array(AddonPageDeclarationSchema).readonly(), { auth: "admin" });
|
|
9231
9230
|
var AddonHttpRouteSchema = object({
|
|
9232
9231
|
method: _enum([
|
|
9233
9232
|
"GET",
|
|
@@ -9462,7 +9461,7 @@ var WidgetMetadataSchema = object({
|
|
|
9462
9461
|
defaultColumns: number().int().min(1).max(12).default(6),
|
|
9463
9462
|
defaultRows: number().int().min(1).max(12).default(1)
|
|
9464
9463
|
});
|
|
9465
|
-
method(_void(), array(WidgetMetadataSchema).readonly());
|
|
9464
|
+
method(_void(), array(WidgetMetadataSchema).readonly(), { auth: "admin" });
|
|
9466
9465
|
/**
|
|
9467
9466
|
* `addon-widgets` — system-scoped singleton aggregator cap. Public-facing
|
|
9468
9467
|
* surface that admin-ui consumes through `useAddonWidgetsListWidgets()`.
|
|
@@ -11086,7 +11085,7 @@ var CustomModelDescriptorSchema = object({
|
|
|
11086
11085
|
stepId: string(),
|
|
11087
11086
|
entry: ModelCatalogEntrySchema
|
|
11088
11087
|
});
|
|
11089
|
-
method(_void(), array(CustomModelDescriptorSchema).readonly());
|
|
11088
|
+
method(_void(), array(CustomModelDescriptorSchema).readonly(), { auth: "admin" });
|
|
11090
11089
|
/**
|
|
11091
11090
|
* Query filter for settings-store collections.
|
|
11092
11091
|
*/
|
|
@@ -11173,7 +11172,8 @@ method(object({
|
|
|
11173
11172
|
}), _void(), { kind: "mutation" }), method(object({
|
|
11174
11173
|
namespace: string().optional(),
|
|
11175
11174
|
collection: string(),
|
|
11176
|
-
filter: QueryFilterSchema.optional()
|
|
11175
|
+
filter: QueryFilterSchema.optional(),
|
|
11176
|
+
columns: array(string()).readonly().optional()
|
|
11177
11177
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
11178
11178
|
namespace: string().optional(),
|
|
11179
11179
|
collection: string(),
|
|
@@ -11236,46 +11236,87 @@ var EngineInfoSchema = object({
|
|
|
11236
11236
|
kind: _enum(["relational", "vector"]),
|
|
11237
11237
|
displayName: string()
|
|
11238
11238
|
});
|
|
11239
|
-
method(_void(), EngineInfoSchema), method(object({
|
|
11239
|
+
method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
11240
11240
|
namespace: string().optional(),
|
|
11241
11241
|
collection: string(),
|
|
11242
11242
|
key: string()
|
|
11243
|
-
}), unknown()), method(object({
|
|
11243
|
+
}), unknown(), { auth: "admin" }), method(object({
|
|
11244
11244
|
namespace: string().optional(),
|
|
11245
11245
|
collection: string(),
|
|
11246
11246
|
key: string(),
|
|
11247
11247
|
value: unknown()
|
|
11248
|
-
}), _void(), {
|
|
11248
|
+
}), _void(), {
|
|
11249
|
+
kind: "mutation",
|
|
11250
|
+
auth: "admin"
|
|
11251
|
+
}), method(object({
|
|
11249
11252
|
namespace: string().optional(),
|
|
11250
11253
|
collection: string(),
|
|
11251
|
-
filter: QueryFilterSchema.optional()
|
|
11252
|
-
|
|
11254
|
+
filter: QueryFilterSchema.optional(),
|
|
11255
|
+
/**
|
|
11256
|
+
* SQL-level column projection — MUST mirror `settings-store.query`.
|
|
11257
|
+
*
|
|
11258
|
+
* ⚠ An earlier version of this comment blamed Zod stripping, and that
|
|
11259
|
+
* was wrong — corrected 2026-08-26 after the hop map
|
|
11260
|
+
* (`docs/design/2026-08-26-mappa-hop-argomenti.md`) traced the path.
|
|
11261
|
+
* There is **no Zod parse at all** between the door and the engine: the
|
|
11262
|
+
* dispatcher forwards the payload verbatim and UDS carries it whole. A
|
|
11263
|
+
* field declared here reaches `SqliteSettingsBackend` either way.
|
|
11264
|
+
*
|
|
11265
|
+
* What actually lost `columns` was the THIRD declaration of this shape:
|
|
11266
|
+
* `SettingsQueryInput` in `interfaces/storage.ts`, a hand-written TS
|
|
11267
|
+
* interface the engine destructures from. The field existed on both
|
|
11268
|
+
* schemas and the engine still never read it, because nothing checks a
|
|
11269
|
+
* registered provider against `InferProvider<cap>` —
|
|
11270
|
+
* `ProviderRegistration.provider` is typed `object`.
|
|
11271
|
+
*
|
|
11272
|
+
* It is declared here anyway, and must stay in step with
|
|
11273
|
+
* `settings-store.query`: a caller reading only the cap definitions has
|
|
11274
|
+
* to be able to see that this call carries a projection.
|
|
11275
|
+
* `data-door-schema-parity.spec.ts` keeps the two aligned.
|
|
11276
|
+
*/
|
|
11277
|
+
columns: array(string()).readonly().optional()
|
|
11278
|
+
}), array(SettingsRecordSchema).readonly(), { auth: "admin" }), method(object({
|
|
11253
11279
|
namespace: string().optional(),
|
|
11254
11280
|
collection: string(),
|
|
11255
11281
|
record: SettingsRecordSchema
|
|
11256
|
-
}), _void(), {
|
|
11282
|
+
}), _void(), {
|
|
11283
|
+
kind: "mutation",
|
|
11284
|
+
auth: "admin"
|
|
11285
|
+
}), method(object({
|
|
11257
11286
|
namespace: string().optional(),
|
|
11258
11287
|
collection: string(),
|
|
11259
11288
|
id: string(),
|
|
11260
11289
|
data: record(string(), unknown())
|
|
11261
|
-
}), _void(), {
|
|
11290
|
+
}), _void(), {
|
|
11291
|
+
kind: "mutation",
|
|
11292
|
+
auth: "admin"
|
|
11293
|
+
}), method(object({
|
|
11262
11294
|
namespace: string().optional(),
|
|
11263
11295
|
collection: string(),
|
|
11264
11296
|
key: string()
|
|
11265
|
-
}), _void(), {
|
|
11297
|
+
}), _void(), {
|
|
11298
|
+
kind: "mutation",
|
|
11299
|
+
auth: "admin"
|
|
11300
|
+
}), method(object({
|
|
11266
11301
|
namespace: string().optional(),
|
|
11267
11302
|
collection: string(),
|
|
11268
11303
|
filter: MutationFilterSchema
|
|
11269
|
-
}), object({ deleted: number().int() }), {
|
|
11304
|
+
}), object({ deleted: number().int() }), {
|
|
11305
|
+
kind: "mutation",
|
|
11306
|
+
auth: "admin"
|
|
11307
|
+
}), method(object({
|
|
11270
11308
|
namespace: string().optional(),
|
|
11271
11309
|
collection: string(),
|
|
11272
11310
|
filter: MutationFilterSchema,
|
|
11273
11311
|
data: record(string(), unknown())
|
|
11274
|
-
}), object({ updated: number().int() }), {
|
|
11312
|
+
}), object({ updated: number().int() }), {
|
|
11313
|
+
kind: "mutation",
|
|
11314
|
+
auth: "admin"
|
|
11315
|
+
}), method(object({
|
|
11275
11316
|
namespace: string().optional(),
|
|
11276
11317
|
collection: string(),
|
|
11277
11318
|
filter: QueryFilterSchema.optional()
|
|
11278
|
-
}), number()), method(object({
|
|
11319
|
+
}), number(), { auth: "admin" }), method(object({
|
|
11279
11320
|
namespace: string().optional(),
|
|
11280
11321
|
collection: string(),
|
|
11281
11322
|
field: string(),
|
|
@@ -11285,15 +11326,18 @@ method(_void(), EngineInfoSchema), method(object({
|
|
|
11285
11326
|
}), array(object({
|
|
11286
11327
|
bucket: number().int(),
|
|
11287
11328
|
count: number().int()
|
|
11288
|
-
})).readonly()), method(object({
|
|
11329
|
+
})).readonly(), { auth: "admin" }), method(object({
|
|
11289
11330
|
namespace: string().optional(),
|
|
11290
11331
|
collection: string()
|
|
11291
|
-
}), boolean()), method(object({
|
|
11332
|
+
}), boolean(), { auth: "admin" }), method(object({
|
|
11292
11333
|
namespace: string().optional(),
|
|
11293
11334
|
collection: string(),
|
|
11294
11335
|
columns: array(CollectionColumnSchema).readonly(),
|
|
11295
11336
|
indexes: array(CollectionIndexSchema).readonly().optional()
|
|
11296
|
-
}), _void(), {
|
|
11337
|
+
}), _void(), {
|
|
11338
|
+
kind: "mutation",
|
|
11339
|
+
auth: "admin"
|
|
11340
|
+
});
|
|
11297
11341
|
/**
|
|
11298
11342
|
* shm ring usage stats for a `frameSink: 'shm'` decoder session —
|
|
11299
11343
|
* exposed via `decoder.getShmStats` so downstream consumers can
|
|
@@ -12528,7 +12572,7 @@ method(object({
|
|
|
12528
12572
|
crop: _instanceof(Uint8Array),
|
|
12529
12573
|
width: number(),
|
|
12530
12574
|
height: number()
|
|
12531
|
-
}), EmbeddingResultSchema), method(object({ text: string() }), EmbeddingResultSchema), method(_void(), EmbeddingInfoSchema);
|
|
12575
|
+
}), EmbeddingResultSchema, { auth: "admin" }), method(object({ text: string() }), EmbeddingResultSchema, { auth: "admin" }), method(_void(), EmbeddingInfoSchema, { auth: "admin" });
|
|
12532
12576
|
/**
|
|
12533
12577
|
* filesystem-browse — per-node capability for browsing the node's local
|
|
12534
12578
|
* filesystem. Reads are unconfined (whole filesystem, from `/` down); WRITES
|
|
@@ -12821,19 +12865,22 @@ method(LlmGenerateBaseInputSchema.extend({
|
|
|
12821
12865
|
runtime: ManagedRuntimeConfigSchema,
|
|
12822
12866
|
/** The managed profile's timeout, threaded by the hub provider. */
|
|
12823
12867
|
timeoutMs: number().int().positive().optional()
|
|
12824
|
-
}), LlmGenerateResultSchema, {
|
|
12868
|
+
}), LlmGenerateResultSchema, {
|
|
12869
|
+
kind: "mutation",
|
|
12870
|
+
auth: "admin"
|
|
12871
|
+
}), method(object({ runtime: ManagedRuntimeConfigSchema }), LlmRuntimeStatusSchema, {
|
|
12825
12872
|
kind: "mutation",
|
|
12826
12873
|
auth: "admin"
|
|
12827
12874
|
}), method(object({}), _void(), {
|
|
12828
12875
|
kind: "mutation",
|
|
12829
12876
|
auth: "admin"
|
|
12830
|
-
}), method(object({}), LlmRuntimeStatusSchema), method(object({ model: ManagedModelRefSchema }), _void(), {
|
|
12877
|
+
}), method(object({}), LlmRuntimeStatusSchema, { auth: "admin" }), method(object({ model: ManagedModelRefSchema }), _void(), {
|
|
12831
12878
|
kind: "mutation",
|
|
12832
12879
|
auth: "admin"
|
|
12833
12880
|
}), method(object({ file: string() }), _void(), {
|
|
12834
12881
|
kind: "mutation",
|
|
12835
12882
|
auth: "admin"
|
|
12836
|
-
}), method(object({}), array(LlmNodeModelSchema)), method(object({}), LlmRuntimeDiskUsageSchema);
|
|
12883
|
+
}), method(object({}), array(LlmNodeModelSchema), { auth: "admin" }), method(object({}), LlmRuntimeDiskUsageSchema, { auth: "admin" });
|
|
12837
12884
|
/**
|
|
12838
12885
|
* `llm` — consumer-facing LLM surface (spec §1-§3). Collection-mode: array
|
|
12839
12886
|
* methods concat-fan across providers; single-row methods route to ONE
|
|
@@ -16344,7 +16391,647 @@ var OauthIntegrationDescriptorSchema = object({
|
|
|
16344
16391
|
*/
|
|
16345
16392
|
refreshTokenTtlSec: union([number().int().positive(), literal("never")]).optional()
|
|
16346
16393
|
});
|
|
16347
|
-
method(_void(), OauthIntegrationDescriptorSchema);
|
|
16394
|
+
method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" });
|
|
16395
|
+
/**
|
|
16396
|
+
* Reference to the frame's retained NATIVE surface + the parent crop's placement
|
|
16397
|
+
* within the frame, so the executor can re-cut a leaf child ROI at native
|
|
16398
|
+
* resolution on the detail plane. See the `runPipeline` `nativeCropRef` field.
|
|
16399
|
+
*/
|
|
16400
|
+
var NativeCropRefSchema = object({
|
|
16401
|
+
/** Handle keying the retained native surface (node-pinned to its owner). */
|
|
16402
|
+
handle: FrameHandleSchema,
|
|
16403
|
+
/** The parent crop's padded/clamped rectangle in FRAME-space pixels. */
|
|
16404
|
+
cropFrameSpace: object({
|
|
16405
|
+
x: number(),
|
|
16406
|
+
y: number(),
|
|
16407
|
+
w: number(),
|
|
16408
|
+
h: number()
|
|
16409
|
+
})
|
|
16410
|
+
});
|
|
16411
|
+
object({
|
|
16412
|
+
crop: object({
|
|
16413
|
+
left: number(),
|
|
16414
|
+
top: number(),
|
|
16415
|
+
width: number().positive(),
|
|
16416
|
+
height: number().positive()
|
|
16417
|
+
}).optional(),
|
|
16418
|
+
content: object({
|
|
16419
|
+
width: number().int().positive(),
|
|
16420
|
+
height: number().int().positive()
|
|
16421
|
+
}),
|
|
16422
|
+
fit: _enum(["stretch", "contain"]),
|
|
16423
|
+
format: _enum([
|
|
16424
|
+
"rgb",
|
|
16425
|
+
"gray",
|
|
16426
|
+
"jpeg"
|
|
16427
|
+
])
|
|
16428
|
+
});
|
|
16429
|
+
/**
|
|
16430
|
+
* Process-local frame identity. It is serializable so it can ride an in-process
|
|
16431
|
+
* capability call, but `registryId` deliberately prevents resolution in any
|
|
16432
|
+
* other process or execution group.
|
|
16433
|
+
*/
|
|
16434
|
+
var FrameRefSchema = object({
|
|
16435
|
+
registryId: string().min(1),
|
|
16436
|
+
id: string().min(1),
|
|
16437
|
+
width: number().int().positive(),
|
|
16438
|
+
height: number().int().positive(),
|
|
16439
|
+
format: _enum(["rgb", "gray"]),
|
|
16440
|
+
timestamp: number(),
|
|
16441
|
+
capturedAt: number().optional()
|
|
16442
|
+
});
|
|
16443
|
+
var ModelFormatSchema$1 = _enum([
|
|
16444
|
+
"onnx",
|
|
16445
|
+
"coreml",
|
|
16446
|
+
"openvino",
|
|
16447
|
+
"tflite",
|
|
16448
|
+
"pt",
|
|
16449
|
+
"gguf"
|
|
16450
|
+
]);
|
|
16451
|
+
var PipelineSlotSchema = _enum([
|
|
16452
|
+
"detector",
|
|
16453
|
+
"cropper",
|
|
16454
|
+
"classifier",
|
|
16455
|
+
"refiner",
|
|
16456
|
+
"audio-classifier"
|
|
16457
|
+
]);
|
|
16458
|
+
var PipelineEngineChoiceSchema = object({
|
|
16459
|
+
runtime: _enum(["node", "python"]),
|
|
16460
|
+
backend: string(),
|
|
16461
|
+
format: ModelFormatSchema$1,
|
|
16462
|
+
device: string().optional()
|
|
16463
|
+
});
|
|
16464
|
+
var AvailableEngineSchema = object({
|
|
16465
|
+
engine: PipelineEngineChoiceSchema,
|
|
16466
|
+
devices: array(object({
|
|
16467
|
+
id: string(),
|
|
16468
|
+
label: string(),
|
|
16469
|
+
description: string().optional()
|
|
16470
|
+
})).readonly(),
|
|
16471
|
+
defaultDevice: string()
|
|
16472
|
+
});
|
|
16473
|
+
var PipelineDefaultStepSchema = lazy(() => object({
|
|
16474
|
+
addonId: string(),
|
|
16475
|
+
addonName: string(),
|
|
16476
|
+
slot: PipelineSlotSchema,
|
|
16477
|
+
inputClasses: array(string()).readonly(),
|
|
16478
|
+
outputClasses: array(string()).readonly(),
|
|
16479
|
+
enabled: boolean(),
|
|
16480
|
+
modelId: string(),
|
|
16481
|
+
children: array(PipelineDefaultStepSchema).readonly(),
|
|
16482
|
+
group: string().optional(),
|
|
16483
|
+
settings: record(string(), unknown()).optional()
|
|
16484
|
+
}));
|
|
16485
|
+
var PipelineTemplateStepSchema = lazy(() => object({
|
|
16486
|
+
addonId: string(),
|
|
16487
|
+
enabled: boolean(),
|
|
16488
|
+
modelId: string(),
|
|
16489
|
+
children: array(PipelineTemplateStepSchema).readonly(),
|
|
16490
|
+
settings: record(string(), unknown()).optional()
|
|
16491
|
+
}));
|
|
16492
|
+
var PipelineTemplateSchema$1 = object({
|
|
16493
|
+
id: string(),
|
|
16494
|
+
name: string(),
|
|
16495
|
+
createdAt: string(),
|
|
16496
|
+
updatedAt: string(),
|
|
16497
|
+
engine: PipelineEngineChoiceSchema,
|
|
16498
|
+
steps: array(PipelineTemplateStepSchema).readonly()
|
|
16499
|
+
});
|
|
16500
|
+
var PipelineModelOptionSchema = object({
|
|
16501
|
+
id: string(),
|
|
16502
|
+
name: string(),
|
|
16503
|
+
formats: record(string(), object({
|
|
16504
|
+
downloaded: boolean(),
|
|
16505
|
+
sizeMB: number()
|
|
16506
|
+
})),
|
|
16507
|
+
group: ModelVariantGroupSchema.optional(),
|
|
16508
|
+
legacy: boolean().optional(),
|
|
16509
|
+
provider: ModelProviderIdSchema.optional()
|
|
16510
|
+
});
|
|
16511
|
+
var ConfigFieldBridge = custom();
|
|
16512
|
+
var PipelineAddonSchemaSchema = object({
|
|
16513
|
+
id: string(),
|
|
16514
|
+
name: string(),
|
|
16515
|
+
slot: PipelineSlotSchema,
|
|
16516
|
+
inputClasses: array(string()).readonly(),
|
|
16517
|
+
outputClasses: array(string()).readonly(),
|
|
16518
|
+
childSlots: array(PipelineSlotSchema).readonly(),
|
|
16519
|
+
models: array(PipelineModelOptionSchema).readonly(),
|
|
16520
|
+
defaultModelId: string(),
|
|
16521
|
+
defaultModelIdByFormat: record(string(), string()).optional(),
|
|
16522
|
+
enabledByDefault: boolean().optional(),
|
|
16523
|
+
backfillIntoExistingOverrides: boolean().optional(),
|
|
16524
|
+
defaultConfidence: number(),
|
|
16525
|
+
group: string().optional(),
|
|
16526
|
+
configSchema: array(ConfigFieldBridge).readonly().optional()
|
|
16527
|
+
});
|
|
16528
|
+
var PipelineSlotSchemaSchema = object({
|
|
16529
|
+
id: PipelineSlotSchema,
|
|
16530
|
+
label: string(),
|
|
16531
|
+
priority: number(),
|
|
16532
|
+
parentSlot: PipelineSlotSchema.nullable(),
|
|
16533
|
+
addons: array(PipelineAddonSchemaSchema).readonly()
|
|
16534
|
+
});
|
|
16535
|
+
var PipelineSchemaSchema = object({
|
|
16536
|
+
availableEngines: array(AvailableEngineSchema).readonly(),
|
|
16537
|
+
selectedEngine: PipelineEngineChoiceSchema,
|
|
16538
|
+
slots: array(PipelineSlotSchemaSchema).readonly()
|
|
16539
|
+
});
|
|
16540
|
+
var EngineProvisioningSchema = object({
|
|
16541
|
+
runtimeId: _enum([
|
|
16542
|
+
"onnx",
|
|
16543
|
+
"openvino",
|
|
16544
|
+
"coreml",
|
|
16545
|
+
"edgetpu"
|
|
16546
|
+
]).nullable(),
|
|
16547
|
+
device: string().nullable(),
|
|
16548
|
+
state: _enum([
|
|
16549
|
+
"idle",
|
|
16550
|
+
"installing",
|
|
16551
|
+
"verifying",
|
|
16552
|
+
"ready",
|
|
16553
|
+
"failed"
|
|
16554
|
+
]),
|
|
16555
|
+
progress: number().optional(),
|
|
16556
|
+
error: string().optional(),
|
|
16557
|
+
nextRetryAt: number().optional(),
|
|
16558
|
+
/**
|
|
16559
|
+
* Gate A (config-correctness gate at engine change): human-readable
|
|
16560
|
+
* config issues surfaced EAGERLY when the node's engine changes — model
|
|
16561
|
+
* substitutions ("chose X, running Y") and zero-build steps ("no model
|
|
16562
|
+
* has a <format> build"). Additive/optional: informational only, never
|
|
16563
|
+
* enforced here — `assertEngineReady` (readiness) still gates inference.
|
|
16564
|
+
* Absent/empty when the node-default tree resolves cleanly.
|
|
16565
|
+
*/
|
|
16566
|
+
configIssues: array(string()).optional()
|
|
16567
|
+
});
|
|
16568
|
+
var PipelineStepInputSchema = lazy(() => object({
|
|
16569
|
+
addonId: string(),
|
|
16570
|
+
modelId: string().optional(),
|
|
16571
|
+
enabled: boolean().default(true),
|
|
16572
|
+
children: array(PipelineStepInputSchema).optional(),
|
|
16573
|
+
settings: record(string(), unknown()).optional(),
|
|
16574
|
+
jumpDeviceKey: string().optional()
|
|
16575
|
+
}));
|
|
16576
|
+
var ModelSubstitutionSchema = object({
|
|
16577
|
+
addonId: string(),
|
|
16578
|
+
chosen: string(),
|
|
16579
|
+
running: string(),
|
|
16580
|
+
format: string()
|
|
16581
|
+
});
|
|
16582
|
+
var PipelineValidationIssueSchema = object({
|
|
16583
|
+
addonId: string(),
|
|
16584
|
+
kind: _enum(["unknown-addon", "no-format-build"]),
|
|
16585
|
+
detail: string()
|
|
16586
|
+
});
|
|
16587
|
+
var PipelineValidationResultSchema = object({
|
|
16588
|
+
ok: boolean(),
|
|
16589
|
+
issues: array(PipelineValidationIssueSchema).readonly(),
|
|
16590
|
+
substitutions: array(ModelSubstitutionSchema).readonly(),
|
|
16591
|
+
/** The node's `currentEngine.format` this validation ran against. */
|
|
16592
|
+
format: string()
|
|
16593
|
+
});
|
|
16594
|
+
var ReferenceImageEntrySchema = object({
|
|
16595
|
+
filename: string(),
|
|
16596
|
+
stepIds: array(string()).readonly().optional()
|
|
16597
|
+
});
|
|
16598
|
+
var ReferenceImageBodySchema = object({
|
|
16599
|
+
base64: string(),
|
|
16600
|
+
filename: string()
|
|
16601
|
+
});
|
|
16602
|
+
var ReferenceAudioEntrySchema = object({
|
|
16603
|
+
filename: string(),
|
|
16604
|
+
sizeKb: number()
|
|
16605
|
+
});
|
|
16606
|
+
var ReferenceAudioBodySchema = object({ base64: string() });
|
|
16607
|
+
var AudioBackendSchema = object({
|
|
16608
|
+
id: string(),
|
|
16609
|
+
name: string(),
|
|
16610
|
+
description: string(),
|
|
16611
|
+
available: boolean(),
|
|
16612
|
+
/**
|
|
16613
|
+
* Raw classifier labels this backend can emit (e.g. YAMNet's
|
|
16614
|
+
* 521-class set or Apple SoundAnalysis's 303-class set). Used by
|
|
16615
|
+
* the benchmark UI to populate the `enabledMicroClasses` filter
|
|
16616
|
+
* specific to the selected backend without a separate fetch.
|
|
16617
|
+
*/
|
|
16618
|
+
rawLabels: array(string()).readonly().optional()
|
|
16619
|
+
});
|
|
16620
|
+
var AudioCapabilitiesSchema = object({
|
|
16621
|
+
activeBackend: string(),
|
|
16622
|
+
availableBackends: array(AudioBackendSchema).readonly(),
|
|
16623
|
+
sampleRate: number(),
|
|
16624
|
+
chunkDurationMs: number()
|
|
16625
|
+
});
|
|
16626
|
+
var DownloadModelResultSchema = object({
|
|
16627
|
+
filePath: string(),
|
|
16628
|
+
sizeMB: number(),
|
|
16629
|
+
durationMs: number()
|
|
16630
|
+
});
|
|
16631
|
+
/**
|
|
16632
|
+
* Wrapper carrying a single test run's result. Replaces the legacy
|
|
16633
|
+
* ad-hoc `{labels: [{className, originalClass, score}]}` shape with the
|
|
16634
|
+
* canonical `AudioResult` from the Phase 6 output rework: one
|
|
16635
|
+
* `AudioDetection` per class above `minScore`, top-N candidates in
|
|
16636
|
+
* `debug.alternateLabels['audio-classifier']`, per-source timings in
|
|
16637
|
+
* `debug.stepTimings`. The outer `success`/`error` fields stay so the
|
|
16638
|
+
* benchmark UI can still report a clean failure when the classifier
|
|
16639
|
+
* cap isn't available.
|
|
16640
|
+
*/
|
|
16641
|
+
var AudioTestResultSchema = object({
|
|
16642
|
+
success: boolean(),
|
|
16643
|
+
error: string().optional(),
|
|
16644
|
+
frame: custom().optional()
|
|
16645
|
+
});
|
|
16646
|
+
var PipelineConfigBridge = custom();
|
|
16647
|
+
var ConfigUISchemaBridge = custom();
|
|
16648
|
+
var ConfigUISchemaNullableBridge = custom();
|
|
16649
|
+
var InferenceCapabilitiesBridge = custom();
|
|
16650
|
+
var ModelAvailabilityListBridge = custom();
|
|
16651
|
+
var PipelineRunResultBridge = custom();
|
|
16652
|
+
method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
|
|
16653
|
+
modelId: string(),
|
|
16654
|
+
settings: record(string(), unknown()).readonly()
|
|
16655
|
+
}))), method(object({ steps: record(string(), object({
|
|
16656
|
+
modelId: string(),
|
|
16657
|
+
settings: record(string(), unknown()).readonly()
|
|
16658
|
+
})) }), object({ success: literal(true) }), {
|
|
16659
|
+
kind: "mutation",
|
|
16660
|
+
auth: "admin"
|
|
16661
|
+
}), method(object({ nodeId: string() }), object({
|
|
16662
|
+
success: literal(true),
|
|
16663
|
+
clearedDevices: number()
|
|
16664
|
+
}), {
|
|
16665
|
+
kind: "mutation",
|
|
16666
|
+
auth: "admin"
|
|
16667
|
+
}), method(object({ nodeId: string() }), object({ unhealthy: array(object({
|
|
16668
|
+
/** `<backend>:<device>`, e.g. `openvino:gpu`. */
|
|
16669
|
+
deviceKey: string(),
|
|
16670
|
+
/**
|
|
16671
|
+
* `failed` — the per-device restart budget is exhausted; no pool
|
|
16672
|
+
* will be spawned until an operator re-arms it or the runner
|
|
16673
|
+
* respawns. `backoff` — under budget, waiting out the backoff (or
|
|
16674
|
+
* a cached pool observed dead and not yet condemned).
|
|
16675
|
+
*/
|
|
16676
|
+
state: _enum(["failed", "backoff"]),
|
|
16677
|
+
/** Epoch ms of the death that produced this state. */
|
|
16678
|
+
since: number(),
|
|
16679
|
+
/** Pool deaths inside the current window. */
|
|
16680
|
+
deaths: number(),
|
|
16681
|
+
/** The last death's message. */
|
|
16682
|
+
lastError: string()
|
|
16683
|
+
})).readonly() })), method(object({
|
|
16684
|
+
nodeId: string(),
|
|
16685
|
+
deviceKey: string()
|
|
16686
|
+
}), object({ rearmed: boolean() }), {
|
|
16687
|
+
kind: "mutation",
|
|
16688
|
+
auth: "admin"
|
|
16689
|
+
}), 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({
|
|
16690
|
+
name: string(),
|
|
16691
|
+
steps: array(PipelineTemplateStepSchema).readonly(),
|
|
16692
|
+
engine: PipelineEngineChoiceSchema
|
|
16693
|
+
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({
|
|
16694
|
+
id: string(),
|
|
16695
|
+
name: string().optional(),
|
|
16696
|
+
steps: array(PipelineTemplateStepSchema).readonly().optional()
|
|
16697
|
+
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({ id: string() }), _void(), { kind: "mutation" }), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
|
|
16698
|
+
addonId: string(),
|
|
16699
|
+
modelId: string(),
|
|
16700
|
+
format: ModelFormatSchema$1
|
|
16701
|
+
}), DownloadModelResultSchema, { kind: "mutation" }), method(object({
|
|
16702
|
+
addonId: string(),
|
|
16703
|
+
modelId: string(),
|
|
16704
|
+
format: ModelFormatSchema$1
|
|
16705
|
+
}), object({ success: literal(true) }), { kind: "mutation" }), method(object({
|
|
16706
|
+
engine: PipelineEngineChoiceSchema.optional(),
|
|
16707
|
+
steps: array(PipelineStepInputSchema).min(1),
|
|
16708
|
+
frame: FrameInputSchema.optional(),
|
|
16709
|
+
/**
|
|
16710
|
+
* Process-local lazy frame. Valid only when caller and provider resolve
|
|
16711
|
+
* in the same execution-group process; split/cross-node callers use
|
|
16712
|
+
* `frame`/`image` inline compatibility instead.
|
|
16713
|
+
*/
|
|
16714
|
+
frameRef: FrameRefSchema.optional(),
|
|
16715
|
+
/**
|
|
16716
|
+
* CB5 shm passthrough — a `FrameHandle` naming the same ring slot
|
|
16717
|
+
* the decoded pixels live in. One more member of the one-of
|
|
16718
|
+
* frame/frameHandle/image/imageBase64/referenceImage group.
|
|
16719
|
+
*/
|
|
16720
|
+
frameHandle: FrameHandleSchema.optional(),
|
|
16721
|
+
imageBase64: string().optional(),
|
|
16722
|
+
/**
|
|
16723
|
+
* Binary JPEG bytes — preferred over `imageBase64` on internal
|
|
16724
|
+
* hops (hub → forked worker via Moleculer MsgPack) because it
|
|
16725
|
+
* skips the 33% base64 overhead + the per-call base64 decode on
|
|
16726
|
+
* the detection-pipeline worker. Callers can pass either; exactly
|
|
16727
|
+
* one of `frame`/`image`/`imageBase64`/`referenceImage` is required.
|
|
16728
|
+
*/
|
|
16729
|
+
image: _instanceof(Uint8Array).optional(),
|
|
16730
|
+
referenceImage: string().optional(),
|
|
16731
|
+
deviceId: number().optional(),
|
|
16732
|
+
sessionId: string().optional(),
|
|
16733
|
+
/**
|
|
16734
|
+
* Execution plane. 'full' (default) runs the whole tree — benchmark,
|
|
16735
|
+
* reference-image, and detail-subtree calls. 'frame' is the live
|
|
16736
|
+
* per-frame dispatch: ONLY root-plane steps run; crop children
|
|
16737
|
+
* (inputClasses ≠ null) are skipped and served per-track via
|
|
16738
|
+
* pipelineRunner.runDetailSubtree (two-plane design).
|
|
16739
|
+
*/
|
|
16740
|
+
plane: _enum(["full", "frame"]).optional(),
|
|
16741
|
+
/**
|
|
16742
|
+
* Inference-device selector (Phase 2 multi-device). Format
|
|
16743
|
+
* `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
|
|
16744
|
+
* Omitted ⇒ the runner's default device (current single-engine
|
|
16745
|
+
* behaviour). Selects WHICH device pool of the node runs the call.
|
|
16746
|
+
*/
|
|
16747
|
+
deviceKey: string().optional(),
|
|
16748
|
+
/**
|
|
16749
|
+
* Two-plane NATIVE child-crop reference. Set by `runDetailSubtree` ONLY
|
|
16750
|
+
* when the parent crop was resolved from the frame's retained NATIVE
|
|
16751
|
+
* surface (a frameHandle HIT). Lets the executor re-cut a LEAF crop
|
|
16752
|
+
* child's ROI (plate-ocr, face-embedding, leaf classifiers) at native
|
|
16753
|
+
* resolution from that surface — the SAME quality path faces already
|
|
16754
|
+
* had — instead of the downscaled parent tile. `handle` keys the native
|
|
16755
|
+
* surface (node-pinned to its owner); `cropFrameSpace` is the parent
|
|
16756
|
+
* crop's padded/clamped rectangle in FRAME-space pixels, used to compose
|
|
16757
|
+
* the executor's crop-normalized child ROI back into frame-normalized
|
|
16758
|
+
* coordinates. Auxiliary to the image source (`image`/`frame`/…), NOT one
|
|
16759
|
+
* of the mutually-exclusive image inputs. Absent ⇒ tile-crop children
|
|
16760
|
+
* (today's behaviour on the fallback path).
|
|
16761
|
+
*/
|
|
16762
|
+
nativeCropRef: NativeCropRefSchema.optional()
|
|
16763
|
+
}), PipelineRunResultBridge, { kind: "mutation" }), method(object({
|
|
16764
|
+
engine: PipelineEngineChoiceSchema.optional(),
|
|
16765
|
+
steps: array(PipelineStepInputSchema).min(1),
|
|
16766
|
+
frames: array(FrameInputSchema).min(1).max(255),
|
|
16767
|
+
deviceId: number().optional(),
|
|
16768
|
+
sessionId: string().optional(),
|
|
16769
|
+
/**
|
|
16770
|
+
* Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
|
|
16771
|
+
* the batch to the Python pool's bench preprocess cache
|
|
16772
|
+
* (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
|
|
16773
|
+
* preprocessed ONCE and every later inference is a pure-inference cache
|
|
16774
|
+
* hit — the sustained-throughput run measures inference, not
|
|
16775
|
+
* decode+preprocess+infer. Omitted/0 for live frames (all different →
|
|
16776
|
+
* full preprocess every call, correct). Fresh per sustained run;
|
|
16777
|
+
* released via `uncacheFrame`.
|
|
16778
|
+
*/
|
|
16779
|
+
frameId: number().int().nonnegative().optional(),
|
|
16780
|
+
/** Inference-device selector (Phase 2 multi-device); see runPipeline. */
|
|
16781
|
+
deviceKey: string().optional()
|
|
16782
|
+
}), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
|
|
16783
|
+
data: _instanceof(Uint8Array),
|
|
16784
|
+
width: number().int().positive(),
|
|
16785
|
+
height: number().int().positive(),
|
|
16786
|
+
format: _enum([
|
|
16787
|
+
"rgb",
|
|
16788
|
+
"bgr",
|
|
16789
|
+
"gray"
|
|
16790
|
+
])
|
|
16791
|
+
}), object({
|
|
16792
|
+
frameId: number(),
|
|
16793
|
+
width: number(),
|
|
16794
|
+
height: number()
|
|
16795
|
+
}), { kind: "mutation" }), method(object({
|
|
16796
|
+
stepId: string(),
|
|
16797
|
+
frameId: number().int()
|
|
16798
|
+
}), record(string(), unknown()), { kind: "mutation" }), method(object({ frameId: number().int() }), _void(), { kind: "mutation" }), method(_void(), object({
|
|
16799
|
+
batchMode: string(),
|
|
16800
|
+
windowMs: number(),
|
|
16801
|
+
maxBatchSize: number(),
|
|
16802
|
+
concurrency: number()
|
|
16803
|
+
})), method(_void(), array(object({
|
|
16804
|
+
engineKey: string(),
|
|
16805
|
+
engine: PipelineEngineChoiceSchema,
|
|
16806
|
+
modelsLoaded: array(string()).readonly(),
|
|
16807
|
+
inUseByCameras: array(number()).readonly(),
|
|
16808
|
+
/**
|
|
16809
|
+
* Origin of this resident factory.
|
|
16810
|
+
* - `runtime` — main camera-serving engine (no idle TTL).
|
|
16811
|
+
* - `warm-override` — benchmark/test override held in the warm
|
|
16812
|
+
* cache; auto-disposed after the idle TTL.
|
|
16813
|
+
* - `device-pool` — a concurrent per-device pool (Phase 2
|
|
16814
|
+
* multi-device, keyed by `deviceKey`) resolved
|
|
16815
|
+
* via `resolveDeviceFactory`. Runs alongside the
|
|
16816
|
+
* `runtime` engine on a DIFFERENT accelerator
|
|
16817
|
+
* (NPU / iGPU / Coral) — this is how the
|
|
16818
|
+
* Engines tab shows all pools running at once.
|
|
16819
|
+
*/
|
|
16820
|
+
kind: _enum([
|
|
16821
|
+
"runtime",
|
|
16822
|
+
"warm-override",
|
|
16823
|
+
"device-pool"
|
|
16824
|
+
]),
|
|
16825
|
+
/** Native pid of the underlying Python pool (null when no pool). */
|
|
16826
|
+
poolPid: number().nullable(),
|
|
16827
|
+
/** ms since this factory was last used (null when not warm-tracked). */
|
|
16828
|
+
idleMs: number().nullable(),
|
|
16829
|
+
/** Idle TTL after which `warm-override` factories self-evict (null when not applicable). */
|
|
16830
|
+
idleTtlMs: number().nullable()
|
|
16831
|
+
})).readonly()), method(object({ engine: PipelineEngineChoiceSchema }), object({ success: literal(true) }), {
|
|
16832
|
+
kind: "mutation",
|
|
16833
|
+
auth: "admin"
|
|
16834
|
+
}), method(object({
|
|
16835
|
+
engine: PipelineEngineChoiceSchema,
|
|
16836
|
+
force: boolean().optional()
|
|
16837
|
+
}), object({
|
|
16838
|
+
success: boolean(),
|
|
16839
|
+
reason: string().optional()
|
|
16840
|
+
}), {
|
|
16841
|
+
kind: "mutation",
|
|
16842
|
+
auth: "admin"
|
|
16843
|
+
}), 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({
|
|
16844
|
+
addonId: string(),
|
|
16845
|
+
modelId: string(),
|
|
16846
|
+
filename: string().optional(),
|
|
16847
|
+
settings: record(string(), unknown()).optional()
|
|
16848
|
+
}), AudioTestResultSchema, { kind: "mutation" }), method(_void(), ConfigUISchemaNullableBridge);
|
|
16849
|
+
/**
|
|
16850
|
+
* Per-stage gating mode applied to the zones a rule references.
|
|
16851
|
+
*
|
|
16852
|
+
* - `include`: the rule contributes to a **whitelist** for its stage.
|
|
16853
|
+
* When at least one `include` rule fires for a stage, only entities
|
|
16854
|
+
* inside one of those zones pass that stage.
|
|
16855
|
+
* - `exclude`: the rule contributes to a **blacklist** for its stage.
|
|
16856
|
+
* Entities inside one of those zones are dropped at that stage.
|
|
16857
|
+
*
|
|
16858
|
+
* `monitor`-style observation (count without filtering) is not a rule
|
|
16859
|
+
* mode — zones without any matching rule are observed naturally by
|
|
16860
|
+
* `zone-analytics` (live snapshot + history), so an "I just want to
|
|
16861
|
+
* count, not filter" use case needs no rule at all.
|
|
16862
|
+
*/
|
|
16863
|
+
var ZoneRuleModeEnum = _enum(["include", "exclude"]);
|
|
16864
|
+
/**
|
|
16865
|
+
* Per-consumer rule that references existing zones (geometry) and
|
|
16866
|
+
* defines how a specific pipeline stage should treat them. Each
|
|
16867
|
+
* consumer addon owns its own `ZoneRule[]` array in its per-device
|
|
16868
|
+
* settings:
|
|
16869
|
+
*
|
|
16870
|
+
* - `addon-motion-wasm` → `motionZoneRules: ZoneRule[]` (motion stage)
|
|
16871
|
+
* - `addon-detection-pipeline` → `detectionZoneRules: ZoneRule[]` (detection stage)
|
|
16872
|
+
* - future: notification rules, audio gating, etc.
|
|
16873
|
+
*
|
|
16874
|
+
* One rule applies to N zones (`zoneIds[]`) so the operator can
|
|
16875
|
+
* express "ignore motion in ALL of {garden, street}" with a single
|
|
16876
|
+
* rule. `classFilter` narrows the rule to specific object classes —
|
|
16877
|
+
* "drop person detections in the street, but keep cars" is one
|
|
16878
|
+
* `exclude` rule with `classFilter: ['person']`.
|
|
16879
|
+
*
|
|
16880
|
+
* `enabled` is a soft toggle — the operator can keep the rule
|
|
16881
|
+
* configured but inert without deleting it.
|
|
16882
|
+
*/
|
|
16883
|
+
var ZoneRuleSchema = object({
|
|
16884
|
+
/** Stable rule id — survives edits, used by the UI for diffing. */
|
|
16885
|
+
id: string(),
|
|
16886
|
+
/** Optional human-readable label rendered in the rule editor. */
|
|
16887
|
+
name: string().optional(),
|
|
16888
|
+
/** Zones this rule targets. The rule's `mode` applies to ALL
|
|
16889
|
+
* listed zones (OR-set: a detection in any one of them counts).
|
|
16890
|
+
* At least one zone id required — a rule with no targets is a
|
|
16891
|
+
* configuration mistake and the form validator rejects it. */
|
|
16892
|
+
zoneIds: array(string()).min(1).readonly(),
|
|
16893
|
+
mode: ZoneRuleModeEnum,
|
|
16894
|
+
/**
|
|
16895
|
+
* Class names this rule applies to. Empty / undefined ⇒ rule
|
|
16896
|
+
* applies to every class. Class strings match the `macroClass`
|
|
16897
|
+
* field on detections (e.g. `person`, `car`, `dog`).
|
|
16898
|
+
*/
|
|
16899
|
+
classFilter: array(string()).readonly().optional(),
|
|
16900
|
+
/**
|
|
16901
|
+
* Minimum bbox/mask overlap (0–1) with any of the rule's zones
|
|
16902
|
+
* required to consider an entity "in the zone". Defaults to the
|
|
16903
|
+
* consumer's stage default when omitted. Kept for back-compat with
|
|
16904
|
+
* existing per-rule overrides; new operators pick the value via
|
|
16905
|
+
* `bboxInclusionPct` (operator-friendly 0–100). Whichever field is
|
|
16906
|
+
* set, the lower-level engine reads it as a 0–1 fraction.
|
|
16907
|
+
*/
|
|
16908
|
+
overlapThreshold: number().min(0).max(1).optional(),
|
|
16909
|
+
/**
|
|
16910
|
+
* Operator-friendly version of `overlapThreshold` — the percentage
|
|
16911
|
+
* of the detection's bbox that must lie inside the zone for the
|
|
16912
|
+
* rule to match. Documented default is 85%; the engine substitutes
|
|
16913
|
+
* that when the field is omitted (kept optional so existing rules
|
|
16914
|
+
* stored without it stay valid).
|
|
16915
|
+
*
|
|
16916
|
+
* When BOTH `overlapThreshold` and `bboxInclusionPct` are set on a
|
|
16917
|
+
* rule, the engine prefers `bboxInclusionPct` because it's the
|
|
16918
|
+
* field exposed in the UI. Internally both feed the same gate.
|
|
16919
|
+
*/
|
|
16920
|
+
bboxInclusionPct: number().min(0).max(100).optional(),
|
|
16921
|
+
/**
|
|
16922
|
+
* When `true` and a detection has a segmentation mask, use the
|
|
16923
|
+
* mask for overlap instead of the bbox. Detection-stage only;
|
|
16924
|
+
* motion rules ignore this field.
|
|
16925
|
+
*/
|
|
16926
|
+
preferMask: boolean().optional(),
|
|
16927
|
+
/**
|
|
16928
|
+
* Soft-toggle: `false` disables the rule without deleting it.
|
|
16929
|
+
* Defaults to `true` so operators creating a rule via the UI
|
|
16930
|
+
* see it active immediately.
|
|
16931
|
+
*/
|
|
16932
|
+
enabled: boolean().default(true)
|
|
16933
|
+
});
|
|
16934
|
+
array(ZoneRuleSchema).readonly();
|
|
16935
|
+
/**
|
|
16936
|
+
* Zone — pure geometry + identity. NO filtering behaviour.
|
|
16937
|
+
*
|
|
16938
|
+
* Zones describe **where** in the frame the operator wants to flag
|
|
16939
|
+
* something; consumer-owned {@link ZoneRule} arrays describe **how**
|
|
16940
|
+
* each pipeline stage uses them. Splitting the two means a single
|
|
16941
|
+
* polygon "Driveway" can simultaneously back a motion-exclude rule,
|
|
16942
|
+
* a detection-include rule on `['car']`, and an occupancy aggregate
|
|
16943
|
+
* — without three duplicated polygons.
|
|
16944
|
+
*
|
|
16945
|
+
* Owned by the orchestrator addon (provider) and mirrored into the
|
|
16946
|
+
* `zones` device-state slice on every mutation. Consumers
|
|
16947
|
+
* (motion-wasm, pipeline-executor, analytics, admin UI) read either
|
|
16948
|
+
* via `api.zones.listZones` (one-shot) or via `dev.state.zones` (live
|
|
16949
|
+
* mirror with `onChanged`).
|
|
16950
|
+
*
|
|
16951
|
+
* Coordinates are normalised fractions of the frame (0–1) so zones
|
|
16952
|
+
* survive resolution changes and stream profile switches.
|
|
16953
|
+
*
|
|
16954
|
+
* `kind` discriminates between full polygons (closed regions used
|
|
16955
|
+
* for intrusion / occupancy filters) and tripwires (open 2-point
|
|
16956
|
+
* line segments used for cross events). Onboard / firmware-reported
|
|
16957
|
+
* zones (Reolink, ONVIF) are out of scope for now — see the deferred
|
|
16958
|
+
* task list.
|
|
16959
|
+
*/
|
|
16960
|
+
var ZoneKindEnum = _enum(["polygon", "tripwire"]);
|
|
16961
|
+
/** Polygon vertex in fraction-of-frame coordinates (0–1). */
|
|
16962
|
+
var PolygonPointSchema = object({
|
|
16963
|
+
x: number(),
|
|
16964
|
+
y: number()
|
|
16965
|
+
});
|
|
16966
|
+
/** A camera detection zone — pure geometry/identity. */
|
|
16967
|
+
var ZoneSchema = object({
|
|
16968
|
+
id: string(),
|
|
16969
|
+
name: string(),
|
|
16970
|
+
kind: ZoneKindEnum.default("polygon"),
|
|
16971
|
+
/** Polygon vertices, fraction of frame (0–1). */
|
|
16972
|
+
polygon: array(PolygonPointSchema).readonly(),
|
|
16973
|
+
/** Visual color for UI rendering. */
|
|
16974
|
+
color: string().default("#3b82f6")
|
|
16975
|
+
});
|
|
16976
|
+
/**
|
|
16977
|
+
* Zones capability — per-camera CRUD over polygon detection zones.
|
|
16978
|
+
*
|
|
16979
|
+
* Provider lives in `addon-pipeline-orchestrator` (hub-only). Persists
|
|
16980
|
+
* to per-device settings and mirrors into the `zones` device-state
|
|
16981
|
+
* slice on every mutation, so downstream consumers can subscribe via
|
|
16982
|
+
* `dev.state.zones.onChanged`.
|
|
16983
|
+
*
|
|
16984
|
+
* The cap surface only handles geometry + identity; filtering
|
|
16985
|
+
* behaviour (per-class, include/exclude, threshold) lives in the
|
|
16986
|
+
* consumer addons' rule arrays — see `ZoneRuleSchema` exported from
|
|
16987
|
+
* `capabilities/schemas/zone-rule.js`.
|
|
16988
|
+
*/
|
|
16989
|
+
var zonesCapability = {
|
|
16990
|
+
name: "zones",
|
|
16991
|
+
scope: "device",
|
|
16992
|
+
mode: "singleton",
|
|
16993
|
+
deviceTypes: [DeviceType.Camera],
|
|
16994
|
+
methods: {
|
|
16995
|
+
listZones: method(object({ deviceId: number() }), array(ZoneSchema).readonly()),
|
|
16996
|
+
addZone: method(object({
|
|
16997
|
+
deviceId: number(),
|
|
16998
|
+
zone: ZoneSchema
|
|
16999
|
+
}), _void(), {
|
|
17000
|
+
kind: "mutation",
|
|
17001
|
+
auth: "admin"
|
|
17002
|
+
}),
|
|
17003
|
+
removeZone: method(object({
|
|
17004
|
+
deviceId: number(),
|
|
17005
|
+
zoneId: string()
|
|
17006
|
+
}), _void(), {
|
|
17007
|
+
kind: "mutation",
|
|
17008
|
+
auth: "admin"
|
|
17009
|
+
}),
|
|
17010
|
+
updateZone: method(object({
|
|
17011
|
+
deviceId: number(),
|
|
17012
|
+
zone: ZoneSchema
|
|
17013
|
+
}), _void(), {
|
|
17014
|
+
kind: "mutation",
|
|
17015
|
+
auth: "admin"
|
|
17016
|
+
})
|
|
17017
|
+
},
|
|
17018
|
+
/**
|
|
17019
|
+
* Runtime-state slice — the live zone catalogue mirrored by the
|
|
17020
|
+
* orchestrator on every CRUD mutation. Consumers read via
|
|
17021
|
+
* `device.state.zones.value` / `.watch(...)` without round-tripping
|
|
17022
|
+
* the cap, and the codegen DeviceProxy auto-wires the reactive
|
|
17023
|
+
* handle. Slice shape is `{ zones: Zone[] }` so future extensions
|
|
17024
|
+
* (e.g. zone groupings) can sit alongside the polygon list.
|
|
17025
|
+
*/
|
|
17026
|
+
runtimeState: object({ zones: array(ZoneSchema).readonly() }),
|
|
17027
|
+
/**
|
|
17028
|
+
* 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.
|
|
17029
|
+
*
|
|
17030
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
17031
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
17032
|
+
*/
|
|
17033
|
+
durability: "restored"
|
|
17034
|
+
};
|
|
16348
17035
|
/**
|
|
16349
17036
|
* pipeline-analytics — device-scoped wrapper cap. Refines raw
|
|
16350
17037
|
* per-frame detections emitted by the pipeline runner into tracked
|
|
@@ -17434,6 +18121,24 @@ var RebuildStatusSchema = object({
|
|
|
17434
18121
|
/** Present when the pass ended by throwing. */
|
|
17435
18122
|
error: string().nullable()
|
|
17436
18123
|
});
|
|
18124
|
+
var ReplayFrameInputSchema = object({
|
|
18125
|
+
timestamp: number(),
|
|
18126
|
+
frame: PipelineRunResultBridge
|
|
18127
|
+
});
|
|
18128
|
+
var RunReplayFrameProcessorResultSchema = object({ tracks: array(object({
|
|
18129
|
+
className: string(),
|
|
18130
|
+
firstSeenMs: number(),
|
|
18131
|
+
lastSeenMs: number(),
|
|
18132
|
+
/** Bbox of the track's FIRST matched detection, pixel-space in the clip's
|
|
18133
|
+
* frame — a representative box for the diff's `(className, window, IoU)`
|
|
18134
|
+
* pairing (`replay-diff.ts`). A replay does not need the full per-frame
|
|
18135
|
+
* trajectory production's `Track.positions` keeps. */
|
|
18136
|
+
bbox: BoundingBoxSchema,
|
|
18137
|
+
/** How many of the input frames this track matched a real detection on
|
|
18138
|
+
* (never a coasted/extrapolated frame) — the replay's own signal for "how
|
|
18139
|
+
* solid is this track", cheaper than re-deriving it from a trajectory. */
|
|
18140
|
+
framesMatched: number().int()
|
|
18141
|
+
})).readonly() });
|
|
17437
18142
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
17438
18143
|
deviceId: number(),
|
|
17439
18144
|
trackId: string()
|
|
@@ -17539,6 +18244,15 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17539
18244
|
}), method(object({ jobId: string() }), RelocateJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
17540
18245
|
kind: "mutation",
|
|
17541
18246
|
auth: "admin"
|
|
18247
|
+
}), method(RelocateMediaInputSchema, object({ jobId: string() }), {
|
|
18248
|
+
kind: "mutation",
|
|
18249
|
+
auth: "admin"
|
|
18250
|
+
}), method(object({}), array(RelocateJobSchema).readonly(), {
|
|
18251
|
+
kind: "query",
|
|
18252
|
+
auth: "admin"
|
|
18253
|
+
}), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
|
|
18254
|
+
kind: "mutation",
|
|
18255
|
+
auth: "admin"
|
|
17542
18256
|
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
17543
18257
|
kind: "query",
|
|
17544
18258
|
auth: "admin"
|
|
@@ -17595,6 +18309,16 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17595
18309
|
}), RetrainAssistResultSchema, {
|
|
17596
18310
|
kind: "mutation",
|
|
17597
18311
|
auth: "admin"
|
|
18312
|
+
}), method(object({
|
|
18313
|
+
deviceId: number(),
|
|
18314
|
+
source: DetectionSourceSchema,
|
|
18315
|
+
zones: array(ZoneSchema).readonly().optional(),
|
|
18316
|
+
detectionRules: array(ZoneRuleSchema).readonly().optional(),
|
|
18317
|
+
zoneMembershipMinOverlap: number().min(0).max(1).optional(),
|
|
18318
|
+
frames: array(ReplayFrameInputSchema).min(1)
|
|
18319
|
+
}), RunReplayFrameProcessorResultSchema, {
|
|
18320
|
+
kind: "mutation",
|
|
18321
|
+
auth: "admin"
|
|
17598
18322
|
}), method(object({ trackId: string() }), array(RetrainAnnotationSchema).readonly(), {
|
|
17599
18323
|
kind: "query",
|
|
17600
18324
|
auth: "admin"
|
|
@@ -17659,433 +18383,6 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17659
18383
|
eventId: string(),
|
|
17660
18384
|
timestamp: number()
|
|
17661
18385
|
});
|
|
17662
|
-
/**
|
|
17663
|
-
* Reference to the frame's retained NATIVE surface + the parent crop's placement
|
|
17664
|
-
* within the frame, so the executor can re-cut a leaf child ROI at native
|
|
17665
|
-
* resolution on the detail plane. See the `runPipeline` `nativeCropRef` field.
|
|
17666
|
-
*/
|
|
17667
|
-
var NativeCropRefSchema = object({
|
|
17668
|
-
/** Handle keying the retained native surface (node-pinned to its owner). */
|
|
17669
|
-
handle: FrameHandleSchema,
|
|
17670
|
-
/** The parent crop's padded/clamped rectangle in FRAME-space pixels. */
|
|
17671
|
-
cropFrameSpace: object({
|
|
17672
|
-
x: number(),
|
|
17673
|
-
y: number(),
|
|
17674
|
-
w: number(),
|
|
17675
|
-
h: number()
|
|
17676
|
-
})
|
|
17677
|
-
});
|
|
17678
|
-
object({
|
|
17679
|
-
crop: object({
|
|
17680
|
-
left: number(),
|
|
17681
|
-
top: number(),
|
|
17682
|
-
width: number().positive(),
|
|
17683
|
-
height: number().positive()
|
|
17684
|
-
}).optional(),
|
|
17685
|
-
content: object({
|
|
17686
|
-
width: number().int().positive(),
|
|
17687
|
-
height: number().int().positive()
|
|
17688
|
-
}),
|
|
17689
|
-
fit: _enum(["stretch", "contain"]),
|
|
17690
|
-
format: _enum([
|
|
17691
|
-
"rgb",
|
|
17692
|
-
"gray",
|
|
17693
|
-
"jpeg"
|
|
17694
|
-
])
|
|
17695
|
-
});
|
|
17696
|
-
var FrameRefSchema = object({
|
|
17697
|
-
registryId: string().min(1),
|
|
17698
|
-
id: string().min(1),
|
|
17699
|
-
width: number().int().positive(),
|
|
17700
|
-
height: number().int().positive(),
|
|
17701
|
-
format: _enum(["rgb", "gray"]),
|
|
17702
|
-
timestamp: number(),
|
|
17703
|
-
capturedAt: number().optional()
|
|
17704
|
-
});
|
|
17705
|
-
var ModelFormatSchema$1 = _enum([
|
|
17706
|
-
"onnx",
|
|
17707
|
-
"coreml",
|
|
17708
|
-
"openvino",
|
|
17709
|
-
"tflite",
|
|
17710
|
-
"pt",
|
|
17711
|
-
"gguf"
|
|
17712
|
-
]);
|
|
17713
|
-
var PipelineSlotSchema = _enum([
|
|
17714
|
-
"detector",
|
|
17715
|
-
"cropper",
|
|
17716
|
-
"classifier",
|
|
17717
|
-
"refiner",
|
|
17718
|
-
"audio-classifier"
|
|
17719
|
-
]);
|
|
17720
|
-
var PipelineEngineChoiceSchema = object({
|
|
17721
|
-
runtime: _enum(["node", "python"]),
|
|
17722
|
-
backend: string(),
|
|
17723
|
-
format: ModelFormatSchema$1,
|
|
17724
|
-
device: string().optional()
|
|
17725
|
-
});
|
|
17726
|
-
var AvailableEngineSchema = object({
|
|
17727
|
-
engine: PipelineEngineChoiceSchema,
|
|
17728
|
-
devices: array(object({
|
|
17729
|
-
id: string(),
|
|
17730
|
-
label: string(),
|
|
17731
|
-
description: string().optional()
|
|
17732
|
-
})).readonly(),
|
|
17733
|
-
defaultDevice: string()
|
|
17734
|
-
});
|
|
17735
|
-
var PipelineDefaultStepSchema = lazy(() => object({
|
|
17736
|
-
addonId: string(),
|
|
17737
|
-
addonName: string(),
|
|
17738
|
-
slot: PipelineSlotSchema,
|
|
17739
|
-
inputClasses: array(string()).readonly(),
|
|
17740
|
-
outputClasses: array(string()).readonly(),
|
|
17741
|
-
enabled: boolean(),
|
|
17742
|
-
modelId: string(),
|
|
17743
|
-
children: array(PipelineDefaultStepSchema).readonly(),
|
|
17744
|
-
group: string().optional(),
|
|
17745
|
-
settings: record(string(), unknown()).optional()
|
|
17746
|
-
}));
|
|
17747
|
-
var PipelineTemplateStepSchema = lazy(() => object({
|
|
17748
|
-
addonId: string(),
|
|
17749
|
-
enabled: boolean(),
|
|
17750
|
-
modelId: string(),
|
|
17751
|
-
children: array(PipelineTemplateStepSchema).readonly(),
|
|
17752
|
-
settings: record(string(), unknown()).optional()
|
|
17753
|
-
}));
|
|
17754
|
-
var PipelineTemplateSchema$1 = object({
|
|
17755
|
-
id: string(),
|
|
17756
|
-
name: string(),
|
|
17757
|
-
createdAt: string(),
|
|
17758
|
-
updatedAt: string(),
|
|
17759
|
-
engine: PipelineEngineChoiceSchema,
|
|
17760
|
-
steps: array(PipelineTemplateStepSchema).readonly()
|
|
17761
|
-
});
|
|
17762
|
-
var PipelineModelOptionSchema = object({
|
|
17763
|
-
id: string(),
|
|
17764
|
-
name: string(),
|
|
17765
|
-
formats: record(string(), object({
|
|
17766
|
-
downloaded: boolean(),
|
|
17767
|
-
sizeMB: number()
|
|
17768
|
-
})),
|
|
17769
|
-
group: ModelVariantGroupSchema.optional(),
|
|
17770
|
-
legacy: boolean().optional(),
|
|
17771
|
-
provider: ModelProviderIdSchema.optional()
|
|
17772
|
-
});
|
|
17773
|
-
var ConfigFieldBridge = custom();
|
|
17774
|
-
var PipelineAddonSchemaSchema = object({
|
|
17775
|
-
id: string(),
|
|
17776
|
-
name: string(),
|
|
17777
|
-
slot: PipelineSlotSchema,
|
|
17778
|
-
inputClasses: array(string()).readonly(),
|
|
17779
|
-
outputClasses: array(string()).readonly(),
|
|
17780
|
-
childSlots: array(PipelineSlotSchema).readonly(),
|
|
17781
|
-
models: array(PipelineModelOptionSchema).readonly(),
|
|
17782
|
-
defaultModelId: string(),
|
|
17783
|
-
defaultModelIdByFormat: record(string(), string()).optional(),
|
|
17784
|
-
enabledByDefault: boolean().optional(),
|
|
17785
|
-
backfillIntoExistingOverrides: boolean().optional(),
|
|
17786
|
-
defaultConfidence: number(),
|
|
17787
|
-
group: string().optional(),
|
|
17788
|
-
configSchema: array(ConfigFieldBridge).readonly().optional()
|
|
17789
|
-
});
|
|
17790
|
-
var PipelineSlotSchemaSchema = object({
|
|
17791
|
-
id: PipelineSlotSchema,
|
|
17792
|
-
label: string(),
|
|
17793
|
-
priority: number(),
|
|
17794
|
-
parentSlot: PipelineSlotSchema.nullable(),
|
|
17795
|
-
addons: array(PipelineAddonSchemaSchema).readonly()
|
|
17796
|
-
});
|
|
17797
|
-
var PipelineSchemaSchema = object({
|
|
17798
|
-
availableEngines: array(AvailableEngineSchema).readonly(),
|
|
17799
|
-
selectedEngine: PipelineEngineChoiceSchema,
|
|
17800
|
-
slots: array(PipelineSlotSchemaSchema).readonly()
|
|
17801
|
-
});
|
|
17802
|
-
var EngineProvisioningSchema = object({
|
|
17803
|
-
runtimeId: _enum([
|
|
17804
|
-
"onnx",
|
|
17805
|
-
"openvino",
|
|
17806
|
-
"coreml",
|
|
17807
|
-
"edgetpu"
|
|
17808
|
-
]).nullable(),
|
|
17809
|
-
device: string().nullable(),
|
|
17810
|
-
state: _enum([
|
|
17811
|
-
"idle",
|
|
17812
|
-
"installing",
|
|
17813
|
-
"verifying",
|
|
17814
|
-
"ready",
|
|
17815
|
-
"failed"
|
|
17816
|
-
]),
|
|
17817
|
-
progress: number().optional(),
|
|
17818
|
-
error: string().optional(),
|
|
17819
|
-
nextRetryAt: number().optional(),
|
|
17820
|
-
/**
|
|
17821
|
-
* Gate A (config-correctness gate at engine change): human-readable
|
|
17822
|
-
* config issues surfaced EAGERLY when the node's engine changes — model
|
|
17823
|
-
* substitutions ("chose X, running Y") and zero-build steps ("no model
|
|
17824
|
-
* has a <format> build"). Additive/optional: informational only, never
|
|
17825
|
-
* enforced here — `assertEngineReady` (readiness) still gates inference.
|
|
17826
|
-
* Absent/empty when the node-default tree resolves cleanly.
|
|
17827
|
-
*/
|
|
17828
|
-
configIssues: array(string()).optional()
|
|
17829
|
-
});
|
|
17830
|
-
var PipelineStepInputSchema = lazy(() => object({
|
|
17831
|
-
addonId: string(),
|
|
17832
|
-
modelId: string().optional(),
|
|
17833
|
-
enabled: boolean().default(true),
|
|
17834
|
-
children: array(PipelineStepInputSchema).optional(),
|
|
17835
|
-
settings: record(string(), unknown()).optional(),
|
|
17836
|
-
jumpDeviceKey: string().optional()
|
|
17837
|
-
}));
|
|
17838
|
-
var ModelSubstitutionSchema = object({
|
|
17839
|
-
addonId: string(),
|
|
17840
|
-
chosen: string(),
|
|
17841
|
-
running: string(),
|
|
17842
|
-
format: string()
|
|
17843
|
-
});
|
|
17844
|
-
var PipelineValidationIssueSchema = object({
|
|
17845
|
-
addonId: string(),
|
|
17846
|
-
kind: _enum(["unknown-addon", "no-format-build"]),
|
|
17847
|
-
detail: string()
|
|
17848
|
-
});
|
|
17849
|
-
var PipelineValidationResultSchema = object({
|
|
17850
|
-
ok: boolean(),
|
|
17851
|
-
issues: array(PipelineValidationIssueSchema).readonly(),
|
|
17852
|
-
substitutions: array(ModelSubstitutionSchema).readonly(),
|
|
17853
|
-
/** The node's `currentEngine.format` this validation ran against. */
|
|
17854
|
-
format: string()
|
|
17855
|
-
});
|
|
17856
|
-
var ReferenceImageEntrySchema = object({
|
|
17857
|
-
filename: string(),
|
|
17858
|
-
stepIds: array(string()).readonly().optional()
|
|
17859
|
-
});
|
|
17860
|
-
var ReferenceImageBodySchema = object({
|
|
17861
|
-
base64: string(),
|
|
17862
|
-
filename: string()
|
|
17863
|
-
});
|
|
17864
|
-
var ReferenceAudioEntrySchema = object({
|
|
17865
|
-
filename: string(),
|
|
17866
|
-
sizeKb: number()
|
|
17867
|
-
});
|
|
17868
|
-
var ReferenceAudioBodySchema = object({ base64: string() });
|
|
17869
|
-
var AudioBackendSchema = object({
|
|
17870
|
-
id: string(),
|
|
17871
|
-
name: string(),
|
|
17872
|
-
description: string(),
|
|
17873
|
-
available: boolean(),
|
|
17874
|
-
/**
|
|
17875
|
-
* Raw classifier labels this backend can emit (e.g. YAMNet's
|
|
17876
|
-
* 521-class set or Apple SoundAnalysis's 303-class set). Used by
|
|
17877
|
-
* the benchmark UI to populate the `enabledMicroClasses` filter
|
|
17878
|
-
* specific to the selected backend without a separate fetch.
|
|
17879
|
-
*/
|
|
17880
|
-
rawLabels: array(string()).readonly().optional()
|
|
17881
|
-
});
|
|
17882
|
-
var AudioCapabilitiesSchema = object({
|
|
17883
|
-
activeBackend: string(),
|
|
17884
|
-
availableBackends: array(AudioBackendSchema).readonly(),
|
|
17885
|
-
sampleRate: number(),
|
|
17886
|
-
chunkDurationMs: number()
|
|
17887
|
-
});
|
|
17888
|
-
var DownloadModelResultSchema = object({
|
|
17889
|
-
filePath: string(),
|
|
17890
|
-
sizeMB: number(),
|
|
17891
|
-
durationMs: number()
|
|
17892
|
-
});
|
|
17893
|
-
/**
|
|
17894
|
-
* Wrapper carrying a single test run's result. Replaces the legacy
|
|
17895
|
-
* ad-hoc `{labels: [{className, originalClass, score}]}` shape with the
|
|
17896
|
-
* canonical `AudioResult` from the Phase 6 output rework: one
|
|
17897
|
-
* `AudioDetection` per class above `minScore`, top-N candidates in
|
|
17898
|
-
* `debug.alternateLabels['audio-classifier']`, per-source timings in
|
|
17899
|
-
* `debug.stepTimings`. The outer `success`/`error` fields stay so the
|
|
17900
|
-
* benchmark UI can still report a clean failure when the classifier
|
|
17901
|
-
* cap isn't available.
|
|
17902
|
-
*/
|
|
17903
|
-
var AudioTestResultSchema = object({
|
|
17904
|
-
success: boolean(),
|
|
17905
|
-
error: string().optional(),
|
|
17906
|
-
frame: custom().optional()
|
|
17907
|
-
});
|
|
17908
|
-
var PipelineConfigBridge = custom();
|
|
17909
|
-
var ConfigUISchemaBridge = custom();
|
|
17910
|
-
var ConfigUISchemaNullableBridge = custom();
|
|
17911
|
-
var InferenceCapabilitiesBridge = custom();
|
|
17912
|
-
var ModelAvailabilityListBridge = custom();
|
|
17913
|
-
var PipelineRunResultBridge = custom();
|
|
17914
|
-
method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
|
|
17915
|
-
modelId: string(),
|
|
17916
|
-
settings: record(string(), unknown()).readonly()
|
|
17917
|
-
}))), method(object({ steps: record(string(), object({
|
|
17918
|
-
modelId: string(),
|
|
17919
|
-
settings: record(string(), unknown()).readonly()
|
|
17920
|
-
})) }), object({ success: literal(true) }), {
|
|
17921
|
-
kind: "mutation",
|
|
17922
|
-
auth: "admin"
|
|
17923
|
-
}), method(object({ nodeId: string() }), object({
|
|
17924
|
-
success: literal(true),
|
|
17925
|
-
clearedDevices: number()
|
|
17926
|
-
}), {
|
|
17927
|
-
kind: "mutation",
|
|
17928
|
-
auth: "admin"
|
|
17929
|
-
}), 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({
|
|
17930
|
-
name: string(),
|
|
17931
|
-
steps: array(PipelineTemplateStepSchema).readonly(),
|
|
17932
|
-
engine: PipelineEngineChoiceSchema
|
|
17933
|
-
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({
|
|
17934
|
-
id: string(),
|
|
17935
|
-
name: string().optional(),
|
|
17936
|
-
steps: array(PipelineTemplateStepSchema).readonly().optional()
|
|
17937
|
-
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({ id: string() }), _void(), { kind: "mutation" }), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
|
|
17938
|
-
addonId: string(),
|
|
17939
|
-
modelId: string(),
|
|
17940
|
-
format: ModelFormatSchema$1
|
|
17941
|
-
}), DownloadModelResultSchema, { kind: "mutation" }), method(object({
|
|
17942
|
-
addonId: string(),
|
|
17943
|
-
modelId: string(),
|
|
17944
|
-
format: ModelFormatSchema$1
|
|
17945
|
-
}), object({ success: literal(true) }), { kind: "mutation" }), method(object({
|
|
17946
|
-
engine: PipelineEngineChoiceSchema.optional(),
|
|
17947
|
-
steps: array(PipelineStepInputSchema).min(1),
|
|
17948
|
-
frame: FrameInputSchema.optional(),
|
|
17949
|
-
/**
|
|
17950
|
-
* Process-local lazy frame. Valid only when caller and provider resolve
|
|
17951
|
-
* in the same execution-group process; split/cross-node callers use
|
|
17952
|
-
* `frame`/`image` inline compatibility instead.
|
|
17953
|
-
*/
|
|
17954
|
-
frameRef: FrameRefSchema.optional(),
|
|
17955
|
-
/**
|
|
17956
|
-
* CB5 shm passthrough — a `FrameHandle` naming the same ring slot
|
|
17957
|
-
* the decoded pixels live in. One more member of the one-of
|
|
17958
|
-
* frame/frameHandle/image/imageBase64/referenceImage group.
|
|
17959
|
-
*/
|
|
17960
|
-
frameHandle: FrameHandleSchema.optional(),
|
|
17961
|
-
imageBase64: string().optional(),
|
|
17962
|
-
/**
|
|
17963
|
-
* Binary JPEG bytes — preferred over `imageBase64` on internal
|
|
17964
|
-
* hops (hub → forked worker via Moleculer MsgPack) because it
|
|
17965
|
-
* skips the 33% base64 overhead + the per-call base64 decode on
|
|
17966
|
-
* the detection-pipeline worker. Callers can pass either; exactly
|
|
17967
|
-
* one of `frame`/`image`/`imageBase64`/`referenceImage` is required.
|
|
17968
|
-
*/
|
|
17969
|
-
image: _instanceof(Uint8Array).optional(),
|
|
17970
|
-
referenceImage: string().optional(),
|
|
17971
|
-
deviceId: number().optional(),
|
|
17972
|
-
sessionId: string().optional(),
|
|
17973
|
-
/**
|
|
17974
|
-
* Execution plane. 'full' (default) runs the whole tree — benchmark,
|
|
17975
|
-
* reference-image, and detail-subtree calls. 'frame' is the live
|
|
17976
|
-
* per-frame dispatch: ONLY root-plane steps run; crop children
|
|
17977
|
-
* (inputClasses ≠ null) are skipped and served per-track via
|
|
17978
|
-
* pipelineRunner.runDetailSubtree (two-plane design).
|
|
17979
|
-
*/
|
|
17980
|
-
plane: _enum(["full", "frame"]).optional(),
|
|
17981
|
-
/**
|
|
17982
|
-
* Inference-device selector (Phase 2 multi-device). Format
|
|
17983
|
-
* `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
|
|
17984
|
-
* Omitted ⇒ the runner's default device (current single-engine
|
|
17985
|
-
* behaviour). Selects WHICH device pool of the node runs the call.
|
|
17986
|
-
*/
|
|
17987
|
-
deviceKey: string().optional(),
|
|
17988
|
-
/**
|
|
17989
|
-
* Two-plane NATIVE child-crop reference. Set by `runDetailSubtree` ONLY
|
|
17990
|
-
* when the parent crop was resolved from the frame's retained NATIVE
|
|
17991
|
-
* surface (a frameHandle HIT). Lets the executor re-cut a LEAF crop
|
|
17992
|
-
* child's ROI (plate-ocr, face-embedding, leaf classifiers) at native
|
|
17993
|
-
* resolution from that surface — the SAME quality path faces already
|
|
17994
|
-
* had — instead of the downscaled parent tile. `handle` keys the native
|
|
17995
|
-
* surface (node-pinned to its owner); `cropFrameSpace` is the parent
|
|
17996
|
-
* crop's padded/clamped rectangle in FRAME-space pixels, used to compose
|
|
17997
|
-
* the executor's crop-normalized child ROI back into frame-normalized
|
|
17998
|
-
* coordinates. Auxiliary to the image source (`image`/`frame`/…), NOT one
|
|
17999
|
-
* of the mutually-exclusive image inputs. Absent ⇒ tile-crop children
|
|
18000
|
-
* (today's behaviour on the fallback path).
|
|
18001
|
-
*/
|
|
18002
|
-
nativeCropRef: NativeCropRefSchema.optional()
|
|
18003
|
-
}), PipelineRunResultBridge, { kind: "mutation" }), method(object({
|
|
18004
|
-
engine: PipelineEngineChoiceSchema.optional(),
|
|
18005
|
-
steps: array(PipelineStepInputSchema).min(1),
|
|
18006
|
-
frames: array(FrameInputSchema).min(1).max(255),
|
|
18007
|
-
deviceId: number().optional(),
|
|
18008
|
-
sessionId: string().optional(),
|
|
18009
|
-
/**
|
|
18010
|
-
* Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
|
|
18011
|
-
* the batch to the Python pool's bench preprocess cache
|
|
18012
|
-
* (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
|
|
18013
|
-
* preprocessed ONCE and every later inference is a pure-inference cache
|
|
18014
|
-
* hit — the sustained-throughput run measures inference, not
|
|
18015
|
-
* decode+preprocess+infer. Omitted/0 for live frames (all different →
|
|
18016
|
-
* full preprocess every call, correct). Fresh per sustained run;
|
|
18017
|
-
* released via `uncacheFrame`.
|
|
18018
|
-
*/
|
|
18019
|
-
frameId: number().int().nonnegative().optional(),
|
|
18020
|
-
/** Inference-device selector (Phase 2 multi-device); see runPipeline. */
|
|
18021
|
-
deviceKey: string().optional()
|
|
18022
|
-
}), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
|
|
18023
|
-
data: _instanceof(Uint8Array),
|
|
18024
|
-
width: number().int().positive(),
|
|
18025
|
-
height: number().int().positive(),
|
|
18026
|
-
format: _enum([
|
|
18027
|
-
"rgb",
|
|
18028
|
-
"bgr",
|
|
18029
|
-
"gray"
|
|
18030
|
-
])
|
|
18031
|
-
}), object({
|
|
18032
|
-
frameId: number(),
|
|
18033
|
-
width: number(),
|
|
18034
|
-
height: number()
|
|
18035
|
-
}), { kind: "mutation" }), method(object({
|
|
18036
|
-
stepId: string(),
|
|
18037
|
-
frameId: number().int()
|
|
18038
|
-
}), record(string(), unknown()), { kind: "mutation" }), method(object({ frameId: number().int() }), _void(), { kind: "mutation" }), method(_void(), object({
|
|
18039
|
-
batchMode: string(),
|
|
18040
|
-
windowMs: number(),
|
|
18041
|
-
maxBatchSize: number(),
|
|
18042
|
-
concurrency: number()
|
|
18043
|
-
})), method(_void(), array(object({
|
|
18044
|
-
engineKey: string(),
|
|
18045
|
-
engine: PipelineEngineChoiceSchema,
|
|
18046
|
-
modelsLoaded: array(string()).readonly(),
|
|
18047
|
-
inUseByCameras: array(number()).readonly(),
|
|
18048
|
-
/**
|
|
18049
|
-
* Origin of this resident factory.
|
|
18050
|
-
* - `runtime` — main camera-serving engine (no idle TTL).
|
|
18051
|
-
* - `warm-override` — benchmark/test override held in the warm
|
|
18052
|
-
* cache; auto-disposed after the idle TTL.
|
|
18053
|
-
* - `device-pool` — a concurrent per-device pool (Phase 2
|
|
18054
|
-
* multi-device, keyed by `deviceKey`) resolved
|
|
18055
|
-
* via `resolveDeviceFactory`. Runs alongside the
|
|
18056
|
-
* `runtime` engine on a DIFFERENT accelerator
|
|
18057
|
-
* (NPU / iGPU / Coral) — this is how the
|
|
18058
|
-
* Engines tab shows all pools running at once.
|
|
18059
|
-
*/
|
|
18060
|
-
kind: _enum([
|
|
18061
|
-
"runtime",
|
|
18062
|
-
"warm-override",
|
|
18063
|
-
"device-pool"
|
|
18064
|
-
]),
|
|
18065
|
-
/** Native pid of the underlying Python pool (null when no pool). */
|
|
18066
|
-
poolPid: number().nullable(),
|
|
18067
|
-
/** ms since this factory was last used (null when not warm-tracked). */
|
|
18068
|
-
idleMs: number().nullable(),
|
|
18069
|
-
/** Idle TTL after which `warm-override` factories self-evict (null when not applicable). */
|
|
18070
|
-
idleTtlMs: number().nullable()
|
|
18071
|
-
})).readonly()), method(object({ engine: PipelineEngineChoiceSchema }), object({ success: literal(true) }), {
|
|
18072
|
-
kind: "mutation",
|
|
18073
|
-
auth: "admin"
|
|
18074
|
-
}), method(object({
|
|
18075
|
-
engine: PipelineEngineChoiceSchema,
|
|
18076
|
-
force: boolean().optional()
|
|
18077
|
-
}), object({
|
|
18078
|
-
success: boolean(),
|
|
18079
|
-
reason: string().optional()
|
|
18080
|
-
}), {
|
|
18081
|
-
kind: "mutation",
|
|
18082
|
-
auth: "admin"
|
|
18083
|
-
}), 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({
|
|
18084
|
-
addonId: string(),
|
|
18085
|
-
modelId: string(),
|
|
18086
|
-
filename: string().optional(),
|
|
18087
|
-
settings: record(string(), unknown()).optional()
|
|
18088
|
-
}), AudioTestResultSchema, { kind: "mutation" }), method(_void(), ConfigUISchemaNullableBridge);
|
|
18089
18386
|
object({
|
|
18090
18387
|
activeCameras: number(),
|
|
18091
18388
|
throttledCameras: number(),
|
|
@@ -18111,106 +18408,6 @@ var CameraMetricsSchema = object({
|
|
|
18111
18408
|
});
|
|
18112
18409
|
var CameraMetricsWithDeviceIdSchema = CameraMetricsSchema.extend({ deviceId: number() });
|
|
18113
18410
|
/**
|
|
18114
|
-
* Zone — pure geometry + identity. NO filtering behaviour.
|
|
18115
|
-
*
|
|
18116
|
-
* Zones describe **where** in the frame the operator wants to flag
|
|
18117
|
-
* something; consumer-owned {@link ZoneRule} arrays describe **how**
|
|
18118
|
-
* each pipeline stage uses them. Splitting the two means a single
|
|
18119
|
-
* polygon "Driveway" can simultaneously back a motion-exclude rule,
|
|
18120
|
-
* a detection-include rule on `['car']`, and an occupancy aggregate
|
|
18121
|
-
* — without three duplicated polygons.
|
|
18122
|
-
*
|
|
18123
|
-
* Owned by the orchestrator addon (provider) and mirrored into the
|
|
18124
|
-
* `zones` device-state slice on every mutation. Consumers
|
|
18125
|
-
* (motion-wasm, pipeline-executor, analytics, admin UI) read either
|
|
18126
|
-
* via `api.zones.listZones` (one-shot) or via `dev.state.zones` (live
|
|
18127
|
-
* mirror with `onChanged`).
|
|
18128
|
-
*
|
|
18129
|
-
* Coordinates are normalised fractions of the frame (0–1) so zones
|
|
18130
|
-
* survive resolution changes and stream profile switches.
|
|
18131
|
-
*
|
|
18132
|
-
* `kind` discriminates between full polygons (closed regions used
|
|
18133
|
-
* for intrusion / occupancy filters) and tripwires (open 2-point
|
|
18134
|
-
* line segments used for cross events). Onboard / firmware-reported
|
|
18135
|
-
* zones (Reolink, ONVIF) are out of scope for now — see the deferred
|
|
18136
|
-
* task list.
|
|
18137
|
-
*/
|
|
18138
|
-
var ZoneKindEnum = _enum(["polygon", "tripwire"]);
|
|
18139
|
-
/** Polygon vertex in fraction-of-frame coordinates (0–1). */
|
|
18140
|
-
var PolygonPointSchema = object({
|
|
18141
|
-
x: number(),
|
|
18142
|
-
y: number()
|
|
18143
|
-
});
|
|
18144
|
-
/** A camera detection zone — pure geometry/identity. */
|
|
18145
|
-
var ZoneSchema = object({
|
|
18146
|
-
id: string(),
|
|
18147
|
-
name: string(),
|
|
18148
|
-
kind: ZoneKindEnum.default("polygon"),
|
|
18149
|
-
/** Polygon vertices, fraction of frame (0–1). */
|
|
18150
|
-
polygon: array(PolygonPointSchema).readonly(),
|
|
18151
|
-
/** Visual color for UI rendering. */
|
|
18152
|
-
color: string().default("#3b82f6")
|
|
18153
|
-
});
|
|
18154
|
-
/**
|
|
18155
|
-
* Zones capability — per-camera CRUD over polygon detection zones.
|
|
18156
|
-
*
|
|
18157
|
-
* Provider lives in `addon-pipeline-orchestrator` (hub-only). Persists
|
|
18158
|
-
* to per-device settings and mirrors into the `zones` device-state
|
|
18159
|
-
* slice on every mutation, so downstream consumers can subscribe via
|
|
18160
|
-
* `dev.state.zones.onChanged`.
|
|
18161
|
-
*
|
|
18162
|
-
* The cap surface only handles geometry + identity; filtering
|
|
18163
|
-
* behaviour (per-class, include/exclude, threshold) lives in the
|
|
18164
|
-
* consumer addons' rule arrays — see `ZoneRuleSchema` exported from
|
|
18165
|
-
* `capabilities/schemas/zone-rule.js`.
|
|
18166
|
-
*/
|
|
18167
|
-
var zonesCapability = {
|
|
18168
|
-
name: "zones",
|
|
18169
|
-
scope: "device",
|
|
18170
|
-
mode: "singleton",
|
|
18171
|
-
deviceTypes: [DeviceType.Camera],
|
|
18172
|
-
methods: {
|
|
18173
|
-
listZones: method(object({ deviceId: number() }), array(ZoneSchema).readonly()),
|
|
18174
|
-
addZone: method(object({
|
|
18175
|
-
deviceId: number(),
|
|
18176
|
-
zone: ZoneSchema
|
|
18177
|
-
}), _void(), {
|
|
18178
|
-
kind: "mutation",
|
|
18179
|
-
auth: "admin"
|
|
18180
|
-
}),
|
|
18181
|
-
removeZone: method(object({
|
|
18182
|
-
deviceId: number(),
|
|
18183
|
-
zoneId: string()
|
|
18184
|
-
}), _void(), {
|
|
18185
|
-
kind: "mutation",
|
|
18186
|
-
auth: "admin"
|
|
18187
|
-
}),
|
|
18188
|
-
updateZone: method(object({
|
|
18189
|
-
deviceId: number(),
|
|
18190
|
-
zone: ZoneSchema
|
|
18191
|
-
}), _void(), {
|
|
18192
|
-
kind: "mutation",
|
|
18193
|
-
auth: "admin"
|
|
18194
|
-
})
|
|
18195
|
-
},
|
|
18196
|
-
/**
|
|
18197
|
-
* Runtime-state slice — the live zone catalogue mirrored by the
|
|
18198
|
-
* orchestrator on every CRUD mutation. Consumers read via
|
|
18199
|
-
* `device.state.zones.value` / `.watch(...)` without round-tripping
|
|
18200
|
-
* the cap, and the codegen DeviceProxy auto-wires the reactive
|
|
18201
|
-
* handle. Slice shape is `{ zones: Zone[] }` so future extensions
|
|
18202
|
-
* (e.g. zone groupings) can sit alongside the polygon list.
|
|
18203
|
-
*/
|
|
18204
|
-
runtimeState: object({ zones: array(ZoneSchema).readonly() }),
|
|
18205
|
-
/**
|
|
18206
|
-
* 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.
|
|
18207
|
-
*
|
|
18208
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
18209
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
18210
|
-
*/
|
|
18211
|
-
durability: "restored"
|
|
18212
|
-
};
|
|
18213
|
-
/**
|
|
18214
18411
|
* A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
|
|
18215
18412
|
* decode worker resolves it against the RETAINED native frame's real pixel dims,
|
|
18216
18413
|
* so the caller supplies only the detection-res bbox divided by the detection
|
|
@@ -20002,7 +20199,7 @@ method(object({
|
|
|
20002
20199
|
* linking rather than produce an eternal token.
|
|
20003
20200
|
*/
|
|
20004
20201
|
ttlSec: union([number().int().positive(), literal("never")]).optional()
|
|
20005
|
-
}), object({ token: string() })), method(object({ token: string() }), SsoBridgeClaimsSchema.nullable());
|
|
20202
|
+
}), object({ token: string() }), { auth: "admin" }), method(object({ token: string() }), SsoBridgeClaimsSchema.nullable(), { auth: "admin" });
|
|
20006
20203
|
var ProviderListEntrySchema = discriminatedUnion("shouldSaveDiskSpace", [object({
|
|
20007
20204
|
providerId: string().min(1),
|
|
20008
20205
|
displayName: string().min(1),
|
|
@@ -20097,10 +20294,13 @@ var EvictResultSchema = object({
|
|
|
20097
20294
|
/** True when the provider has nothing left it is willing to drop on this location. */
|
|
20098
20295
|
exhausted: boolean()
|
|
20099
20296
|
});
|
|
20100
|
-
method(object({ locationId: string() }), EvictableUsageSchema), method(object({
|
|
20297
|
+
method(object({ locationId: string() }), EvictableUsageSchema, { auth: "admin" }), method(object({
|
|
20101
20298
|
locationId: string(),
|
|
20102
20299
|
targetBytes: number().int().positive()
|
|
20103
|
-
}), EvictResultSchema, {
|
|
20300
|
+
}), EvictResultSchema, {
|
|
20301
|
+
kind: "mutation",
|
|
20302
|
+
auth: "admin"
|
|
20303
|
+
});
|
|
20104
20304
|
method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin" }), method(StorageMigrationInputSchema, object({ jobId: string() }), {
|
|
20105
20305
|
kind: "mutation",
|
|
20106
20306
|
auth: "admin"
|
|
@@ -20160,26 +20360,50 @@ var ReadChunkInputSchema = object({
|
|
|
20160
20360
|
length: number()
|
|
20161
20361
|
});
|
|
20162
20362
|
var EndDownloadInputSchema = object({ downloadId: string() });
|
|
20163
|
-
method(_void(), ProviderInfoSchema), method(object({ config: record(string(), unknown()) }), TestLocationResultSchema, { auth: "admin" }), method(object({
|
|
20363
|
+
method(_void(), ProviderInfoSchema, { auth: "admin" }), method(object({ config: record(string(), unknown()) }), TestLocationResultSchema, { auth: "admin" }), method(object({
|
|
20164
20364
|
location: StorageLocationSchema,
|
|
20165
20365
|
relativePath: string()
|
|
20166
|
-
}), string()), method(object({
|
|
20366
|
+
}), string(), { auth: "admin" }), method(object({
|
|
20167
20367
|
location: StorageLocationSchema,
|
|
20168
20368
|
relativePath: string(),
|
|
20169
20369
|
data: _instanceof(Uint8Array)
|
|
20170
|
-
}), _void(), {
|
|
20370
|
+
}), _void(), {
|
|
20371
|
+
kind: "mutation",
|
|
20372
|
+
auth: "admin"
|
|
20373
|
+
}), method(object({
|
|
20171
20374
|
location: StorageLocationSchema,
|
|
20172
20375
|
relativePath: string()
|
|
20173
|
-
}), _instanceof(Uint8Array)), method(object({
|
|
20376
|
+
}), _instanceof(Uint8Array), { auth: "admin" }), method(object({
|
|
20174
20377
|
location: StorageLocationSchema,
|
|
20175
20378
|
relativePath: string()
|
|
20176
|
-
}), boolean()), method(object({
|
|
20379
|
+
}), boolean(), { auth: "admin" }), method(object({
|
|
20177
20380
|
location: StorageLocationSchema,
|
|
20178
20381
|
prefix: string().optional()
|
|
20179
|
-
}), array(string()).readonly()), method(object({
|
|
20382
|
+
}), array(string()).readonly(), { auth: "admin" }), method(object({
|
|
20180
20383
|
location: StorageLocationSchema,
|
|
20181
20384
|
relativePath: string()
|
|
20182
|
-
}), _void(), {
|
|
20385
|
+
}), _void(), {
|
|
20386
|
+
kind: "mutation",
|
|
20387
|
+
auth: "admin"
|
|
20388
|
+
}), method(object({ location: StorageLocationSchema }), number().nullable(), { auth: "admin" }), method(BeginUploadInputSchema, BeginUploadResultSchema, {
|
|
20389
|
+
kind: "mutation",
|
|
20390
|
+
auth: "admin"
|
|
20391
|
+
}), method(WriteChunkInputSchema, _void(), {
|
|
20392
|
+
kind: "mutation",
|
|
20393
|
+
auth: "admin"
|
|
20394
|
+
}), method(FinalizeUploadInputSchema, _void(), {
|
|
20395
|
+
kind: "mutation",
|
|
20396
|
+
auth: "admin"
|
|
20397
|
+
}), method(AbortUploadInputSchema, _void(), {
|
|
20398
|
+
kind: "mutation",
|
|
20399
|
+
auth: "admin"
|
|
20400
|
+
}), method(BeginDownloadInputSchema, BeginDownloadResultSchema, {
|
|
20401
|
+
kind: "mutation",
|
|
20402
|
+
auth: "admin"
|
|
20403
|
+
}), method(ReadChunkInputSchema, _instanceof(Uint8Array), { auth: "admin" }), method(EndDownloadInputSchema, _void(), {
|
|
20404
|
+
kind: "mutation",
|
|
20405
|
+
auth: "admin"
|
|
20406
|
+
});
|
|
20183
20407
|
/** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
|
|
20184
20408
|
var ProfileSettingsSchemaBridge = unknown().nullable();
|
|
20185
20409
|
var ProfileSettingsBagSchema = record(string(), unknown());
|
|
@@ -20481,7 +20705,8 @@ method(object({
|
|
|
20481
20705
|
access: "create"
|
|
20482
20706
|
}), method(object({ userId: string().optional() }), object({ optionsJSON: record(string(), unknown()) }), {
|
|
20483
20707
|
kind: "mutation",
|
|
20484
|
-
access: "view"
|
|
20708
|
+
access: "view",
|
|
20709
|
+
auth: "admin"
|
|
20485
20710
|
}), method(object({
|
|
20486
20711
|
/** Required — the user the assertion belongs to (verified). */
|
|
20487
20712
|
userId: string(),
|
|
@@ -20489,10 +20714,12 @@ method(object({
|
|
|
20489
20714
|
response: record(string(), unknown())
|
|
20490
20715
|
}), object({ verified: boolean() }), {
|
|
20491
20716
|
kind: "mutation",
|
|
20492
|
-
access: "view"
|
|
20717
|
+
access: "view",
|
|
20718
|
+
auth: "admin"
|
|
20493
20719
|
}), method(object({}), object({ optionsJSON: record(string(), unknown()) }), {
|
|
20494
20720
|
kind: "mutation",
|
|
20495
|
-
access: "view"
|
|
20721
|
+
access: "view",
|
|
20722
|
+
auth: "admin"
|
|
20496
20723
|
}), method(object({
|
|
20497
20724
|
/** AuthenticationResponseJSON from the browser. */
|
|
20498
20725
|
response: record(string(), unknown()) }), object({
|
|
@@ -20500,7 +20727,8 @@ response: record(string(), unknown()) }), object({
|
|
|
20500
20727
|
userId: string().nullable()
|
|
20501
20728
|
}), {
|
|
20502
20729
|
kind: "mutation",
|
|
20503
|
-
access: "view"
|
|
20730
|
+
access: "view",
|
|
20731
|
+
auth: "admin"
|
|
20504
20732
|
}), method(object({ userId: string() }), array(PasskeySummarySchema), { auth: "admin" }), method(object({
|
|
20505
20733
|
userId: string(),
|
|
20506
20734
|
credentialId: string()
|
|
@@ -20672,7 +20900,19 @@ var VectorStatsResultSchema = object({
|
|
|
20672
20900
|
/** False when the backend ranks approximately. */
|
|
20673
20901
|
exact: boolean()
|
|
20674
20902
|
});
|
|
20675
|
-
method(VectorDeclareIndexInputSchema, _void(), {
|
|
20903
|
+
method(VectorDeclareIndexInputSchema, _void(), {
|
|
20904
|
+
kind: "mutation",
|
|
20905
|
+
auth: "admin"
|
|
20906
|
+
}), method(VectorUpsertInputSchema, VectorUpsertResultSchema, {
|
|
20907
|
+
kind: "mutation",
|
|
20908
|
+
auth: "admin"
|
|
20909
|
+
}), method(VectorQueryInputSchema, VectorQueryResultSchema, { auth: "admin" }), method(VectorGetInputSchema, VectorGetResultSchema, { auth: "admin" }), method(VectorDeleteInputSchema, VectorDeleteResultSchema, {
|
|
20910
|
+
kind: "mutation",
|
|
20911
|
+
auth: "admin"
|
|
20912
|
+
}), method(VectorDeleteByFilterInputSchema, VectorDeleteResultSchema, {
|
|
20913
|
+
kind: "mutation",
|
|
20914
|
+
auth: "admin"
|
|
20915
|
+
}), method(VectorStatsInputSchema, VectorStatsResultSchema, { auth: "admin" });
|
|
20676
20916
|
var ClipSchema = object({
|
|
20677
20917
|
/** Opaque, provider-namespaced id. The default provider encodes the time
|
|
20678
20918
|
* window so `getClipPlayback` is self-contained (no event re-query). */
|
|
@@ -23125,7 +23365,27 @@ var MediaFileLiteSchema$1 = object({
|
|
|
23125
23365
|
sizeBytes: number(),
|
|
23126
23366
|
timestamp: number()
|
|
23127
23367
|
});
|
|
23128
|
-
method(
|
|
23368
|
+
method(object({
|
|
23369
|
+
/**
|
|
23370
|
+
* Inline {@link IdentitySchema.coverBase64} on every row.
|
|
23371
|
+
*
|
|
23372
|
+
* Default `false`, the same inversion `listRecentFaces` and
|
|
23373
|
+
* `listPlates` took on 2026-08-25 (see `include-crops-default.ts` for
|
|
23374
|
+
* why the burden belongs on the caller that WANTS the bytes). Measured
|
|
23375
|
+
* on the live hub the same day: four identities cost 40,979 B with the
|
|
23376
|
+
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
23377
|
+
* four times and the viewer holds at `staleTime: 30_000`.
|
|
23378
|
+
*
|
|
23379
|
+
* Nothing loses its avatar: `coverMediaKey` is already on every row and
|
|
23380
|
+
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
23381
|
+
*
|
|
23382
|
+
* **This is an INPUT field, so it does not reach the addon until the
|
|
23383
|
+
* next train** — the hub router validates cap inputs against its own
|
|
23384
|
+
* compiled Zod and strips a key it does not know. Until then the
|
|
23385
|
+
* provider sees `undefined`, which resolves to `false`: the cheap shape
|
|
23386
|
+
* is what ships, and the opt-in becomes reachable when the train lands.
|
|
23387
|
+
*/
|
|
23388
|
+
includeCrops: boolean().optional() }).optional(), array(IdentitySchema).readonly()), method(object({ name: string().min(1) }), IdentitySchema, {
|
|
23129
23389
|
kind: "mutation",
|
|
23130
23390
|
auth: "admin"
|
|
23131
23391
|
}), method(object({
|
|
@@ -26015,8 +26275,10 @@ var PlateInfoSchema = object({
|
|
|
26015
26275
|
keyFrameMediaKey: string().optional(),
|
|
26016
26276
|
base64: string().optional(),
|
|
26017
26277
|
/**
|
|
26018
|
-
* Same crop as a data-plane URL
|
|
26019
|
-
* never inlines JPEG; `listPlates`
|
|
26278
|
+
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
26279
|
+
* crop. `getPlateByTrack` returns this and never inlines JPEG; `listPlates`
|
|
26280
|
+
* and `searchPlates` inline the crop only when their `includeCrops` input is
|
|
26281
|
+
* left at its `true` default.
|
|
26020
26282
|
*/
|
|
26021
26283
|
cropUrl: string().optional()
|
|
26022
26284
|
});
|
|
@@ -26036,14 +26298,34 @@ var PlateClusterSchema = object({
|
|
|
26036
26298
|
});
|
|
26037
26299
|
method(object({
|
|
26038
26300
|
deviceId: number().int().optional(),
|
|
26039
|
-
limit: number().int().positive().optional()
|
|
26301
|
+
limit: number().int().positive().optional(),
|
|
26302
|
+
/**
|
|
26303
|
+
* Inline the base64 crop on every row. Default `true` — the existing
|
|
26304
|
+
* behaviour, kept so no caller breaks.
|
|
26305
|
+
*
|
|
26306
|
+
* Set `false` once the caller renders {@link PlateInfo.cropUrl}.
|
|
26307
|
+
* Measured on the live hub at the 500 rows the Plates view asks for:
|
|
26308
|
+
* 879,403 B and 27.7 s with the crops inline, against a few KiB of
|
|
26309
|
+
* metadata without them — and the browser then caches the images.
|
|
26310
|
+
*
|
|
26311
|
+
* This is the plate twin of `faceGallery.listRecentFaces`'s option;
|
|
26312
|
+
* plates were the one gallery list left without it.
|
|
26313
|
+
*
|
|
26314
|
+
* **This is an INPUT field, so it does not reach the addon until the
|
|
26315
|
+
* next train.** The hub router validates cap inputs against its own
|
|
26316
|
+
* compiled Zod and strips a key it does not know. Until the train
|
|
26317
|
+
* ships, sending `false` is harmless and keeps the crops inline.
|
|
26318
|
+
*/
|
|
26319
|
+
includeCrops: boolean().optional()
|
|
26040
26320
|
}).optional(), array(PlateInfoSchema).readonly()), method(object({
|
|
26041
26321
|
deviceId: number().int(),
|
|
26042
26322
|
trackId: string()
|
|
26043
26323
|
}), PlateInfoSchema.nullable()), method(object({ plateId: string() }), array(MediaFileLiteSchema).readonly()), method(object({
|
|
26044
26324
|
text: string().min(1),
|
|
26045
26325
|
maxDistance: number().int().min(0).optional(),
|
|
26046
|
-
limit: number().int().positive().optional()
|
|
26326
|
+
limit: number().int().positive().optional(),
|
|
26327
|
+
/** See `listPlates.includeCrops`. Default `true`. */
|
|
26328
|
+
includeCrops: boolean().optional()
|
|
26047
26329
|
}), array(PlateInfoSchema).readonly()), method(object({
|
|
26048
26330
|
maxDistance: number().int().min(0).optional(),
|
|
26049
26331
|
minClusterSize: number().int().min(2).optional(),
|
|
@@ -26057,7 +26339,13 @@ method(object({
|
|
|
26057
26339
|
}), method(object({ plateId: string() }), _void(), {
|
|
26058
26340
|
kind: "mutation",
|
|
26059
26341
|
auth: "admin"
|
|
26060
|
-
}), method(
|
|
26342
|
+
}), method(object({
|
|
26343
|
+
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
26344
|
+
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
26345
|
+
* option; `coverMediaKey` + the `event-media` plane carry the picture.
|
|
26346
|
+
* INPUT field: stripped by the hub router until the train ships, which
|
|
26347
|
+
* resolves to `false` and is exactly the intended default. */
|
|
26348
|
+
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
26061
26349
|
kind: "mutation",
|
|
26062
26350
|
auth: "admin"
|
|
26063
26351
|
}), method(object({
|
|
@@ -27578,92 +27866,6 @@ var sceneMonitorCapability = {
|
|
|
27578
27866
|
durability: "session"
|
|
27579
27867
|
};
|
|
27580
27868
|
/**
|
|
27581
|
-
* Per-stage gating mode applied to the zones a rule references.
|
|
27582
|
-
*
|
|
27583
|
-
* - `include`: the rule contributes to a **whitelist** for its stage.
|
|
27584
|
-
* When at least one `include` rule fires for a stage, only entities
|
|
27585
|
-
* inside one of those zones pass that stage.
|
|
27586
|
-
* - `exclude`: the rule contributes to a **blacklist** for its stage.
|
|
27587
|
-
* Entities inside one of those zones are dropped at that stage.
|
|
27588
|
-
*
|
|
27589
|
-
* `monitor`-style observation (count without filtering) is not a rule
|
|
27590
|
-
* mode — zones without any matching rule are observed naturally by
|
|
27591
|
-
* `zone-analytics` (live snapshot + history), so an "I just want to
|
|
27592
|
-
* count, not filter" use case needs no rule at all.
|
|
27593
|
-
*/
|
|
27594
|
-
var ZoneRuleModeEnum = _enum(["include", "exclude"]);
|
|
27595
|
-
/**
|
|
27596
|
-
* Per-consumer rule that references existing zones (geometry) and
|
|
27597
|
-
* defines how a specific pipeline stage should treat them. Each
|
|
27598
|
-
* consumer addon owns its own `ZoneRule[]` array in its per-device
|
|
27599
|
-
* settings:
|
|
27600
|
-
*
|
|
27601
|
-
* - `addon-motion-wasm` → `motionZoneRules: ZoneRule[]` (motion stage)
|
|
27602
|
-
* - `addon-detection-pipeline` → `detectionZoneRules: ZoneRule[]` (detection stage)
|
|
27603
|
-
* - future: notification rules, audio gating, etc.
|
|
27604
|
-
*
|
|
27605
|
-
* One rule applies to N zones (`zoneIds[]`) so the operator can
|
|
27606
|
-
* express "ignore motion in ALL of {garden, street}" with a single
|
|
27607
|
-
* rule. `classFilter` narrows the rule to specific object classes —
|
|
27608
|
-
* "drop person detections in the street, but keep cars" is one
|
|
27609
|
-
* `exclude` rule with `classFilter: ['person']`.
|
|
27610
|
-
*
|
|
27611
|
-
* `enabled` is a soft toggle — the operator can keep the rule
|
|
27612
|
-
* configured but inert without deleting it.
|
|
27613
|
-
*/
|
|
27614
|
-
var ZoneRuleSchema = object({
|
|
27615
|
-
/** Stable rule id — survives edits, used by the UI for diffing. */
|
|
27616
|
-
id: string(),
|
|
27617
|
-
/** Optional human-readable label rendered in the rule editor. */
|
|
27618
|
-
name: string().optional(),
|
|
27619
|
-
/** Zones this rule targets. The rule's `mode` applies to ALL
|
|
27620
|
-
* listed zones (OR-set: a detection in any one of them counts).
|
|
27621
|
-
* At least one zone id required — a rule with no targets is a
|
|
27622
|
-
* configuration mistake and the form validator rejects it. */
|
|
27623
|
-
zoneIds: array(string()).min(1).readonly(),
|
|
27624
|
-
mode: ZoneRuleModeEnum,
|
|
27625
|
-
/**
|
|
27626
|
-
* Class names this rule applies to. Empty / undefined ⇒ rule
|
|
27627
|
-
* applies to every class. Class strings match the `macroClass`
|
|
27628
|
-
* field on detections (e.g. `person`, `car`, `dog`).
|
|
27629
|
-
*/
|
|
27630
|
-
classFilter: array(string()).readonly().optional(),
|
|
27631
|
-
/**
|
|
27632
|
-
* Minimum bbox/mask overlap (0–1) with any of the rule's zones
|
|
27633
|
-
* required to consider an entity "in the zone". Defaults to the
|
|
27634
|
-
* consumer's stage default when omitted. Kept for back-compat with
|
|
27635
|
-
* existing per-rule overrides; new operators pick the value via
|
|
27636
|
-
* `bboxInclusionPct` (operator-friendly 0–100). Whichever field is
|
|
27637
|
-
* set, the lower-level engine reads it as a 0–1 fraction.
|
|
27638
|
-
*/
|
|
27639
|
-
overlapThreshold: number().min(0).max(1).optional(),
|
|
27640
|
-
/**
|
|
27641
|
-
* Operator-friendly version of `overlapThreshold` — the percentage
|
|
27642
|
-
* of the detection's bbox that must lie inside the zone for the
|
|
27643
|
-
* rule to match. Documented default is 85%; the engine substitutes
|
|
27644
|
-
* that when the field is omitted (kept optional so existing rules
|
|
27645
|
-
* stored without it stay valid).
|
|
27646
|
-
*
|
|
27647
|
-
* When BOTH `overlapThreshold` and `bboxInclusionPct` are set on a
|
|
27648
|
-
* rule, the engine prefers `bboxInclusionPct` because it's the
|
|
27649
|
-
* field exposed in the UI. Internally both feed the same gate.
|
|
27650
|
-
*/
|
|
27651
|
-
bboxInclusionPct: number().min(0).max(100).optional(),
|
|
27652
|
-
/**
|
|
27653
|
-
* When `true` and a detection has a segmentation mask, use the
|
|
27654
|
-
* mask for overlap instead of the bbox. Detection-stage only;
|
|
27655
|
-
* motion rules ignore this field.
|
|
27656
|
-
*/
|
|
27657
|
-
preferMask: boolean().optional(),
|
|
27658
|
-
/**
|
|
27659
|
-
* Soft-toggle: `false` disables the rule without deleting it.
|
|
27660
|
-
* Defaults to `true` so operators creating a rule via the UI
|
|
27661
|
-
* see it active immediately.
|
|
27662
|
-
*/
|
|
27663
|
-
enabled: boolean().default(true)
|
|
27664
|
-
});
|
|
27665
|
-
array(ZoneRuleSchema).readonly();
|
|
27666
|
-
/**
|
|
27667
27869
|
* Script-runner cap. Models HA `script.*` entities on
|
|
27668
27870
|
* `DeviceType.Script`. A Script is a pre-recorded action sequence
|
|
27669
27871
|
* that can be invoked imperatively — optionally with a variables
|
|
@@ -33316,6 +33518,12 @@ Object.freeze({
|
|
|
33316
33518
|
addonId: null,
|
|
33317
33519
|
access: "create"
|
|
33318
33520
|
},
|
|
33521
|
+
"pipelineAnalytics.cancelRelocateMedia": {
|
|
33522
|
+
capName: "pipeline-analytics",
|
|
33523
|
+
capScope: "device",
|
|
33524
|
+
addonId: null,
|
|
33525
|
+
access: "create"
|
|
33526
|
+
},
|
|
33319
33527
|
"pipelineAnalytics.cancelStorageMigrationMove": {
|
|
33320
33528
|
capName: "pipeline-analytics",
|
|
33321
33529
|
capScope: "device",
|
|
@@ -33490,6 +33698,12 @@ Object.freeze({
|
|
|
33490
33698
|
addonId: null,
|
|
33491
33699
|
access: "view"
|
|
33492
33700
|
},
|
|
33701
|
+
"pipelineAnalytics.listRelocateMediaJobs": {
|
|
33702
|
+
capName: "pipeline-analytics",
|
|
33703
|
+
capScope: "device",
|
|
33704
|
+
addonId: null,
|
|
33705
|
+
access: "view"
|
|
33706
|
+
},
|
|
33493
33707
|
"pipelineAnalytics.listRetrainAnnotations": {
|
|
33494
33708
|
capName: "pipeline-analytics",
|
|
33495
33709
|
capScope: "device",
|
|
@@ -33568,6 +33782,12 @@ Object.freeze({
|
|
|
33568
33782
|
addonId: null,
|
|
33569
33783
|
access: "create"
|
|
33570
33784
|
},
|
|
33785
|
+
"pipelineAnalytics.relocateMedia": {
|
|
33786
|
+
capName: "pipeline-analytics",
|
|
33787
|
+
capScope: "device",
|
|
33788
|
+
addonId: null,
|
|
33789
|
+
access: "create"
|
|
33790
|
+
},
|
|
33571
33791
|
"pipelineAnalytics.restageRetrainTrack": {
|
|
33572
33792
|
capName: "pipeline-analytics",
|
|
33573
33793
|
capScope: "device",
|
|
@@ -33580,6 +33800,12 @@ Object.freeze({
|
|
|
33580
33800
|
addonId: null,
|
|
33581
33801
|
access: "create"
|
|
33582
33802
|
},
|
|
33803
|
+
"pipelineAnalytics.runReplayFrameProcessor": {
|
|
33804
|
+
capName: "pipeline-analytics",
|
|
33805
|
+
capScope: "device",
|
|
33806
|
+
addonId: null,
|
|
33807
|
+
access: "create"
|
|
33808
|
+
},
|
|
33583
33809
|
"pipelineAnalytics.saveRetrainAnnotations": {
|
|
33584
33810
|
capName: "pipeline-analytics",
|
|
33585
33811
|
capScope: "device",
|
|
@@ -33712,6 +33938,12 @@ Object.freeze({
|
|
|
33712
33938
|
addonId: null,
|
|
33713
33939
|
access: "view"
|
|
33714
33940
|
},
|
|
33941
|
+
"pipelineExecutor.getInferenceDeviceHealth": {
|
|
33942
|
+
capName: "pipeline-executor",
|
|
33943
|
+
capScope: "system",
|
|
33944
|
+
addonId: null,
|
|
33945
|
+
access: "view"
|
|
33946
|
+
},
|
|
33715
33947
|
"pipelineExecutor.getOrchestratorConfigSchema": {
|
|
33716
33948
|
capName: "pipeline-executor",
|
|
33717
33949
|
capScope: "system",
|
|
@@ -33784,6 +34016,12 @@ Object.freeze({
|
|
|
33784
34016
|
addonId: null,
|
|
33785
34017
|
access: "view"
|
|
33786
34018
|
},
|
|
34019
|
+
"pipelineExecutor.rearmInferenceDevice": {
|
|
34020
|
+
capName: "pipeline-executor",
|
|
34021
|
+
capScope: "system",
|
|
34022
|
+
addonId: null,
|
|
34023
|
+
access: "create"
|
|
34024
|
+
},
|
|
33787
34025
|
"pipelineExecutor.runAudioTest": {
|
|
33788
34026
|
capName: "pipeline-executor",
|
|
33789
34027
|
capScope: "system",
|
|
@@ -37032,6 +37270,11 @@ Object.freeze({
|
|
|
37032
37270
|
form: "single",
|
|
37033
37271
|
optional: false
|
|
37034
37272
|
}],
|
|
37273
|
+
"pipelineAnalytics.runReplayFrameProcessor": [{
|
|
37274
|
+
name: "deviceId",
|
|
37275
|
+
form: "single",
|
|
37276
|
+
optional: false
|
|
37277
|
+
}],
|
|
37035
37278
|
"pipelineAnalytics.saveRetrainAnnotations": [{
|
|
37036
37279
|
name: "deviceId",
|
|
37037
37280
|
form: "single",
|
|
@@ -44431,7 +44674,10 @@ function sanitizeProfileSettings(profileId, raw) {
|
|
|
44431
44674
|
showContainers: true,
|
|
44432
44675
|
showSensors: true
|
|
44433
44676
|
};
|
|
44434
|
-
for (const plugin of GLANCES_PLUGINS)
|
|
44677
|
+
for (const plugin of GLANCES_PLUGINS) {
|
|
44678
|
+
const value = bag[plugin.key];
|
|
44679
|
+
if (typeof value === "boolean") out[plugin.key] = value;
|
|
44680
|
+
}
|
|
44435
44681
|
return out;
|
|
44436
44682
|
}
|
|
44437
44683
|
function profileSettingsToArgs(profileId, settings) {
|