@camstack/addon-model-studio 1.1.172 → 1.1.174
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/{MotionZonesSettings-QVVEC220.mjs → MotionZonesSettings-DavNeZt1.mjs} +2 -2
- package/dist/{PrivacyMaskSettings-xeMI1BTC.mjs → PrivacyMaskSettings-bWW0b0eT.mjs} +4 -4
- package/dist/{SceneMonitorEditor-C269t1tC.mjs → SceneMonitorEditor-DuXCuccO.mjs} +3 -3
- package/dist/_stub.js +10 -10
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-Co04mmEH.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-C_y_ArLj.mjs} +3 -3
- package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DwoBFtDL.mjs +26 -0
- package/dist/{hostInit-GDWPIFmC.mjs → hostInit-nK0BL4EK.mjs} +2 -2
- package/dist/model-studio.addon.js +1324 -735
- package/dist/model-studio.addon.mjs +1324 -735
- package/dist/{player-overlays-CjVxAzYe.mjs → player-overlays-BZLfX48i.mjs} +1 -1
- package/dist/remoteEntry.js +1 -1
- package/dist/{responsive-CH1mGJTo.mjs → responsive-DAticuj8.mjs} +1 -1
- package/dist/{scene-monitor-copy-BIVlnlk5.mjs → scene-monitor-copy-CuI6S0HF.mjs} +1 -1
- package/dist/{square-Bul4urrS.mjs → square-Dh-K-SIJ.mjs} +1 -1
- package/dist/{trash-2-DqNDJcPu.mjs → trash-2-Cuodqp-m.mjs} +1 -1
- package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-SwmSP59i.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-mbmirjVC.mjs} +1 -1
- package/package.json +1 -1
- package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CEMfSnqp.mjs +0 -26
|
@@ -5884,7 +5884,7 @@ var ZodIssueCode = {
|
|
|
5884
5884
|
var ZodFirstPartyTypeKind;
|
|
5885
5885
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5886
5886
|
//#endregion
|
|
5887
|
-
//#region ../types/dist/sleep-
|
|
5887
|
+
//#region ../types/dist/sleep-BaRu0bS5.mjs
|
|
5888
5888
|
/**
|
|
5889
5889
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5890
5890
|
* window to float samples (D455).
|
|
@@ -10020,7 +10020,7 @@ var ModelFormatEntrySchema = object({
|
|
|
10020
10020
|
/** Multi-file payload (directory members or sibling files). */
|
|
10021
10021
|
files: array(string()).readonly().optional(),
|
|
10022
10022
|
/** Runtime(s) that can use this format. If omitted, inferred from ModelFormat key */
|
|
10023
|
-
runtimes: array(_enum(["
|
|
10023
|
+
runtimes: array(_enum(["python"])).readonly().optional()
|
|
10024
10024
|
});
|
|
10025
10025
|
/**
|
|
10026
10026
|
* Extra file that must be downloaded alongside the model (e.g., labels JSON, dict.txt).
|
|
@@ -10101,10 +10101,17 @@ var ModelCatalogEntrySchema = object({
|
|
|
10101
10101
|
inputChannels: number().int().positive().optional(),
|
|
10102
10102
|
labels: array(LabelDefinitionSchema).readonly(),
|
|
10103
10103
|
inputLayout: _enum(["nchw", "nhwc"]).optional(),
|
|
10104
|
+
/**
|
|
10105
|
+
* `'scrfd'` applies InsightFace's SCRFD input contract, `(x - 127.5) / 128`
|
|
10106
|
+
* (upstream `insightface/model_zoo/scrfd.py`), instead of the historical
|
|
10107
|
+
* plain `/255`. Measured against COCO GT: 188 → 196 faces found on the
|
|
10108
|
+
* `scrfd-2.5g` catalog entry (2026-09-26 model-replacement spike, §2.4-2).
|
|
10109
|
+
*/
|
|
10104
10110
|
inputNormalization: _enum([
|
|
10105
10111
|
"zero-one",
|
|
10106
10112
|
"imagenet",
|
|
10107
|
-
"none"
|
|
10113
|
+
"none",
|
|
10114
|
+
"scrfd"
|
|
10108
10115
|
]).optional(),
|
|
10109
10116
|
/**
|
|
10110
10117
|
* The model already applies softmax IN-GRAPH — its raw output is a
|
|
@@ -10206,7 +10213,8 @@ var ModelConvertMetadataSchema = object({
|
|
|
10206
10213
|
inputNormalization: _enum([
|
|
10207
10214
|
"zero-one",
|
|
10208
10215
|
"imagenet",
|
|
10209
|
-
"none"
|
|
10216
|
+
"none",
|
|
10217
|
+
"scrfd"
|
|
10210
10218
|
]).optional(),
|
|
10211
10219
|
preprocessMode: _enum(["letterbox", "resize"]).optional(),
|
|
10212
10220
|
outputFormat: _enum([
|
|
@@ -17624,6 +17632,9 @@ var NcSystemEventKindSchema = _enum([
|
|
|
17624
17632
|
"device-battery-normal",
|
|
17625
17633
|
"device-consumable-low",
|
|
17626
17634
|
"device-consumable-normal",
|
|
17635
|
+
"device-tank-low",
|
|
17636
|
+
"device-tank-full",
|
|
17637
|
+
"device-tank-normal",
|
|
17627
17638
|
"stream-online",
|
|
17628
17639
|
"stream-offline",
|
|
17629
17640
|
"node-online",
|
|
@@ -17661,6 +17672,29 @@ var NC_LEGACY_SYSTEM_EVENT_KINDS = new Set([
|
|
|
17661
17672
|
]);
|
|
17662
17673
|
NcSystemEventKindSchema.options.filter((kind) => !NC_LEGACY_SYSTEM_EVENT_KINDS.has(kind));
|
|
17663
17674
|
/**
|
|
17675
|
+
* The panel's transitions, as ONE list.
|
|
17676
|
+
*
|
|
17677
|
+
* Named here rather than spelled out at each of the four sites that need them
|
|
17678
|
+
* (the emitter, the intake, the editor group, the combined-notification gate),
|
|
17679
|
+
* because a transition added to the enum and forgotten at one of them is an
|
|
17680
|
+
* alarm state nobody can be notified about. That is exactly what this list
|
|
17681
|
+
* failed to prevent while it held three: `alarm-arming` was the fourth.
|
|
17682
|
+
*
|
|
17683
|
+
* In LIFECYCLE order, which is the order an editor lists them in and the order
|
|
17684
|
+
* a person experiences them — not the order they were added.
|
|
17685
|
+
*/
|
|
17686
|
+
var NC_ALARM_SYSTEM_EVENT_KINDS = [
|
|
17687
|
+
"alarm-arm-refused",
|
|
17688
|
+
"alarm-check-failed",
|
|
17689
|
+
"alarm-arming",
|
|
17690
|
+
"alarm-armed",
|
|
17691
|
+
"alarm-pending",
|
|
17692
|
+
"alarm-triggered",
|
|
17693
|
+
"alarm-rearmed",
|
|
17694
|
+
"alarm-sensor-bypass",
|
|
17695
|
+
"alarm-disarmed"
|
|
17696
|
+
];
|
|
17697
|
+
/**
|
|
17664
17698
|
* One coherent system-event condition. `kinds` is the required opt-in safety
|
|
17665
17699
|
* gate; the remaining lists are optional narrowing filters relevant to the
|
|
17666
17700
|
* selected kinds.
|
|
@@ -17694,7 +17728,22 @@ var NcSystemEventConditionSchema = object({
|
|
|
17694
17728
|
*/
|
|
17695
17729
|
excludeDeviceIds: array(number().int()).min(1).optional(),
|
|
17696
17730
|
nodeIds: array(string().min(1)).min(1).optional(),
|
|
17697
|
-
packageNames: array(string().min(1)).min(1).optional()
|
|
17731
|
+
packageNames: array(string().min(1)).min(1).optional(),
|
|
17732
|
+
/**
|
|
17733
|
+
* At or below this remaining-life %, a consumable is LOW for THIS rule
|
|
17734
|
+
* (D642). Absent = {@link NC_CONSUMABLE_LOW_PERCENT_DEFAULT}; at most
|
|
17735
|
+
* {@link NC_CONSUMABLE_LOW_PERCENT_MAX}, so every episode can recover. Scoped to the
|
|
17736
|
+
* consumable kinds (`systemEventFilterApplies`) and to the device-events
|
|
17737
|
+
* family; ignored on every other kind.
|
|
17738
|
+
*
|
|
17739
|
+
* It is a property of the RULE because the operator decided so: a rule at
|
|
17740
|
+
* 25 must be told about a filter at 20 %, a rule at 10 must not. The hub
|
|
17741
|
+
* keeps one episode per (threshold, device, item) — its own hysteresis, its
|
|
17742
|
+
* own reminder — and a rule hears only the episode judged at ITS threshold,
|
|
17743
|
+
* exactly as an occupancy rule hears only the edge of its own count. A
|
|
17744
|
+
* provider's own `replace` verdict is low at every threshold.
|
|
17745
|
+
*/
|
|
17746
|
+
consumableLowPercent: number().int().min(1).max(95).optional()
|
|
17698
17747
|
});
|
|
17699
17748
|
/** Hard ceiling on a window (24h). A snooze that could not expire would be an
|
|
17700
17749
|
* outage the operator asked for once and forgot. */
|
|
@@ -17712,6 +17761,25 @@ var NcScheduleSchema = object({
|
|
|
17712
17761
|
/** Active OUTSIDE the windows (e.g. "only outside business hours"). */
|
|
17713
17762
|
invert: boolean().optional()
|
|
17714
17763
|
});
|
|
17764
|
+
/**
|
|
17765
|
+
* How a system-event rule of the `device-events` or `system` family speaks
|
|
17766
|
+
* (D647): at once, per event (`instant`, the only behaviour before D647), or
|
|
17767
|
+
* as a STATE SUMMARY at the end of each window of `schedule`.
|
|
17768
|
+
*/
|
|
17769
|
+
var NcSystemEventDeliveryModeSchema = _enum(["instant", "summary"]);
|
|
17770
|
+
/**
|
|
17771
|
+
* `summary`: the rule sends NOTHING per event. When a window of `schedule`
|
|
17772
|
+
* CLOSES, it sends one notification with the current state of its kinds
|
|
17773
|
+
* (low batteries, consumables to replace, devices offline, updates
|
|
17774
|
+
* available, ...), after its own filters. Nothing to report sends nothing.
|
|
17775
|
+
* The schedule is the ordinary `NcSchedule` (weekly windows, IANA timezone,
|
|
17776
|
+
* midnight crossing); the send time is each window's END. Refused on the
|
|
17777
|
+
* `alarm` family, which stays instant (`systemEventDeliveryProblems`).
|
|
17778
|
+
*/
|
|
17779
|
+
var NcSystemEventDeliverySchema = discriminatedUnion("mode", [object({ mode: literal("instant") }), object({
|
|
17780
|
+
mode: literal("summary"),
|
|
17781
|
+
schedule: NcScheduleSchema
|
|
17782
|
+
})]);
|
|
17715
17783
|
/** Fuzzy plate matcher — OCR noise makes exact match useless (spec row 12/13). */
|
|
17716
17784
|
var NcPlateMatcherSchema = object({
|
|
17717
17785
|
/**
|
|
@@ -17837,6 +17905,16 @@ var NcCrossingSchema = _enum([
|
|
|
17837
17905
|
"exit",
|
|
17838
17906
|
"any"
|
|
17839
17907
|
]);
|
|
17908
|
+
/**
|
|
17909
|
+
* Which edge of a BOOLEAN sensor fires a device-event rule (D640).
|
|
17910
|
+
* - `raised` — the sensor went high: water detected, smoke, open, tampered.
|
|
17911
|
+
* - `cleared` — it went back: dry, clear, closed.
|
|
17912
|
+
* - absent — both edges, which is what every rule authored before this did.
|
|
17913
|
+
*
|
|
17914
|
+
* There is no third member for "both": absence already says it, and a value
|
|
17915
|
+
* that means the same as absence is a second way to write one rule.
|
|
17916
|
+
*/
|
|
17917
|
+
var NcSensorTransitionSchema = _enum(["raised", "cleared"]);
|
|
17840
17918
|
/** Admin-zone membership condition (zone IDs as stamped by the ZoneEngine). */
|
|
17841
17919
|
var NcZoneConditionSchema = object({
|
|
17842
17920
|
ids: array(string().min(1)).min(1),
|
|
@@ -18026,6 +18104,20 @@ var NcConditionsSchema = object({
|
|
|
18026
18104
|
scene: NcSceneConditionSchema.optional(),
|
|
18027
18105
|
/** Device scope — absent = all devices. */
|
|
18028
18106
|
devices: array(number()).optional(),
|
|
18107
|
+
/**
|
|
18108
|
+
* Device EXCLUSION (D641) — "every device except these". Judged on the SAME
|
|
18109
|
+
* subject ids {@link devices} is judged on (the camera, the sensor that
|
|
18110
|
+
* fired, a linked set's sensor and row cameras), so a sensor fanned out per
|
|
18111
|
+
* linked camera is excluded exactly where an include would have tested it.
|
|
18112
|
+
* `min(1)`: an empty exclusion excludes nothing and is written as absent.
|
|
18113
|
+
*
|
|
18114
|
+
* Not for `system-event` rules — those carry their own
|
|
18115
|
+
* `systemEvent.excludeDeviceIds` (D636), and the hub refuses this key there.
|
|
18116
|
+
* Editors present the two lists as ONE field (All | Only these | All except
|
|
18117
|
+
* these); the engine evaluates each independently, so a legacy rule
|
|
18118
|
+
* carrying both still means "these, minus those".
|
|
18119
|
+
*/
|
|
18120
|
+
devicesExclude: array(number()).min(1).optional(),
|
|
18029
18121
|
/** Detector class names (any overlap with the record's class set). */
|
|
18030
18122
|
classes: array(string().min(1)).optional(),
|
|
18031
18123
|
/** Veto classes — any overlap fails the rule. */
|
|
@@ -18159,6 +18251,16 @@ var NcConditionsSchema = object({
|
|
|
18159
18251
|
*/
|
|
18160
18252
|
sensorKinds: array(string().min(1)).optional(),
|
|
18161
18253
|
/**
|
|
18254
|
+
* DEVICE-EVENT only (D640). Fire on one edge of a boolean sensor —
|
|
18255
|
+
* {@link NcSensorTransitionSchema}. Which field of the slice means "raised"
|
|
18256
|
+
* is `@camstack/types` → `notification/sensor-raised.ts`. A reading the
|
|
18257
|
+
* engine cannot place (a kind with no raise, an unreadable slice) PASSES:
|
|
18258
|
+
* the condition fails open towards notifying, never towards silence. Editors
|
|
18259
|
+
* offer it only when every chosen {@link sensorKinds} member has a raise
|
|
18260
|
+
* (`sensorTransitionOffered`), and the hub refuses it on any other delivery.
|
|
18261
|
+
*/
|
|
18262
|
+
sensorTransition: NcSensorTransitionSchema.optional(),
|
|
18263
|
+
/**
|
|
18162
18264
|
* PACKAGE-EVENT only. Which package phase fires the rule — `delivered`
|
|
18163
18265
|
* (a parked parcel appeared), `picked-up` (it departed), or `both`. Fails
|
|
18164
18266
|
* when the subject's phase does not match (a subject always carries a phase
|
|
@@ -18413,6 +18515,16 @@ var NcRuleInputSchema = object({
|
|
|
18413
18515
|
delivery: NcDeliverySchema,
|
|
18414
18516
|
conditions: NcConditionsSchema.default({}),
|
|
18415
18517
|
schedule: NcScheduleSchema.optional(),
|
|
18518
|
+
/**
|
|
18519
|
+
* A `device-events` / `system` rule's delivery (D647): absent or `instant`
|
|
18520
|
+
* is a notification per event; `summary` is one state summary per closed
|
|
18521
|
+
* window of its schedule. `.optional()` and never defaulted: absent must
|
|
18522
|
+
* keep meaning what every rule authored before D647 meant, with no
|
|
18523
|
+
* migration. Top-level rather than inside `conditions.systemEvent`, so a
|
|
18524
|
+
* client that does not know it (an older viewer re-sending `conditions`
|
|
18525
|
+
* whole) leaves it standing through the store's patch merge.
|
|
18526
|
+
*/
|
|
18527
|
+
systemEventDelivery: NcSystemEventDeliverySchema.optional(),
|
|
18416
18528
|
/** May be empty when `targetUsers` addresses at least one user — the
|
|
18417
18529
|
* "at least one addressee" invariant is enforced by the provider, because
|
|
18418
18530
|
* a cross-field refine here would break `NcRulePatchSchema.partial()`. */
|
|
@@ -18641,6 +18753,28 @@ var NcRuleSchema = NcRuleInputSchema.extend({
|
|
|
18641
18753
|
*/
|
|
18642
18754
|
disabledTargetIds: array(string()).default([])
|
|
18643
18755
|
});
|
|
18756
|
+
/** One section of a previewed state summary. `unavailable` = its state could not be read. */
|
|
18757
|
+
var NcStateSummaryPreviewSectionSchema = object({
|
|
18758
|
+
id: string(),
|
|
18759
|
+
status: _enum(["read", "unavailable"]),
|
|
18760
|
+
items: number().int().nonnegative(),
|
|
18761
|
+
reason: string().optional()
|
|
18762
|
+
});
|
|
18763
|
+
/**
|
|
18764
|
+
* The summary a rule would send now. `empty` = nothing to report and every
|
|
18765
|
+
* section read: such a summary is NOT sent. `dropped` counts the open states
|
|
18766
|
+
* the rule's own filters (or a camera mute) left out, by reason.
|
|
18767
|
+
* `excludedGroups` names the kind groups selected that have no state to report
|
|
18768
|
+
* (backups & exports).
|
|
18769
|
+
*/
|
|
18770
|
+
var NcStateSummaryPreviewSchema = object({
|
|
18771
|
+
empty: boolean(),
|
|
18772
|
+
count: number().int().nonnegative(),
|
|
18773
|
+
text: string(),
|
|
18774
|
+
sections: array(NcStateSummaryPreviewSectionSchema),
|
|
18775
|
+
dropped: record(string(), number().int().nonnegative()),
|
|
18776
|
+
excludedGroups: array(string())
|
|
18777
|
+
});
|
|
18644
18778
|
var NcTestResultSchema = object({
|
|
18645
18779
|
recordId: string(),
|
|
18646
18780
|
recordKind: _enum([
|
|
@@ -18732,6 +18866,13 @@ var NcTemplateVarDescriptorSchema = object({
|
|
|
18732
18866
|
kinds: array(NcTemplateVarKindSchema).optional(),
|
|
18733
18867
|
deliveries: array(NcDeliverySchema).optional(),
|
|
18734
18868
|
systemEventKinds: array(NcSystemEventKindSchema).optional(),
|
|
18869
|
+
/**
|
|
18870
|
+
* Which system-event DELIVERY has a value for it (D647). Absent = an
|
|
18871
|
+
* instant row only when the descriptor names `systemEventKinds` (a
|
|
18872
|
+
* per-event fact: a summary row has no single device), and both otherwise.
|
|
18873
|
+
* `['summary']` marks the state-summary vocabulary (`{{summaryText}}`, ...).
|
|
18874
|
+
*/
|
|
18875
|
+
systemEventDeliveries: array(NcSystemEventDeliveryModeSchema).optional(),
|
|
18735
18876
|
dynamic: object({
|
|
18736
18877
|
prefix: literal("count_"),
|
|
18737
18878
|
from: literal("classes")
|
|
@@ -18744,7 +18885,9 @@ var NcTemplatePreviewInputSchema = object({
|
|
|
18744
18885
|
field: NcTemplateFieldSchema,
|
|
18745
18886
|
kind: NcRuleKindSchema.optional(),
|
|
18746
18887
|
delivery: NcDeliverySchema.optional(),
|
|
18747
|
-
systemEventKinds: array(NcSystemEventKindSchema).optional()
|
|
18888
|
+
systemEventKinds: array(NcSystemEventKindSchema).optional(),
|
|
18889
|
+
/** The rule's system-event delivery (D647); absent = instant. */
|
|
18890
|
+
systemEventDelivery: NcSystemEventDeliveryModeSchema.optional()
|
|
18748
18891
|
}),
|
|
18749
18892
|
template: object({
|
|
18750
18893
|
title: string().max(500).optional(),
|
|
@@ -18777,6 +18920,7 @@ var NcConditionDescriptorSchema = object({
|
|
|
18777
18920
|
/** Editor widget the UI renders — never hardcode per-condition forms. */
|
|
18778
18921
|
valueType: _enum([
|
|
18779
18922
|
"deviceIdList",
|
|
18923
|
+
"deviceIdExcludeList",
|
|
18780
18924
|
"stringList",
|
|
18781
18925
|
"number01",
|
|
18782
18926
|
"number",
|
|
@@ -18787,6 +18931,7 @@ var NcConditionDescriptorSchema = object({
|
|
|
18787
18931
|
"plateMatcher",
|
|
18788
18932
|
"packagePhase",
|
|
18789
18933
|
"crossingSelect",
|
|
18934
|
+
"sensorTransition",
|
|
18790
18935
|
"polygonDraw",
|
|
18791
18936
|
"occupancy",
|
|
18792
18937
|
"audio",
|
|
@@ -18937,6 +19082,28 @@ var NcHistoryFilterSchema = object({
|
|
|
18937
19082
|
limit: number().int().min(1).max(500).default(100)
|
|
18938
19083
|
});
|
|
18939
19084
|
/**
|
|
19085
|
+
* Every rule's last run, in one answer.
|
|
19086
|
+
*
|
|
19087
|
+
* A rule ABSENT from `runs` produced no delivery inside `horizonMs` — how far
|
|
19088
|
+
* back this answer looked, in ms before the hub's now. It is the outbox prune
|
|
19089
|
+
* window (7 days by default, operator-configurable), NARROWED when the read hit
|
|
19090
|
+
* its row bound: the answer never claims a window it did not read. `null` means
|
|
19091
|
+
* the operator keeps the outbox forever AND the read reached its end, so absent
|
|
19092
|
+
* means "never on record". A UI derives its "not in the last N days" from this
|
|
19093
|
+
* value, never from a constant — and only when the call ANSWERED (D315).
|
|
19094
|
+
*/
|
|
19095
|
+
var NcRuleLastRunsSchema = object({
|
|
19096
|
+
runs: array(object({
|
|
19097
|
+
ruleId: string(),
|
|
19098
|
+
/** Fire time of the newest row (`createdAt`, epoch ms). */
|
|
19099
|
+
lastAt: number(),
|
|
19100
|
+
status: NcHistoryStatusSchema,
|
|
19101
|
+
/** The camera/device of that row (a digest row files under its first camera). */
|
|
19102
|
+
deviceId: number()
|
|
19103
|
+
})),
|
|
19104
|
+
horizonMs: number().nonnegative().nullable()
|
|
19105
|
+
});
|
|
19106
|
+
/**
|
|
18940
19107
|
* What a snooze covers. Broader scopes win when several overlap, so one window
|
|
18941
19108
|
* leaves ONE digest rather than a rule snooze and a whole-feed snooze both
|
|
18942
19109
|
* summarising the same silence.
|
|
@@ -19117,6 +19284,14 @@ var NcAlarmModeCoverageSchema = object({
|
|
|
19117
19284
|
/** Ids named by the covering rules. A SUBSET when `allDevices` is true. */
|
|
19118
19285
|
deviceIds: array(number().int()),
|
|
19119
19286
|
/**
|
|
19287
|
+
* D641: the ids NOT covered although `allDevices` is true — every unscoped
|
|
19288
|
+
* covering rule EXCLUDES them (`conditions.devicesExclude`) and no named rule
|
|
19289
|
+
* covers them. Always `[]` when `allDevices` is false. Excluded by the rules,
|
|
19290
|
+
* which is not the same as skipped by a switch: never in `skippedDevices`.
|
|
19291
|
+
* Defaulted so an answer computed before this field parses as "none".
|
|
19292
|
+
*/
|
|
19293
|
+
allDevicesExcept: array(number().int()).default([]),
|
|
19294
|
+
/**
|
|
19120
19295
|
* Devices this mode NAMES but cannot actually arm, each with the switch that
|
|
19121
19296
|
* excludes it.
|
|
19122
19297
|
*
|
|
@@ -19246,13 +19421,17 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
|
|
|
19246
19421
|
}), object({ results: array(NcTestResultSchema) }), {
|
|
19247
19422
|
kind: "mutation",
|
|
19248
19423
|
auth: "admin"
|
|
19424
|
+
}), method(object({ rule: NcRuleInputSchema }), NcStateSummaryPreviewSchema, {
|
|
19425
|
+
kind: "mutation",
|
|
19426
|
+
auth: "admin",
|
|
19427
|
+
access: "view"
|
|
19249
19428
|
}), method(object({}), object({
|
|
19250
19429
|
catalog: array(NcConditionDescriptorSchema),
|
|
19251
19430
|
taxonomy: NcTaxonomySchema.optional()
|
|
19252
19431
|
})), method(object({}), object({ vars: array(NcTemplateVarDescriptorSchema) })), method(NcTemplatePreviewInputSchema, NcTemplatePreviewSchema, {
|
|
19253
19432
|
kind: "mutation",
|
|
19254
19433
|
access: "view"
|
|
19255
|
-
}), method(object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), object({ entries: array(NcHistoryEntrySchema) }), { auth: "admin" }), method(object({ artifactId: string().min(1) }), object({ url: string().nullable() }), { auth: "admin" }), method(object({}), object({ snoozes: array(NcSnoozeSchema) }), { caller: "required" }), method(object({ snooze: NcSnoozeInputSchema }), object({ snooze: NcSnoozeSchema }), {
|
|
19434
|
+
}), method(object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), object({ entries: array(NcHistoryEntrySchema) }), { auth: "admin" }), method(object({}), NcRuleLastRunsSchema, { auth: "admin" }), method(object({ artifactId: string().min(1) }), object({ url: string().nullable() }), { auth: "admin" }), method(object({}), object({ snoozes: array(NcSnoozeSchema) }), { caller: "required" }), method(object({ snooze: NcSnoozeInputSchema }), object({ snooze: NcSnoozeSchema }), {
|
|
19256
19435
|
kind: "mutation",
|
|
19257
19436
|
caller: "required"
|
|
19258
19437
|
}), method(object({ snoozeId: string() }), object({ success: literal(true) }), {
|
|
@@ -19592,606 +19771,6 @@ var OauthIntegrationDescriptorSchema = object({
|
|
|
19592
19771
|
});
|
|
19593
19772
|
method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" });
|
|
19594
19773
|
/**
|
|
19595
|
-
* Reference to the frame's retained NATIVE surface + the parent crop's placement
|
|
19596
|
-
* within the frame, so the executor can re-cut a leaf child ROI at native
|
|
19597
|
-
* resolution on the detail plane. See the `runPipeline` `nativeCropRef` field.
|
|
19598
|
-
*/
|
|
19599
|
-
var NativeCropRefSchema = object({
|
|
19600
|
-
/** Handle keying the retained native surface (node-pinned to its owner). */
|
|
19601
|
-
handle: FrameHandleSchema,
|
|
19602
|
-
/** The parent crop's padded/clamped rectangle in FRAME-space pixels. */
|
|
19603
|
-
cropFrameSpace: object({
|
|
19604
|
-
x: number(),
|
|
19605
|
-
y: number(),
|
|
19606
|
-
w: number(),
|
|
19607
|
-
h: number()
|
|
19608
|
-
})
|
|
19609
|
-
});
|
|
19610
|
-
object({
|
|
19611
|
-
crop: object({
|
|
19612
|
-
left: number(),
|
|
19613
|
-
top: number(),
|
|
19614
|
-
width: number().positive(),
|
|
19615
|
-
height: number().positive()
|
|
19616
|
-
}).optional(),
|
|
19617
|
-
content: object({
|
|
19618
|
-
width: number().int().positive(),
|
|
19619
|
-
height: number().int().positive()
|
|
19620
|
-
}),
|
|
19621
|
-
fit: _enum(["stretch", "contain"]),
|
|
19622
|
-
format: _enum([
|
|
19623
|
-
"rgb",
|
|
19624
|
-
"gray",
|
|
19625
|
-
"jpeg"
|
|
19626
|
-
])
|
|
19627
|
-
});
|
|
19628
|
-
/**
|
|
19629
|
-
* Process-local frame identity. It is serializable so it can ride an in-process
|
|
19630
|
-
* capability call, but `registryId` deliberately prevents resolution in any
|
|
19631
|
-
* other process or execution group.
|
|
19632
|
-
*/
|
|
19633
|
-
var FrameRefSchema = object({
|
|
19634
|
-
registryId: string().min(1),
|
|
19635
|
-
id: string().min(1),
|
|
19636
|
-
width: number().int().positive(),
|
|
19637
|
-
height: number().int().positive(),
|
|
19638
|
-
format: _enum(["rgb", "gray"]),
|
|
19639
|
-
timestamp: number(),
|
|
19640
|
-
capturedAt: number().optional()
|
|
19641
|
-
});
|
|
19642
|
-
var ModelFormatSchema$1 = _enum([
|
|
19643
|
-
"onnx",
|
|
19644
|
-
"coreml",
|
|
19645
|
-
"openvino",
|
|
19646
|
-
"tflite",
|
|
19647
|
-
"pt",
|
|
19648
|
-
"gguf"
|
|
19649
|
-
]);
|
|
19650
|
-
var PipelineSlotSchema = _enum([
|
|
19651
|
-
"detector",
|
|
19652
|
-
"cropper",
|
|
19653
|
-
"classifier",
|
|
19654
|
-
"refiner",
|
|
19655
|
-
"audio-classifier"
|
|
19656
|
-
]);
|
|
19657
|
-
var PipelineEngineChoiceSchema = object({
|
|
19658
|
-
runtime: _enum(["node", "python"]),
|
|
19659
|
-
backend: string(),
|
|
19660
|
-
format: ModelFormatSchema$1,
|
|
19661
|
-
device: string().optional()
|
|
19662
|
-
});
|
|
19663
|
-
var AvailableEngineSchema = object({
|
|
19664
|
-
engine: PipelineEngineChoiceSchema,
|
|
19665
|
-
devices: array(object({
|
|
19666
|
-
id: string(),
|
|
19667
|
-
label: string(),
|
|
19668
|
-
description: string().optional()
|
|
19669
|
-
})).readonly(),
|
|
19670
|
-
defaultDevice: string()
|
|
19671
|
-
});
|
|
19672
|
-
var PipelineDefaultStepSchema = lazy(() => object({
|
|
19673
|
-
addonId: string(),
|
|
19674
|
-
addonName: string(),
|
|
19675
|
-
slot: PipelineSlotSchema,
|
|
19676
|
-
inputClasses: array(string()).readonly(),
|
|
19677
|
-
outputClasses: array(string()).readonly(),
|
|
19678
|
-
enabled: boolean(),
|
|
19679
|
-
modelId: string(),
|
|
19680
|
-
children: array(PipelineDefaultStepSchema).readonly(),
|
|
19681
|
-
group: string().optional(),
|
|
19682
|
-
settings: record(string(), unknown()).optional()
|
|
19683
|
-
}));
|
|
19684
|
-
var PipelineTemplateStepSchema = lazy(() => object({
|
|
19685
|
-
addonId: string(),
|
|
19686
|
-
enabled: boolean(),
|
|
19687
|
-
modelId: string(),
|
|
19688
|
-
children: array(PipelineTemplateStepSchema).readonly(),
|
|
19689
|
-
settings: record(string(), unknown()).optional()
|
|
19690
|
-
}));
|
|
19691
|
-
var PipelineTemplateSchema$1 = object({
|
|
19692
|
-
id: string(),
|
|
19693
|
-
name: string(),
|
|
19694
|
-
createdAt: string(),
|
|
19695
|
-
updatedAt: string(),
|
|
19696
|
-
engine: PipelineEngineChoiceSchema,
|
|
19697
|
-
steps: array(PipelineTemplateStepSchema).readonly()
|
|
19698
|
-
});
|
|
19699
|
-
var PipelineModelOptionSchema = object({
|
|
19700
|
-
id: string(),
|
|
19701
|
-
name: string(),
|
|
19702
|
-
formats: record(string(), object({
|
|
19703
|
-
downloaded: boolean(),
|
|
19704
|
-
sizeMB: number()
|
|
19705
|
-
})),
|
|
19706
|
-
group: ModelVariantGroupSchema.optional(),
|
|
19707
|
-
legacy: boolean().optional(),
|
|
19708
|
-
provider: ModelProviderIdSchema.optional()
|
|
19709
|
-
});
|
|
19710
|
-
var ConfigFieldBridge = custom();
|
|
19711
|
-
var PipelineAddonSchemaSchema = object({
|
|
19712
|
-
id: string(),
|
|
19713
|
-
name: string(),
|
|
19714
|
-
slot: PipelineSlotSchema,
|
|
19715
|
-
inputClasses: array(string()).readonly(),
|
|
19716
|
-
outputClasses: array(string()).readonly(),
|
|
19717
|
-
childSlots: array(PipelineSlotSchema).readonly(),
|
|
19718
|
-
models: array(PipelineModelOptionSchema).readonly(),
|
|
19719
|
-
defaultModelId: string(),
|
|
19720
|
-
defaultModelIdByFormat: record(string(), string()).optional(),
|
|
19721
|
-
enabledByDefault: boolean().optional(),
|
|
19722
|
-
backfillIntoExistingOverrides: boolean().optional(),
|
|
19723
|
-
defaultConfidence: number(),
|
|
19724
|
-
group: string().optional(),
|
|
19725
|
-
configSchema: array(ConfigFieldBridge).readonly().optional()
|
|
19726
|
-
});
|
|
19727
|
-
var PipelineSlotSchemaSchema = object({
|
|
19728
|
-
id: PipelineSlotSchema,
|
|
19729
|
-
label: string(),
|
|
19730
|
-
priority: number(),
|
|
19731
|
-
parentSlot: PipelineSlotSchema.nullable(),
|
|
19732
|
-
addons: array(PipelineAddonSchemaSchema).readonly()
|
|
19733
|
-
});
|
|
19734
|
-
var PipelineSchemaSchema = object({
|
|
19735
|
-
availableEngines: array(AvailableEngineSchema).readonly(),
|
|
19736
|
-
selectedEngine: PipelineEngineChoiceSchema,
|
|
19737
|
-
slots: array(PipelineSlotSchemaSchema).readonly()
|
|
19738
|
-
});
|
|
19739
|
-
var EngineProvisioningSchema = object({
|
|
19740
|
-
runtimeId: _enum([
|
|
19741
|
-
"onnx",
|
|
19742
|
-
"openvino",
|
|
19743
|
-
"coreml",
|
|
19744
|
-
"edgetpu"
|
|
19745
|
-
]).nullable(),
|
|
19746
|
-
device: string().nullable(),
|
|
19747
|
-
state: _enum([
|
|
19748
|
-
"idle",
|
|
19749
|
-
"installing",
|
|
19750
|
-
"verifying",
|
|
19751
|
-
"ready",
|
|
19752
|
-
"failed"
|
|
19753
|
-
]),
|
|
19754
|
-
progress: number().optional(),
|
|
19755
|
-
error: string().optional(),
|
|
19756
|
-
nextRetryAt: number().optional(),
|
|
19757
|
-
/**
|
|
19758
|
-
* Gate A (config-correctness gate at engine change): human-readable
|
|
19759
|
-
* config issues surfaced EAGERLY when the node's engine changes — model
|
|
19760
|
-
* substitutions ("chose X, running Y") and zero-build steps ("no model
|
|
19761
|
-
* has a <format> build"). Additive/optional: informational only, never
|
|
19762
|
-
* enforced here — `assertEngineReady` (readiness) still gates inference.
|
|
19763
|
-
* Absent/empty when the node-default tree resolves cleanly.
|
|
19764
|
-
*/
|
|
19765
|
-
configIssues: array(string()).optional()
|
|
19766
|
-
});
|
|
19767
|
-
var PipelineStepInputSchema = lazy(() => object({
|
|
19768
|
-
addonId: string(),
|
|
19769
|
-
modelId: string().optional(),
|
|
19770
|
-
enabled: boolean().default(true),
|
|
19771
|
-
children: array(PipelineStepInputSchema).optional(),
|
|
19772
|
-
settings: record(string(), unknown()).optional(),
|
|
19773
|
-
jumpDeviceKey: string().optional()
|
|
19774
|
-
}));
|
|
19775
|
-
var ModelSubstitutionSchema = object({
|
|
19776
|
-
addonId: string(),
|
|
19777
|
-
chosen: string(),
|
|
19778
|
-
running: string(),
|
|
19779
|
-
format: string()
|
|
19780
|
-
});
|
|
19781
|
-
var PipelineValidationIssueSchema = object({
|
|
19782
|
-
addonId: string(),
|
|
19783
|
-
kind: _enum(["unknown-addon", "no-format-build"]),
|
|
19784
|
-
detail: string()
|
|
19785
|
-
});
|
|
19786
|
-
var PipelineValidationResultSchema = object({
|
|
19787
|
-
ok: boolean(),
|
|
19788
|
-
issues: array(PipelineValidationIssueSchema).readonly(),
|
|
19789
|
-
substitutions: array(ModelSubstitutionSchema).readonly(),
|
|
19790
|
-
/** The node's `currentEngine.format` this validation ran against. */
|
|
19791
|
-
format: string()
|
|
19792
|
-
});
|
|
19793
|
-
var ReferenceImageEntrySchema = object({
|
|
19794
|
-
filename: string(),
|
|
19795
|
-
stepIds: array(string()).readonly().optional()
|
|
19796
|
-
});
|
|
19797
|
-
var ReferenceImageBodySchema = object({
|
|
19798
|
-
base64: string(),
|
|
19799
|
-
filename: string()
|
|
19800
|
-
});
|
|
19801
|
-
var ReferenceAudioEntrySchema = object({
|
|
19802
|
-
filename: string(),
|
|
19803
|
-
sizeKb: number()
|
|
19804
|
-
});
|
|
19805
|
-
var ReferenceAudioBodySchema = object({ base64: string() });
|
|
19806
|
-
var AudioBackendSchema = object({
|
|
19807
|
-
id: string(),
|
|
19808
|
-
name: string(),
|
|
19809
|
-
description: string(),
|
|
19810
|
-
available: boolean(),
|
|
19811
|
-
/**
|
|
19812
|
-
* Raw classifier labels this backend can emit (e.g. YAMNet's
|
|
19813
|
-
* 521-class set or Apple SoundAnalysis's 303-class set). Used by
|
|
19814
|
-
* the benchmark UI to populate the `enabledMicroClasses` filter
|
|
19815
|
-
* specific to the selected backend without a separate fetch.
|
|
19816
|
-
*/
|
|
19817
|
-
rawLabels: array(string()).readonly().optional()
|
|
19818
|
-
});
|
|
19819
|
-
var AudioCapabilitiesSchema = object({
|
|
19820
|
-
activeBackend: string(),
|
|
19821
|
-
availableBackends: array(AudioBackendSchema).readonly(),
|
|
19822
|
-
sampleRate: number(),
|
|
19823
|
-
chunkDurationMs: number()
|
|
19824
|
-
});
|
|
19825
|
-
var DownloadModelResultSchema = object({
|
|
19826
|
-
filePath: string(),
|
|
19827
|
-
sizeMB: number(),
|
|
19828
|
-
durationMs: number()
|
|
19829
|
-
});
|
|
19830
|
-
/**
|
|
19831
|
-
* Wrapper carrying a single test run's result. Replaces the legacy
|
|
19832
|
-
* ad-hoc `{labels: [{className, originalClass, score}]}` shape with the
|
|
19833
|
-
* canonical `AudioResult` from the Phase 6 output rework: one
|
|
19834
|
-
* `AudioDetection` per class above `minScore`, top-N candidates in
|
|
19835
|
-
* `debug.alternateLabels['audio-classifier']`, per-source timings in
|
|
19836
|
-
* `debug.stepTimings`. The outer `success`/`error` fields stay so the
|
|
19837
|
-
* benchmark UI can still report a clean failure when the classifier
|
|
19838
|
-
* cap isn't available.
|
|
19839
|
-
*/
|
|
19840
|
-
var AudioTestResultSchema = object({
|
|
19841
|
-
success: boolean(),
|
|
19842
|
-
error: string().optional(),
|
|
19843
|
-
frame: custom().optional()
|
|
19844
|
-
});
|
|
19845
|
-
var PipelineConfigBridge = custom();
|
|
19846
|
-
var ConfigUISchemaBridge = custom();
|
|
19847
|
-
var ConfigUISchemaNullableBridge = custom();
|
|
19848
|
-
var InferenceCapabilitiesBridge = custom();
|
|
19849
|
-
var ModelAvailabilityListBridge = custom();
|
|
19850
|
-
var PipelineRunResultBridge = custom();
|
|
19851
|
-
method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
|
|
19852
|
-
modelId: string(),
|
|
19853
|
-
settings: record(string(), unknown()).readonly()
|
|
19854
|
-
}))), method(object({ steps: record(string(), object({
|
|
19855
|
-
modelId: string(),
|
|
19856
|
-
settings: record(string(), unknown()).readonly()
|
|
19857
|
-
})) }), object({ success: literal(true) }), {
|
|
19858
|
-
kind: "mutation",
|
|
19859
|
-
auth: "admin"
|
|
19860
|
-
}), method(object({ nodeId: string() }), object({
|
|
19861
|
-
success: literal(true),
|
|
19862
|
-
clearedDevices: number()
|
|
19863
|
-
}), {
|
|
19864
|
-
kind: "mutation",
|
|
19865
|
-
auth: "admin"
|
|
19866
|
-
}), method(object({ nodeId: string() }), object({ unhealthy: array(object({
|
|
19867
|
-
/** `<backend>:<device>`, e.g. `openvino:gpu`. */
|
|
19868
|
-
deviceKey: string(),
|
|
19869
|
-
/**
|
|
19870
|
-
* `failed` — the per-device restart budget is exhausted; no pool
|
|
19871
|
-
* will be spawned until an operator re-arms it or the runner
|
|
19872
|
-
* respawns. `backoff` — under budget, waiting out the backoff (or
|
|
19873
|
-
* a cached pool observed dead and not yet condemned).
|
|
19874
|
-
*/
|
|
19875
|
-
state: _enum(["failed", "backoff"]),
|
|
19876
|
-
/** Epoch ms of the death that produced this state. */
|
|
19877
|
-
since: number(),
|
|
19878
|
-
/** Pool deaths inside the current window. */
|
|
19879
|
-
deaths: number(),
|
|
19880
|
-
/** The last death's message. */
|
|
19881
|
-
lastError: string()
|
|
19882
|
-
})).readonly() })), method(object({
|
|
19883
|
-
nodeId: string(),
|
|
19884
|
-
deviceKey: string()
|
|
19885
|
-
}), object({ rearmed: boolean() }), {
|
|
19886
|
-
kind: "mutation",
|
|
19887
|
-
auth: "admin"
|
|
19888
|
-
}), 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({
|
|
19889
|
-
name: string(),
|
|
19890
|
-
steps: array(PipelineTemplateStepSchema).readonly(),
|
|
19891
|
-
engine: PipelineEngineChoiceSchema
|
|
19892
|
-
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({
|
|
19893
|
-
id: string(),
|
|
19894
|
-
name: string().optional(),
|
|
19895
|
-
steps: array(PipelineTemplateStepSchema).readonly().optional()
|
|
19896
|
-
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({ id: string() }), _void(), { kind: "mutation" }), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
|
|
19897
|
-
addonId: string(),
|
|
19898
|
-
modelId: string(),
|
|
19899
|
-
format: ModelFormatSchema$1
|
|
19900
|
-
}), DownloadModelResultSchema, { kind: "mutation" }), method(object({
|
|
19901
|
-
addonId: string(),
|
|
19902
|
-
modelId: string(),
|
|
19903
|
-
format: ModelFormatSchema$1
|
|
19904
|
-
}), object({ success: literal(true) }), { kind: "mutation" }), method(object({
|
|
19905
|
-
engine: PipelineEngineChoiceSchema.optional(),
|
|
19906
|
-
steps: array(PipelineStepInputSchema).min(1),
|
|
19907
|
-
frame: FrameInputSchema.optional(),
|
|
19908
|
-
/**
|
|
19909
|
-
* Process-local lazy frame. Valid only when caller and provider resolve
|
|
19910
|
-
* in the same execution-group process; split/cross-node callers use
|
|
19911
|
-
* `frame`/`image` inline compatibility instead.
|
|
19912
|
-
*/
|
|
19913
|
-
frameRef: FrameRefSchema.optional(),
|
|
19914
|
-
/**
|
|
19915
|
-
* CB5 shm passthrough — a `FrameHandle` naming the same ring slot
|
|
19916
|
-
* the decoded pixels live in. One more member of the one-of
|
|
19917
|
-
* frame/frameHandle/image/imageBase64/referenceImage group.
|
|
19918
|
-
*/
|
|
19919
|
-
frameHandle: FrameHandleSchema.optional(),
|
|
19920
|
-
imageBase64: string().optional(),
|
|
19921
|
-
/**
|
|
19922
|
-
* Binary JPEG bytes — preferred over `imageBase64` on internal
|
|
19923
|
-
* hops (hub → forked worker via Moleculer MsgPack) because it
|
|
19924
|
-
* skips the 33% base64 overhead + the per-call base64 decode on
|
|
19925
|
-
* the detection-pipeline worker. Callers can pass either; exactly
|
|
19926
|
-
* one of `frame`/`image`/`imageBase64`/`referenceImage` is required.
|
|
19927
|
-
*/
|
|
19928
|
-
image: _instanceof(Uint8Array).optional(),
|
|
19929
|
-
referenceImage: string().optional(),
|
|
19930
|
-
deviceId: number().optional(),
|
|
19931
|
-
sessionId: string().optional(),
|
|
19932
|
-
/**
|
|
19933
|
-
* Execution plane. 'full' (default) runs the whole tree — benchmark,
|
|
19934
|
-
* reference-image, and detail-subtree calls. 'frame' is the live
|
|
19935
|
-
* per-frame dispatch: ONLY root-plane steps run; crop children
|
|
19936
|
-
* (inputClasses ≠ null) are skipped and served per-track via
|
|
19937
|
-
* pipelineRunner.runDetailSubtree (two-plane design).
|
|
19938
|
-
*/
|
|
19939
|
-
plane: _enum(["full", "frame"]).optional(),
|
|
19940
|
-
/**
|
|
19941
|
-
* Inference-device selector (Phase 2 multi-device). Format
|
|
19942
|
-
* `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
|
|
19943
|
-
* Omitted ⇒ the runner's default device (current single-engine
|
|
19944
|
-
* behaviour). Selects WHICH device pool of the node runs the call.
|
|
19945
|
-
*/
|
|
19946
|
-
deviceKey: string().optional(),
|
|
19947
|
-
/**
|
|
19948
|
-
* Two-plane NATIVE child-crop reference. Set by `runDetailSubtree` ONLY
|
|
19949
|
-
* when the parent crop was resolved from the frame's retained NATIVE
|
|
19950
|
-
* surface (a frameHandle HIT). Lets the executor re-cut a LEAF crop
|
|
19951
|
-
* child's ROI (plate-ocr, face-embedding, leaf classifiers) at native
|
|
19952
|
-
* resolution from that surface — the SAME quality path faces already
|
|
19953
|
-
* had — instead of the downscaled parent tile. `handle` keys the native
|
|
19954
|
-
* surface (node-pinned to its owner); `cropFrameSpace` is the parent
|
|
19955
|
-
* crop's padded/clamped rectangle in FRAME-space pixels, used to compose
|
|
19956
|
-
* the executor's crop-normalized child ROI back into frame-normalized
|
|
19957
|
-
* coordinates. Auxiliary to the image source (`image`/`frame`/…), NOT one
|
|
19958
|
-
* of the mutually-exclusive image inputs. Absent ⇒ tile-crop children
|
|
19959
|
-
* (today's behaviour on the fallback path).
|
|
19960
|
-
*/
|
|
19961
|
-
nativeCropRef: NativeCropRefSchema.optional()
|
|
19962
|
-
}), PipelineRunResultBridge, { kind: "mutation" }), method(object({
|
|
19963
|
-
engine: PipelineEngineChoiceSchema.optional(),
|
|
19964
|
-
steps: array(PipelineStepInputSchema).min(1),
|
|
19965
|
-
frames: array(FrameInputSchema).min(1).max(255),
|
|
19966
|
-
deviceId: number().optional(),
|
|
19967
|
-
sessionId: string().optional(),
|
|
19968
|
-
/**
|
|
19969
|
-
* Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
|
|
19970
|
-
* the batch to the Python pool's bench preprocess cache
|
|
19971
|
-
* (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
|
|
19972
|
-
* preprocessed ONCE and every later inference is a pure-inference cache
|
|
19973
|
-
* hit — the sustained-throughput run measures inference, not
|
|
19974
|
-
* decode+preprocess+infer. Omitted/0 for live frames (all different →
|
|
19975
|
-
* full preprocess every call, correct). Fresh per sustained run;
|
|
19976
|
-
* released via `uncacheFrame`.
|
|
19977
|
-
*/
|
|
19978
|
-
frameId: number().int().nonnegative().optional(),
|
|
19979
|
-
/** Inference-device selector (Phase 2 multi-device); see runPipeline. */
|
|
19980
|
-
deviceKey: string().optional()
|
|
19981
|
-
}), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
|
|
19982
|
-
data: _instanceof(Uint8Array),
|
|
19983
|
-
width: number().int().positive(),
|
|
19984
|
-
height: number().int().positive(),
|
|
19985
|
-
format: _enum([
|
|
19986
|
-
"rgb",
|
|
19987
|
-
"bgr",
|
|
19988
|
-
"gray"
|
|
19989
|
-
])
|
|
19990
|
-
}), object({
|
|
19991
|
-
frameId: number(),
|
|
19992
|
-
width: number(),
|
|
19993
|
-
height: number()
|
|
19994
|
-
}), { kind: "mutation" }), method(object({
|
|
19995
|
-
stepId: string(),
|
|
19996
|
-
frameId: number().int()
|
|
19997
|
-
}), record(string(), unknown()), { kind: "mutation" }), method(object({ frameId: number().int() }), _void(), { kind: "mutation" }), method(_void(), object({
|
|
19998
|
-
batchMode: string(),
|
|
19999
|
-
windowMs: number(),
|
|
20000
|
-
maxBatchSize: number(),
|
|
20001
|
-
concurrency: number()
|
|
20002
|
-
})), method(_void(), array(object({
|
|
20003
|
-
engineKey: string(),
|
|
20004
|
-
engine: PipelineEngineChoiceSchema,
|
|
20005
|
-
modelsLoaded: array(string()).readonly(),
|
|
20006
|
-
inUseByCameras: array(number()).readonly(),
|
|
20007
|
-
/**
|
|
20008
|
-
* Origin of this resident factory.
|
|
20009
|
-
* - `runtime` — main camera-serving engine (no idle TTL).
|
|
20010
|
-
* - `warm-override` — benchmark/test override held in the warm
|
|
20011
|
-
* cache; auto-disposed after the idle TTL.
|
|
20012
|
-
* - `device-pool` — a concurrent per-device pool (Phase 2
|
|
20013
|
-
* multi-device, keyed by `deviceKey`) resolved
|
|
20014
|
-
* via `resolveDeviceFactory`. Runs alongside the
|
|
20015
|
-
* `runtime` engine on a DIFFERENT accelerator
|
|
20016
|
-
* (NPU / iGPU / Coral) — this is how the
|
|
20017
|
-
* Engines tab shows all pools running at once.
|
|
20018
|
-
*/
|
|
20019
|
-
kind: _enum([
|
|
20020
|
-
"runtime",
|
|
20021
|
-
"warm-override",
|
|
20022
|
-
"device-pool"
|
|
20023
|
-
]),
|
|
20024
|
-
/** Native pid of the underlying Python pool (null when no pool). */
|
|
20025
|
-
poolPid: number().nullable(),
|
|
20026
|
-
/** ms since this factory was last used (null when not warm-tracked). */
|
|
20027
|
-
idleMs: number().nullable(),
|
|
20028
|
-
/** Idle TTL after which `warm-override` factories self-evict (null when not applicable). */
|
|
20029
|
-
idleTtlMs: number().nullable()
|
|
20030
|
-
})).readonly()), method(object({ engine: PipelineEngineChoiceSchema }), object({ success: literal(true) }), {
|
|
20031
|
-
kind: "mutation",
|
|
20032
|
-
auth: "admin"
|
|
20033
|
-
}), method(object({
|
|
20034
|
-
engine: PipelineEngineChoiceSchema,
|
|
20035
|
-
force: boolean().optional()
|
|
20036
|
-
}), object({
|
|
20037
|
-
success: boolean(),
|
|
20038
|
-
reason: string().optional()
|
|
20039
|
-
}), {
|
|
20040
|
-
kind: "mutation",
|
|
20041
|
-
auth: "admin"
|
|
20042
|
-
}), 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({
|
|
20043
|
-
addonId: string(),
|
|
20044
|
-
modelId: string(),
|
|
20045
|
-
filename: string().optional(),
|
|
20046
|
-
settings: record(string(), unknown()).optional()
|
|
20047
|
-
}), AudioTestResultSchema, { kind: "mutation" }), method(_void(), ConfigUISchemaNullableBridge);
|
|
20048
|
-
/**
|
|
20049
|
-
* Per-stage gating mode applied to the zones a rule references.
|
|
20050
|
-
*
|
|
20051
|
-
* - `include`: the rule contributes to a **whitelist** for its stage.
|
|
20052
|
-
* When at least one `include` rule fires for a stage, only entities
|
|
20053
|
-
* inside one of those zones pass that stage.
|
|
20054
|
-
* - `exclude`: the rule contributes to a **blacklist** for its stage.
|
|
20055
|
-
* Entities inside one of those zones are dropped at that stage.
|
|
20056
|
-
*
|
|
20057
|
-
* `monitor`-style observation (count without filtering) is not a rule
|
|
20058
|
-
* mode — zones without any matching rule are observed naturally by
|
|
20059
|
-
* `zone-analytics` (live snapshot + history), so an "I just want to
|
|
20060
|
-
* count, not filter" use case needs no rule at all.
|
|
20061
|
-
*/
|
|
20062
|
-
var ZoneRuleModeEnum = _enum(["include", "exclude"]);
|
|
20063
|
-
/**
|
|
20064
|
-
* Per-consumer rule that references existing zones (geometry) and
|
|
20065
|
-
* defines how a specific pipeline stage should treat them. Each
|
|
20066
|
-
* consumer addon owns its own `ZoneRule[]` array in its per-device
|
|
20067
|
-
* settings:
|
|
20068
|
-
*
|
|
20069
|
-
* - `addon-motion-wasm` → `motionZoneRules: ZoneRule[]` (motion stage)
|
|
20070
|
-
* - `addon-detection-pipeline` → `detectionZoneRules: ZoneRule[]` (detection stage)
|
|
20071
|
-
* - future: notification rules, audio gating, etc.
|
|
20072
|
-
*
|
|
20073
|
-
* One rule applies to N zones (`zoneIds[]`) so the operator can
|
|
20074
|
-
* express "ignore motion in ALL of {garden, street}" with a single
|
|
20075
|
-
* rule. `classFilter` narrows the rule to specific object classes —
|
|
20076
|
-
* "drop person detections in the street, but keep cars" is one
|
|
20077
|
-
* `exclude` rule with `classFilter: ['person']`.
|
|
20078
|
-
*
|
|
20079
|
-
* `enabled` is a soft toggle — the operator can keep the rule
|
|
20080
|
-
* configured but inert without deleting it.
|
|
20081
|
-
*/
|
|
20082
|
-
var ZoneRuleSchema = object({
|
|
20083
|
-
/** Stable rule id — survives edits, used by the UI for diffing. */
|
|
20084
|
-
id: string(),
|
|
20085
|
-
/** Optional human-readable label rendered in the rule editor. */
|
|
20086
|
-
name: string().optional(),
|
|
20087
|
-
/** Zones this rule targets. The rule's `mode` applies to ALL
|
|
20088
|
-
* listed zones (OR-set: a detection in any one of them counts).
|
|
20089
|
-
* At least one zone id required — a rule with no targets is a
|
|
20090
|
-
* configuration mistake and the form validator rejects it. */
|
|
20091
|
-
zoneIds: array(string()).min(1).readonly(),
|
|
20092
|
-
mode: ZoneRuleModeEnum,
|
|
20093
|
-
/**
|
|
20094
|
-
* Class names this rule applies to. Empty / undefined ⇒ rule
|
|
20095
|
-
* applies to every class. Class strings match the `macroClass`
|
|
20096
|
-
* field on detections (e.g. `person`, `car`, `dog`).
|
|
20097
|
-
*/
|
|
20098
|
-
classFilter: array(string()).readonly().optional(),
|
|
20099
|
-
/**
|
|
20100
|
-
* Minimum bbox/mask overlap (0–1) with any of the rule's zones
|
|
20101
|
-
* required to consider an entity "in the zone". Defaults to the
|
|
20102
|
-
* consumer's stage default when omitted. Kept for back-compat with
|
|
20103
|
-
* existing per-rule overrides; new operators pick the value via
|
|
20104
|
-
* `bboxInclusionPct` (operator-friendly 0–100). Whichever field is
|
|
20105
|
-
* set, the lower-level engine reads it as a 0–1 fraction.
|
|
20106
|
-
*/
|
|
20107
|
-
overlapThreshold: number().min(0).max(1).optional(),
|
|
20108
|
-
/**
|
|
20109
|
-
* Operator-friendly version of `overlapThreshold` — the percentage
|
|
20110
|
-
* of the detection's bbox that must lie inside the zone for the
|
|
20111
|
-
* rule to match. Documented default is 85%; the engine substitutes
|
|
20112
|
-
* that when the field is omitted (kept optional so existing rules
|
|
20113
|
-
* stored without it stay valid).
|
|
20114
|
-
*
|
|
20115
|
-
* When BOTH `overlapThreshold` and `bboxInclusionPct` are set on a
|
|
20116
|
-
* rule, the engine prefers `bboxInclusionPct` because it's the
|
|
20117
|
-
* field exposed in the UI. Internally both feed the same gate.
|
|
20118
|
-
*/
|
|
20119
|
-
bboxInclusionPct: number().min(0).max(100).optional(),
|
|
20120
|
-
/**
|
|
20121
|
-
* When `true` and a detection has a segmentation mask, use the
|
|
20122
|
-
* mask for overlap instead of the bbox. Detection-stage only;
|
|
20123
|
-
* motion rules ignore this field.
|
|
20124
|
-
*/
|
|
20125
|
-
preferMask: boolean().optional(),
|
|
20126
|
-
/**
|
|
20127
|
-
* Soft-toggle: `false` disables the rule without deleting it.
|
|
20128
|
-
* Defaults to `true` so operators creating a rule via the UI
|
|
20129
|
-
* see it active immediately.
|
|
20130
|
-
*/
|
|
20131
|
-
enabled: boolean().default(true)
|
|
20132
|
-
});
|
|
20133
|
-
array(ZoneRuleSchema).readonly();
|
|
20134
|
-
/**
|
|
20135
|
-
* Zone — pure geometry + identity. NO filtering behaviour.
|
|
20136
|
-
*
|
|
20137
|
-
* Zones describe **where** in the frame the operator wants to flag
|
|
20138
|
-
* something; consumer-owned {@link ZoneRule} arrays describe **how**
|
|
20139
|
-
* each pipeline stage uses them. Splitting the two means a single
|
|
20140
|
-
* polygon "Driveway" can simultaneously back a motion-exclude rule,
|
|
20141
|
-
* a detection-include rule on `['car']`, and an occupancy aggregate
|
|
20142
|
-
* — without three duplicated polygons.
|
|
20143
|
-
*
|
|
20144
|
-
* Owned by the orchestrator addon (provider) and mirrored into the
|
|
20145
|
-
* `zones` device-state slice on every mutation. Consumers
|
|
20146
|
-
* (motion-wasm, pipeline-executor, analytics, admin UI) read either
|
|
20147
|
-
* via `api.zones.listZones` (one-shot) or via `dev.state.zones` (live
|
|
20148
|
-
* mirror with `onChanged`).
|
|
20149
|
-
*
|
|
20150
|
-
* Coordinates are normalised fractions of the frame (0–1) so zones
|
|
20151
|
-
* survive resolution changes and stream profile switches.
|
|
20152
|
-
*
|
|
20153
|
-
* `kind` discriminates between full polygons (closed regions used
|
|
20154
|
-
* for intrusion / occupancy filters) and tripwires (open 2-point
|
|
20155
|
-
* line segments used for cross events). Onboard / firmware-reported
|
|
20156
|
-
* zones (Reolink, ONVIF) are out of scope for now — see the deferred
|
|
20157
|
-
* task list.
|
|
20158
|
-
*/
|
|
20159
|
-
var ZoneKindEnum = _enum(["polygon", "tripwire"]);
|
|
20160
|
-
/** Polygon vertex in fraction-of-frame coordinates (0–1). */
|
|
20161
|
-
var PolygonPointSchema = object({
|
|
20162
|
-
x: number(),
|
|
20163
|
-
y: number()
|
|
20164
|
-
});
|
|
20165
|
-
/** A camera detection zone — pure geometry/identity. */
|
|
20166
|
-
var ZoneSchema = object({
|
|
20167
|
-
id: string(),
|
|
20168
|
-
name: string(),
|
|
20169
|
-
kind: ZoneKindEnum.default("polygon"),
|
|
20170
|
-
/** Polygon vertices, fraction of frame (0–1). */
|
|
20171
|
-
polygon: array(PolygonPointSchema).readonly(),
|
|
20172
|
-
/** Visual color for UI rendering. */
|
|
20173
|
-
color: string().default("#3b82f6")
|
|
20174
|
-
});
|
|
20175
|
-
DeviceType.Camera, method(object({ deviceId: number() }), array(ZoneSchema).readonly()), method(object({
|
|
20176
|
-
deviceId: number(),
|
|
20177
|
-
zone: ZoneSchema
|
|
20178
|
-
}), _void(), {
|
|
20179
|
-
kind: "mutation",
|
|
20180
|
-
auth: "admin"
|
|
20181
|
-
}), method(object({
|
|
20182
|
-
deviceId: number(),
|
|
20183
|
-
zoneId: string()
|
|
20184
|
-
}), _void(), {
|
|
20185
|
-
kind: "mutation",
|
|
20186
|
-
auth: "admin"
|
|
20187
|
-
}), method(object({
|
|
20188
|
-
deviceId: number(),
|
|
20189
|
-
zone: ZoneSchema
|
|
20190
|
-
}), _void(), {
|
|
20191
|
-
kind: "mutation",
|
|
20192
|
-
auth: "admin"
|
|
20193
|
-
}), object({ zones: array(ZoneSchema).readonly() });
|
|
20194
|
-
/**
|
|
20195
19774
|
* pipeline-analytics — device-scoped wrapper cap. Refines raw
|
|
20196
19775
|
* per-frame detections emitted by the pipeline runner into tracked
|
|
20197
19776
|
* objects, per-kind event collections (motion / object / audio), and
|
|
@@ -20762,6 +20341,22 @@ var TrackSchema = object({
|
|
|
20762
20341
|
* omit it. Render nothing when absent.
|
|
20763
20342
|
*/
|
|
20764
20343
|
previewMissReason: string().optional(),
|
|
20344
|
+
/**
|
|
20345
|
+
* The ROOT model that produced this track — the `FrameResult.rootModelId` of
|
|
20346
|
+
* the frame it was BORN on (D646). What a later replay compares against, so
|
|
20347
|
+
* "the original model" is named rather than assumed. A birth fact: never
|
|
20348
|
+
* rewritten by a later frame. **Absent ≠ unknown-model**: a row from before
|
|
20349
|
+
* the column, and a track the camera's own detector produced, carry none.
|
|
20350
|
+
*/
|
|
20351
|
+
modelId: string().optional(),
|
|
20352
|
+
/**
|
|
20353
|
+
* Size (px) of the detection frame this track's `positions[].bbox` live in —
|
|
20354
|
+
* the frame it was born on, else the camera's latest analysis frame at
|
|
20355
|
+
* persist time. Divide a position by these to normalise it. Absent when the
|
|
20356
|
+
* size was never known.
|
|
20357
|
+
*/
|
|
20358
|
+
frameWidth: number().optional(),
|
|
20359
|
+
frameHeight: number().optional(),
|
|
20765
20360
|
...TrackFlagFields,
|
|
20766
20361
|
...TrackRetrainFields
|
|
20767
20362
|
});
|
|
@@ -21768,24 +21363,6 @@ var MediaReclaimStatusSchema = object({
|
|
|
21768
21363
|
finishedAtMs: number().nullable(),
|
|
21769
21364
|
error: string().nullable()
|
|
21770
21365
|
});
|
|
21771
|
-
var ReplayFrameInputSchema = object({
|
|
21772
|
-
timestamp: number(),
|
|
21773
|
-
frame: PipelineRunResultBridge
|
|
21774
|
-
});
|
|
21775
|
-
var RunReplayFrameProcessorResultSchema = object({ tracks: array(object({
|
|
21776
|
-
className: string(),
|
|
21777
|
-
firstSeenMs: number(),
|
|
21778
|
-
lastSeenMs: number(),
|
|
21779
|
-
/** Bbox of the track's FIRST matched detection, pixel-space in the clip's
|
|
21780
|
-
* frame — a representative box for the diff's `(className, window, IoU)`
|
|
21781
|
-
* pairing (`replay-diff.ts`). A replay does not need the full per-frame
|
|
21782
|
-
* trajectory production's `Track.positions` keeps. */
|
|
21783
|
-
bbox: BoundingBoxSchema,
|
|
21784
|
-
/** How many of the input frames this track matched a real detection on
|
|
21785
|
-
* (never a coasted/extrapolated frame) — the replay's own signal for "how
|
|
21786
|
-
* solid is this track", cheaper than re-deriving it from a trajectory. */
|
|
21787
|
-
framesMatched: number().int()
|
|
21788
|
-
})).readonly() });
|
|
21789
21366
|
/**
|
|
21790
21367
|
* The long-term series a camera produces. A closed union so a typo cannot
|
|
21791
21368
|
* invent one, and the ONE declaration of it — the addon's `AnalyticsLtsSeries`
|
|
@@ -21999,108 +21576,570 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21999
21576
|
}), {
|
|
22000
21577
|
kind: "mutation",
|
|
22001
21578
|
auth: "admin"
|
|
22002
|
-
}), method(object({ frameId: string() }), object({
|
|
22003
|
-
base64: string(),
|
|
22004
|
-
width: number().int(),
|
|
22005
|
-
height: number().int()
|
|
21579
|
+
}), method(object({ frameId: string() }), object({
|
|
21580
|
+
base64: string(),
|
|
21581
|
+
width: number().int(),
|
|
21582
|
+
height: number().int()
|
|
21583
|
+
}), {
|
|
21584
|
+
kind: "query",
|
|
21585
|
+
auth: "admin"
|
|
21586
|
+
}), method(object({
|
|
21587
|
+
deviceId: number(),
|
|
21588
|
+
trackId: string(),
|
|
21589
|
+
frameId: string(),
|
|
21590
|
+
subject: RetrainAssistSubjectSchema,
|
|
21591
|
+
/** Which node runs it. Absent ⇒ wherever an unowned call lands. */
|
|
21592
|
+
nodeId: string().optional()
|
|
21593
|
+
}), RetrainAssistResultSchema, {
|
|
21594
|
+
kind: "mutation",
|
|
21595
|
+
auth: "admin"
|
|
21596
|
+
}), method(object({ trackId: string() }), array(RetrainAnnotationSchema).readonly(), {
|
|
21597
|
+
kind: "query",
|
|
21598
|
+
auth: "admin"
|
|
21599
|
+
}), method(object({
|
|
21600
|
+
deviceId: number(),
|
|
21601
|
+
trackId: string(),
|
|
21602
|
+
frameId: string(),
|
|
21603
|
+
annotations: array(RetrainAnnotationDraftSchema)
|
|
21604
|
+
}), array(RetrainAnnotationSchema).readonly(), {
|
|
21605
|
+
kind: "mutation",
|
|
21606
|
+
auth: "admin"
|
|
21607
|
+
}), method(object({
|
|
21608
|
+
deviceId: number(),
|
|
21609
|
+
trackId: string()
|
|
21610
|
+
}), RetrainTransitionResultSchema, {
|
|
21611
|
+
kind: "mutation",
|
|
21612
|
+
auth: "admin"
|
|
21613
|
+
}), method(object({
|
|
21614
|
+
deviceId: number(),
|
|
21615
|
+
trackId: string()
|
|
21616
|
+
}), RetrainTransitionResultSchema, {
|
|
21617
|
+
kind: "mutation",
|
|
21618
|
+
auth: "admin"
|
|
21619
|
+
}), method(object({ deviceIds: array(number()).optional() }), object({ url: string() }), {
|
|
21620
|
+
kind: "query",
|
|
21621
|
+
auth: "admin"
|
|
21622
|
+
}), method(object({
|
|
21623
|
+
/** Which of the three event tables owns the row. */
|
|
21624
|
+
ownerType: EventOwnerTypeSchema,
|
|
21625
|
+
/** The event's rowid in that table (D474: an event id is a number). */
|
|
21626
|
+
eventId: number().int(),
|
|
21627
|
+
kind: MediaFileKindEnum.optional(),
|
|
21628
|
+
deviceId: number()
|
|
21629
|
+
}), array(MediaFileSchema).readonly()), method(object({
|
|
21630
|
+
trackId: string(),
|
|
21631
|
+
kinds: array(MediaFileKindEnum).optional(),
|
|
21632
|
+
deviceId: number()
|
|
21633
|
+
}), array(MediaFileSchema).readonly()), method(object({
|
|
21634
|
+
trackId: string(),
|
|
21635
|
+
deviceId: number()
|
|
21636
|
+
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
21637
|
+
ownerType: EventOwnerTypeSchema,
|
|
21638
|
+
eventId: number().int(),
|
|
21639
|
+
deviceId: number()
|
|
21640
|
+
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
21641
|
+
deviceId: number(),
|
|
21642
|
+
ownerKind: MediaPresenceOwnerKindSchema,
|
|
21643
|
+
ownerIds: array(string()).max(5e3)
|
|
21644
|
+
}), array(string()).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
21645
|
+
kind: "mutation",
|
|
21646
|
+
auth: "admin"
|
|
21647
|
+
}), method(RebuildObjectEmbeddingsInput, RebuildObjectEmbeddingsResultSchema, {
|
|
21648
|
+
kind: "mutation",
|
|
21649
|
+
auth: "admin"
|
|
21650
|
+
}), method(object({}), RebuildStatusSchema), object({
|
|
21651
|
+
deviceId: number(),
|
|
21652
|
+
timestamp: number(),
|
|
21653
|
+
frameWidth: number(),
|
|
21654
|
+
frameHeight: number(),
|
|
21655
|
+
detections: array(OverlayDetectionSchema).readonly()
|
|
21656
|
+
}), object({
|
|
21657
|
+
deviceId: number(),
|
|
21658
|
+
trackId: string(),
|
|
21659
|
+
className: string()
|
|
21660
|
+
}), object({
|
|
21661
|
+
deviceId: number(),
|
|
21662
|
+
trackId: string(),
|
|
21663
|
+
className: string(),
|
|
21664
|
+
durationMs: number()
|
|
21665
|
+
}), object({
|
|
21666
|
+
deviceId: number(),
|
|
21667
|
+
kind: EventKindSchema,
|
|
21668
|
+
eventId: string(),
|
|
21669
|
+
timestamp: number()
|
|
21670
|
+
});
|
|
21671
|
+
/**
|
|
21672
|
+
* Reference to the frame's retained NATIVE surface + the parent crop's placement
|
|
21673
|
+
* within the frame, so the executor can re-cut a leaf child ROI at native
|
|
21674
|
+
* resolution on the detail plane. See the `runPipeline` `nativeCropRef` field.
|
|
21675
|
+
*/
|
|
21676
|
+
var NativeCropRefSchema = object({
|
|
21677
|
+
/** Handle keying the retained native surface (node-pinned to its owner). */
|
|
21678
|
+
handle: FrameHandleSchema,
|
|
21679
|
+
/** The parent crop's padded/clamped rectangle in FRAME-space pixels. */
|
|
21680
|
+
cropFrameSpace: object({
|
|
21681
|
+
x: number(),
|
|
21682
|
+
y: number(),
|
|
21683
|
+
w: number(),
|
|
21684
|
+
h: number()
|
|
21685
|
+
})
|
|
21686
|
+
});
|
|
21687
|
+
object({
|
|
21688
|
+
crop: object({
|
|
21689
|
+
left: number(),
|
|
21690
|
+
top: number(),
|
|
21691
|
+
width: number().positive(),
|
|
21692
|
+
height: number().positive()
|
|
21693
|
+
}).optional(),
|
|
21694
|
+
content: object({
|
|
21695
|
+
width: number().int().positive(),
|
|
21696
|
+
height: number().int().positive()
|
|
21697
|
+
}),
|
|
21698
|
+
fit: _enum(["stretch", "contain"]),
|
|
21699
|
+
format: _enum([
|
|
21700
|
+
"rgb",
|
|
21701
|
+
"gray",
|
|
21702
|
+
"jpeg"
|
|
21703
|
+
])
|
|
21704
|
+
});
|
|
21705
|
+
/**
|
|
21706
|
+
* Process-local frame identity. It is serializable so it can ride an in-process
|
|
21707
|
+
* capability call, but `registryId` deliberately prevents resolution in any
|
|
21708
|
+
* other process or execution group.
|
|
21709
|
+
*/
|
|
21710
|
+
var FrameRefSchema = object({
|
|
21711
|
+
registryId: string().min(1),
|
|
21712
|
+
id: string().min(1),
|
|
21713
|
+
width: number().int().positive(),
|
|
21714
|
+
height: number().int().positive(),
|
|
21715
|
+
format: _enum(["rgb", "gray"]),
|
|
21716
|
+
timestamp: number(),
|
|
21717
|
+
capturedAt: number().optional()
|
|
21718
|
+
});
|
|
21719
|
+
var ModelFormatSchema$1 = _enum([
|
|
21720
|
+
"onnx",
|
|
21721
|
+
"coreml",
|
|
21722
|
+
"openvino",
|
|
21723
|
+
"tflite",
|
|
21724
|
+
"pt",
|
|
21725
|
+
"gguf"
|
|
21726
|
+
]);
|
|
21727
|
+
var PipelineSlotSchema = _enum([
|
|
21728
|
+
"detector",
|
|
21729
|
+
"cropper",
|
|
21730
|
+
"classifier",
|
|
21731
|
+
"refiner",
|
|
21732
|
+
"audio-classifier"
|
|
21733
|
+
]);
|
|
21734
|
+
var PipelineEngineChoiceSchema = object({
|
|
21735
|
+
runtime: literal("python"),
|
|
21736
|
+
backend: string(),
|
|
21737
|
+
format: ModelFormatSchema$1,
|
|
21738
|
+
device: string().optional()
|
|
21739
|
+
});
|
|
21740
|
+
/**
|
|
21741
|
+
* One pool's resolved provisioning (`getEffectiveTuning`). `numWorkers` is the
|
|
21742
|
+
* knob that lifts a saturated pool (`inference-devices.md`); `concurrency` is
|
|
21743
|
+
* per-worker in-flight requests. `deviceKey` echoes the pool asked about —
|
|
21744
|
+
* `null` for the node-default pool.
|
|
21745
|
+
*/
|
|
21746
|
+
var EffectiveTuningSchema = object({
|
|
21747
|
+
deviceKey: string().nullable(),
|
|
21748
|
+
runtime: string(),
|
|
21749
|
+
batchMode: string(),
|
|
21750
|
+
windowMs: number(),
|
|
21751
|
+
maxBatchSize: number(),
|
|
21752
|
+
concurrency: number(),
|
|
21753
|
+
numWorkers: number()
|
|
21754
|
+
});
|
|
21755
|
+
var AvailableEngineSchema = object({
|
|
21756
|
+
engine: PipelineEngineChoiceSchema,
|
|
21757
|
+
devices: array(object({
|
|
21758
|
+
id: string(),
|
|
21759
|
+
label: string(),
|
|
21760
|
+
description: string().optional()
|
|
21761
|
+
})).readonly(),
|
|
21762
|
+
defaultDevice: string()
|
|
21763
|
+
});
|
|
21764
|
+
var PipelineDefaultStepSchema = lazy(() => object({
|
|
21765
|
+
addonId: string(),
|
|
21766
|
+
addonName: string(),
|
|
21767
|
+
slot: PipelineSlotSchema,
|
|
21768
|
+
inputClasses: array(string()).readonly(),
|
|
21769
|
+
outputClasses: array(string()).readonly(),
|
|
21770
|
+
enabled: boolean(),
|
|
21771
|
+
modelId: string(),
|
|
21772
|
+
children: array(PipelineDefaultStepSchema).readonly(),
|
|
21773
|
+
group: string().optional(),
|
|
21774
|
+
settings: record(string(), unknown()).optional()
|
|
21775
|
+
}));
|
|
21776
|
+
var PipelineTemplateStepSchema = lazy(() => object({
|
|
21777
|
+
addonId: string(),
|
|
21778
|
+
enabled: boolean(),
|
|
21779
|
+
modelId: string(),
|
|
21780
|
+
children: array(PipelineTemplateStepSchema).readonly(),
|
|
21781
|
+
settings: record(string(), unknown()).optional()
|
|
21782
|
+
}));
|
|
21783
|
+
var PipelineTemplateSchema$1 = object({
|
|
21784
|
+
id: string(),
|
|
21785
|
+
name: string(),
|
|
21786
|
+
createdAt: string(),
|
|
21787
|
+
updatedAt: string(),
|
|
21788
|
+
engine: PipelineEngineChoiceSchema,
|
|
21789
|
+
steps: array(PipelineTemplateStepSchema).readonly()
|
|
21790
|
+
});
|
|
21791
|
+
var PipelineModelOptionSchema = object({
|
|
21792
|
+
id: string(),
|
|
21793
|
+
name: string(),
|
|
21794
|
+
formats: record(string(), object({
|
|
21795
|
+
downloaded: boolean(),
|
|
21796
|
+
sizeMB: number()
|
|
21797
|
+
})),
|
|
21798
|
+
group: ModelVariantGroupSchema.optional(),
|
|
21799
|
+
legacy: boolean().optional(),
|
|
21800
|
+
provider: ModelProviderIdSchema.optional()
|
|
21801
|
+
});
|
|
21802
|
+
var ConfigFieldBridge = custom();
|
|
21803
|
+
var PipelineAddonSchemaSchema = object({
|
|
21804
|
+
id: string(),
|
|
21805
|
+
name: string(),
|
|
21806
|
+
slot: PipelineSlotSchema,
|
|
21807
|
+
inputClasses: array(string()).readonly(),
|
|
21808
|
+
outputClasses: array(string()).readonly(),
|
|
21809
|
+
childSlots: array(PipelineSlotSchema).readonly(),
|
|
21810
|
+
models: array(PipelineModelOptionSchema).readonly(),
|
|
21811
|
+
defaultModelId: string(),
|
|
21812
|
+
defaultModelIdByFormat: record(string(), string()).optional(),
|
|
21813
|
+
enabledByDefault: boolean().optional(),
|
|
21814
|
+
backfillIntoExistingOverrides: boolean().optional(),
|
|
21815
|
+
defaultConfidence: number(),
|
|
21816
|
+
group: string().optional(),
|
|
21817
|
+
configSchema: array(ConfigFieldBridge).readonly().optional()
|
|
21818
|
+
});
|
|
21819
|
+
var PipelineSlotSchemaSchema = object({
|
|
21820
|
+
id: PipelineSlotSchema,
|
|
21821
|
+
label: string(),
|
|
21822
|
+
priority: number(),
|
|
21823
|
+
parentSlot: PipelineSlotSchema.nullable(),
|
|
21824
|
+
addons: array(PipelineAddonSchemaSchema).readonly()
|
|
21825
|
+
});
|
|
21826
|
+
var PipelineSchemaSchema = object({
|
|
21827
|
+
availableEngines: array(AvailableEngineSchema).readonly(),
|
|
21828
|
+
selectedEngine: PipelineEngineChoiceSchema,
|
|
21829
|
+
slots: array(PipelineSlotSchemaSchema).readonly()
|
|
21830
|
+
});
|
|
21831
|
+
var EngineProvisioningSchema = object({
|
|
21832
|
+
runtimeId: _enum([
|
|
21833
|
+
"onnx",
|
|
21834
|
+
"openvino",
|
|
21835
|
+
"coreml",
|
|
21836
|
+
"edgetpu"
|
|
21837
|
+
]).nullable(),
|
|
21838
|
+
device: string().nullable(),
|
|
21839
|
+
state: _enum([
|
|
21840
|
+
"idle",
|
|
21841
|
+
"installing",
|
|
21842
|
+
"verifying",
|
|
21843
|
+
"ready",
|
|
21844
|
+
"failed"
|
|
21845
|
+
]),
|
|
21846
|
+
progress: number().optional(),
|
|
21847
|
+
error: string().optional(),
|
|
21848
|
+
nextRetryAt: number().optional(),
|
|
21849
|
+
/**
|
|
21850
|
+
* Gate A (config-correctness gate at engine change): human-readable
|
|
21851
|
+
* config issues surfaced EAGERLY when the node's engine changes — model
|
|
21852
|
+
* substitutions ("chose X, running Y") and zero-build steps ("no model
|
|
21853
|
+
* has a <format> build"). Additive/optional: informational only, never
|
|
21854
|
+
* enforced here — `assertEngineReady` (readiness) still gates inference.
|
|
21855
|
+
* Absent/empty when the node-default tree resolves cleanly.
|
|
21856
|
+
*/
|
|
21857
|
+
configIssues: array(string()).optional()
|
|
21858
|
+
});
|
|
21859
|
+
var PipelineStepInputSchema = lazy(() => object({
|
|
21860
|
+
addonId: string(),
|
|
21861
|
+
modelId: string().optional(),
|
|
21862
|
+
enabled: boolean().default(true),
|
|
21863
|
+
children: array(PipelineStepInputSchema).optional(),
|
|
21864
|
+
settings: record(string(), unknown()).optional(),
|
|
21865
|
+
jumpDeviceKey: string().optional()
|
|
21866
|
+
}));
|
|
21867
|
+
var ModelSubstitutionSchema = object({
|
|
21868
|
+
addonId: string(),
|
|
21869
|
+
chosen: string(),
|
|
21870
|
+
running: string(),
|
|
21871
|
+
format: string()
|
|
21872
|
+
});
|
|
21873
|
+
var PipelineValidationIssueSchema = object({
|
|
21874
|
+
addonId: string(),
|
|
21875
|
+
kind: _enum([
|
|
21876
|
+
"unknown-addon",
|
|
21877
|
+
"no-format-build",
|
|
21878
|
+
"unknown-device"
|
|
21879
|
+
]),
|
|
21880
|
+
detail: string()
|
|
21881
|
+
});
|
|
21882
|
+
var PipelineValidationResultSchema = object({
|
|
21883
|
+
ok: boolean(),
|
|
21884
|
+
issues: array(PipelineValidationIssueSchema).readonly(),
|
|
21885
|
+
substitutions: array(ModelSubstitutionSchema).readonly(),
|
|
21886
|
+
/** The node's `currentEngine.format` this validation ran against. */
|
|
21887
|
+
format: string()
|
|
21888
|
+
});
|
|
21889
|
+
var ReferenceImageEntrySchema = object({
|
|
21890
|
+
filename: string(),
|
|
21891
|
+
stepIds: array(string()).readonly().optional()
|
|
21892
|
+
});
|
|
21893
|
+
var ReferenceImageBodySchema = object({
|
|
21894
|
+
base64: string(),
|
|
21895
|
+
filename: string()
|
|
21896
|
+
});
|
|
21897
|
+
var ReferenceAudioEntrySchema = object({
|
|
21898
|
+
filename: string(),
|
|
21899
|
+
sizeKb: number()
|
|
21900
|
+
});
|
|
21901
|
+
var ReferenceAudioBodySchema = object({ base64: string() });
|
|
21902
|
+
var AudioBackendSchema = object({
|
|
21903
|
+
id: string(),
|
|
21904
|
+
name: string(),
|
|
21905
|
+
description: string(),
|
|
21906
|
+
available: boolean(),
|
|
21907
|
+
/**
|
|
21908
|
+
* Raw classifier labels this backend can emit (e.g. YAMNet's
|
|
21909
|
+
* 521-class set or Apple SoundAnalysis's 303-class set). Used by
|
|
21910
|
+
* the benchmark UI to populate the `enabledMicroClasses` filter
|
|
21911
|
+
* specific to the selected backend without a separate fetch.
|
|
21912
|
+
*/
|
|
21913
|
+
rawLabels: array(string()).readonly().optional()
|
|
21914
|
+
});
|
|
21915
|
+
var AudioCapabilitiesSchema = object({
|
|
21916
|
+
activeBackend: string(),
|
|
21917
|
+
availableBackends: array(AudioBackendSchema).readonly(),
|
|
21918
|
+
sampleRate: number(),
|
|
21919
|
+
chunkDurationMs: number()
|
|
21920
|
+
});
|
|
21921
|
+
var DownloadModelResultSchema = object({
|
|
21922
|
+
filePath: string(),
|
|
21923
|
+
sizeMB: number(),
|
|
21924
|
+
durationMs: number()
|
|
21925
|
+
});
|
|
21926
|
+
/**
|
|
21927
|
+
* Wrapper carrying a single test run's result. Replaces the legacy
|
|
21928
|
+
* ad-hoc `{labels: [{className, originalClass, score}]}` shape with the
|
|
21929
|
+
* canonical `AudioResult` from the Phase 6 output rework: one
|
|
21930
|
+
* `AudioDetection` per class above `minScore`, top-N candidates in
|
|
21931
|
+
* `debug.alternateLabels['audio-classifier']`, per-source timings in
|
|
21932
|
+
* `debug.stepTimings`. The outer `success`/`error` fields stay so the
|
|
21933
|
+
* benchmark UI can still report a clean failure when the classifier
|
|
21934
|
+
* cap isn't available.
|
|
21935
|
+
*/
|
|
21936
|
+
var AudioTestResultSchema = object({
|
|
21937
|
+
success: boolean(),
|
|
21938
|
+
error: string().optional(),
|
|
21939
|
+
frame: custom().optional()
|
|
21940
|
+
});
|
|
21941
|
+
var PipelineConfigBridge = custom();
|
|
21942
|
+
var ConfigUISchemaBridge = custom();
|
|
21943
|
+
var ConfigUISchemaNullableBridge = custom();
|
|
21944
|
+
var InferenceCapabilitiesBridge = custom();
|
|
21945
|
+
var ModelAvailabilityListBridge = custom();
|
|
21946
|
+
var PipelineRunResultBridge = custom();
|
|
21947
|
+
method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
|
|
21948
|
+
modelId: string(),
|
|
21949
|
+
settings: record(string(), unknown()).readonly()
|
|
21950
|
+
}))), method(object({ steps: record(string(), object({
|
|
21951
|
+
modelId: string(),
|
|
21952
|
+
settings: record(string(), unknown()).readonly()
|
|
21953
|
+
})) }), object({ success: literal(true) }), {
|
|
21954
|
+
kind: "mutation",
|
|
21955
|
+
auth: "admin"
|
|
21956
|
+
}), method(object({ nodeId: string() }), object({
|
|
21957
|
+
success: literal(true),
|
|
21958
|
+
clearedDevices: number()
|
|
22006
21959
|
}), {
|
|
22007
|
-
kind: "query",
|
|
22008
|
-
auth: "admin"
|
|
22009
|
-
}), method(object({
|
|
22010
|
-
deviceId: number(),
|
|
22011
|
-
trackId: string(),
|
|
22012
|
-
frameId: string(),
|
|
22013
|
-
subject: RetrainAssistSubjectSchema,
|
|
22014
|
-
/** Which node runs it. Absent ⇒ wherever an unowned call lands. */
|
|
22015
|
-
nodeId: string().optional()
|
|
22016
|
-
}), RetrainAssistResultSchema, {
|
|
22017
|
-
kind: "mutation",
|
|
22018
|
-
auth: "admin"
|
|
22019
|
-
}), method(object({
|
|
22020
|
-
deviceId: number(),
|
|
22021
|
-
source: DetectionSourceSchema,
|
|
22022
|
-
zones: array(ZoneSchema).readonly().optional(),
|
|
22023
|
-
detectionRules: array(ZoneRuleSchema).readonly().optional(),
|
|
22024
|
-
zoneMembershipMinOverlap: number().min(0).max(1).optional(),
|
|
22025
|
-
frames: array(ReplayFrameInputSchema).min(1)
|
|
22026
|
-
}), RunReplayFrameProcessorResultSchema, {
|
|
22027
|
-
kind: "mutation",
|
|
22028
|
-
auth: "admin"
|
|
22029
|
-
}), method(object({ trackId: string() }), array(RetrainAnnotationSchema).readonly(), {
|
|
22030
|
-
kind: "query",
|
|
22031
|
-
auth: "admin"
|
|
22032
|
-
}), method(object({
|
|
22033
|
-
deviceId: number(),
|
|
22034
|
-
trackId: string(),
|
|
22035
|
-
frameId: string(),
|
|
22036
|
-
annotations: array(RetrainAnnotationDraftSchema)
|
|
22037
|
-
}), array(RetrainAnnotationSchema).readonly(), {
|
|
22038
21960
|
kind: "mutation",
|
|
22039
21961
|
auth: "admin"
|
|
22040
|
-
}), method(object({
|
|
22041
|
-
|
|
22042
|
-
|
|
22043
|
-
|
|
21962
|
+
}), method(object({ nodeId: string() }), object({ unhealthy: array(object({
|
|
21963
|
+
/** `<backend>:<device>`, e.g. `openvino:gpu`. */
|
|
21964
|
+
deviceKey: string(),
|
|
21965
|
+
/**
|
|
21966
|
+
* `failed` — the per-device restart budget is exhausted; no pool
|
|
21967
|
+
* will be spawned until an operator re-arms it or the runner
|
|
21968
|
+
* respawns. `backoff` — under budget, waiting out the backoff (or
|
|
21969
|
+
* a cached pool observed dead and not yet condemned).
|
|
21970
|
+
*/
|
|
21971
|
+
state: _enum(["failed", "backoff"]),
|
|
21972
|
+
/** Epoch ms of the death that produced this state. */
|
|
21973
|
+
since: number(),
|
|
21974
|
+
/** Pool deaths inside the current window. */
|
|
21975
|
+
deaths: number(),
|
|
21976
|
+
/** The last death's message. */
|
|
21977
|
+
lastError: string()
|
|
21978
|
+
})).readonly() })), method(object({
|
|
21979
|
+
nodeId: string(),
|
|
21980
|
+
deviceKey: string()
|
|
21981
|
+
}), object({ rearmed: boolean() }), {
|
|
22044
21982
|
kind: "mutation",
|
|
22045
21983
|
auth: "admin"
|
|
22046
|
-
}), method(object({
|
|
22047
|
-
|
|
22048
|
-
|
|
22049
|
-
}),
|
|
21984
|
+
}), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({
|
|
21985
|
+
steps: array(PipelineStepInputSchema),
|
|
21986
|
+
deviceKey: string().optional()
|
|
21987
|
+
}), PipelineValidationResultSchema), method(_void(), array(PipelineTemplateSchema$1).readonly()), method(object({
|
|
21988
|
+
name: string(),
|
|
21989
|
+
steps: array(PipelineTemplateStepSchema).readonly(),
|
|
21990
|
+
engine: PipelineEngineChoiceSchema
|
|
21991
|
+
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({
|
|
21992
|
+
id: string(),
|
|
21993
|
+
name: string().optional(),
|
|
21994
|
+
steps: array(PipelineTemplateStepSchema).readonly().optional()
|
|
21995
|
+
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({ id: string() }), _void(), { kind: "mutation" }), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
|
|
21996
|
+
addonId: string(),
|
|
21997
|
+
modelId: string(),
|
|
21998
|
+
format: ModelFormatSchema$1
|
|
21999
|
+
}), DownloadModelResultSchema, { kind: "mutation" }), method(object({
|
|
22000
|
+
addonId: string(),
|
|
22001
|
+
modelId: string(),
|
|
22002
|
+
format: ModelFormatSchema$1
|
|
22003
|
+
}), object({ success: literal(true) }), { kind: "mutation" }), method(object({
|
|
22004
|
+
steps: array(PipelineStepInputSchema).min(1),
|
|
22005
|
+
frame: FrameInputSchema.optional(),
|
|
22006
|
+
/**
|
|
22007
|
+
* Process-local lazy frame. Valid only when caller and provider resolve
|
|
22008
|
+
* in the same execution-group process; split/cross-node callers use
|
|
22009
|
+
* `frame`/`image` inline compatibility instead.
|
|
22010
|
+
*/
|
|
22011
|
+
frameRef: FrameRefSchema.optional(),
|
|
22012
|
+
/**
|
|
22013
|
+
* CB5 shm passthrough — a `FrameHandle` naming the same ring slot
|
|
22014
|
+
* the decoded pixels live in. One more member of the one-of
|
|
22015
|
+
* frame/frameHandle/image/imageBase64/referenceImage group.
|
|
22016
|
+
*/
|
|
22017
|
+
frameHandle: FrameHandleSchema.optional(),
|
|
22018
|
+
imageBase64: string().optional(),
|
|
22019
|
+
/**
|
|
22020
|
+
* Binary JPEG bytes — preferred over `imageBase64` on internal
|
|
22021
|
+
* hops (hub → forked worker via Moleculer MsgPack) because it
|
|
22022
|
+
* skips the 33% base64 overhead + the per-call base64 decode on
|
|
22023
|
+
* the detection-pipeline worker. Callers can pass either; exactly
|
|
22024
|
+
* one of `frame`/`image`/`imageBase64`/`referenceImage` is required.
|
|
22025
|
+
*/
|
|
22026
|
+
image: _instanceof(Uint8Array).optional(),
|
|
22027
|
+
referenceImage: string().optional(),
|
|
22028
|
+
deviceId: number().optional(),
|
|
22029
|
+
sessionId: string().optional(),
|
|
22030
|
+
/**
|
|
22031
|
+
* Execution plane. 'full' (default) runs the whole tree — benchmark,
|
|
22032
|
+
* reference-image, and detail-subtree calls. 'frame' is the live
|
|
22033
|
+
* per-frame dispatch: ONLY root-plane steps run; crop children
|
|
22034
|
+
* (inputClasses ≠ null) are skipped and served per-track via
|
|
22035
|
+
* pipelineRunner.runDetailSubtree (two-plane design).
|
|
22036
|
+
*/
|
|
22037
|
+
plane: _enum(["full", "frame"]).optional(),
|
|
22038
|
+
/**
|
|
22039
|
+
* Inference-device selector (Phase 2 multi-device). Format
|
|
22040
|
+
* `<backend>:<device>` (e.g. `openvino:gpu`, `edgetpu:usb`, `cpu`).
|
|
22041
|
+
* Omitted ⇒ the runner's default device (current single-engine
|
|
22042
|
+
* behaviour). Selects WHICH device pool of the node runs the call.
|
|
22043
|
+
*/
|
|
22044
|
+
deviceKey: string().optional(),
|
|
22045
|
+
/**
|
|
22046
|
+
* Two-plane NATIVE child-crop reference. Set by `runDetailSubtree` ONLY
|
|
22047
|
+
* when the parent crop was resolved from the frame's retained NATIVE
|
|
22048
|
+
* surface (a frameHandle HIT). Lets the executor re-cut a LEAF crop
|
|
22049
|
+
* child's ROI (plate-ocr, face-embedding, leaf classifiers) at native
|
|
22050
|
+
* resolution from that surface — the SAME quality path faces already
|
|
22051
|
+
* had — instead of the downscaled parent tile. `handle` keys the native
|
|
22052
|
+
* surface (node-pinned to its owner); `cropFrameSpace` is the parent
|
|
22053
|
+
* crop's padded/clamped rectangle in FRAME-space pixels, used to compose
|
|
22054
|
+
* the executor's crop-normalized child ROI back into frame-normalized
|
|
22055
|
+
* coordinates. Auxiliary to the image source (`image`/`frame`/…), NOT one
|
|
22056
|
+
* of the mutually-exclusive image inputs. Absent ⇒ tile-crop children
|
|
22057
|
+
* (today's behaviour on the fallback path).
|
|
22058
|
+
*/
|
|
22059
|
+
nativeCropRef: NativeCropRefSchema.optional(),
|
|
22060
|
+
/**
|
|
22061
|
+
* Offline REPLAY of stored media for `deviceId` (D56, D646): the
|
|
22062
|
+
* camera's zone gate and overrides apply as live, every executing
|
|
22063
|
+
* step runs EXACTLY the model it names on the `deviceKey` pool it
|
|
22064
|
+
* names or the call refuses (`model-not-servable` /
|
|
22065
|
+
* `device-not-servable`), and nothing reaches the camera's live
|
|
22066
|
+
* trace stream. Absent ⇒ unchanged behaviour.
|
|
22067
|
+
*/
|
|
22068
|
+
replay: literal(true).optional()
|
|
22069
|
+
}), PipelineRunResultBridge, { kind: "mutation" }), method(object({
|
|
22070
|
+
steps: array(PipelineStepInputSchema).min(1),
|
|
22071
|
+
frames: array(FrameInputSchema).min(1).max(255),
|
|
22072
|
+
deviceId: number().optional(),
|
|
22073
|
+
sessionId: string().optional(),
|
|
22074
|
+
/**
|
|
22075
|
+
* Pure-inference benchmark hint. A NONZERO uint32 pins every frame in
|
|
22076
|
+
* the batch to the Python pool's bench preprocess cache
|
|
22077
|
+
* (`_bench_frame_id`) so a REPEATED benchmark frame is decoded +
|
|
22078
|
+
* preprocessed ONCE and every later inference is a pure-inference cache
|
|
22079
|
+
* hit — the sustained-throughput run measures inference, not
|
|
22080
|
+
* decode+preprocess+infer. Omitted/0 for live frames (all different →
|
|
22081
|
+
* full preprocess every call, correct). Fresh per sustained run;
|
|
22082
|
+
* released via `uncacheFrame`.
|
|
22083
|
+
*/
|
|
22084
|
+
frameId: number().int().nonnegative().optional(),
|
|
22085
|
+
/** Inference-device selector (Phase 2 multi-device); see runPipeline. */
|
|
22086
|
+
deviceKey: string().optional()
|
|
22087
|
+
}), object({ results: array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }), method(object({
|
|
22088
|
+
data: _instanceof(Uint8Array),
|
|
22089
|
+
width: number().int().positive(),
|
|
22090
|
+
height: number().int().positive(),
|
|
22091
|
+
format: _enum([
|
|
22092
|
+
"rgb",
|
|
22093
|
+
"bgr",
|
|
22094
|
+
"gray"
|
|
22095
|
+
])
|
|
22096
|
+
}), object({
|
|
22097
|
+
frameId: number(),
|
|
22098
|
+
width: number(),
|
|
22099
|
+
height: number()
|
|
22100
|
+
}), { kind: "mutation" }), method(object({
|
|
22101
|
+
stepId: string(),
|
|
22102
|
+
frameId: number().int()
|
|
22103
|
+
}), record(string(), unknown()), { kind: "mutation" }), method(object({ frameId: number().int() }), _void(), { kind: "mutation" }), method(object({ deviceKey: string().optional() }), EffectiveTuningSchema), method(_void(), array(object({
|
|
22104
|
+
engineKey: string(),
|
|
22105
|
+
engine: PipelineEngineChoiceSchema,
|
|
22106
|
+
modelsLoaded: array(string()).readonly(),
|
|
22107
|
+
inUseByCameras: array(number()).readonly(),
|
|
22108
|
+
/**
|
|
22109
|
+
* Origin of this resident factory.
|
|
22110
|
+
* - `runtime` — main camera-serving engine (no idle TTL).
|
|
22111
|
+
* - `device-pool` — a concurrent per-device pool (Phase 2
|
|
22112
|
+
* multi-device, keyed by `deviceKey`) resolved
|
|
22113
|
+
* via `resolveDeviceFactory`. Runs alongside the
|
|
22114
|
+
* `runtime` engine on a DIFFERENT accelerator
|
|
22115
|
+
* (NPU / iGPU / Coral) — this is how the
|
|
22116
|
+
* Engines tab shows all pools running at once.
|
|
22117
|
+
*/
|
|
22118
|
+
kind: _enum(["runtime", "device-pool"]),
|
|
22119
|
+
/** Native pid of the underlying Python pool (null when no pool). */
|
|
22120
|
+
poolPid: number().nullable(),
|
|
22121
|
+
/** ms since this factory was last used (null when not warm-tracked). */
|
|
22122
|
+
idleMs: number().nullable(),
|
|
22123
|
+
/** Idle TTL after which the factory self-evicts (null when not applicable). */
|
|
22124
|
+
idleTtlMs: number().nullable()
|
|
22125
|
+
})).readonly()), method(object({ engine: PipelineEngineChoiceSchema }), object({ success: literal(true) }), {
|
|
22050
22126
|
kind: "mutation",
|
|
22051
22127
|
auth: "admin"
|
|
22052
|
-
}), method(object({ deviceIds: array(number()).optional() }), object({ url: string() }), {
|
|
22053
|
-
kind: "query",
|
|
22054
|
-
auth: "admin"
|
|
22055
22128
|
}), method(object({
|
|
22056
|
-
|
|
22057
|
-
|
|
22058
|
-
|
|
22059
|
-
|
|
22060
|
-
|
|
22061
|
-
|
|
22062
|
-
}), array(MediaFileSchema).readonly()), method(object({
|
|
22063
|
-
trackId: string(),
|
|
22064
|
-
kinds: array(MediaFileKindEnum).optional(),
|
|
22065
|
-
deviceId: number()
|
|
22066
|
-
}), array(MediaFileSchema).readonly()), method(object({
|
|
22067
|
-
trackId: string(),
|
|
22068
|
-
deviceId: number()
|
|
22069
|
-
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
22070
|
-
ownerType: EventOwnerTypeSchema,
|
|
22071
|
-
eventId: number().int(),
|
|
22072
|
-
deviceId: number()
|
|
22073
|
-
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
22074
|
-
deviceId: number(),
|
|
22075
|
-
ownerKind: MediaPresenceOwnerKindSchema,
|
|
22076
|
-
ownerIds: array(string()).max(5e3)
|
|
22077
|
-
}), array(string()).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
22078
|
-
kind: "mutation",
|
|
22079
|
-
auth: "admin"
|
|
22080
|
-
}), method(RebuildObjectEmbeddingsInput, RebuildObjectEmbeddingsResultSchema, {
|
|
22129
|
+
engine: PipelineEngineChoiceSchema,
|
|
22130
|
+
force: boolean().optional()
|
|
22131
|
+
}), object({
|
|
22132
|
+
success: boolean(),
|
|
22133
|
+
reason: string().optional()
|
|
22134
|
+
}), {
|
|
22081
22135
|
kind: "mutation",
|
|
22082
22136
|
auth: "admin"
|
|
22083
|
-
}), method(object({}),
|
|
22084
|
-
|
|
22085
|
-
|
|
22086
|
-
|
|
22087
|
-
|
|
22088
|
-
|
|
22089
|
-
}), object({
|
|
22090
|
-
deviceId: number(),
|
|
22091
|
-
trackId: string(),
|
|
22092
|
-
className: string()
|
|
22093
|
-
}), object({
|
|
22094
|
-
deviceId: number(),
|
|
22095
|
-
trackId: string(),
|
|
22096
|
-
className: string(),
|
|
22097
|
-
durationMs: number()
|
|
22098
|
-
}), object({
|
|
22099
|
-
deviceId: number(),
|
|
22100
|
-
kind: EventKindSchema,
|
|
22101
|
-
eventId: string(),
|
|
22102
|
-
timestamp: number()
|
|
22103
|
-
});
|
|
22137
|
+
}), 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({
|
|
22138
|
+
addonId: string(),
|
|
22139
|
+
modelId: string(),
|
|
22140
|
+
filename: string().optional(),
|
|
22141
|
+
settings: record(string(), unknown()).optional()
|
|
22142
|
+
}), AudioTestResultSchema, { kind: "mutation" }), method(_void(), ConfigUISchemaNullableBridge);
|
|
22104
22143
|
object({
|
|
22105
22144
|
activeCameras: number(),
|
|
22106
22145
|
throttledCameras: number(),
|
|
@@ -22126,6 +22165,66 @@ var CameraMetricsSchema = object({
|
|
|
22126
22165
|
});
|
|
22127
22166
|
var CameraMetricsWithDeviceIdSchema = CameraMetricsSchema.extend({ deviceId: number() });
|
|
22128
22167
|
/**
|
|
22168
|
+
* Zone — pure geometry + identity. NO filtering behaviour.
|
|
22169
|
+
*
|
|
22170
|
+
* Zones describe **where** in the frame the operator wants to flag
|
|
22171
|
+
* something; consumer-owned {@link ZoneRule} arrays describe **how**
|
|
22172
|
+
* each pipeline stage uses them. Splitting the two means a single
|
|
22173
|
+
* polygon "Driveway" can simultaneously back a motion-exclude rule,
|
|
22174
|
+
* a detection-include rule on `['car']`, and an occupancy aggregate
|
|
22175
|
+
* — without three duplicated polygons.
|
|
22176
|
+
*
|
|
22177
|
+
* Owned by the orchestrator addon (provider) and mirrored into the
|
|
22178
|
+
* `zones` device-state slice on every mutation. Consumers
|
|
22179
|
+
* (motion-wasm, pipeline-executor, analytics, admin UI) read either
|
|
22180
|
+
* via `api.zones.listZones` (one-shot) or via `dev.state.zones` (live
|
|
22181
|
+
* mirror with `onChanged`).
|
|
22182
|
+
*
|
|
22183
|
+
* Coordinates are normalised fractions of the frame (0–1) so zones
|
|
22184
|
+
* survive resolution changes and stream profile switches.
|
|
22185
|
+
*
|
|
22186
|
+
* `kind` discriminates between full polygons (closed regions used
|
|
22187
|
+
* for intrusion / occupancy filters) and tripwires (open 2-point
|
|
22188
|
+
* line segments used for cross events). Onboard / firmware-reported
|
|
22189
|
+
* zones (Reolink, ONVIF) are out of scope for now — see the deferred
|
|
22190
|
+
* task list.
|
|
22191
|
+
*/
|
|
22192
|
+
var ZoneKindEnum = _enum(["polygon", "tripwire"]);
|
|
22193
|
+
/** Polygon vertex in fraction-of-frame coordinates (0–1). */
|
|
22194
|
+
var PolygonPointSchema = object({
|
|
22195
|
+
x: number(),
|
|
22196
|
+
y: number()
|
|
22197
|
+
});
|
|
22198
|
+
/** A camera detection zone — pure geometry/identity. */
|
|
22199
|
+
var ZoneSchema = object({
|
|
22200
|
+
id: string(),
|
|
22201
|
+
name: string(),
|
|
22202
|
+
kind: ZoneKindEnum.default("polygon"),
|
|
22203
|
+
/** Polygon vertices, fraction of frame (0–1). */
|
|
22204
|
+
polygon: array(PolygonPointSchema).readonly(),
|
|
22205
|
+
/** Visual color for UI rendering. */
|
|
22206
|
+
color: string().default("#3b82f6")
|
|
22207
|
+
});
|
|
22208
|
+
DeviceType.Camera, method(object({ deviceId: number() }), array(ZoneSchema).readonly()), method(object({
|
|
22209
|
+
deviceId: number(),
|
|
22210
|
+
zone: ZoneSchema
|
|
22211
|
+
}), _void(), {
|
|
22212
|
+
kind: "mutation",
|
|
22213
|
+
auth: "admin"
|
|
22214
|
+
}), method(object({
|
|
22215
|
+
deviceId: number(),
|
|
22216
|
+
zoneId: string()
|
|
22217
|
+
}), _void(), {
|
|
22218
|
+
kind: "mutation",
|
|
22219
|
+
auth: "admin"
|
|
22220
|
+
}), method(object({
|
|
22221
|
+
deviceId: number(),
|
|
22222
|
+
zone: ZoneSchema
|
|
22223
|
+
}), _void(), {
|
|
22224
|
+
kind: "mutation",
|
|
22225
|
+
auth: "admin"
|
|
22226
|
+
}), object({ zones: array(ZoneSchema).readonly() });
|
|
22227
|
+
/**
|
|
22129
22228
|
* A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
|
|
22130
22229
|
* decode worker resolves it against the RETAINED native frame's real pixel dims,
|
|
22131
22230
|
* so the caller supplies only the detection-res bbox divided by the detection
|
|
@@ -22312,7 +22411,17 @@ var DetailResultSchema = object({
|
|
|
22312
22411
|
/** Face short side (px) measured on the NATIVE crop surface. The `bbox`
|
|
22313
22412
|
* above is detection-frame px (≈6× smaller on a 4K camera) — min-face-size
|
|
22314
22413
|
* consumers MUST prefer this when present (2026-07-22 native-gate fix). */
|
|
22315
|
-
nativeFaceShortSidePx: number().optional()
|
|
22414
|
+
nativeFaceShortSidePx: number().optional(),
|
|
22415
|
+
/**
|
|
22416
|
+
* The five facial landmarks of a `face` detail, in the SAME frame space as
|
|
22417
|
+
* `bbox` (D644). Additive and optional: post-analysis stores them beside the
|
|
22418
|
+
* face's source frame so a future alignment can be re-derived exactly; a
|
|
22419
|
+
* runner that predates the field sends none and the face is stored without.
|
|
22420
|
+
*/
|
|
22421
|
+
landmarks: array(object({
|
|
22422
|
+
x: number(),
|
|
22423
|
+
y: number()
|
|
22424
|
+
})).optional()
|
|
22316
22425
|
});
|
|
22317
22426
|
/**
|
|
22318
22427
|
* Why an executing node REFUSED a stateless step run (`runStatelessStep`).
|
|
@@ -23698,7 +23807,11 @@ function buildDescriptor(capName, kind) {
|
|
|
23698
23807
|
icon: legacyIcon(t.iconId)
|
|
23699
23808
|
};
|
|
23700
23809
|
}
|
|
23701
|
-
|
|
23810
|
+
/**
|
|
23811
|
+
* Sensor / control cap name → static event-kind descriptor. A linked device
|
|
23812
|
+
* contributes one entry per bound cap present in this map.
|
|
23813
|
+
*/
|
|
23814
|
+
var EVENT_KIND_BY_CAP = Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
|
|
23702
23815
|
/**
|
|
23703
23816
|
* server-management — per-NODE singleton capability for a node's ROOT
|
|
23704
23817
|
* package lifecycle (runtime-updatable node packages).
|
|
@@ -30633,7 +30746,7 @@ var HardwareInfoSchema = object({
|
|
|
30633
30746
|
coral: CoralInfoSchema.nullable().optional()
|
|
30634
30747
|
});
|
|
30635
30748
|
var PlatformScoreSchema = object({
|
|
30636
|
-
runtime:
|
|
30749
|
+
runtime: literal("python"),
|
|
30637
30750
|
backend: string(),
|
|
30638
30751
|
format: _enum([
|
|
30639
30752
|
"onnx",
|
|
@@ -30670,7 +30783,7 @@ var ModelRequirementSchema = object({
|
|
|
30670
30783
|
});
|
|
30671
30784
|
var ResolvedInferenceConfigSchema = object({
|
|
30672
30785
|
modelId: string(),
|
|
30673
|
-
runtime:
|
|
30786
|
+
runtime: literal("python"),
|
|
30674
30787
|
backend: string(),
|
|
30675
30788
|
format: ModelFormatSchema,
|
|
30676
30789
|
reason: string()
|
|
@@ -32877,6 +32990,92 @@ DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSche
|
|
|
32877
32990
|
kind: "mutation",
|
|
32878
32991
|
auth: "admin"
|
|
32879
32992
|
});
|
|
32993
|
+
/**
|
|
32994
|
+
* Per-stage gating mode applied to the zones a rule references.
|
|
32995
|
+
*
|
|
32996
|
+
* - `include`: the rule contributes to a **whitelist** for its stage.
|
|
32997
|
+
* When at least one `include` rule fires for a stage, only entities
|
|
32998
|
+
* inside one of those zones pass that stage.
|
|
32999
|
+
* - `exclude`: the rule contributes to a **blacklist** for its stage.
|
|
33000
|
+
* Entities inside one of those zones are dropped at that stage.
|
|
33001
|
+
*
|
|
33002
|
+
* `monitor`-style observation (count without filtering) is not a rule
|
|
33003
|
+
* mode — zones without any matching rule are observed naturally by
|
|
33004
|
+
* `zone-analytics` (live snapshot + history), so an "I just want to
|
|
33005
|
+
* count, not filter" use case needs no rule at all.
|
|
33006
|
+
*/
|
|
33007
|
+
var ZoneRuleModeEnum = _enum(["include", "exclude"]);
|
|
33008
|
+
/**
|
|
33009
|
+
* Per-consumer rule that references existing zones (geometry) and
|
|
33010
|
+
* defines how a specific pipeline stage should treat them. Each
|
|
33011
|
+
* consumer addon owns its own `ZoneRule[]` array in its per-device
|
|
33012
|
+
* settings:
|
|
33013
|
+
*
|
|
33014
|
+
* - `addon-motion-wasm` → `motionZoneRules: ZoneRule[]` (motion stage)
|
|
33015
|
+
* - `addon-detection-pipeline` → `detectionZoneRules: ZoneRule[]` (detection stage)
|
|
33016
|
+
* - future: notification rules, audio gating, etc.
|
|
33017
|
+
*
|
|
33018
|
+
* One rule applies to N zones (`zoneIds[]`) so the operator can
|
|
33019
|
+
* express "ignore motion in ALL of {garden, street}" with a single
|
|
33020
|
+
* rule. `classFilter` narrows the rule to specific object classes —
|
|
33021
|
+
* "drop person detections in the street, but keep cars" is one
|
|
33022
|
+
* `exclude` rule with `classFilter: ['person']`.
|
|
33023
|
+
*
|
|
33024
|
+
* `enabled` is a soft toggle — the operator can keep the rule
|
|
33025
|
+
* configured but inert without deleting it.
|
|
33026
|
+
*/
|
|
33027
|
+
var ZoneRuleSchema = object({
|
|
33028
|
+
/** Stable rule id — survives edits, used by the UI for diffing. */
|
|
33029
|
+
id: string(),
|
|
33030
|
+
/** Optional human-readable label rendered in the rule editor. */
|
|
33031
|
+
name: string().optional(),
|
|
33032
|
+
/** Zones this rule targets. The rule's `mode` applies to ALL
|
|
33033
|
+
* listed zones (OR-set: a detection in any one of them counts).
|
|
33034
|
+
* At least one zone id required — a rule with no targets is a
|
|
33035
|
+
* configuration mistake and the form validator rejects it. */
|
|
33036
|
+
zoneIds: array(string()).min(1).readonly(),
|
|
33037
|
+
mode: ZoneRuleModeEnum,
|
|
33038
|
+
/**
|
|
33039
|
+
* Class names this rule applies to. Empty / undefined ⇒ rule
|
|
33040
|
+
* applies to every class. Class strings match the `macroClass`
|
|
33041
|
+
* field on detections (e.g. `person`, `car`, `dog`).
|
|
33042
|
+
*/
|
|
33043
|
+
classFilter: array(string()).readonly().optional(),
|
|
33044
|
+
/**
|
|
33045
|
+
* Minimum bbox/mask overlap (0–1) with any of the rule's zones
|
|
33046
|
+
* required to consider an entity "in the zone". Defaults to the
|
|
33047
|
+
* consumer's stage default when omitted. Kept for back-compat with
|
|
33048
|
+
* existing per-rule overrides; new operators pick the value via
|
|
33049
|
+
* `bboxInclusionPct` (operator-friendly 0–100). Whichever field is
|
|
33050
|
+
* set, the lower-level engine reads it as a 0–1 fraction.
|
|
33051
|
+
*/
|
|
33052
|
+
overlapThreshold: number().min(0).max(1).optional(),
|
|
33053
|
+
/**
|
|
33054
|
+
* Operator-friendly version of `overlapThreshold` — the percentage
|
|
33055
|
+
* of the detection's bbox that must lie inside the zone for the
|
|
33056
|
+
* rule to match. Documented default is 85%; the engine substitutes
|
|
33057
|
+
* that when the field is omitted (kept optional so existing rules
|
|
33058
|
+
* stored without it stay valid).
|
|
33059
|
+
*
|
|
33060
|
+
* When BOTH `overlapThreshold` and `bboxInclusionPct` are set on a
|
|
33061
|
+
* rule, the engine prefers `bboxInclusionPct` because it's the
|
|
33062
|
+
* field exposed in the UI. Internally both feed the same gate.
|
|
33063
|
+
*/
|
|
33064
|
+
bboxInclusionPct: number().min(0).max(100).optional(),
|
|
33065
|
+
/**
|
|
33066
|
+
* When `true` and a detection has a segmentation mask, use the
|
|
33067
|
+
* mask for overlap instead of the bbox. Detection-stage only;
|
|
33068
|
+
* motion rules ignore this field.
|
|
33069
|
+
*/
|
|
33070
|
+
preferMask: boolean().optional(),
|
|
33071
|
+
/**
|
|
33072
|
+
* Soft-toggle: `false` disables the rule without deleting it.
|
|
33073
|
+
* Defaults to `true` so operators creating a rule via the UI
|
|
33074
|
+
* see it active immediately.
|
|
33075
|
+
*/
|
|
33076
|
+
enabled: boolean().default(true)
|
|
33077
|
+
});
|
|
33078
|
+
array(ZoneRuleSchema).readonly();
|
|
32880
33079
|
object({
|
|
32881
33080
|
/** Whether the script is currently executing. */
|
|
32882
33081
|
isRunning: boolean(),
|
|
@@ -34258,6 +34457,42 @@ DeviceType.Camera, method(object({
|
|
|
34258
34457
|
package: array(ZoneRuleSchema).readonly()
|
|
34259
34458
|
});
|
|
34260
34459
|
/**
|
|
34460
|
+
* LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
|
|
34461
|
+
* valutatore puro del suo FRONTE.
|
|
34462
|
+
*
|
|
34463
|
+
* Viveva dentro il builtin virtual-doorbell
|
|
34464
|
+
* (`@camstack/system` — `builtins/doorbell/trigger-engine.ts`) e i suoi
|
|
34465
|
+
* predicati erano privati al modulo. Il recorder ne ha bisogno per il trigger
|
|
34466
|
+
* `RecordingTriggers.sensorDeviceIds`: copiarla avrebbe creato la SECONDA
|
|
34467
|
+
* tabella, che diverge alla prima cap aggiunta e il cui sintomo — "il sensore
|
|
34468
|
+
* fa suonare il campanello ma non registra" — è esattamente D62. Quindi si
|
|
34469
|
+
* SPOSTA qui e il doorbell la ri-esporta.
|
|
34470
|
+
*
|
|
34471
|
+
* ⚠ NON è `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), e le
|
|
34472
|
+
* due non vanno unificate: quella risponde a "qual è la PAROLA di stato per una
|
|
34473
|
+
* regola" (e include `presence`, `cover`, `alarm-panel`), questa a "qual è il
|
|
34474
|
+
* booleano il cui FRONTE conta". Vocabolari deliberatamente diversi.
|
|
34475
|
+
*/
|
|
34476
|
+
/**
|
|
34477
|
+
* Known binary / switch source caps → the boolean slice field whose
|
|
34478
|
+
* false→true rise counts as ACTIVE. Every entry is "fire on active".
|
|
34479
|
+
* Sensors whose "active" reading is not a plain boolean (presence's string
|
|
34480
|
+
* state, connectivity's connected flag) are deliberately excluded — a
|
|
34481
|
+
* reconnect is not a doorbell press, and it is not a recording either.
|
|
34482
|
+
*/
|
|
34483
|
+
var SOURCE_CAP_ACTIVE_FIELD = {
|
|
34484
|
+
contact: "entryOpen",
|
|
34485
|
+
binary: "on",
|
|
34486
|
+
switch: "on",
|
|
34487
|
+
motion: "detected",
|
|
34488
|
+
flood: "flooded",
|
|
34489
|
+
gas: "detected",
|
|
34490
|
+
smoke: "detected",
|
|
34491
|
+
"carbon-monoxide": "detected",
|
|
34492
|
+
vibration: "detected",
|
|
34493
|
+
tamper: "tampered"
|
|
34494
|
+
};
|
|
34495
|
+
/**
|
|
34261
34496
|
* Accessory device helpers — shared across drivers.
|
|
34262
34497
|
*
|
|
34263
34498
|
* Many vendor-specific drivers register accessory child devices on
|
|
@@ -39163,6 +39398,12 @@ Object.freeze({
|
|
|
39163
39398
|
addonId: null,
|
|
39164
39399
|
access: "view"
|
|
39165
39400
|
},
|
|
39401
|
+
"notificationRules.getRuleLastRuns": {
|
|
39402
|
+
capName: "notification-rules",
|
|
39403
|
+
capScope: "system",
|
|
39404
|
+
addonId: null,
|
|
39405
|
+
access: "view"
|
|
39406
|
+
},
|
|
39166
39407
|
"notificationRules.getTemplateCatalog": {
|
|
39167
39408
|
capName: "notification-rules",
|
|
39168
39409
|
capScope: "system",
|
|
@@ -39187,6 +39428,12 @@ Object.freeze({
|
|
|
39187
39428
|
addonId: null,
|
|
39188
39429
|
access: "view"
|
|
39189
39430
|
},
|
|
39431
|
+
"notificationRules.previewStateSummary": {
|
|
39432
|
+
capName: "notification-rules",
|
|
39433
|
+
capScope: "system",
|
|
39434
|
+
addonId: null,
|
|
39435
|
+
access: "view"
|
|
39436
|
+
},
|
|
39190
39437
|
"notificationRules.previewTemplate": {
|
|
39191
39438
|
capName: "notification-rules",
|
|
39192
39439
|
capScope: "system",
|
|
@@ -39763,12 +40010,6 @@ Object.freeze({
|
|
|
39763
40010
|
addonId: null,
|
|
39764
40011
|
access: "create"
|
|
39765
40012
|
},
|
|
39766
|
-
"pipelineAnalytics.runReplayFrameProcessor": {
|
|
39767
|
-
capName: "pipeline-analytics",
|
|
39768
|
-
capScope: "device",
|
|
39769
|
-
addonId: null,
|
|
39770
|
-
access: "create"
|
|
39771
|
-
},
|
|
39772
40013
|
"pipelineAnalytics.saveRetrainAnnotations": {
|
|
39773
40014
|
capName: "pipeline-analytics",
|
|
39774
40015
|
capScope: "device",
|
|
@@ -43866,11 +44107,6 @@ Object.freeze({
|
|
|
43866
44107
|
form: "single",
|
|
43867
44108
|
optional: false
|
|
43868
44109
|
}],
|
|
43869
|
-
"pipelineAnalytics.runReplayFrameProcessor": [{
|
|
43870
|
-
name: "deviceId",
|
|
43871
|
-
form: "single",
|
|
43872
|
-
optional: false
|
|
43873
|
-
}],
|
|
43874
44110
|
"pipelineAnalytics.saveRetrainAnnotations": [{
|
|
43875
44111
|
name: "deviceId",
|
|
43876
44112
|
form: "single",
|
|
@@ -44759,12 +44995,55 @@ var NC_AUDIO_DEFAULTS = {
|
|
|
44759
44995
|
samplingSeconds: 10
|
|
44760
44996
|
};
|
|
44761
44997
|
new Set(["devices", "classes"]);
|
|
44762
|
-
/**
|
|
44998
|
+
/**
|
|
44999
|
+
* WHICH narrowing filter speaks about WHICH system-event kind — one predicate,
|
|
45000
|
+
* consumed by the rule ENGINE and by every rule EDITOR.
|
|
45001
|
+
*
|
|
45002
|
+
* ── The failure this file exists for ───────────────────────────────────────
|
|
45003
|
+
* `NcSystemEventConditionSchema` carries four optional narrowing lists
|
|
45004
|
+
* (`deviceIds`, `deviceTypes`, `nodeIds`, `packageNames`) beside a required
|
|
45005
|
+
* `kinds` gate. They are not four filters over one vocabulary: each belongs to
|
|
45006
|
+
* a FAMILY of kinds and is meaningless outside it. A node going away has no
|
|
45007
|
+
* device type; a completed export has no package; `stream-offline` deliberately
|
|
45008
|
+
* carries no device type at all (a stream belongs to a camera by construction).
|
|
45009
|
+
*
|
|
45010
|
+
* The engine applied all four to every kind, so a filter from one family failed
|
|
45011
|
+
* a kind from another family CLOSED. The operator's live rule "Eventi di
|
|
45012
|
+
* sistema" selected eleven kinds and set `deviceTypes: ['camera']` — the only
|
|
45013
|
+
* way to say "only my cameras" about the two liveness kinds — and NINE of the
|
|
45014
|
+
* eleven silently stopped being deliverable. Four days of history contained
|
|
45015
|
+
* `device-online` and `device-offline` and nothing else, across a window in
|
|
45016
|
+
* which agents were restarted and addons were updated.
|
|
45017
|
+
*
|
|
45018
|
+
* Both editors already computed this scoping, to decide which filter boxes to
|
|
45019
|
+
* render; the cap's own docblock already promised it ("Narrow a `device-*` kind
|
|
45020
|
+
* to these device TYPES"). Only the engine disagreed, and it disagreed in the
|
|
45021
|
+
* destructive direction. So the rule is stated ONCE, here, and the engine and
|
|
45022
|
+
* the editors are readers of it rather than three independent authors.
|
|
45023
|
+
*
|
|
45024
|
+
* ── The direction ─────────────────────────────────────────────────────────
|
|
45025
|
+
* Out of family ⇒ the filter is IGNORED, never fail-closed. An editor that
|
|
45026
|
+
* hides a box has already told the operator this filter does not speak about
|
|
45027
|
+
* these kinds, so honouring it as an exclusion contradicts the only
|
|
45028
|
+
* explanation the operator was ever given. Inside its family the filter still
|
|
45029
|
+
* narrows, and still fails CLOSED on a subject that cannot produce the identity
|
|
45030
|
+
* it tests (a device the mirror cannot name is not evidence of a camera).
|
|
45031
|
+
*/
|
|
45032
|
+
/**
|
|
45033
|
+
* Every filter, for the callers that must cover all of them (guards, tests).
|
|
45034
|
+
*
|
|
45035
|
+
* `consumableLowPercent` (D642) is not a list but it is a filter in exactly
|
|
45036
|
+
* this sense: it belongs to a family of kinds (the consumable pair) and the
|
|
45037
|
+
* engine consults it only there. It differs in one way the readers must know —
|
|
45038
|
+
* its ABSENCE is not "no narrowing" but the default threshold, because a
|
|
45039
|
+
* consumable episode is always judged at SOME threshold.
|
|
45040
|
+
*/
|
|
44763
45041
|
var NC_SYSTEM_EVENT_FILTER_KEYS = [
|
|
44764
45042
|
"deviceIds",
|
|
44765
45043
|
"deviceTypes",
|
|
44766
45044
|
"nodeIds",
|
|
44767
|
-
"packageNames"
|
|
45045
|
+
"packageNames",
|
|
45046
|
+
"consumableLowPercent"
|
|
44768
45047
|
];
|
|
44769
45048
|
new Map(Object.entries({
|
|
44770
45049
|
"device-online": "device-events",
|
|
@@ -44775,6 +45054,9 @@ new Map(Object.entries({
|
|
|
44775
45054
|
"device-battery-normal": "device-events",
|
|
44776
45055
|
"device-consumable-low": "device-events",
|
|
44777
45056
|
"device-consumable-normal": "device-events",
|
|
45057
|
+
"device-tank-low": "device-events",
|
|
45058
|
+
"device-tank-full": "device-events",
|
|
45059
|
+
"device-tank-normal": "device-events",
|
|
44778
45060
|
"stream-online": "device-events",
|
|
44779
45061
|
"stream-offline": "device-events",
|
|
44780
45062
|
"detection-blind": "device-events",
|
|
@@ -44804,11 +45086,141 @@ new Map(Object.entries({
|
|
|
44804
45086
|
"camera-enabled": null
|
|
44805
45087
|
}));
|
|
44806
45088
|
[...NC_SYSTEM_EVENT_FILTER_KEYS];
|
|
45089
|
+
var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
45090
|
+
{
|
|
45091
|
+
id: "device-state",
|
|
45092
|
+
family: "device-events",
|
|
45093
|
+
label: "Device state",
|
|
45094
|
+
kinds: [
|
|
45095
|
+
"device-offline",
|
|
45096
|
+
"device-online",
|
|
45097
|
+
"device-disabled",
|
|
45098
|
+
"device-enabled"
|
|
45099
|
+
]
|
|
45100
|
+
},
|
|
45101
|
+
{
|
|
45102
|
+
id: "streams",
|
|
45103
|
+
family: "device-events",
|
|
45104
|
+
label: "Streams",
|
|
45105
|
+
kinds: ["stream-offline", "stream-online"]
|
|
45106
|
+
},
|
|
45107
|
+
{
|
|
45108
|
+
id: "battery",
|
|
45109
|
+
family: "device-events",
|
|
45110
|
+
label: "Battery",
|
|
45111
|
+
kinds: ["device-battery-low", "device-battery-normal"]
|
|
45112
|
+
},
|
|
45113
|
+
{
|
|
45114
|
+
id: "consumables",
|
|
45115
|
+
family: "device-events",
|
|
45116
|
+
label: "Consumables",
|
|
45117
|
+
kinds: ["device-consumable-low", "device-consumable-normal"]
|
|
45118
|
+
},
|
|
45119
|
+
{
|
|
45120
|
+
id: "tanks",
|
|
45121
|
+
family: "device-events",
|
|
45122
|
+
label: "Tanks",
|
|
45123
|
+
kinds: [
|
|
45124
|
+
"device-tank-low",
|
|
45125
|
+
"device-tank-full",
|
|
45126
|
+
"device-tank-normal"
|
|
45127
|
+
]
|
|
45128
|
+
},
|
|
45129
|
+
{
|
|
45130
|
+
id: "detection-blind",
|
|
45131
|
+
family: "device-events",
|
|
45132
|
+
label: "Detecting nothing",
|
|
45133
|
+
kinds: ["detection-blind"]
|
|
45134
|
+
},
|
|
45135
|
+
{
|
|
45136
|
+
id: "nodes",
|
|
45137
|
+
family: "system",
|
|
45138
|
+
label: "Nodes",
|
|
45139
|
+
kinds: [
|
|
45140
|
+
"node-offline",
|
|
45141
|
+
"node-online",
|
|
45142
|
+
"node-inference-unavailable"
|
|
45143
|
+
]
|
|
45144
|
+
},
|
|
45145
|
+
{
|
|
45146
|
+
id: "addons",
|
|
45147
|
+
family: "system",
|
|
45148
|
+
label: "Addons",
|
|
45149
|
+
kinds: [
|
|
45150
|
+
"addon-crash-loop",
|
|
45151
|
+
"addon-update-available",
|
|
45152
|
+
"addon-updated"
|
|
45153
|
+
]
|
|
45154
|
+
},
|
|
45155
|
+
{
|
|
45156
|
+
id: "updates",
|
|
45157
|
+
family: "system",
|
|
45158
|
+
label: "Server & container updates",
|
|
45159
|
+
kinds: [
|
|
45160
|
+
"server-update-available",
|
|
45161
|
+
"server-updated",
|
|
45162
|
+
"wrapper-update-available"
|
|
45163
|
+
]
|
|
45164
|
+
},
|
|
45165
|
+
{
|
|
45166
|
+
id: "backups-exports",
|
|
45167
|
+
family: "system",
|
|
45168
|
+
label: "Backups & exports",
|
|
45169
|
+
kinds: ["backup-completed", "export-completed"]
|
|
45170
|
+
},
|
|
45171
|
+
{
|
|
45172
|
+
id: "alarm",
|
|
45173
|
+
family: "alarm",
|
|
45174
|
+
label: "Alarm",
|
|
45175
|
+
kinds: NC_ALARM_SYSTEM_EVENT_KINDS
|
|
45176
|
+
}
|
|
45177
|
+
];
|
|
45178
|
+
function systemEventKindsOfFamily(family) {
|
|
45179
|
+
return NC_SYSTEM_EVENT_KIND_GROUP_SPECS.filter((g) => g.family === family).flatMap((g) => g.kinds);
|
|
45180
|
+
}
|
|
44807
45181
|
NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
|
|
45182
|
+
/**
|
|
45183
|
+
* WHICH WAY A BOOLEAN SENSOR MOVED — read off the one slice a sensor event
|
|
45184
|
+
* persists (D640 "a sensor rule fires on the raise, the clear, or both").
|
|
45185
|
+
*
|
|
45186
|
+
* A device-event rule over a flood sensor notified on BOTH edges: water
|
|
45187
|
+
* detected, and back to dry. `NcConditions.sensorTransition` lets the rule
|
|
45188
|
+
* name one edge; this file answers, for one `SensorEvent`, which edge it is.
|
|
45189
|
+
*
|
|
45190
|
+
* NOT A SECOND TABLE. The "which boolean of this cap counts as HIGH" question
|
|
45191
|
+
* already has one answer, `SOURCE_CAP_ACTIVE_FIELD`
|
|
45192
|
+
* (`catalogs/sensor-active-state.ts`, the doorbell's and the recorder's edge
|
|
45193
|
+
* table), and a sensor event names its kind, not its cap. So the table here is
|
|
45194
|
+
* DERIVED: event kind → cap (`EVENT_KIND_BY_CAP`) → that cap's active field.
|
|
45195
|
+
* Only kinds whose taxonomy category is `sensor` take part — a switch has an
|
|
45196
|
+
* `on` boolean too, but "it triggers / it clears" is not a sentence about a
|
|
45197
|
+
* light, and offering it there would be a knob with a misleading label.
|
|
45198
|
+
* `presence` is a WORD (`home` / `not_home` / a zone), not a boolean, and is
|
|
45199
|
+
* absent from the source table, so it is absent here.
|
|
45200
|
+
*
|
|
45201
|
+
* `undefined` = never guessed: a kind with no raise (a doorbell press, a
|
|
45202
|
+
* button, a cover), or a slice whose field is missing or not a boolean. The
|
|
45203
|
+
* engine then does NOT filter — a flood alert must not go silent because one
|
|
45204
|
+
* read came back unreadable (the same stance as the alarm's `sensorEdgeOf`).
|
|
45205
|
+
*
|
|
45206
|
+
* Pure, RN-safe: the viewer imports the support rule from here.
|
|
45207
|
+
*/
|
|
45208
|
+
/** Event kind → the boolean field of its cap slice that means "raised". */
|
|
45209
|
+
var NC_SENSOR_RAISED_FIELD_BY_KIND = Object.freeze(Object.fromEntries(Object.entries(EVENT_KIND_BY_CAP).flatMap(([capName, descriptor]) => {
|
|
45210
|
+
const field = SOURCE_CAP_ACTIVE_FIELD[capName];
|
|
45211
|
+
if (field === void 0 || descriptor.category !== "sensor") return [];
|
|
45212
|
+
return [[descriptor.kind, field]];
|
|
45213
|
+
})));
|
|
45214
|
+
Object.freeze(Object.keys(NC_SENSOR_RAISED_FIELD_BY_KIND));
|
|
44808
45215
|
var RULE_BODY_ONLY = ["body"];
|
|
44809
45216
|
var RULE_TEXT = ["title", "body"];
|
|
44810
45217
|
var BATTERY = ["device-battery-low", "device-battery-normal"];
|
|
44811
45218
|
var CONSUMABLE = ["device-consumable-low", "device-consumable-normal"];
|
|
45219
|
+
var TANK = [
|
|
45220
|
+
"device-tank-low",
|
|
45221
|
+
"device-tank-full",
|
|
45222
|
+
"device-tank-normal"
|
|
45223
|
+
];
|
|
44812
45224
|
var UPDATES = [
|
|
44813
45225
|
"addon-update-available",
|
|
44814
45226
|
"server-update-available",
|
|
@@ -44834,12 +45246,189 @@ var DEVICE_EVENTS = [
|
|
|
44834
45246
|
"device-enabled",
|
|
44835
45247
|
...BATTERY,
|
|
44836
45248
|
...CONSUMABLE,
|
|
45249
|
+
...TANK,
|
|
44837
45250
|
"stream-online",
|
|
44838
45251
|
"stream-offline",
|
|
44839
45252
|
"detection-blind",
|
|
44840
45253
|
...ALARM
|
|
44841
45254
|
];
|
|
44842
|
-
|
|
45255
|
+
/** Every kind a summary may speak about — the two summarisable families. */
|
|
45256
|
+
var SUMMARISABLE = [...systemEventKindsOfFamily("device-events"), ...systemEventKindsOfFamily("system")];
|
|
45257
|
+
/** One per summary SECTION (`NC_STATE_SUMMARY_SECTIONS` in the notification
|
|
45258
|
+
* centre): the section's lines, offered when one of its kinds is selected. */
|
|
45259
|
+
var STATE_SUMMARY_SECTION_VARS = [
|
|
45260
|
+
{
|
|
45261
|
+
name: "summaryDevices",
|
|
45262
|
+
label: "Summary: devices offline / switched off",
|
|
45263
|
+
example: "Garage — offline since 07:12",
|
|
45264
|
+
kinds: [
|
|
45265
|
+
"device-offline",
|
|
45266
|
+
"device-online",
|
|
45267
|
+
"device-disabled",
|
|
45268
|
+
"device-enabled"
|
|
45269
|
+
]
|
|
45270
|
+
},
|
|
45271
|
+
{
|
|
45272
|
+
name: "summaryStreams",
|
|
45273
|
+
label: "Summary: streams offline",
|
|
45274
|
+
example: "Ingresso (high) — since 06:40",
|
|
45275
|
+
kinds: ["stream-offline", "stream-online"]
|
|
45276
|
+
},
|
|
45277
|
+
{
|
|
45278
|
+
name: "summaryBattery",
|
|
45279
|
+
label: "Summary: low batteries",
|
|
45280
|
+
example: "Sensore porta — 8 %",
|
|
45281
|
+
kinds: BATTERY
|
|
45282
|
+
},
|
|
45283
|
+
{
|
|
45284
|
+
name: "summaryConsumables",
|
|
45285
|
+
label: "Summary: consumables",
|
|
45286
|
+
example: "Robot — filter 10 %",
|
|
45287
|
+
kinds: CONSUMABLE
|
|
45288
|
+
},
|
|
45289
|
+
{
|
|
45290
|
+
name: "summaryTanks",
|
|
45291
|
+
label: "Summary: tanks",
|
|
45292
|
+
example: "Robot — clean water low",
|
|
45293
|
+
kinds: TANK
|
|
45294
|
+
},
|
|
45295
|
+
{
|
|
45296
|
+
name: "summaryDetection",
|
|
45297
|
+
label: "Summary: cameras detecting nothing",
|
|
45298
|
+
example: "Ingresso — since 05:10",
|
|
45299
|
+
kinds: ["detection-blind"]
|
|
45300
|
+
},
|
|
45301
|
+
{
|
|
45302
|
+
name: "summaryNodes",
|
|
45303
|
+
label: "Summary: nodes",
|
|
45304
|
+
example: "little-unraid — offline since 03:00",
|
|
45305
|
+
kinds: [
|
|
45306
|
+
"node-offline",
|
|
45307
|
+
"node-online",
|
|
45308
|
+
"node-inference-unavailable"
|
|
45309
|
+
]
|
|
45310
|
+
},
|
|
45311
|
+
{
|
|
45312
|
+
name: "summaryAddons",
|
|
45313
|
+
label: "Summary: addons",
|
|
45314
|
+
example: "@camstack/addon-recorder 1.2.3 → 1.2.4",
|
|
45315
|
+
kinds: [
|
|
45316
|
+
"addon-crash-loop",
|
|
45317
|
+
"addon-update-available",
|
|
45318
|
+
"addon-updated"
|
|
45319
|
+
]
|
|
45320
|
+
},
|
|
45321
|
+
{
|
|
45322
|
+
name: "summaryUpdates",
|
|
45323
|
+
label: "Summary: server & container updates",
|
|
45324
|
+
example: "server 1.2.377 → 1.2.378",
|
|
45325
|
+
kinds: [
|
|
45326
|
+
"server-update-available",
|
|
45327
|
+
"server-updated",
|
|
45328
|
+
"wrapper-update-available"
|
|
45329
|
+
]
|
|
45330
|
+
}
|
|
45331
|
+
];
|
|
45332
|
+
var STATE_SUMMARY_VARS = [
|
|
45333
|
+
{
|
|
45334
|
+
name: "summaryText",
|
|
45335
|
+
label: "Summary: every section",
|
|
45336
|
+
description: "One block per section with something to report, one line per item.",
|
|
45337
|
+
example: "Batterie scariche: Sensore porta — 8 %",
|
|
45338
|
+
group: "system",
|
|
45339
|
+
families: ["rule"],
|
|
45340
|
+
fields: [...RULE_TEXT],
|
|
45341
|
+
kinds: ["system"],
|
|
45342
|
+
systemEventKinds: [...SUMMARISABLE],
|
|
45343
|
+
systemEventDeliveries: ["summary"]
|
|
45344
|
+
},
|
|
45345
|
+
{
|
|
45346
|
+
name: "summaryCount",
|
|
45347
|
+
label: "Summary: items reported",
|
|
45348
|
+
example: "3",
|
|
45349
|
+
group: "system",
|
|
45350
|
+
families: ["rule"],
|
|
45351
|
+
fields: [...RULE_TEXT],
|
|
45352
|
+
kinds: ["system"],
|
|
45353
|
+
systemEventKinds: [...SUMMARISABLE],
|
|
45354
|
+
systemEventDeliveries: ["summary"]
|
|
45355
|
+
},
|
|
45356
|
+
...STATE_SUMMARY_SECTION_VARS.map((v) => ({
|
|
45357
|
+
name: v.name,
|
|
45358
|
+
label: v.label,
|
|
45359
|
+
example: v.example,
|
|
45360
|
+
group: "system",
|
|
45361
|
+
families: ["rule"],
|
|
45362
|
+
fields: [...RULE_TEXT],
|
|
45363
|
+
kinds: ["system"],
|
|
45364
|
+
systemEventKinds: [...v.kinds],
|
|
45365
|
+
systemEventDeliveries: ["summary"]
|
|
45366
|
+
}))
|
|
45367
|
+
];
|
|
45368
|
+
[
|
|
45369
|
+
[...DEVICE_EVENTS],
|
|
45370
|
+
([...RULE_TEXT], [...COMBINED_ALARM]),
|
|
45371
|
+
([...RULE_TEXT], [...COMBINED_ALARM]),
|
|
45372
|
+
[...RULE_TEXT],
|
|
45373
|
+
([...RULE_TEXT], [...COMBINED_ALARM]),
|
|
45374
|
+
([...RULE_TEXT], [...PACKAGE_UPDATES]),
|
|
45375
|
+
[...RULE_TEXT],
|
|
45376
|
+
([...RULE_TEXT], [...COMBINED_ALARM]),
|
|
45377
|
+
([...RULE_TEXT], [...COMBINED_ALARM]),
|
|
45378
|
+
([...RULE_TEXT], [...COMBINED_ALARM]),
|
|
45379
|
+
[...RULE_TEXT],
|
|
45380
|
+
[...RULE_TEXT],
|
|
45381
|
+
[...RULE_TEXT],
|
|
45382
|
+
[...RULE_TEXT],
|
|
45383
|
+
[...RULE_TEXT],
|
|
45384
|
+
[...RULE_TEXT],
|
|
45385
|
+
[...RULE_TEXT],
|
|
45386
|
+
[...RULE_TEXT],
|
|
45387
|
+
[...RULE_BODY_ONLY],
|
|
45388
|
+
[...RULE_TEXT],
|
|
45389
|
+
([...RULE_TEXT], [...DEVICE_EVENTS]),
|
|
45390
|
+
([...RULE_TEXT], [...DEVICE_EVENTS]),
|
|
45391
|
+
([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
|
|
45392
|
+
([...RULE_TEXT], [...CONSUMABLE]),
|
|
45393
|
+
([...RULE_TEXT], [...TANK]),
|
|
45394
|
+
[...RULE_TEXT],
|
|
45395
|
+
([...RULE_TEXT], [...UPDATES]),
|
|
45396
|
+
([...RULE_TEXT], [...UPDATES]),
|
|
45397
|
+
[...RULE_TEXT],
|
|
45398
|
+
[...RULE_TEXT],
|
|
45399
|
+
[...RULE_TEXT],
|
|
45400
|
+
([...RULE_TEXT], [...UPDATES]),
|
|
45401
|
+
([...RULE_TEXT], [...PACKAGE_UPDATES]),
|
|
45402
|
+
([...RULE_TEXT], [...PACKAGE_UPDATES]),
|
|
45403
|
+
([...RULE_TEXT], [...UPDATES]),
|
|
45404
|
+
([...RULE_TEXT], [...UPDATES]),
|
|
45405
|
+
([...RULE_TEXT], [...PACKAGE_UPDATES]),
|
|
45406
|
+
[...RULE_TEXT],
|
|
45407
|
+
[...RULE_TEXT],
|
|
45408
|
+
[...RULE_TEXT],
|
|
45409
|
+
[...RULE_TEXT],
|
|
45410
|
+
[...RULE_TEXT],
|
|
45411
|
+
[...RULE_TEXT],
|
|
45412
|
+
[...RULE_TEXT],
|
|
45413
|
+
[...RULE_TEXT],
|
|
45414
|
+
[...RULE_TEXT],
|
|
45415
|
+
[...RULE_TEXT],
|
|
45416
|
+
[...RULE_TEXT],
|
|
45417
|
+
[...RULE_TEXT],
|
|
45418
|
+
[...RULE_TEXT],
|
|
45419
|
+
[...RULE_TEXT],
|
|
45420
|
+
[...RULE_TEXT],
|
|
45421
|
+
[...RULE_TEXT],
|
|
45422
|
+
[...RULE_TEXT],
|
|
45423
|
+
[...RULE_TEXT],
|
|
45424
|
+
[...RULE_TEXT],
|
|
45425
|
+
[...RULE_TEXT],
|
|
45426
|
+
[...RULE_TEXT],
|
|
45427
|
+
[...RULE_TEXT],
|
|
45428
|
+
[...RULE_TEXT],
|
|
45429
|
+
[...RULE_TEXT],
|
|
45430
|
+
...STATE_SUMMARY_VARS
|
|
45431
|
+
];
|
|
44843
45432
|
/**
|
|
44844
45433
|
* TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
|
|
44845
45434
|
*
|