@camstack/system 1.2.25 → 1.2.26
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/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/device-manager/device-aggregation.d.ts +18 -0
- package/dist/builtins/device-manager/device-manager.addon.js +47 -1
- package/dist/builtins/device-manager/device-manager.addon.mjs +47 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +0 -19
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +143 -67
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +143 -67
- package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +67 -7
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-CS0pdC8l.js → dist-Cu72wsz5.js} +132 -3
- package/dist/{dist-CIek6F9X.mjs → dist-DimX9eZy.mjs} +132 -3
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
|
@@ -37,6 +37,21 @@ export type StorageProviderLookup = () => readonly IStorageProviderImpl[];
|
|
|
37
37
|
* remote), the safe default for the early-boot / in-memory path.
|
|
38
38
|
*/
|
|
39
39
|
export type NodeLocalResolver = (providerId: string) => boolean | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Where a single dispatch must execute: which `storage-provider`, on which
|
|
42
|
+
* node. `providerId` alone is NOT a routing key — every node's filesystem
|
|
43
|
+
* provider registers under the same id, so a target without its `nodeId`
|
|
44
|
+
* silently resolves to whichever node asked (the hub).
|
|
45
|
+
*
|
|
46
|
+
* `nodeId` absent = node-agnostic (S3/SFTP/WebDAV): reachable from anywhere,
|
|
47
|
+
* so the local provider runs it.
|
|
48
|
+
*/
|
|
49
|
+
export interface StorageDispatchTarget {
|
|
50
|
+
readonly providerId: string;
|
|
51
|
+
readonly nodeId?: string;
|
|
52
|
+
}
|
|
53
|
+
/** The two chunked-I/O session families the orchestrator tracks. */
|
|
54
|
+
export type StorageSessionKind = 'upload' | 'download';
|
|
40
55
|
export declare class StorageOrchestratorService {
|
|
41
56
|
private readonly logger;
|
|
42
57
|
private readonly getProviders;
|
|
@@ -54,8 +69,6 @@ export declare class StorageOrchestratorService {
|
|
|
54
69
|
* the provider appears. See {@link attachStore}.
|
|
55
70
|
*/
|
|
56
71
|
private locationStore;
|
|
57
|
-
/** This node's id — locations pinned to OTHER nodes dispatch remotely. */
|
|
58
|
-
private readonly localNodeId;
|
|
59
72
|
/** Cross-node provider resolver (hub wiring: a node-routed capability
|
|
60
73
|
* proxy over `storage-provider`). Absent → remote locations error. */
|
|
61
74
|
private readonly getRemoteProvider?;
|
|
@@ -76,6 +89,15 @@ export declare class StorageOrchestratorService {
|
|
|
76
89
|
* early-boot path that predates the resolver wiring.
|
|
77
90
|
*/
|
|
78
91
|
private nodeLocalResolver;
|
|
92
|
+
/** `localNodeId` with any forked-child `/addon` suffix stripped. */
|
|
93
|
+
private readonly localNode;
|
|
94
|
+
/**
|
|
95
|
+
* `<kind>:<sessionId>` → the dispatch target that OPENED the session.
|
|
96
|
+
* Chunked I/O carries no `StorageLocation` after the first hop, so without
|
|
97
|
+
* this the follow-up chunks fall back to a `providerId`-only lookup — which
|
|
98
|
+
* on a multi-node cluster means the hub's filesystem, not the agent's.
|
|
99
|
+
*/
|
|
100
|
+
private readonly sessionTargets;
|
|
79
101
|
constructor(logger: IScopedLogger, getProviders: StorageProviderLookup,
|
|
80
102
|
/**
|
|
81
103
|
* Optional persistence backend. When supplied, `initialize()`
|
|
@@ -96,6 +118,12 @@ export declare class StorageOrchestratorService {
|
|
|
96
118
|
/** Cross-node provider resolver (hub wiring: a node-routed capability
|
|
97
119
|
* proxy over `storage-provider`). Absent → remote locations error. */
|
|
98
120
|
getRemoteProvider?: ((nodeId: string) => IStorageProviderImpl | null) | undefined);
|
|
121
|
+
/**
|
|
122
|
+
* The node this orchestrator runs on, with any forked-child `/addon`
|
|
123
|
+
* suffix stripped. A location whose `nodeId` differs is NOT this node's
|
|
124
|
+
* to touch — its bytes, and its free space, live elsewhere.
|
|
125
|
+
*/
|
|
126
|
+
getLocalNodeId(): string;
|
|
99
127
|
/** True once a persistence store is wired (constructor or {@link attachStore}). */
|
|
100
128
|
hasStore(): boolean;
|
|
101
129
|
/**
|
|
@@ -210,13 +238,45 @@ export declare class StorageOrchestratorService {
|
|
|
210
238
|
*/
|
|
211
239
|
resolveRef(ref: StorageLocationRef): StorageLocation;
|
|
212
240
|
/**
|
|
213
|
-
* Find the storage-provider that backs a given location
|
|
214
|
-
* `
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
241
|
+
* Find the storage-provider that backs a given location — the entry point
|
|
242
|
+
* every consumer-facing `storage` cap method funnels through.
|
|
243
|
+
*
|
|
244
|
+
* Routing key is `(providerId, nodeId)`, never `providerId` alone: every
|
|
245
|
+
* node's FilesystemStorageProvider registers under the SAME providerId, so
|
|
246
|
+
* a providerId-only match resolves to whichever node asked. That is how a
|
|
247
|
+
* location created on an agent ended up writing to the HUB's filesystem
|
|
248
|
+
* (root-caused 2026-07-29).
|
|
218
249
|
*/
|
|
219
250
|
getProviderFor(location: StorageLocation): Promise<IStorageProviderImpl>;
|
|
251
|
+
/**
|
|
252
|
+
* Resolve one dispatch target to the provider that must execute it.
|
|
253
|
+
*
|
|
254
|
+
* `descriptor` is the operator-facing subject of the error message
|
|
255
|
+
* (`location "recordings:disk"`, `uploadId "u-42"`); `locationId` is the
|
|
256
|
+
* structured tag for the log line when there is a location behind the
|
|
257
|
+
* dispatch (chunked sessions carry only the session id).
|
|
258
|
+
*
|
|
259
|
+
* Both failure branches LOG before throwing, and NEITHER falls back to the
|
|
260
|
+
* local provider — a silent fallback is the bug this method exists to fix.
|
|
261
|
+
*/
|
|
262
|
+
private getProviderForTarget;
|
|
263
|
+
/**
|
|
264
|
+
* Remember which provider — and on which NODE — opened a chunked session.
|
|
265
|
+
* `beginUpload` / `beginDownload` carry a `StorageLocation`; every later
|
|
266
|
+
* chunk carries only the session id, and a session id issued by an agent
|
|
267
|
+
* means nothing to the hub's provider.
|
|
268
|
+
*/
|
|
269
|
+
rememberSession(kind: StorageSessionKind, sessionId: string, location: StorageLocation): void;
|
|
270
|
+
/** Drop a session's routing entry (finalize / abort / end). */
|
|
271
|
+
forgetSession(kind: StorageSessionKind, sessionId: string): void;
|
|
272
|
+
/** Drop every session entry (addon shutdown). */
|
|
273
|
+
clearSessions(): void;
|
|
274
|
+
/**
|
|
275
|
+
* Resolve the provider that owns an in-flight chunked session, on the node
|
|
276
|
+
* that opened it. Throws when the orchestrator has no record of the open
|
|
277
|
+
* call (provider gone, or a chunk for a session it never issued).
|
|
278
|
+
*/
|
|
279
|
+
getProviderForSession(kind: StorageSessionKind, sessionId: string): Promise<IStorageProviderImpl>;
|
|
220
280
|
/** Convenience: lookup by id (returns `undefined` if not found). */
|
|
221
281
|
getLocationById(id: string): StorageLocation | undefined;
|
|
222
282
|
/**
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-Cu72wsz5.js");
|
|
7
7
|
//#region src/builtins/system-config/system-config.addon.ts
|
|
8
8
|
/**
|
|
9
9
|
* Built-in `system-config` addon — Phase 4 of the settings redesign.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { St as hydrateSchema, at as BaseAddon, it as errMsg } from "../../dist-
|
|
1
|
+
import { St as hydrateSchema, at as BaseAddon, it as errMsg } from "../../dist-DimX9eZy.mjs";
|
|
2
2
|
//#region src/builtins/system-config/system-config.addon.ts
|
|
3
3
|
/**
|
|
4
4
|
* Built-in `system-config` addon — Phase 4 of the settings redesign.
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-Cu72wsz5.js");
|
|
7
7
|
const require_formatter = require("../../formatter-DqAKDlvN.js");
|
|
8
8
|
let node_path = require("node:path");
|
|
9
9
|
node_path = require_chunk.__toESM(node_path);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { at as BaseAddon, z as logDestinationCapability } from "../../dist-
|
|
1
|
+
import { at as BaseAddon, z as logDestinationCapability } from "../../dist-DimX9eZy.mjs";
|
|
2
2
|
import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
|
|
3
3
|
import * as path$1 from "node:path";
|
|
4
4
|
import path from "node:path";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
let zod = require("zod");
|
|
2
|
-
//#region ../types/dist/event-category-
|
|
2
|
+
//#region ../types/dist/event-category-Bz24uP1U.mjs
|
|
3
3
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
4
4
|
EventCategory["SystemBoot"] = "system.boot";
|
|
5
5
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -270,6 +270,19 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
270
270
|
*/
|
|
271
271
|
EventCategory["DeviceStateChanged"] = "device.state-changed";
|
|
272
272
|
/**
|
|
273
|
+
* Frame occupancy for a camera CHANGED — a tracked object was gained or
|
|
274
|
+
* lost. Carries `{ deviceId, totalObjects, byClass, zones }`.
|
|
275
|
+
*
|
|
276
|
+
* Emitted only on a change, so a steady scene is silent. It exists so a
|
|
277
|
+
* client can stop polling `zoneAnalytics.getCurrentSnapshot`: that was the
|
|
278
|
+
* one live badge with no push signal at all, and it cost a request every
|
|
279
|
+
* four seconds per visible camera.
|
|
280
|
+
*
|
|
281
|
+
* Like every event it is telemetry and may be dropped ([D8]) — a consumer
|
|
282
|
+
* keeps a slow reconcile rather than trusting it alone.
|
|
283
|
+
*/
|
|
284
|
+
EventCategory["ZoneAnalyticsOccupancyChanged"] = "zone-analytics.occupancy-changed";
|
|
285
|
+
/**
|
|
273
286
|
* Cap event fired by every device that registers the `battery`
|
|
274
287
|
* capability. Mirrors the cap definition's `onStatusChanged`. Carries
|
|
275
288
|
* `{ deviceId, status: BatteryStatus }`. Subscribers (alert center,
|
|
@@ -5326,6 +5339,29 @@ var NcOccupancyConditionSchema = zod.z.object({
|
|
|
5326
5339
|
count: zod.z.number().int().min(0).default(1),
|
|
5327
5340
|
sustainSeconds: zod.z.number().int().min(0).max(3600).default(15)
|
|
5328
5341
|
});
|
|
5342
|
+
/**
|
|
5343
|
+
* Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
|
|
5344
|
+
*
|
|
5345
|
+
* The values are not symmetric, and deliberately so — the absent value has to
|
|
5346
|
+
* mean exactly what every rule authored before this condition existed already
|
|
5347
|
+
* does:
|
|
5348
|
+
* - `enter` — entries and every NON-crossing record (movement state,
|
|
5349
|
+
* package, sensor). Exits are rejected. **This is the absent behaviour**:
|
|
5350
|
+
* an operator who never asked for exits must not start receiving them.
|
|
5351
|
+
* - `exit` — ONLY an exit crossing. A record that is not a crossing at all
|
|
5352
|
+
* fails closed, because "the car left the drive" is a question about a
|
|
5353
|
+
* boundary, not about a detection.
|
|
5354
|
+
* - `any` — no direction filter; entries, exits and non-crossings alike.
|
|
5355
|
+
*
|
|
5356
|
+
* A rule asking for a direction should normally also scope `zones`, which the
|
|
5357
|
+
* engine evaluates against the crossed zone as well as the current membership
|
|
5358
|
+
* (an exit's membership no longer contains the zone it just left).
|
|
5359
|
+
*/
|
|
5360
|
+
var NcCrossingSchema = zod.z.enum([
|
|
5361
|
+
"enter",
|
|
5362
|
+
"exit",
|
|
5363
|
+
"any"
|
|
5364
|
+
]);
|
|
5329
5365
|
/** Admin-zone membership condition (zone IDs as stamped by the ZoneEngine). */
|
|
5330
5366
|
var NcZoneConditionSchema = zod.z.object({
|
|
5331
5367
|
ids: zod.z.array(zod.z.string().min(1)).min(1),
|
|
@@ -5350,6 +5386,13 @@ var NcConditionsSchema = zod.z.object({
|
|
|
5350
5386
|
/** Veto zones — any hit fails the rule. */
|
|
5351
5387
|
zonesExclude: zod.z.array(zod.z.string().min(1)).optional(),
|
|
5352
5388
|
/**
|
|
5389
|
+
* Zone-crossing direction. IMMEDIATE only — a crossing is a per-event fact
|
|
5390
|
+
* and a closed track carries none, so a `track-end` rule asking for one
|
|
5391
|
+
* fails closed (use `zones`, which tests `zonesVisited`). ABSENT = `enter`,
|
|
5392
|
+
* which is exactly today's behaviour. See {@link NcCrossingSchema}.
|
|
5393
|
+
*/
|
|
5394
|
+
crossing: NcCrossingSchema.optional(),
|
|
5395
|
+
/**
|
|
5353
5396
|
* Exact (case-insensitive) match on the record's collapsed `label`
|
|
5354
5397
|
* (identity name / plate text / subclass).
|
|
5355
5398
|
*/
|
|
@@ -5538,11 +5581,31 @@ var NcMediaPolicySchema = zod.z.object({
|
|
|
5538
5581
|
*/
|
|
5539
5582
|
profile: CamProfileSchema.optional()
|
|
5540
5583
|
});
|
|
5584
|
+
/**
|
|
5585
|
+
* Cooldown GRANULARITY over the subject's class — how much a fired
|
|
5586
|
+
* notification suppresses.
|
|
5587
|
+
* - `shared` (default, and the absent value) — one window for the whole
|
|
5588
|
+
* rule/scope: a cat silences the next dog for `cooldownSec`.
|
|
5589
|
+
* - `per-class` — an independent window per detected class, so cat→dog fires
|
|
5590
|
+
* at once and cat→cat still waits.
|
|
5591
|
+
*
|
|
5592
|
+
* AUDIO subjects are ALWAYS per-class regardless of this setting: a scream
|
|
5593
|
+
* must not be swallowed by a bark's window (the precedent this generalizes —
|
|
5594
|
+
* see `cooldownKey` in the rule engine).
|
|
5595
|
+
*/
|
|
5596
|
+
var NcThrottleGranularitySchema = zod.z.enum(["shared", "per-class"]);
|
|
5541
5597
|
/** Throttle — cooldown survives restarts (rebuilt from the outbox on boot). */
|
|
5542
5598
|
var NcThrottleSchema = zod.z.object({
|
|
5543
5599
|
cooldownSec: zod.z.number().int().min(0).max(86400).default(60),
|
|
5544
5600
|
/** `rule` = one shared cooldown; `rule-device` = per-camera cooldown. */
|
|
5545
|
-
scope: zod.z.enum(["rule", "rule-device"]).default("rule-device")
|
|
5601
|
+
scope: zod.z.enum(["rule", "rule-device"]).default("rule-device"),
|
|
5602
|
+
/**
|
|
5603
|
+
* Class granularity of the cooldown key. Optional rather than defaulted:
|
|
5604
|
+
* a Zod default does NOT run on the addon→addon cap path, so a persisted
|
|
5605
|
+
* rule authored before this field simply carries none — and the engine
|
|
5606
|
+
* reads absent as `shared`, the pre-existing behaviour.
|
|
5607
|
+
*/
|
|
5608
|
+
granularity: NcThrottleGranularitySchema.optional()
|
|
5546
5609
|
});
|
|
5547
5610
|
/** Client-supplied rule fields (server stamps id/createdBy/createdAt/updatedAt). */
|
|
5548
5611
|
var NcRuleInputSchema = zod.z.object({
|
|
@@ -5650,6 +5713,7 @@ var NcConditionDescriptorSchema = zod.z.object({
|
|
|
5650
5713
|
"schedule",
|
|
5651
5714
|
"plateMatcher",
|
|
5652
5715
|
"packagePhase",
|
|
5716
|
+
"crossingSelect",
|
|
5653
5717
|
"polygonDraw",
|
|
5654
5718
|
"occupancy"
|
|
5655
5719
|
]),
|
|
@@ -15673,7 +15737,29 @@ var deviceManagerCapability = {
|
|
|
15673
15737
|
getDeviceStatusAggregate: method(zod.z.object({
|
|
15674
15738
|
deviceId: zod.z.number(),
|
|
15675
15739
|
caps: zod.z.array(zod.z.string()).readonly().optional()
|
|
15676
|
-
}), zod.z.record(zod.z.string(), zod.z.unknown().nullable()))
|
|
15740
|
+
}), zod.z.record(zod.z.string(), zod.z.unknown().nullable())),
|
|
15741
|
+
/**
|
|
15742
|
+
* The same aggregate, for a LIST of devices in one round-trip.
|
|
15743
|
+
*
|
|
15744
|
+
* The viewer's camera list is the caller this exists for. Each card asked
|
|
15745
|
+
* for its own badges — battery here, recording mode there — so a ten-camera
|
|
15746
|
+
* install issued N separate procedures per reconcile, each its own message
|
|
15747
|
+
* on the one WebSocket that also carries the WebRTC signalling (the client
|
|
15748
|
+
* has no `httpBatchLink`, so there is no transport-level batching to lean
|
|
15749
|
+
* on: collapsing has to happen at the procedure level, which is here).
|
|
15750
|
+
*
|
|
15751
|
+
* Keyed by device id as a STRING — a JSON object cannot key by number, and
|
|
15752
|
+
* pretending otherwise is how a record survives the wire only in tests.
|
|
15753
|
+
* The per-device value is exactly what `getDeviceStatusAggregate` returns,
|
|
15754
|
+
* so a caller can move between the two without reshaping anything.
|
|
15755
|
+
*
|
|
15756
|
+
* `caps` matters more here than in the single call: a client that needs two
|
|
15757
|
+
* caps should not pay for every status-carrying cap × every device.
|
|
15758
|
+
*/
|
|
15759
|
+
getDeviceStatusAggregateBatch: method(zod.z.object({
|
|
15760
|
+
deviceIds: zod.z.array(zod.z.number()).readonly(),
|
|
15761
|
+
caps: zod.z.array(zod.z.string()).readonly().optional()
|
|
15762
|
+
}), zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.unknown().nullable())))
|
|
15677
15763
|
}
|
|
15678
15764
|
};
|
|
15679
15765
|
/**
|
|
@@ -17399,6 +17485,37 @@ var MotionEventSchema = zod.z.object({
|
|
|
17399
17485
|
* Absent on legacy rows ⇒ treat as `pipeline`.
|
|
17400
17486
|
*/
|
|
17401
17487
|
var DetectionSourceSchema = zod.z.enum(["pipeline", "onboard"]);
|
|
17488
|
+
/**
|
|
17489
|
+
* Which WAY a subject crossed a zone boundary. An entry and an exit are two
|
|
17490
|
+
* different notifications ("the parcel arrived" / "the car left the drive"),
|
|
17491
|
+
* and until this existed they were indistinguishable on the persisted record —
|
|
17492
|
+
* which is why exits were computed and dropped at the emit boundary rather
|
|
17493
|
+
* than doubling every zone-scoped rule.
|
|
17494
|
+
*/
|
|
17495
|
+
var ZoneCrossingDirectionSchema = zod.z.enum(["enter", "exit"]);
|
|
17496
|
+
/**
|
|
17497
|
+
* The confirmed zone crossing that produced an object event. Present ONLY on
|
|
17498
|
+
* an event emitted BY a crossing (`zone.enter` / `zone.exit`); a movement-state
|
|
17499
|
+
* event (`object.entering` / `leaving` / `stationary` / `loitering`) and an
|
|
17500
|
+
* appearance event carry none, so a rule asking for a direction fails closed
|
|
17501
|
+
* on them.
|
|
17502
|
+
*
|
|
17503
|
+
* Exactly ONE crossing per event: the emitter turns each confirmed crossing
|
|
17504
|
+
* into its own event, so a frame in which a track enters A while leaving B
|
|
17505
|
+
* produces two events with two directions — never one ambiguous row.
|
|
17506
|
+
*
|
|
17507
|
+
* `zoneId` is load-bearing for an EXIT: the event's `zones` list is the
|
|
17508
|
+
* membership the box has NOW, and by definition it no longer contains the zone
|
|
17509
|
+
* that was just left. Without the id here, a zone-scoped rule could never match
|
|
17510
|
+
* the exit it asked for.
|
|
17511
|
+
*/
|
|
17512
|
+
var ZoneCrossingSchema = zod.z.object({
|
|
17513
|
+
direction: ZoneCrossingDirectionSchema,
|
|
17514
|
+
/** Admin zone id crossed. */
|
|
17515
|
+
zoneId: zod.z.string(),
|
|
17516
|
+
/** Zone display name at crossing time (falls back to the id). */
|
|
17517
|
+
zoneName: zod.z.string().optional()
|
|
17518
|
+
});
|
|
17402
17519
|
var ObjectEventSchema = zod.z.object({
|
|
17403
17520
|
...BaseEventFields,
|
|
17404
17521
|
kind: zod.z.literal("object"),
|
|
@@ -17425,6 +17542,12 @@ var ObjectEventSchema = zod.z.object({
|
|
|
17425
17542
|
zones: zod.z.array(zod.z.string()).readonly().optional(),
|
|
17426
17543
|
/** Omitted in slim projection. */
|
|
17427
17544
|
state: TrackStateSchema.optional(),
|
|
17545
|
+
/**
|
|
17546
|
+
* The zone crossing this event IS, when it is one. Absent on every other
|
|
17547
|
+
* event kind (movement state, appearance, package) — see
|
|
17548
|
+
* {@link ZoneCrossingSchema}. Omitted in slim projection.
|
|
17549
|
+
*/
|
|
17550
|
+
zoneCrossing: ZoneCrossingSchema.optional(),
|
|
17428
17551
|
/** Detection-frame dimensions in pixels — let consumers normalize the
|
|
17429
17552
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
17430
17553
|
frameWidth: zod.z.number().optional(),
|
|
@@ -24958,6 +25081,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
24958
25081
|
addonId: null,
|
|
24959
25082
|
access: "view"
|
|
24960
25083
|
},
|
|
25084
|
+
"deviceManager.getDeviceStatusAggregateBatch": {
|
|
25085
|
+
capName: "device-manager",
|
|
25086
|
+
capScope: "system",
|
|
25087
|
+
addonId: null,
|
|
25088
|
+
access: "view"
|
|
25089
|
+
},
|
|
24961
25090
|
"deviceManager.getLinkedDevices": {
|
|
24962
25091
|
capName: "device-manager",
|
|
24963
25092
|
capScope: "system",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
//#region ../types/dist/event-category-
|
|
2
|
+
//#region ../types/dist/event-category-Bz24uP1U.mjs
|
|
3
3
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
4
4
|
EventCategory["SystemBoot"] = "system.boot";
|
|
5
5
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -270,6 +270,19 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
270
270
|
*/
|
|
271
271
|
EventCategory["DeviceStateChanged"] = "device.state-changed";
|
|
272
272
|
/**
|
|
273
|
+
* Frame occupancy for a camera CHANGED — a tracked object was gained or
|
|
274
|
+
* lost. Carries `{ deviceId, totalObjects, byClass, zones }`.
|
|
275
|
+
*
|
|
276
|
+
* Emitted only on a change, so a steady scene is silent. It exists so a
|
|
277
|
+
* client can stop polling `zoneAnalytics.getCurrentSnapshot`: that was the
|
|
278
|
+
* one live badge with no push signal at all, and it cost a request every
|
|
279
|
+
* four seconds per visible camera.
|
|
280
|
+
*
|
|
281
|
+
* Like every event it is telemetry and may be dropped ([D8]) — a consumer
|
|
282
|
+
* keeps a slow reconcile rather than trusting it alone.
|
|
283
|
+
*/
|
|
284
|
+
EventCategory["ZoneAnalyticsOccupancyChanged"] = "zone-analytics.occupancy-changed";
|
|
285
|
+
/**
|
|
273
286
|
* Cap event fired by every device that registers the `battery`
|
|
274
287
|
* capability. Mirrors the cap definition's `onStatusChanged`. Carries
|
|
275
288
|
* `{ deviceId, status: BatteryStatus }`. Subscribers (alert center,
|
|
@@ -5326,6 +5339,29 @@ var NcOccupancyConditionSchema = z.object({
|
|
|
5326
5339
|
count: z.number().int().min(0).default(1),
|
|
5327
5340
|
sustainSeconds: z.number().int().min(0).max(3600).default(15)
|
|
5328
5341
|
});
|
|
5342
|
+
/**
|
|
5343
|
+
* Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
|
|
5344
|
+
*
|
|
5345
|
+
* The values are not symmetric, and deliberately so — the absent value has to
|
|
5346
|
+
* mean exactly what every rule authored before this condition existed already
|
|
5347
|
+
* does:
|
|
5348
|
+
* - `enter` — entries and every NON-crossing record (movement state,
|
|
5349
|
+
* package, sensor). Exits are rejected. **This is the absent behaviour**:
|
|
5350
|
+
* an operator who never asked for exits must not start receiving them.
|
|
5351
|
+
* - `exit` — ONLY an exit crossing. A record that is not a crossing at all
|
|
5352
|
+
* fails closed, because "the car left the drive" is a question about a
|
|
5353
|
+
* boundary, not about a detection.
|
|
5354
|
+
* - `any` — no direction filter; entries, exits and non-crossings alike.
|
|
5355
|
+
*
|
|
5356
|
+
* A rule asking for a direction should normally also scope `zones`, which the
|
|
5357
|
+
* engine evaluates against the crossed zone as well as the current membership
|
|
5358
|
+
* (an exit's membership no longer contains the zone it just left).
|
|
5359
|
+
*/
|
|
5360
|
+
var NcCrossingSchema = z.enum([
|
|
5361
|
+
"enter",
|
|
5362
|
+
"exit",
|
|
5363
|
+
"any"
|
|
5364
|
+
]);
|
|
5329
5365
|
/** Admin-zone membership condition (zone IDs as stamped by the ZoneEngine). */
|
|
5330
5366
|
var NcZoneConditionSchema = z.object({
|
|
5331
5367
|
ids: z.array(z.string().min(1)).min(1),
|
|
@@ -5350,6 +5386,13 @@ var NcConditionsSchema = z.object({
|
|
|
5350
5386
|
/** Veto zones — any hit fails the rule. */
|
|
5351
5387
|
zonesExclude: z.array(z.string().min(1)).optional(),
|
|
5352
5388
|
/**
|
|
5389
|
+
* Zone-crossing direction. IMMEDIATE only — a crossing is a per-event fact
|
|
5390
|
+
* and a closed track carries none, so a `track-end` rule asking for one
|
|
5391
|
+
* fails closed (use `zones`, which tests `zonesVisited`). ABSENT = `enter`,
|
|
5392
|
+
* which is exactly today's behaviour. See {@link NcCrossingSchema}.
|
|
5393
|
+
*/
|
|
5394
|
+
crossing: NcCrossingSchema.optional(),
|
|
5395
|
+
/**
|
|
5353
5396
|
* Exact (case-insensitive) match on the record's collapsed `label`
|
|
5354
5397
|
* (identity name / plate text / subclass).
|
|
5355
5398
|
*/
|
|
@@ -5538,11 +5581,31 @@ var NcMediaPolicySchema = z.object({
|
|
|
5538
5581
|
*/
|
|
5539
5582
|
profile: CamProfileSchema.optional()
|
|
5540
5583
|
});
|
|
5584
|
+
/**
|
|
5585
|
+
* Cooldown GRANULARITY over the subject's class — how much a fired
|
|
5586
|
+
* notification suppresses.
|
|
5587
|
+
* - `shared` (default, and the absent value) — one window for the whole
|
|
5588
|
+
* rule/scope: a cat silences the next dog for `cooldownSec`.
|
|
5589
|
+
* - `per-class` — an independent window per detected class, so cat→dog fires
|
|
5590
|
+
* at once and cat→cat still waits.
|
|
5591
|
+
*
|
|
5592
|
+
* AUDIO subjects are ALWAYS per-class regardless of this setting: a scream
|
|
5593
|
+
* must not be swallowed by a bark's window (the precedent this generalizes —
|
|
5594
|
+
* see `cooldownKey` in the rule engine).
|
|
5595
|
+
*/
|
|
5596
|
+
var NcThrottleGranularitySchema = z.enum(["shared", "per-class"]);
|
|
5541
5597
|
/** Throttle — cooldown survives restarts (rebuilt from the outbox on boot). */
|
|
5542
5598
|
var NcThrottleSchema = z.object({
|
|
5543
5599
|
cooldownSec: z.number().int().min(0).max(86400).default(60),
|
|
5544
5600
|
/** `rule` = one shared cooldown; `rule-device` = per-camera cooldown. */
|
|
5545
|
-
scope: z.enum(["rule", "rule-device"]).default("rule-device")
|
|
5601
|
+
scope: z.enum(["rule", "rule-device"]).default("rule-device"),
|
|
5602
|
+
/**
|
|
5603
|
+
* Class granularity of the cooldown key. Optional rather than defaulted:
|
|
5604
|
+
* a Zod default does NOT run on the addon→addon cap path, so a persisted
|
|
5605
|
+
* rule authored before this field simply carries none — and the engine
|
|
5606
|
+
* reads absent as `shared`, the pre-existing behaviour.
|
|
5607
|
+
*/
|
|
5608
|
+
granularity: NcThrottleGranularitySchema.optional()
|
|
5546
5609
|
});
|
|
5547
5610
|
/** Client-supplied rule fields (server stamps id/createdBy/createdAt/updatedAt). */
|
|
5548
5611
|
var NcRuleInputSchema = z.object({
|
|
@@ -5650,6 +5713,7 @@ var NcConditionDescriptorSchema = z.object({
|
|
|
5650
5713
|
"schedule",
|
|
5651
5714
|
"plateMatcher",
|
|
5652
5715
|
"packagePhase",
|
|
5716
|
+
"crossingSelect",
|
|
5653
5717
|
"polygonDraw",
|
|
5654
5718
|
"occupancy"
|
|
5655
5719
|
]),
|
|
@@ -15673,7 +15737,29 @@ var deviceManagerCapability = {
|
|
|
15673
15737
|
getDeviceStatusAggregate: method(z.object({
|
|
15674
15738
|
deviceId: z.number(),
|
|
15675
15739
|
caps: z.array(z.string()).readonly().optional()
|
|
15676
|
-
}), z.record(z.string(), z.unknown().nullable()))
|
|
15740
|
+
}), z.record(z.string(), z.unknown().nullable())),
|
|
15741
|
+
/**
|
|
15742
|
+
* The same aggregate, for a LIST of devices in one round-trip.
|
|
15743
|
+
*
|
|
15744
|
+
* The viewer's camera list is the caller this exists for. Each card asked
|
|
15745
|
+
* for its own badges — battery here, recording mode there — so a ten-camera
|
|
15746
|
+
* install issued N separate procedures per reconcile, each its own message
|
|
15747
|
+
* on the one WebSocket that also carries the WebRTC signalling (the client
|
|
15748
|
+
* has no `httpBatchLink`, so there is no transport-level batching to lean
|
|
15749
|
+
* on: collapsing has to happen at the procedure level, which is here).
|
|
15750
|
+
*
|
|
15751
|
+
* Keyed by device id as a STRING — a JSON object cannot key by number, and
|
|
15752
|
+
* pretending otherwise is how a record survives the wire only in tests.
|
|
15753
|
+
* The per-device value is exactly what `getDeviceStatusAggregate` returns,
|
|
15754
|
+
* so a caller can move between the two without reshaping anything.
|
|
15755
|
+
*
|
|
15756
|
+
* `caps` matters more here than in the single call: a client that needs two
|
|
15757
|
+
* caps should not pay for every status-carrying cap × every device.
|
|
15758
|
+
*/
|
|
15759
|
+
getDeviceStatusAggregateBatch: method(z.object({
|
|
15760
|
+
deviceIds: z.array(z.number()).readonly(),
|
|
15761
|
+
caps: z.array(z.string()).readonly().optional()
|
|
15762
|
+
}), z.record(z.string(), z.record(z.string(), z.unknown().nullable())))
|
|
15677
15763
|
}
|
|
15678
15764
|
};
|
|
15679
15765
|
/**
|
|
@@ -17399,6 +17485,37 @@ var MotionEventSchema = z.object({
|
|
|
17399
17485
|
* Absent on legacy rows ⇒ treat as `pipeline`.
|
|
17400
17486
|
*/
|
|
17401
17487
|
var DetectionSourceSchema = z.enum(["pipeline", "onboard"]);
|
|
17488
|
+
/**
|
|
17489
|
+
* Which WAY a subject crossed a zone boundary. An entry and an exit are two
|
|
17490
|
+
* different notifications ("the parcel arrived" / "the car left the drive"),
|
|
17491
|
+
* and until this existed they were indistinguishable on the persisted record —
|
|
17492
|
+
* which is why exits were computed and dropped at the emit boundary rather
|
|
17493
|
+
* than doubling every zone-scoped rule.
|
|
17494
|
+
*/
|
|
17495
|
+
var ZoneCrossingDirectionSchema = z.enum(["enter", "exit"]);
|
|
17496
|
+
/**
|
|
17497
|
+
* The confirmed zone crossing that produced an object event. Present ONLY on
|
|
17498
|
+
* an event emitted BY a crossing (`zone.enter` / `zone.exit`); a movement-state
|
|
17499
|
+
* event (`object.entering` / `leaving` / `stationary` / `loitering`) and an
|
|
17500
|
+
* appearance event carry none, so a rule asking for a direction fails closed
|
|
17501
|
+
* on them.
|
|
17502
|
+
*
|
|
17503
|
+
* Exactly ONE crossing per event: the emitter turns each confirmed crossing
|
|
17504
|
+
* into its own event, so a frame in which a track enters A while leaving B
|
|
17505
|
+
* produces two events with two directions — never one ambiguous row.
|
|
17506
|
+
*
|
|
17507
|
+
* `zoneId` is load-bearing for an EXIT: the event's `zones` list is the
|
|
17508
|
+
* membership the box has NOW, and by definition it no longer contains the zone
|
|
17509
|
+
* that was just left. Without the id here, a zone-scoped rule could never match
|
|
17510
|
+
* the exit it asked for.
|
|
17511
|
+
*/
|
|
17512
|
+
var ZoneCrossingSchema = z.object({
|
|
17513
|
+
direction: ZoneCrossingDirectionSchema,
|
|
17514
|
+
/** Admin zone id crossed. */
|
|
17515
|
+
zoneId: z.string(),
|
|
17516
|
+
/** Zone display name at crossing time (falls back to the id). */
|
|
17517
|
+
zoneName: z.string().optional()
|
|
17518
|
+
});
|
|
17402
17519
|
var ObjectEventSchema = z.object({
|
|
17403
17520
|
...BaseEventFields,
|
|
17404
17521
|
kind: z.literal("object"),
|
|
@@ -17425,6 +17542,12 @@ var ObjectEventSchema = z.object({
|
|
|
17425
17542
|
zones: z.array(z.string()).readonly().optional(),
|
|
17426
17543
|
/** Omitted in slim projection. */
|
|
17427
17544
|
state: TrackStateSchema.optional(),
|
|
17545
|
+
/**
|
|
17546
|
+
* The zone crossing this event IS, when it is one. Absent on every other
|
|
17547
|
+
* event kind (movement state, appearance, package) — see
|
|
17548
|
+
* {@link ZoneCrossingSchema}. Omitted in slim projection.
|
|
17549
|
+
*/
|
|
17550
|
+
zoneCrossing: ZoneCrossingSchema.optional(),
|
|
17428
17551
|
/** Detection-frame dimensions in pixels — let consumers normalize the
|
|
17429
17552
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
17430
17553
|
frameWidth: z.number().optional(),
|
|
@@ -24958,6 +25081,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
24958
25081
|
addonId: null,
|
|
24959
25082
|
access: "view"
|
|
24960
25083
|
},
|
|
25084
|
+
"deviceManager.getDeviceStatusAggregateBatch": {
|
|
25085
|
+
capName: "device-manager",
|
|
25086
|
+
capScope: "system",
|
|
25087
|
+
addonId: null,
|
|
25088
|
+
access: "view"
|
|
25089
|
+
},
|
|
24961
25090
|
"deviceManager.getLinkedDevices": {
|
|
24962
25091
|
capName: "device-manager",
|
|
24963
25092
|
capScope: "system",
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("./chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("./dist-
|
|
3
|
+
const require_dist = require("./dist-Cu72wsz5.js");
|
|
4
4
|
const require_model_download_service = require("./model-download-service-hf0ookyy.js");
|
|
5
5
|
const require_manifest_python_deps = require("./manifest-python-deps-COgal7Jy.js");
|
|
6
6
|
const require_resource_monitor = require("./resource-monitor-DNNomR-i.js");
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as __toCommonJS, i as __require, n as __esmMin, o as __toESM$1, r as __exportAll, t as __commonJSMin$1 } from "./chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import { B as logLevelAtMost, Dt as readinessKey, Et as parseJsonUnknown$1, F as isVoidInput, I as kebabToCamel, L as lifecycleJobSchema, M as isArrayOutputSchema, N as isCollectionArrayMethod, Ot as resolveCapMount, P as isObjectInput, Tt as parseJsonObject, V as looseSchema, W as objectInputDeclaresAddonId, _t as asString$1, c as RUNTIME_DEFAULTS, ct as DEVICE_STATUS_METHOD, ft as ReadinessRegistry, gt as asNumber, ht as asJsonObject$1, it as errMsg$1, jt as EventCategory$1, k as extractNestedAddonId, kt as scopeKey, m as addonSettingsCapability, ot as DATAPLANE_SECRET_HEADER$1, pt as ReadinessTimeoutError, q as procedureAuthKey, s as METHOD_ACCESS_MAP, st as DEVICE_SETTINGS_CONTRIBUTION_METHODS, t as ALL_CAPABILITY_DEFINITIONS, vt as createEvent, xt as expandCapMethods, yt as emitDownForOwnedCaps } from "./dist-
|
|
2
|
+
import { B as logLevelAtMost, Dt as readinessKey, Et as parseJsonUnknown$1, F as isVoidInput, I as kebabToCamel, L as lifecycleJobSchema, M as isArrayOutputSchema, N as isCollectionArrayMethod, Ot as resolveCapMount, P as isObjectInput, Tt as parseJsonObject, V as looseSchema, W as objectInputDeclaresAddonId, _t as asString$1, c as RUNTIME_DEFAULTS, ct as DEVICE_STATUS_METHOD, ft as ReadinessRegistry, gt as asNumber, ht as asJsonObject$1, it as errMsg$1, jt as EventCategory$1, k as extractNestedAddonId, kt as scopeKey, m as addonSettingsCapability, ot as DATAPLANE_SECRET_HEADER$1, pt as ReadinessTimeoutError, q as procedureAuthKey, s as METHOD_ACCESS_MAP, st as DEVICE_SETTINGS_CONTRIBUTION_METHODS, t as ALL_CAPABILITY_DEFINITIONS, vt as createEvent, xt as expandCapMethods, yt as emitDownForOwnedCaps } from "./dist-DimX9eZy.mjs";
|
|
3
3
|
import { a as downloadModel, c as getModelFilePath, d as contentTypeFor, f as createAuthenticatedFileServer, h as resolveFilePath, i as downloadFile, l as isModelDownloaded, m as parseTokenizedUrl, n as collectModelFiles, o as ensureModel, p as parseRangeHeader, r as deleteModelFromDisk, s as fetchJson, t as ModelDownloadService, u as createFileDataPlaneHandler } from "./model-download-service-Cp9f4dk6.mjs";
|
|
4
4
|
import { $ as buildNativeCapProxy, A as createHubCapForwardService, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, Ct as resolveAddonClass, D as localProviderLink, E as ipcParentLink, F as createUdsLogger, G as callWithServiceDiscovery, H as CapRouteResolver, I as createUdsLoggerWithControl, J as UdsLocalTransportServer, K as createLocalTransport, L as LocalChildClient, M as createUdsEventBridge, N as createUdsEventBus, O as HUB_CAP_FWD_ACTION, P as udsChildLogToWorkerEntry, Q as encodeFrame, R as LocalChildRegistry, S as brokerCallForCap, St as runNpm, T as ipcChildLink, U as CapRouteError, V as AGENT_CAP_FWD_SERVICE, W as classifyCapRoute, X as localEndpointPath, Y as SocketChannel, Z as FrameDecoder, _ as createKernelHwAccel, _t as CapabilityHandle, a as getWorkerDeviceRegistry, b as __resetCapUsageRegistryForTests, bt as installManifestNativeDeps, c as setHubConnected, ct as NATIVE_PROVIDER_SERVICE_INFIX, d as getBrokerEventBus, dt as capBareAction, et as buildUdsNativeCapProxy, f as getMoleculerEventStats, ft as capServiceName, g as AddonDepsManager, gt as DeviceRegistry, h as subscribePassthrough, ht as serializeTypedArrays, i as createUdsAddonContext, it as mountNativeCapService, j as createParentUnownedCallHandler, k as HUB_CAP_FWD_SERVICE, l as EVENT_TOPIC_PREFIX, lt as capActionName, m as setNodeEventInterest, mt as deserializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as createAddonService, p as registerEventBusService, pt as parseCapAction, q as UdsLocalTransportClient, r as createAddonContext, s as getOrInitReadinessRegistryForClient, st as validateProviderRegistrations, t as installManifestPythonDeps, tt as createBrokerDeviceManagerApi, u as clusterEventTopic, ut as capActionSuffix, v as resolveHwAccel, vt as CapabilityUnavailableError, w as buildLinkChain, wt as createAddonDataPlaneFacility, x as getCapUsageRegistry, xt as resolveNpmInvocation, y as CapUsageRegistry, yt as copyBundledNativeModules, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-julrfvyf.mjs";
|
|
5
5
|
import { n as getSinglePidStats, t as getPidStats } from "./resource-monitor-BkP504Vq.mjs";
|