@camstack/addon-provider-dreo 0.2.99 → 0.2.101
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon.js +292 -58
- package/dist/addon.mjs +292 -58
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -35,7 +35,7 @@ var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["modu
|
|
|
35
35
|
//#endregion
|
|
36
36
|
let crypto$1 = require("crypto");
|
|
37
37
|
let events = require("events");
|
|
38
|
-
//#region ../types/dist/event-category-
|
|
38
|
+
//#region ../types/dist/event-category-ZyX6jcse.mjs
|
|
39
39
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
40
40
|
EventCategory["SystemBoot"] = "system.boot";
|
|
41
41
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -596,7 +596,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
596
596
|
* a package zone — a newly-appeared stationary object of a package class
|
|
597
597
|
* that cleared the class / zone / dwell / size gates. Payload:
|
|
598
598
|
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
599
|
-
* entryId, className, zoneIds,
|
|
599
|
+
* entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
|
|
600
600
|
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
601
601
|
* this bus topic drives notifier rules + live UI. See
|
|
602
602
|
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
@@ -5382,7 +5382,7 @@ var ZodIssueCode = {
|
|
|
5382
5382
|
var ZodFirstPartyTypeKind;
|
|
5383
5383
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5384
5384
|
//#endregion
|
|
5385
|
-
//#region ../types/dist/sleep-
|
|
5385
|
+
//#region ../types/dist/sleep-DBKu2-U5.mjs
|
|
5386
5386
|
/**
|
|
5387
5387
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5388
5388
|
* window to float samples (D455).
|
|
@@ -7349,13 +7349,30 @@ new Set([
|
|
|
7349
7349
|
"scene",
|
|
7350
7350
|
"motion",
|
|
7351
7351
|
"object",
|
|
7352
|
-
"audio"
|
|
7352
|
+
"audio",
|
|
7353
|
+
"mosaic"
|
|
7353
7354
|
]);
|
|
7354
|
-
|
|
7355
|
+
/**
|
|
7356
|
+
* The owner types that are event tables, in the order the event-media resolver
|
|
7357
|
+
* should consider them. Exported so a consumer asking "is this key an event?"
|
|
7358
|
+
* does not re-spell the list and drift from it.
|
|
7359
|
+
*/
|
|
7360
|
+
var EVENT_OWNER_TYPES = [
|
|
7355
7361
|
"motion",
|
|
7356
7362
|
"object",
|
|
7357
7363
|
"audio"
|
|
7358
|
-
]
|
|
7364
|
+
];
|
|
7365
|
+
/**
|
|
7366
|
+
* The same list as a Zod enum, for the cap inputs that must NAME the table
|
|
7367
|
+
* (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
|
|
7368
|
+
* `(table, id)`).
|
|
7369
|
+
*
|
|
7370
|
+
* Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
|
|
7371
|
+
* table would otherwise be accepted by the codec and refused at the door, with
|
|
7372
|
+
* nothing failing until a caller asked.
|
|
7373
|
+
*/
|
|
7374
|
+
var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
|
|
7375
|
+
new Set(EVENT_OWNER_TYPES);
|
|
7359
7376
|
var EncodeProfileSchema = object({
|
|
7360
7377
|
video: object({
|
|
7361
7378
|
codec: _enum([
|
|
@@ -7394,7 +7411,23 @@ var EncodeProfileSchema = object({
|
|
|
7394
7411
|
"zerolatency",
|
|
7395
7412
|
"film",
|
|
7396
7413
|
"animation"
|
|
7397
|
-
]).optional()
|
|
7414
|
+
]).optional(),
|
|
7415
|
+
/**
|
|
7416
|
+
* ONE slice per access unit.
|
|
7417
|
+
*
|
|
7418
|
+
* `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
|
|
7419
|
+
* the encoder as five NAL slices that share one RTP timestamp and carry one
|
|
7420
|
+
* marker bit. A libwebrtc depacketiser sees five frame-starts and one
|
|
7421
|
+
* frame-end per frame: the first pictures render and the video then freezes
|
|
7422
|
+
* for good while the audio, on its own plane, plays on. Measured on this hub
|
|
7423
|
+
* 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
|
|
7424
|
+
*
|
|
7425
|
+
* A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
|
|
7426
|
+
* `outputArgs` on purpose: an opaque array is part of the sharing key, so two
|
|
7427
|
+
* consumers meaning the same thing spelled differently would stop sharing one
|
|
7428
|
+
* child. Absent means "whatever the encoder does" — today's behaviour.
|
|
7429
|
+
*/
|
|
7430
|
+
singleSlicePerFrame: boolean().optional()
|
|
7398
7431
|
}),
|
|
7399
7432
|
audio: union([literal("passthrough"), object({
|
|
7400
7433
|
codec: _enum([
|
|
@@ -7444,7 +7477,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
|
|
|
7444
7477
|
audio: "passthrough"
|
|
7445
7478
|
};
|
|
7446
7479
|
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7447
|
-
({ ...BASE_LIVE_EGRESS_PROFILE });
|
|
7480
|
+
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7448
7481
|
/**
|
|
7449
7482
|
* Deep wiring healthcheck — snapshot of active reachability probes across
|
|
7450
7483
|
* every declared capability + widget of every installed plugin, on every
|
|
@@ -12554,6 +12587,16 @@ method(object({
|
|
|
12554
12587
|
filter: QueryFilterSchema.optional(),
|
|
12555
12588
|
columns: array(string()).readonly().optional()
|
|
12556
12589
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
12590
|
+
namespace: string().optional(),
|
|
12591
|
+
collection: string(),
|
|
12592
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
12593
|
+
* index on the collection. Never empty. */
|
|
12594
|
+
conflict: array(string()).readonly(),
|
|
12595
|
+
record: BulkRecordSchema
|
|
12596
|
+
}), object({
|
|
12597
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
12598
|
+
* row's own id on an update. */
|
|
12599
|
+
id: union([string(), number()]) }), { kind: "mutation" }), method(object({
|
|
12557
12600
|
namespace: string().optional(),
|
|
12558
12601
|
collection: string(),
|
|
12559
12602
|
record: object({
|
|
@@ -12688,6 +12731,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
12688
12731
|
id: union([string(), number()]) }), {
|
|
12689
12732
|
kind: "mutation",
|
|
12690
12733
|
auth: "admin"
|
|
12734
|
+
}), method(object({
|
|
12735
|
+
namespace: string().optional(),
|
|
12736
|
+
collection: string(),
|
|
12737
|
+
conflict: array(string()).readonly(),
|
|
12738
|
+
record: BulkRecordSchema
|
|
12739
|
+
}), object({ id: union([string(), number()]) }), {
|
|
12740
|
+
kind: "mutation",
|
|
12741
|
+
auth: "admin"
|
|
12691
12742
|
}), method(object({
|
|
12692
12743
|
namespace: string().optional(),
|
|
12693
12744
|
collection: string(),
|
|
@@ -19187,8 +19238,8 @@ var TrackPositionSchema = object({
|
|
|
19187
19238
|
var TrackSnapshotSchema = object({
|
|
19188
19239
|
timestamp: number(),
|
|
19189
19240
|
position: TrackPositionSchema,
|
|
19190
|
-
/**
|
|
19191
|
-
|
|
19241
|
+
/** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
|
|
19242
|
+
mediaId: number().int()
|
|
19192
19243
|
});
|
|
19193
19244
|
/**
|
|
19194
19245
|
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
@@ -19792,14 +19843,14 @@ var ObjectEventSchema = object({
|
|
|
19792
19843
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
19793
19844
|
frameWidth: number().optional(),
|
|
19794
19845
|
frameHeight: number().optional(),
|
|
19795
|
-
/**
|
|
19796
|
-
|
|
19797
|
-
/** Design B:
|
|
19846
|
+
/** Media row id of the crop attached to this event (if any) — D482. */
|
|
19847
|
+
mediaId: number().int().optional(),
|
|
19848
|
+
/** Design B: media row id of the track's native-resolution key frame (the
|
|
19798
19849
|
* best-detection full frame). Resolve via the event-media data-plane
|
|
19799
|
-
* (`/addon/<addonId>/event-media/<
|
|
19850
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
|
|
19800
19851
|
* draws `bbox` over the native frame. Absent on legacy rows / non-decoded
|
|
19801
|
-
* sources — consumers fall back to `
|
|
19802
|
-
|
|
19852
|
+
* sources — consumers fall back to `mediaId` (the tight crop). */
|
|
19853
|
+
keyFrameMediaId: number().int().optional(),
|
|
19803
19854
|
/** Populated by B5 (recording playback URL for this event). */
|
|
19804
19855
|
mediaUrl: string().optional(),
|
|
19805
19856
|
/** The parent track's key-event importance [0,1], propagated to every object
|
|
@@ -19849,7 +19900,7 @@ var MediaFileKindEnum = _enum([
|
|
|
19849
19900
|
* hub-main's heap on the way past — for an `<img>` that would have cached it.
|
|
19850
19901
|
*
|
|
19851
19902
|
* `url` points at the `event-media` data plane
|
|
19852
|
-
* (`/addon/<addonId>/event-media/<
|
|
19903
|
+
* (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
|
|
19853
19904
|
* with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
|
|
19854
19905
|
* render a `?variant=thumb`, and streams. The hub gate in front of it requires
|
|
19855
19906
|
* a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
|
|
@@ -19857,10 +19908,13 @@ var MediaFileKindEnum = _enum([
|
|
|
19857
19908
|
* `data-plane-access.ts` for the rule and the one gap it does not close
|
|
19858
19909
|
* (per-device scoping).
|
|
19859
19910
|
*
|
|
19860
|
-
* The URL is built from the row's
|
|
19861
|
-
*
|
|
19911
|
+
* The URL is built from the row's own id, which since D482 says nothing about
|
|
19912
|
+
* the row's owner or kind — and that is the point. The published `kind` is not
|
|
19913
|
+
* the stored one (a track's face/plate crop is stored as `crop` under
|
|
19862
19914
|
* `('face'|'plate', '<prefix>-<trackId>')` and published as
|
|
19863
|
-
* `faceCrop`/`plateCrop
|
|
19915
|
+
* `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
|
|
19916
|
+
* taken from `row.key` verbatim or it 404'd exactly those two rows. An id
|
|
19917
|
+
* cannot be mis-reconstructed, because there is nothing in it to reconstruct.
|
|
19864
19918
|
*
|
|
19865
19919
|
* ## `base64` is TRANSITIONAL and is going away
|
|
19866
19920
|
*
|
|
@@ -19873,7 +19927,19 @@ var MediaFileKindEnum = _enum([
|
|
|
19873
19927
|
* `analytics-query-facade.ts`; nothing else reads it.
|
|
19874
19928
|
*/
|
|
19875
19929
|
var MediaFileSchema = object({
|
|
19876
|
-
|
|
19930
|
+
/**
|
|
19931
|
+
* The media row's OWN id — the rowid SQLite assigned it (D482).
|
|
19932
|
+
*
|
|
19933
|
+
* It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
|
|
19934
|
+
* [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
|
|
19935
|
+
* per-table rowid aliases, so `object:101314` and `motion:101314` are two
|
|
19936
|
+
* different rows that spell the same number, and a track whose
|
|
19937
|
+
* `bestEventId` was an object event was served a motion event's snapshot —
|
|
19938
|
+
* a night-time thumbnail on an afternoon track, with no error anywhere. A
|
|
19939
|
+
* surrogate id cannot name the wrong row's owner, because it names no owner
|
|
19940
|
+
* at all.
|
|
19941
|
+
*/
|
|
19942
|
+
mediaId: number().int(),
|
|
19877
19943
|
kind: MediaFileKindEnum,
|
|
19878
19944
|
sizeBytes: number(),
|
|
19879
19945
|
timestamp: number()
|
|
@@ -19981,7 +20047,7 @@ var RetrainTrackSchema = object({
|
|
|
19981
20047
|
});
|
|
19982
20048
|
/** A frame the picker may offer — an index row, no blob was read to produce it. */
|
|
19983
20049
|
var RetrainFrameCandidateSchema = object({
|
|
19984
|
-
|
|
20050
|
+
mediaId: number().int(),
|
|
19985
20051
|
kind: MediaFileKindEnum,
|
|
19986
20052
|
timestamp: number(),
|
|
19987
20053
|
sizeBytes: number().int(),
|
|
@@ -19995,7 +20061,7 @@ var RetrainFrameSchema = object({
|
|
|
19995
20061
|
deviceId: number(),
|
|
19996
20062
|
trackId: string(),
|
|
19997
20063
|
/** Provenance only. It may already point at nothing — that is expected. */
|
|
19998
|
-
|
|
20064
|
+
sourceMediaId: number().int(),
|
|
19999
20065
|
sourceKind: MediaFileKindEnum,
|
|
20000
20066
|
sizeBytes: number().int(),
|
|
20001
20067
|
width: number().int(),
|
|
@@ -20011,7 +20077,7 @@ var RetrainCopyRefusalSchema = _enum([
|
|
|
20011
20077
|
var RetrainFrameSelectionSchema = object({
|
|
20012
20078
|
copied: array(RetrainFrameSchema).readonly(),
|
|
20013
20079
|
refused: array(object({
|
|
20014
|
-
|
|
20080
|
+
sourceMediaId: number().int(),
|
|
20015
20081
|
reason: RetrainCopyRefusalSchema
|
|
20016
20082
|
})).readonly()
|
|
20017
20083
|
});
|
|
@@ -20019,7 +20085,7 @@ var RetrainFrameListSchema = object({
|
|
|
20019
20085
|
candidates: array(RetrainFrameCandidateSchema).readonly(),
|
|
20020
20086
|
copies: array(RetrainFrameSchema).readonly(),
|
|
20021
20087
|
/** What the page pre-selects — the native key frame when one survives. */
|
|
20022
|
-
|
|
20088
|
+
autoPickMediaId: number().int().optional()
|
|
20023
20089
|
});
|
|
20024
20090
|
/** What the operator asked the assist to look for. */
|
|
20025
20091
|
var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
|
|
@@ -20114,9 +20180,11 @@ var RecentTracksQueryInput = object({
|
|
|
20114
20180
|
});
|
|
20115
20181
|
/**
|
|
20116
20182
|
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
20117
|
-
* `
|
|
20118
|
-
* served by the event-media plane
|
|
20119
|
-
* member visible has been materialised
|
|
20183
|
+
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
20184
|
+
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
20185
|
+
* first frame with a member visible has been materialised (D482 — it was the
|
|
20186
|
+
* row's composite key, which embedded the owner and could name another table's
|
|
20187
|
+
* row once event ids became per-table rowids).
|
|
20120
20188
|
*/
|
|
20121
20189
|
var SummarySchema = object({
|
|
20122
20190
|
id: string(),
|
|
@@ -20125,19 +20193,115 @@ var SummarySchema = object({
|
|
|
20125
20193
|
lastActiveAt: number(),
|
|
20126
20194
|
sealedAt: number().nullable(),
|
|
20127
20195
|
memberCount: number().int().nonnegative(),
|
|
20128
|
-
|
|
20196
|
+
groupShotMediaId: number().int().nullable()
|
|
20129
20197
|
});
|
|
20130
20198
|
var SummariesQueryInput = object({
|
|
20131
20199
|
deviceIds: array(number()).min(1),
|
|
20132
20200
|
since: number().optional(),
|
|
20133
20201
|
until: number().optional(),
|
|
20134
|
-
limit: number().int().min(1).max(200).default(50)
|
|
20202
|
+
limit: number().int().min(1).max(200).default(50),
|
|
20203
|
+
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
20204
|
+
* meaning of "dog" on every summary surface. */
|
|
20205
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
20135
20206
|
});
|
|
20136
|
-
var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
|
|
20137
20207
|
var SummaryDetailSchema = object({
|
|
20138
20208
|
summary: SummarySchema,
|
|
20139
|
-
/**
|
|
20140
|
-
|
|
20209
|
+
/** Members in absorption order, oldest join first. */
|
|
20210
|
+
members: array(object({
|
|
20211
|
+
trackId: string(),
|
|
20212
|
+
/**
|
|
20213
|
+
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
20214
|
+
* and the track no longer exists to fill it.
|
|
20215
|
+
*
|
|
20216
|
+
* The join, not the latest opinion: class voting can re-decide a track's
|
|
20217
|
+
* class afterwards, and a group's composition is the history of who came
|
|
20218
|
+
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
20219
|
+
* dog" — rather than being handed a second, denormalised tally that would
|
|
20220
|
+
* drift from the members it claims to describe.
|
|
20221
|
+
*/
|
|
20222
|
+
className: string().nullable(),
|
|
20223
|
+
/** `primary` is the one member that carries the group's identity. */
|
|
20224
|
+
role: _enum([
|
|
20225
|
+
"primary",
|
|
20226
|
+
"sibling",
|
|
20227
|
+
"child"
|
|
20228
|
+
]).nullable(),
|
|
20229
|
+
joinedAt: number(),
|
|
20230
|
+
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
20231
|
+
* at read time. Absent when nothing resolved, never an empty string. */
|
|
20232
|
+
label: string().optional(),
|
|
20233
|
+
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
20234
|
+
* recognised nobody, and absent for a member whose track has been pruned —
|
|
20235
|
+
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
20236
|
+
subLabel: string().optional()
|
|
20237
|
+
})).readonly()
|
|
20238
|
+
});
|
|
20239
|
+
/**
|
|
20240
|
+
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
20241
|
+
*
|
|
20242
|
+
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
20243
|
+
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
20244
|
+
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
20245
|
+
* are on {@link getSummary}: shipping every member of every group so a client
|
|
20246
|
+
* can count them turns a page of two hundred groups into a thousand records to
|
|
20247
|
+
* draw two hundred badges.
|
|
20248
|
+
*/
|
|
20249
|
+
var SummaryListItemSchema = object({
|
|
20250
|
+
summary: SummarySchema,
|
|
20251
|
+
/** Class counts, most numerous first; `className: null` is a member whose
|
|
20252
|
+
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
20253
|
+
classes: array(object({
|
|
20254
|
+
className: string().nullable(),
|
|
20255
|
+
count: number().int().positive()
|
|
20256
|
+
})).readonly()
|
|
20257
|
+
});
|
|
20258
|
+
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
20259
|
+
/**
|
|
20260
|
+
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
20261
|
+
*
|
|
20262
|
+
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
20263
|
+
* summaries feed that could only answer "the last N for these cameras"
|
|
20264
|
+
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
20265
|
+
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
20266
|
+
* "newest" means, on one screen.
|
|
20267
|
+
*/
|
|
20268
|
+
var RecentSummariesQueryInput = object({
|
|
20269
|
+
/** Devices to merge. An empty array yields an empty page. */
|
|
20270
|
+
deviceIds: array(number()),
|
|
20271
|
+
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
20272
|
+
since: number().optional(),
|
|
20273
|
+
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
20274
|
+
until: number().optional(),
|
|
20275
|
+
limit: number().int().min(1).max(500).default(100),
|
|
20276
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
20277
|
+
cursor: string().optional(),
|
|
20278
|
+
/**
|
|
20279
|
+
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
20280
|
+
* deliberately the same name: the events filter tree emits one list of ticked
|
|
20281
|
+
* taxonomy nodes, and a summaries feed that called it something else would
|
|
20282
|
+
* make the operator's one filter component produce two shapes.
|
|
20283
|
+
*
|
|
20284
|
+
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
20285
|
+
* me the arrivals with a dog" has to return the group of four people who had
|
|
20286
|
+
* one with them; a filter on the group's own fields could only ever answer
|
|
20287
|
+
* about its primary.
|
|
20288
|
+
*
|
|
20289
|
+
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
20290
|
+
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
20291
|
+
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
20292
|
+
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
20293
|
+
* that read only the class would answer "animal" and never "dog".
|
|
20294
|
+
*
|
|
20295
|
+
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
20296
|
+
*/
|
|
20297
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
20298
|
+
});
|
|
20299
|
+
var RecentSummariesPageSchema = object({
|
|
20300
|
+
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
20301
|
+
* {@link listSummaries} — one list shape, so a card renders the same
|
|
20302
|
+
* whichever feed drew it. */
|
|
20303
|
+
summaries: array(SummaryListItemSchema).readonly(),
|
|
20304
|
+
nextCursor: string().nullable()
|
|
20141
20305
|
});
|
|
20142
20306
|
var RecentTracksPageSchema = object({
|
|
20143
20307
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -20551,7 +20715,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20551
20715
|
classes: array(string()).optional(),
|
|
20552
20716
|
/** See {@link ExcludeSourcesDoc}. */
|
|
20553
20717
|
excludeSources: array(TrackSourceSchema).optional()
|
|
20554
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20718
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20555
20719
|
kind: "mutation",
|
|
20556
20720
|
auth: "admin"
|
|
20557
20721
|
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
|
|
@@ -20679,7 +20843,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20679
20843
|
}), method(object({
|
|
20680
20844
|
deviceId: number(),
|
|
20681
20845
|
trackId: string(),
|
|
20682
|
-
|
|
20846
|
+
mediaIds: array(number().int()).min(1)
|
|
20683
20847
|
}), RetrainFrameSelectionSchema, {
|
|
20684
20848
|
kind: "mutation",
|
|
20685
20849
|
auth: "admin"
|
|
@@ -20747,7 +20911,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20747
20911
|
kind: "query",
|
|
20748
20912
|
auth: "admin"
|
|
20749
20913
|
}), method(object({
|
|
20750
|
-
|
|
20914
|
+
/** Which of the three event tables owns the row. */
|
|
20915
|
+
ownerType: EventOwnerTypeSchema,
|
|
20916
|
+
/** The event's rowid in that table (D474: an event id is a number). */
|
|
20917
|
+
eventId: number().int(),
|
|
20751
20918
|
kind: MediaFileKindEnum.optional(),
|
|
20752
20919
|
deviceId: number()
|
|
20753
20920
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
@@ -20758,7 +20925,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20758
20925
|
trackId: string(),
|
|
20759
20926
|
deviceId: number()
|
|
20760
20927
|
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
20761
|
-
|
|
20928
|
+
ownerType: EventOwnerTypeSchema,
|
|
20929
|
+
eventId: number().int(),
|
|
20762
20930
|
deviceId: number()
|
|
20763
20931
|
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
20764
20932
|
kind: "mutation",
|
|
@@ -25959,8 +26127,8 @@ var IdentitySchema = object({
|
|
|
25959
26127
|
id: string(),
|
|
25960
26128
|
name: string(),
|
|
25961
26129
|
sampleCount: number().int().nonnegative(),
|
|
25962
|
-
|
|
25963
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
26130
|
+
coverMediaId: number().int().optional(),
|
|
26131
|
+
/** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
|
|
25964
26132
|
* Lets the UI render the person's face avatar instead of a placeholder icon. */
|
|
25965
26133
|
coverBase64: string().optional()
|
|
25966
26134
|
});
|
|
@@ -25986,8 +26154,8 @@ var IdentitySampleAuditRowSchema = object({
|
|
|
25986
26154
|
enrolledAt: number().int(),
|
|
25987
26155
|
deviceId: number().int().optional(),
|
|
25988
26156
|
source: _enum(["detected", "photo"]),
|
|
25989
|
-
/** The enrolled crop's media
|
|
25990
|
-
|
|
26157
|
+
/** The enrolled crop's media row id, so the panel can show the evidence. */
|
|
26158
|
+
mediaId: number().int().optional(),
|
|
25991
26159
|
/**
|
|
25992
26160
|
* False = the sample is stamped with a DIFFERENT face model, and a cosine
|
|
25993
26161
|
* across feature spaces is a well-formed float with no meaning. Every number
|
|
@@ -26056,15 +26224,15 @@ var FaceInfoSchema = object({
|
|
|
26056
26224
|
*/
|
|
26057
26225
|
cropUrl: string().optional(),
|
|
26058
26226
|
/** Design B: the face bbox (pixel space) on the key frame — lets a detail
|
|
26059
|
-
* view draw the box over the native `
|
|
26227
|
+
* view draw the box over the native `keyFrameMediaId` frame. Absent on
|
|
26060
26228
|
* legacy rows written before design B. */
|
|
26061
26229
|
faceBbox: BoundingBoxSchema.optional(),
|
|
26062
26230
|
/** Design B: MediaStore key of the track's native-resolution key frame.
|
|
26063
26231
|
* Fetch the native JPEG via the event-media data-plane
|
|
26064
|
-
* (`/addon/<addonId>/event-media/<
|
|
26232
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
|
|
26065
26233
|
* track produced no key frame (e.g. native/onboard source) — the UI falls
|
|
26066
26234
|
* back to the inline `base64` face crop. */
|
|
26067
|
-
|
|
26235
|
+
keyFrameMediaId: number().int().optional(),
|
|
26068
26236
|
/** Winning identity-match cosine (0..1) for this face's track, when an
|
|
26069
26237
|
* identity was auto-confirmed. Lets the UI surface WHY a face was assigned
|
|
26070
26238
|
* (confidence badge / low-confidence audit). Absent on legacy rows and on
|
|
@@ -26133,11 +26301,14 @@ var FaceClusterSchema = object({
|
|
|
26133
26301
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
26134
26302
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
26135
26303
|
*
|
|
26136
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
26137
|
-
* media
|
|
26304
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
26305
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
26306
|
+
* access decision.
|
|
26138
26307
|
*/
|
|
26139
26308
|
var MediaFileLiteSchema$1 = object({
|
|
26140
|
-
|
|
26309
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
26310
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
26311
|
+
mediaId: number().int(),
|
|
26141
26312
|
kind: string(),
|
|
26142
26313
|
url: string(),
|
|
26143
26314
|
sizeBytes: number(),
|
|
@@ -26154,7 +26325,7 @@ method(object({
|
|
|
26154
26325
|
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
26155
26326
|
* four times and the viewer holds at `staleTime: 30_000`.
|
|
26156
26327
|
*
|
|
26157
|
-
* Nothing loses its avatar: `
|
|
26328
|
+
* Nothing loses its avatar: `coverMediaId` is already on every row and
|
|
26158
26329
|
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
26159
26330
|
*
|
|
26160
26331
|
* **This is an INPUT field, so it does not reach the addon until the
|
|
@@ -29517,8 +29688,8 @@ var VehicleSchema = object({
|
|
|
29517
29688
|
id: string(),
|
|
29518
29689
|
name: string(),
|
|
29519
29690
|
sampleCount: number().int().nonnegative(),
|
|
29520
|
-
|
|
29521
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
29691
|
+
coverMediaId: number().int().optional(),
|
|
29692
|
+
/** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
|
|
29522
29693
|
coverBase64: string().optional()
|
|
29523
29694
|
});
|
|
29524
29695
|
var VehicleSampleInfoSchema = object({
|
|
@@ -29551,7 +29722,7 @@ var PlateInfoSchema = object({
|
|
|
29551
29722
|
/** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
|
|
29552
29723
|
plateBbox: BoundingBoxSchema.optional(),
|
|
29553
29724
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
29554
|
-
|
|
29725
|
+
keyFrameMediaId: number().int().optional(),
|
|
29555
29726
|
base64: string().optional(),
|
|
29556
29727
|
/**
|
|
29557
29728
|
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
@@ -29572,11 +29743,14 @@ var PlateInfoSchema = object({
|
|
|
29572
29743
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
29573
29744
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
29574
29745
|
*
|
|
29575
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
29576
|
-
* media
|
|
29746
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
29747
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
29748
|
+
* access decision.
|
|
29577
29749
|
*/
|
|
29578
29750
|
var MediaFileLiteSchema = object({
|
|
29579
|
-
|
|
29751
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
29752
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
29753
|
+
mediaId: number().int(),
|
|
29580
29754
|
kind: string(),
|
|
29581
29755
|
url: string(),
|
|
29582
29756
|
sizeBytes: number(),
|
|
@@ -29635,7 +29809,7 @@ method(object({
|
|
|
29635
29809
|
}), method(object({
|
|
29636
29810
|
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
29637
29811
|
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
29638
|
-
* option; `
|
|
29812
|
+
* option; `coverMediaId` + the `event-media` plane carry the picture.
|
|
29639
29813
|
* INPUT field: stripped by the hub router until the train ships, which
|
|
29640
29814
|
* resolves to `false` and is exactly the intended default. */
|
|
29641
29815
|
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
@@ -31204,7 +31378,14 @@ var SceneReferenceSchema = object({
|
|
|
31204
31378
|
modelId: string(),
|
|
31205
31379
|
condition: SceneConditionSchema,
|
|
31206
31380
|
capturedAt: number(),
|
|
31207
|
-
|
|
31381
|
+
/**
|
|
31382
|
+
* The reference thumbnail's media ROW id (D482).
|
|
31383
|
+
*
|
|
31384
|
+
* The name already said `mediaId` while the value was the row's composite
|
|
31385
|
+
* key — a leftover that read as done and was not. It is the row's own id
|
|
31386
|
+
* now, addressed at `/addon/<addonId>/event-media/m/<id>`.
|
|
31387
|
+
*/
|
|
31388
|
+
thumbnailMediaId: number().int().optional(),
|
|
31208
31389
|
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
31209
31390
|
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
31210
31391
|
* normalized rect frame a different piece of world, and the scene would
|
|
@@ -32295,7 +32476,29 @@ var LoggingSettingsPatchSchema = object({
|
|
|
32295
32476
|
* disarmed the channels it did not mention would make the Levels page and
|
|
32296
32477
|
* the Diagnostics page fight over the same value.
|
|
32297
32478
|
*/
|
|
32298
|
-
channels: array(LogChannelWindowPatchSchema).readonly().optional()
|
|
32479
|
+
channels: array(LogChannelWindowPatchSchema).readonly().optional(),
|
|
32480
|
+
/**
|
|
32481
|
+
* How many days the analytics OPS LOG is kept — the audit trail of what
|
|
32482
|
+
* retention actually deleted.
|
|
32483
|
+
*
|
|
32484
|
+
* It lives HERE, on the logging document, and not on the analytics addon's
|
|
32485
|
+
* settings form, on the operator's instruction: every other log-ish window in
|
|
32486
|
+
* this system is configured through this one document, and a retention audit
|
|
32487
|
+
* configured somewhere else is a second place to look when the question is
|
|
32488
|
+
* "what happened to my data".
|
|
32489
|
+
*
|
|
32490
|
+
* That placement has a cost worth stating: this document ships in the
|
|
32491
|
+
* framework closure, so this knob needs a published `@camstack/server` while
|
|
32492
|
+
* the four windows beside it (D485) reach a node on `camstack deploy`.
|
|
32493
|
+
*
|
|
32494
|
+
* `retention-model.ts` argued this one must NOT follow a device window,
|
|
32495
|
+
* because the audit trail is the history of the SWEEP and not of the camera.
|
|
32496
|
+
* That argument stands and is untouched — what changes is that 30 days stops
|
|
32497
|
+
* being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
|
|
32498
|
+
* rather than 0-as-delete: an audit log truncated to nothing is precisely the
|
|
32499
|
+
* state in which the next 9.5 GiB leak cannot be explained.
|
|
32500
|
+
*/
|
|
32501
|
+
opsLogRetentionDays: number().int().min(0).max(3650).optional()
|
|
32299
32502
|
});
|
|
32300
32503
|
/**
|
|
32301
32504
|
* Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
|
|
@@ -32368,6 +32571,14 @@ var LoggingSettingsStateSchema = object({
|
|
|
32368
32571
|
channels: array(LogChannelDescriptorSchema).readonly(),
|
|
32369
32572
|
/** The channels ARMED right now, each with its deadline. */
|
|
32370
32573
|
activeChannels: array(LogChannelWindowStateSchema).readonly(),
|
|
32574
|
+
/**
|
|
32575
|
+
* The ops-log window in days, as it is in force. `0` = kept forever.
|
|
32576
|
+
*
|
|
32577
|
+
* Reported rather than left to the caller's memory of what it wrote: this is
|
|
32578
|
+
* the value the analytics sweep will actually use, and an operator asking how
|
|
32579
|
+
* long their audit trail lives should not have to infer it from a default.
|
|
32580
|
+
*/
|
|
32581
|
+
opsLogRetentionDays: number().int().min(0),
|
|
32371
32582
|
persisted: boolean()
|
|
32372
32583
|
});
|
|
32373
32584
|
method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string(), unknown()), _null(), {
|
|
@@ -33188,7 +33399,7 @@ var StationaryObjectSchema = object({
|
|
|
33188
33399
|
/** Enrichment label carried from the source track (identity / plate). */
|
|
33189
33400
|
label: string().optional(),
|
|
33190
33401
|
/** Native-resolution key-frame media key for the parked object's best image. */
|
|
33191
|
-
|
|
33402
|
+
keyFrameMediaId: number().int().optional()
|
|
33192
33403
|
});
|
|
33193
33404
|
var CameraOccupancySnapshotSchema = object({
|
|
33194
33405
|
/** Frame timestamp of the inference result that produced this snapshot. */
|
|
@@ -35926,6 +36137,12 @@ Object.freeze({
|
|
|
35926
36137
|
addonId: null,
|
|
35927
36138
|
access: "create"
|
|
35928
36139
|
},
|
|
36140
|
+
"dataStoreProvider.upsert": {
|
|
36141
|
+
capName: "data-store-provider",
|
|
36142
|
+
capScope: "system",
|
|
36143
|
+
addonId: null,
|
|
36144
|
+
access: "create"
|
|
36145
|
+
},
|
|
35929
36146
|
"dayNight.getOptions": {
|
|
35930
36147
|
capName: "day-night",
|
|
35931
36148
|
capScope: "device",
|
|
@@ -38362,6 +38579,12 @@ Object.freeze({
|
|
|
38362
38579
|
addonId: null,
|
|
38363
38580
|
access: "view"
|
|
38364
38581
|
},
|
|
38582
|
+
"pipelineAnalytics.listRecentSummaries": {
|
|
38583
|
+
capName: "pipeline-analytics",
|
|
38584
|
+
capScope: "device",
|
|
38585
|
+
addonId: null,
|
|
38586
|
+
access: "view"
|
|
38587
|
+
},
|
|
38365
38588
|
"pipelineAnalytics.listRecentTracks": {
|
|
38366
38589
|
capName: "pipeline-analytics",
|
|
38367
38590
|
capScope: "device",
|
|
@@ -39790,6 +40013,12 @@ Object.freeze({
|
|
|
39790
40013
|
addonId: null,
|
|
39791
40014
|
access: "create"
|
|
39792
40015
|
},
|
|
40016
|
+
"settingsStore.upsert": {
|
|
40017
|
+
capName: "settings-store",
|
|
40018
|
+
capScope: "system",
|
|
40019
|
+
addonId: null,
|
|
40020
|
+
access: "create"
|
|
40021
|
+
},
|
|
39793
40022
|
"smtpProvider.getStatus": {
|
|
39794
40023
|
capName: "smtp-provider",
|
|
39795
40024
|
capScope: "system",
|
|
@@ -42183,6 +42412,11 @@ Object.freeze({
|
|
|
42183
42412
|
form: "single",
|
|
42184
42413
|
optional: true
|
|
42185
42414
|
}],
|
|
42415
|
+
"pipelineAnalytics.listRecentSummaries": [{
|
|
42416
|
+
name: "deviceIds",
|
|
42417
|
+
form: "array",
|
|
42418
|
+
optional: false
|
|
42419
|
+
}],
|
|
42186
42420
|
"pipelineAnalytics.listRecentTracks": [{
|
|
42187
42421
|
name: "deviceIds",
|
|
42188
42422
|
form: "array",
|
package/dist/addon.mjs
CHANGED
|
@@ -36,7 +36,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
36
36
|
var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
37
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
38
38
|
//#endregion
|
|
39
|
-
//#region ../types/dist/event-category-
|
|
39
|
+
//#region ../types/dist/event-category-ZyX6jcse.mjs
|
|
40
40
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
41
41
|
EventCategory["SystemBoot"] = "system.boot";
|
|
42
42
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -597,7 +597,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
597
597
|
* a package zone — a newly-appeared stationary object of a package class
|
|
598
598
|
* that cleared the class / zone / dwell / size gates. Payload:
|
|
599
599
|
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
600
|
-
* entryId, className, zoneIds,
|
|
600
|
+
* entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
|
|
601
601
|
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
602
602
|
* this bus topic drives notifier rules + live UI. See
|
|
603
603
|
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
@@ -5383,7 +5383,7 @@ var ZodIssueCode = {
|
|
|
5383
5383
|
var ZodFirstPartyTypeKind;
|
|
5384
5384
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5385
5385
|
//#endregion
|
|
5386
|
-
//#region ../types/dist/sleep-
|
|
5386
|
+
//#region ../types/dist/sleep-DBKu2-U5.mjs
|
|
5387
5387
|
/**
|
|
5388
5388
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5389
5389
|
* window to float samples (D455).
|
|
@@ -7350,13 +7350,30 @@ new Set([
|
|
|
7350
7350
|
"scene",
|
|
7351
7351
|
"motion",
|
|
7352
7352
|
"object",
|
|
7353
|
-
"audio"
|
|
7353
|
+
"audio",
|
|
7354
|
+
"mosaic"
|
|
7354
7355
|
]);
|
|
7355
|
-
|
|
7356
|
+
/**
|
|
7357
|
+
* The owner types that are event tables, in the order the event-media resolver
|
|
7358
|
+
* should consider them. Exported so a consumer asking "is this key an event?"
|
|
7359
|
+
* does not re-spell the list and drift from it.
|
|
7360
|
+
*/
|
|
7361
|
+
var EVENT_OWNER_TYPES = [
|
|
7356
7362
|
"motion",
|
|
7357
7363
|
"object",
|
|
7358
7364
|
"audio"
|
|
7359
|
-
]
|
|
7365
|
+
];
|
|
7366
|
+
/**
|
|
7367
|
+
* The same list as a Zod enum, for the cap inputs that must NAME the table
|
|
7368
|
+
* (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
|
|
7369
|
+
* `(table, id)`).
|
|
7370
|
+
*
|
|
7371
|
+
* Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
|
|
7372
|
+
* table would otherwise be accepted by the codec and refused at the door, with
|
|
7373
|
+
* nothing failing until a caller asked.
|
|
7374
|
+
*/
|
|
7375
|
+
var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
|
|
7376
|
+
new Set(EVENT_OWNER_TYPES);
|
|
7360
7377
|
var EncodeProfileSchema = object({
|
|
7361
7378
|
video: object({
|
|
7362
7379
|
codec: _enum([
|
|
@@ -7395,7 +7412,23 @@ var EncodeProfileSchema = object({
|
|
|
7395
7412
|
"zerolatency",
|
|
7396
7413
|
"film",
|
|
7397
7414
|
"animation"
|
|
7398
|
-
]).optional()
|
|
7415
|
+
]).optional(),
|
|
7416
|
+
/**
|
|
7417
|
+
* ONE slice per access unit.
|
|
7418
|
+
*
|
|
7419
|
+
* `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
|
|
7420
|
+
* the encoder as five NAL slices that share one RTP timestamp and carry one
|
|
7421
|
+
* marker bit. A libwebrtc depacketiser sees five frame-starts and one
|
|
7422
|
+
* frame-end per frame: the first pictures render and the video then freezes
|
|
7423
|
+
* for good while the audio, on its own plane, plays on. Measured on this hub
|
|
7424
|
+
* 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
|
|
7425
|
+
*
|
|
7426
|
+
* A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
|
|
7427
|
+
* `outputArgs` on purpose: an opaque array is part of the sharing key, so two
|
|
7428
|
+
* consumers meaning the same thing spelled differently would stop sharing one
|
|
7429
|
+
* child. Absent means "whatever the encoder does" — today's behaviour.
|
|
7430
|
+
*/
|
|
7431
|
+
singleSlicePerFrame: boolean().optional()
|
|
7399
7432
|
}),
|
|
7400
7433
|
audio: union([literal("passthrough"), object({
|
|
7401
7434
|
codec: _enum([
|
|
@@ -7445,7 +7478,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
|
|
|
7445
7478
|
audio: "passthrough"
|
|
7446
7479
|
};
|
|
7447
7480
|
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7448
|
-
({ ...BASE_LIVE_EGRESS_PROFILE });
|
|
7481
|
+
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7449
7482
|
/**
|
|
7450
7483
|
* Deep wiring healthcheck — snapshot of active reachability probes across
|
|
7451
7484
|
* every declared capability + widget of every installed plugin, on every
|
|
@@ -12555,6 +12588,16 @@ method(object({
|
|
|
12555
12588
|
filter: QueryFilterSchema.optional(),
|
|
12556
12589
|
columns: array(string()).readonly().optional()
|
|
12557
12590
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
12591
|
+
namespace: string().optional(),
|
|
12592
|
+
collection: string(),
|
|
12593
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
12594
|
+
* index on the collection. Never empty. */
|
|
12595
|
+
conflict: array(string()).readonly(),
|
|
12596
|
+
record: BulkRecordSchema
|
|
12597
|
+
}), object({
|
|
12598
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
12599
|
+
* row's own id on an update. */
|
|
12600
|
+
id: union([string(), number()]) }), { kind: "mutation" }), method(object({
|
|
12558
12601
|
namespace: string().optional(),
|
|
12559
12602
|
collection: string(),
|
|
12560
12603
|
record: object({
|
|
@@ -12689,6 +12732,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
12689
12732
|
id: union([string(), number()]) }), {
|
|
12690
12733
|
kind: "mutation",
|
|
12691
12734
|
auth: "admin"
|
|
12735
|
+
}), method(object({
|
|
12736
|
+
namespace: string().optional(),
|
|
12737
|
+
collection: string(),
|
|
12738
|
+
conflict: array(string()).readonly(),
|
|
12739
|
+
record: BulkRecordSchema
|
|
12740
|
+
}), object({ id: union([string(), number()]) }), {
|
|
12741
|
+
kind: "mutation",
|
|
12742
|
+
auth: "admin"
|
|
12692
12743
|
}), method(object({
|
|
12693
12744
|
namespace: string().optional(),
|
|
12694
12745
|
collection: string(),
|
|
@@ -19188,8 +19239,8 @@ var TrackPositionSchema = object({
|
|
|
19188
19239
|
var TrackSnapshotSchema = object({
|
|
19189
19240
|
timestamp: number(),
|
|
19190
19241
|
position: TrackPositionSchema,
|
|
19191
|
-
/**
|
|
19192
|
-
|
|
19242
|
+
/** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
|
|
19243
|
+
mediaId: number().int()
|
|
19193
19244
|
});
|
|
19194
19245
|
/**
|
|
19195
19246
|
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
@@ -19793,14 +19844,14 @@ var ObjectEventSchema = object({
|
|
|
19793
19844
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
19794
19845
|
frameWidth: number().optional(),
|
|
19795
19846
|
frameHeight: number().optional(),
|
|
19796
|
-
/**
|
|
19797
|
-
|
|
19798
|
-
/** Design B:
|
|
19847
|
+
/** Media row id of the crop attached to this event (if any) — D482. */
|
|
19848
|
+
mediaId: number().int().optional(),
|
|
19849
|
+
/** Design B: media row id of the track's native-resolution key frame (the
|
|
19799
19850
|
* best-detection full frame). Resolve via the event-media data-plane
|
|
19800
|
-
* (`/addon/<addonId>/event-media/<
|
|
19851
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
|
|
19801
19852
|
* draws `bbox` over the native frame. Absent on legacy rows / non-decoded
|
|
19802
|
-
* sources — consumers fall back to `
|
|
19803
|
-
|
|
19853
|
+
* sources — consumers fall back to `mediaId` (the tight crop). */
|
|
19854
|
+
keyFrameMediaId: number().int().optional(),
|
|
19804
19855
|
/** Populated by B5 (recording playback URL for this event). */
|
|
19805
19856
|
mediaUrl: string().optional(),
|
|
19806
19857
|
/** The parent track's key-event importance [0,1], propagated to every object
|
|
@@ -19850,7 +19901,7 @@ var MediaFileKindEnum = _enum([
|
|
|
19850
19901
|
* hub-main's heap on the way past — for an `<img>` that would have cached it.
|
|
19851
19902
|
*
|
|
19852
19903
|
* `url` points at the `event-media` data plane
|
|
19853
|
-
* (`/addon/<addonId>/event-media/<
|
|
19904
|
+
* (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
|
|
19854
19905
|
* with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
|
|
19855
19906
|
* render a `?variant=thumb`, and streams. The hub gate in front of it requires
|
|
19856
19907
|
* a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
|
|
@@ -19858,10 +19909,13 @@ var MediaFileKindEnum = _enum([
|
|
|
19858
19909
|
* `data-plane-access.ts` for the rule and the one gap it does not close
|
|
19859
19910
|
* (per-device scoping).
|
|
19860
19911
|
*
|
|
19861
|
-
* The URL is built from the row's
|
|
19862
|
-
*
|
|
19912
|
+
* The URL is built from the row's own id, which since D482 says nothing about
|
|
19913
|
+
* the row's owner or kind — and that is the point. The published `kind` is not
|
|
19914
|
+
* the stored one (a track's face/plate crop is stored as `crop` under
|
|
19863
19915
|
* `('face'|'plate', '<prefix>-<trackId>')` and published as
|
|
19864
|
-
* `faceCrop`/`plateCrop
|
|
19916
|
+
* `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
|
|
19917
|
+
* taken from `row.key` verbatim or it 404'd exactly those two rows. An id
|
|
19918
|
+
* cannot be mis-reconstructed, because there is nothing in it to reconstruct.
|
|
19865
19919
|
*
|
|
19866
19920
|
* ## `base64` is TRANSITIONAL and is going away
|
|
19867
19921
|
*
|
|
@@ -19874,7 +19928,19 @@ var MediaFileKindEnum = _enum([
|
|
|
19874
19928
|
* `analytics-query-facade.ts`; nothing else reads it.
|
|
19875
19929
|
*/
|
|
19876
19930
|
var MediaFileSchema = object({
|
|
19877
|
-
|
|
19931
|
+
/**
|
|
19932
|
+
* The media row's OWN id — the rowid SQLite assigned it (D482).
|
|
19933
|
+
*
|
|
19934
|
+
* It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
|
|
19935
|
+
* [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
|
|
19936
|
+
* per-table rowid aliases, so `object:101314` and `motion:101314` are two
|
|
19937
|
+
* different rows that spell the same number, and a track whose
|
|
19938
|
+
* `bestEventId` was an object event was served a motion event's snapshot —
|
|
19939
|
+
* a night-time thumbnail on an afternoon track, with no error anywhere. A
|
|
19940
|
+
* surrogate id cannot name the wrong row's owner, because it names no owner
|
|
19941
|
+
* at all.
|
|
19942
|
+
*/
|
|
19943
|
+
mediaId: number().int(),
|
|
19878
19944
|
kind: MediaFileKindEnum,
|
|
19879
19945
|
sizeBytes: number(),
|
|
19880
19946
|
timestamp: number()
|
|
@@ -19982,7 +20048,7 @@ var RetrainTrackSchema = object({
|
|
|
19982
20048
|
});
|
|
19983
20049
|
/** A frame the picker may offer — an index row, no blob was read to produce it. */
|
|
19984
20050
|
var RetrainFrameCandidateSchema = object({
|
|
19985
|
-
|
|
20051
|
+
mediaId: number().int(),
|
|
19986
20052
|
kind: MediaFileKindEnum,
|
|
19987
20053
|
timestamp: number(),
|
|
19988
20054
|
sizeBytes: number().int(),
|
|
@@ -19996,7 +20062,7 @@ var RetrainFrameSchema = object({
|
|
|
19996
20062
|
deviceId: number(),
|
|
19997
20063
|
trackId: string(),
|
|
19998
20064
|
/** Provenance only. It may already point at nothing — that is expected. */
|
|
19999
|
-
|
|
20065
|
+
sourceMediaId: number().int(),
|
|
20000
20066
|
sourceKind: MediaFileKindEnum,
|
|
20001
20067
|
sizeBytes: number().int(),
|
|
20002
20068
|
width: number().int(),
|
|
@@ -20012,7 +20078,7 @@ var RetrainCopyRefusalSchema = _enum([
|
|
|
20012
20078
|
var RetrainFrameSelectionSchema = object({
|
|
20013
20079
|
copied: array(RetrainFrameSchema).readonly(),
|
|
20014
20080
|
refused: array(object({
|
|
20015
|
-
|
|
20081
|
+
sourceMediaId: number().int(),
|
|
20016
20082
|
reason: RetrainCopyRefusalSchema
|
|
20017
20083
|
})).readonly()
|
|
20018
20084
|
});
|
|
@@ -20020,7 +20086,7 @@ var RetrainFrameListSchema = object({
|
|
|
20020
20086
|
candidates: array(RetrainFrameCandidateSchema).readonly(),
|
|
20021
20087
|
copies: array(RetrainFrameSchema).readonly(),
|
|
20022
20088
|
/** What the page pre-selects — the native key frame when one survives. */
|
|
20023
|
-
|
|
20089
|
+
autoPickMediaId: number().int().optional()
|
|
20024
20090
|
});
|
|
20025
20091
|
/** What the operator asked the assist to look for. */
|
|
20026
20092
|
var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
|
|
@@ -20115,9 +20181,11 @@ var RecentTracksQueryInput = object({
|
|
|
20115
20181
|
});
|
|
20116
20182
|
/**
|
|
20117
20183
|
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
20118
|
-
* `
|
|
20119
|
-
* served by the event-media plane
|
|
20120
|
-
* member visible has been materialised
|
|
20184
|
+
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
20185
|
+
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
20186
|
+
* first frame with a member visible has been materialised (D482 — it was the
|
|
20187
|
+
* row's composite key, which embedded the owner and could name another table's
|
|
20188
|
+
* row once event ids became per-table rowids).
|
|
20121
20189
|
*/
|
|
20122
20190
|
var SummarySchema = object({
|
|
20123
20191
|
id: string(),
|
|
@@ -20126,19 +20194,115 @@ var SummarySchema = object({
|
|
|
20126
20194
|
lastActiveAt: number(),
|
|
20127
20195
|
sealedAt: number().nullable(),
|
|
20128
20196
|
memberCount: number().int().nonnegative(),
|
|
20129
|
-
|
|
20197
|
+
groupShotMediaId: number().int().nullable()
|
|
20130
20198
|
});
|
|
20131
20199
|
var SummariesQueryInput = object({
|
|
20132
20200
|
deviceIds: array(number()).min(1),
|
|
20133
20201
|
since: number().optional(),
|
|
20134
20202
|
until: number().optional(),
|
|
20135
|
-
limit: number().int().min(1).max(200).default(50)
|
|
20203
|
+
limit: number().int().min(1).max(200).default(50),
|
|
20204
|
+
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
20205
|
+
* meaning of "dog" on every summary surface. */
|
|
20206
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
20136
20207
|
});
|
|
20137
|
-
var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
|
|
20138
20208
|
var SummaryDetailSchema = object({
|
|
20139
20209
|
summary: SummarySchema,
|
|
20140
|
-
/**
|
|
20141
|
-
|
|
20210
|
+
/** Members in absorption order, oldest join first. */
|
|
20211
|
+
members: array(object({
|
|
20212
|
+
trackId: string(),
|
|
20213
|
+
/**
|
|
20214
|
+
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
20215
|
+
* and the track no longer exists to fill it.
|
|
20216
|
+
*
|
|
20217
|
+
* The join, not the latest opinion: class voting can re-decide a track's
|
|
20218
|
+
* class afterwards, and a group's composition is the history of who came
|
|
20219
|
+
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
20220
|
+
* dog" — rather than being handed a second, denormalised tally that would
|
|
20221
|
+
* drift from the members it claims to describe.
|
|
20222
|
+
*/
|
|
20223
|
+
className: string().nullable(),
|
|
20224
|
+
/** `primary` is the one member that carries the group's identity. */
|
|
20225
|
+
role: _enum([
|
|
20226
|
+
"primary",
|
|
20227
|
+
"sibling",
|
|
20228
|
+
"child"
|
|
20229
|
+
]).nullable(),
|
|
20230
|
+
joinedAt: number(),
|
|
20231
|
+
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
20232
|
+
* at read time. Absent when nothing resolved, never an empty string. */
|
|
20233
|
+
label: string().optional(),
|
|
20234
|
+
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
20235
|
+
* recognised nobody, and absent for a member whose track has been pruned —
|
|
20236
|
+
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
20237
|
+
subLabel: string().optional()
|
|
20238
|
+
})).readonly()
|
|
20239
|
+
});
|
|
20240
|
+
/**
|
|
20241
|
+
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
20242
|
+
*
|
|
20243
|
+
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
20244
|
+
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
20245
|
+
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
20246
|
+
* are on {@link getSummary}: shipping every member of every group so a client
|
|
20247
|
+
* can count them turns a page of two hundred groups into a thousand records to
|
|
20248
|
+
* draw two hundred badges.
|
|
20249
|
+
*/
|
|
20250
|
+
var SummaryListItemSchema = object({
|
|
20251
|
+
summary: SummarySchema,
|
|
20252
|
+
/** Class counts, most numerous first; `className: null` is a member whose
|
|
20253
|
+
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
20254
|
+
classes: array(object({
|
|
20255
|
+
className: string().nullable(),
|
|
20256
|
+
count: number().int().positive()
|
|
20257
|
+
})).readonly()
|
|
20258
|
+
});
|
|
20259
|
+
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
20260
|
+
/**
|
|
20261
|
+
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
20262
|
+
*
|
|
20263
|
+
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
20264
|
+
* summaries feed that could only answer "the last N for these cameras"
|
|
20265
|
+
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
20266
|
+
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
20267
|
+
* "newest" means, on one screen.
|
|
20268
|
+
*/
|
|
20269
|
+
var RecentSummariesQueryInput = object({
|
|
20270
|
+
/** Devices to merge. An empty array yields an empty page. */
|
|
20271
|
+
deviceIds: array(number()),
|
|
20272
|
+
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
20273
|
+
since: number().optional(),
|
|
20274
|
+
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
20275
|
+
until: number().optional(),
|
|
20276
|
+
limit: number().int().min(1).max(500).default(100),
|
|
20277
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
20278
|
+
cursor: string().optional(),
|
|
20279
|
+
/**
|
|
20280
|
+
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
20281
|
+
* deliberately the same name: the events filter tree emits one list of ticked
|
|
20282
|
+
* taxonomy nodes, and a summaries feed that called it something else would
|
|
20283
|
+
* make the operator's one filter component produce two shapes.
|
|
20284
|
+
*
|
|
20285
|
+
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
20286
|
+
* me the arrivals with a dog" has to return the group of four people who had
|
|
20287
|
+
* one with them; a filter on the group's own fields could only ever answer
|
|
20288
|
+
* about its primary.
|
|
20289
|
+
*
|
|
20290
|
+
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
20291
|
+
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
20292
|
+
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
20293
|
+
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
20294
|
+
* that read only the class would answer "animal" and never "dog".
|
|
20295
|
+
*
|
|
20296
|
+
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
20297
|
+
*/
|
|
20298
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
20299
|
+
});
|
|
20300
|
+
var RecentSummariesPageSchema = object({
|
|
20301
|
+
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
20302
|
+
* {@link listSummaries} — one list shape, so a card renders the same
|
|
20303
|
+
* whichever feed drew it. */
|
|
20304
|
+
summaries: array(SummaryListItemSchema).readonly(),
|
|
20305
|
+
nextCursor: string().nullable()
|
|
20142
20306
|
});
|
|
20143
20307
|
var RecentTracksPageSchema = object({
|
|
20144
20308
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -20552,7 +20716,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20552
20716
|
classes: array(string()).optional(),
|
|
20553
20717
|
/** See {@link ExcludeSourcesDoc}. */
|
|
20554
20718
|
excludeSources: array(TrackSourceSchema).optional()
|
|
20555
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20719
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20556
20720
|
kind: "mutation",
|
|
20557
20721
|
auth: "admin"
|
|
20558
20722
|
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
|
|
@@ -20680,7 +20844,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20680
20844
|
}), method(object({
|
|
20681
20845
|
deviceId: number(),
|
|
20682
20846
|
trackId: string(),
|
|
20683
|
-
|
|
20847
|
+
mediaIds: array(number().int()).min(1)
|
|
20684
20848
|
}), RetrainFrameSelectionSchema, {
|
|
20685
20849
|
kind: "mutation",
|
|
20686
20850
|
auth: "admin"
|
|
@@ -20748,7 +20912,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20748
20912
|
kind: "query",
|
|
20749
20913
|
auth: "admin"
|
|
20750
20914
|
}), method(object({
|
|
20751
|
-
|
|
20915
|
+
/** Which of the three event tables owns the row. */
|
|
20916
|
+
ownerType: EventOwnerTypeSchema,
|
|
20917
|
+
/** The event's rowid in that table (D474: an event id is a number). */
|
|
20918
|
+
eventId: number().int(),
|
|
20752
20919
|
kind: MediaFileKindEnum.optional(),
|
|
20753
20920
|
deviceId: number()
|
|
20754
20921
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
@@ -20759,7 +20926,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20759
20926
|
trackId: string(),
|
|
20760
20927
|
deviceId: number()
|
|
20761
20928
|
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
20762
|
-
|
|
20929
|
+
ownerType: EventOwnerTypeSchema,
|
|
20930
|
+
eventId: number().int(),
|
|
20763
20931
|
deviceId: number()
|
|
20764
20932
|
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
20765
20933
|
kind: "mutation",
|
|
@@ -25960,8 +26128,8 @@ var IdentitySchema = object({
|
|
|
25960
26128
|
id: string(),
|
|
25961
26129
|
name: string(),
|
|
25962
26130
|
sampleCount: number().int().nonnegative(),
|
|
25963
|
-
|
|
25964
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
26131
|
+
coverMediaId: number().int().optional(),
|
|
26132
|
+
/** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
|
|
25965
26133
|
* Lets the UI render the person's face avatar instead of a placeholder icon. */
|
|
25966
26134
|
coverBase64: string().optional()
|
|
25967
26135
|
});
|
|
@@ -25987,8 +26155,8 @@ var IdentitySampleAuditRowSchema = object({
|
|
|
25987
26155
|
enrolledAt: number().int(),
|
|
25988
26156
|
deviceId: number().int().optional(),
|
|
25989
26157
|
source: _enum(["detected", "photo"]),
|
|
25990
|
-
/** The enrolled crop's media
|
|
25991
|
-
|
|
26158
|
+
/** The enrolled crop's media row id, so the panel can show the evidence. */
|
|
26159
|
+
mediaId: number().int().optional(),
|
|
25992
26160
|
/**
|
|
25993
26161
|
* False = the sample is stamped with a DIFFERENT face model, and a cosine
|
|
25994
26162
|
* across feature spaces is a well-formed float with no meaning. Every number
|
|
@@ -26057,15 +26225,15 @@ var FaceInfoSchema = object({
|
|
|
26057
26225
|
*/
|
|
26058
26226
|
cropUrl: string().optional(),
|
|
26059
26227
|
/** Design B: the face bbox (pixel space) on the key frame — lets a detail
|
|
26060
|
-
* view draw the box over the native `
|
|
26228
|
+
* view draw the box over the native `keyFrameMediaId` frame. Absent on
|
|
26061
26229
|
* legacy rows written before design B. */
|
|
26062
26230
|
faceBbox: BoundingBoxSchema.optional(),
|
|
26063
26231
|
/** Design B: MediaStore key of the track's native-resolution key frame.
|
|
26064
26232
|
* Fetch the native JPEG via the event-media data-plane
|
|
26065
|
-
* (`/addon/<addonId>/event-media/<
|
|
26233
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
|
|
26066
26234
|
* track produced no key frame (e.g. native/onboard source) — the UI falls
|
|
26067
26235
|
* back to the inline `base64` face crop. */
|
|
26068
|
-
|
|
26236
|
+
keyFrameMediaId: number().int().optional(),
|
|
26069
26237
|
/** Winning identity-match cosine (0..1) for this face's track, when an
|
|
26070
26238
|
* identity was auto-confirmed. Lets the UI surface WHY a face was assigned
|
|
26071
26239
|
* (confidence badge / low-confidence audit). Absent on legacy rows and on
|
|
@@ -26134,11 +26302,14 @@ var FaceClusterSchema = object({
|
|
|
26134
26302
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
26135
26303
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
26136
26304
|
*
|
|
26137
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
26138
|
-
* media
|
|
26305
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
26306
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
26307
|
+
* access decision.
|
|
26139
26308
|
*/
|
|
26140
26309
|
var MediaFileLiteSchema$1 = object({
|
|
26141
|
-
|
|
26310
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
26311
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
26312
|
+
mediaId: number().int(),
|
|
26142
26313
|
kind: string(),
|
|
26143
26314
|
url: string(),
|
|
26144
26315
|
sizeBytes: number(),
|
|
@@ -26155,7 +26326,7 @@ method(object({
|
|
|
26155
26326
|
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
26156
26327
|
* four times and the viewer holds at `staleTime: 30_000`.
|
|
26157
26328
|
*
|
|
26158
|
-
* Nothing loses its avatar: `
|
|
26329
|
+
* Nothing loses its avatar: `coverMediaId` is already on every row and
|
|
26159
26330
|
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
26160
26331
|
*
|
|
26161
26332
|
* **This is an INPUT field, so it does not reach the addon until the
|
|
@@ -29518,8 +29689,8 @@ var VehicleSchema = object({
|
|
|
29518
29689
|
id: string(),
|
|
29519
29690
|
name: string(),
|
|
29520
29691
|
sampleCount: number().int().nonnegative(),
|
|
29521
|
-
|
|
29522
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
29692
|
+
coverMediaId: number().int().optional(),
|
|
29693
|
+
/** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
|
|
29523
29694
|
coverBase64: string().optional()
|
|
29524
29695
|
});
|
|
29525
29696
|
var VehicleSampleInfoSchema = object({
|
|
@@ -29552,7 +29723,7 @@ var PlateInfoSchema = object({
|
|
|
29552
29723
|
/** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
|
|
29553
29724
|
plateBbox: BoundingBoxSchema.optional(),
|
|
29554
29725
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
29555
|
-
|
|
29726
|
+
keyFrameMediaId: number().int().optional(),
|
|
29556
29727
|
base64: string().optional(),
|
|
29557
29728
|
/**
|
|
29558
29729
|
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
@@ -29573,11 +29744,14 @@ var PlateInfoSchema = object({
|
|
|
29573
29744
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
29574
29745
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
29575
29746
|
*
|
|
29576
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
29577
|
-
* media
|
|
29747
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
29748
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
29749
|
+
* access decision.
|
|
29578
29750
|
*/
|
|
29579
29751
|
var MediaFileLiteSchema = object({
|
|
29580
|
-
|
|
29752
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
29753
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
29754
|
+
mediaId: number().int(),
|
|
29581
29755
|
kind: string(),
|
|
29582
29756
|
url: string(),
|
|
29583
29757
|
sizeBytes: number(),
|
|
@@ -29636,7 +29810,7 @@ method(object({
|
|
|
29636
29810
|
}), method(object({
|
|
29637
29811
|
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
29638
29812
|
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
29639
|
-
* option; `
|
|
29813
|
+
* option; `coverMediaId` + the `event-media` plane carry the picture.
|
|
29640
29814
|
* INPUT field: stripped by the hub router until the train ships, which
|
|
29641
29815
|
* resolves to `false` and is exactly the intended default. */
|
|
29642
29816
|
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
@@ -31205,7 +31379,14 @@ var SceneReferenceSchema = object({
|
|
|
31205
31379
|
modelId: string(),
|
|
31206
31380
|
condition: SceneConditionSchema,
|
|
31207
31381
|
capturedAt: number(),
|
|
31208
|
-
|
|
31382
|
+
/**
|
|
31383
|
+
* The reference thumbnail's media ROW id (D482).
|
|
31384
|
+
*
|
|
31385
|
+
* The name already said `mediaId` while the value was the row's composite
|
|
31386
|
+
* key — a leftover that read as done and was not. It is the row's own id
|
|
31387
|
+
* now, addressed at `/addon/<addonId>/event-media/m/<id>`.
|
|
31388
|
+
*/
|
|
31389
|
+
thumbnailMediaId: number().int().optional(),
|
|
31209
31390
|
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
31210
31391
|
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
31211
31392
|
* normalized rect frame a different piece of world, and the scene would
|
|
@@ -32296,7 +32477,29 @@ var LoggingSettingsPatchSchema = object({
|
|
|
32296
32477
|
* disarmed the channels it did not mention would make the Levels page and
|
|
32297
32478
|
* the Diagnostics page fight over the same value.
|
|
32298
32479
|
*/
|
|
32299
|
-
channels: array(LogChannelWindowPatchSchema).readonly().optional()
|
|
32480
|
+
channels: array(LogChannelWindowPatchSchema).readonly().optional(),
|
|
32481
|
+
/**
|
|
32482
|
+
* How many days the analytics OPS LOG is kept — the audit trail of what
|
|
32483
|
+
* retention actually deleted.
|
|
32484
|
+
*
|
|
32485
|
+
* It lives HERE, on the logging document, and not on the analytics addon's
|
|
32486
|
+
* settings form, on the operator's instruction: every other log-ish window in
|
|
32487
|
+
* this system is configured through this one document, and a retention audit
|
|
32488
|
+
* configured somewhere else is a second place to look when the question is
|
|
32489
|
+
* "what happened to my data".
|
|
32490
|
+
*
|
|
32491
|
+
* That placement has a cost worth stating: this document ships in the
|
|
32492
|
+
* framework closure, so this knob needs a published `@camstack/server` while
|
|
32493
|
+
* the four windows beside it (D485) reach a node on `camstack deploy`.
|
|
32494
|
+
*
|
|
32495
|
+
* `retention-model.ts` argued this one must NOT follow a device window,
|
|
32496
|
+
* because the audit trail is the history of the SWEEP and not of the camera.
|
|
32497
|
+
* That argument stands and is untouched — what changes is that 30 days stops
|
|
32498
|
+
* being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
|
|
32499
|
+
* rather than 0-as-delete: an audit log truncated to nothing is precisely the
|
|
32500
|
+
* state in which the next 9.5 GiB leak cannot be explained.
|
|
32501
|
+
*/
|
|
32502
|
+
opsLogRetentionDays: number().int().min(0).max(3650).optional()
|
|
32300
32503
|
});
|
|
32301
32504
|
/**
|
|
32302
32505
|
* Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
|
|
@@ -32369,6 +32572,14 @@ var LoggingSettingsStateSchema = object({
|
|
|
32369
32572
|
channels: array(LogChannelDescriptorSchema).readonly(),
|
|
32370
32573
|
/** The channels ARMED right now, each with its deadline. */
|
|
32371
32574
|
activeChannels: array(LogChannelWindowStateSchema).readonly(),
|
|
32575
|
+
/**
|
|
32576
|
+
* The ops-log window in days, as it is in force. `0` = kept forever.
|
|
32577
|
+
*
|
|
32578
|
+
* Reported rather than left to the caller's memory of what it wrote: this is
|
|
32579
|
+
* the value the analytics sweep will actually use, and an operator asking how
|
|
32580
|
+
* long their audit trail lives should not have to infer it from a default.
|
|
32581
|
+
*/
|
|
32582
|
+
opsLogRetentionDays: number().int().min(0),
|
|
32372
32583
|
persisted: boolean()
|
|
32373
32584
|
});
|
|
32374
32585
|
method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string(), unknown()), _null(), {
|
|
@@ -33189,7 +33400,7 @@ var StationaryObjectSchema = object({
|
|
|
33189
33400
|
/** Enrichment label carried from the source track (identity / plate). */
|
|
33190
33401
|
label: string().optional(),
|
|
33191
33402
|
/** Native-resolution key-frame media key for the parked object's best image. */
|
|
33192
|
-
|
|
33403
|
+
keyFrameMediaId: number().int().optional()
|
|
33193
33404
|
});
|
|
33194
33405
|
var CameraOccupancySnapshotSchema = object({
|
|
33195
33406
|
/** Frame timestamp of the inference result that produced this snapshot. */
|
|
@@ -35927,6 +36138,12 @@ Object.freeze({
|
|
|
35927
36138
|
addonId: null,
|
|
35928
36139
|
access: "create"
|
|
35929
36140
|
},
|
|
36141
|
+
"dataStoreProvider.upsert": {
|
|
36142
|
+
capName: "data-store-provider",
|
|
36143
|
+
capScope: "system",
|
|
36144
|
+
addonId: null,
|
|
36145
|
+
access: "create"
|
|
36146
|
+
},
|
|
35930
36147
|
"dayNight.getOptions": {
|
|
35931
36148
|
capName: "day-night",
|
|
35932
36149
|
capScope: "device",
|
|
@@ -38363,6 +38580,12 @@ Object.freeze({
|
|
|
38363
38580
|
addonId: null,
|
|
38364
38581
|
access: "view"
|
|
38365
38582
|
},
|
|
38583
|
+
"pipelineAnalytics.listRecentSummaries": {
|
|
38584
|
+
capName: "pipeline-analytics",
|
|
38585
|
+
capScope: "device",
|
|
38586
|
+
addonId: null,
|
|
38587
|
+
access: "view"
|
|
38588
|
+
},
|
|
38366
38589
|
"pipelineAnalytics.listRecentTracks": {
|
|
38367
38590
|
capName: "pipeline-analytics",
|
|
38368
38591
|
capScope: "device",
|
|
@@ -39791,6 +40014,12 @@ Object.freeze({
|
|
|
39791
40014
|
addonId: null,
|
|
39792
40015
|
access: "create"
|
|
39793
40016
|
},
|
|
40017
|
+
"settingsStore.upsert": {
|
|
40018
|
+
capName: "settings-store",
|
|
40019
|
+
capScope: "system",
|
|
40020
|
+
addonId: null,
|
|
40021
|
+
access: "create"
|
|
40022
|
+
},
|
|
39794
40023
|
"smtpProvider.getStatus": {
|
|
39795
40024
|
capName: "smtp-provider",
|
|
39796
40025
|
capScope: "system",
|
|
@@ -42184,6 +42413,11 @@ Object.freeze({
|
|
|
42184
42413
|
form: "single",
|
|
42185
42414
|
optional: true
|
|
42186
42415
|
}],
|
|
42416
|
+
"pipelineAnalytics.listRecentSummaries": [{
|
|
42417
|
+
name: "deviceIds",
|
|
42418
|
+
form: "array",
|
|
42419
|
+
optional: false
|
|
42420
|
+
}],
|
|
42187
42421
|
"pipelineAnalytics.listRecentTracks": [{
|
|
42188
42422
|
name: "deviceIds",
|
|
42189
42423
|
form: "array",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-dreo",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.101",
|
|
4
4
|
"description": "Dreo smart-device (fan / air-circulator / purifier / heater / humidifier) device-provider addon for CamStack — wraps the @apocaliss92/nodedreo Dreo cloud client (REST + WebSocket)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|