@camstack/addon-provider-petkit 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
|
@@ -1101,7 +1101,7 @@ var Nodepetkit = class {
|
|
|
1101
1101
|
}
|
|
1102
1102
|
};
|
|
1103
1103
|
//#endregion
|
|
1104
|
-
//#region ../types/dist/event-category-
|
|
1104
|
+
//#region ../types/dist/event-category-ZyX6jcse.mjs
|
|
1105
1105
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
1106
1106
|
EventCategory["SystemBoot"] = "system.boot";
|
|
1107
1107
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -1662,7 +1662,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
1662
1662
|
* a package zone — a newly-appeared stationary object of a package class
|
|
1663
1663
|
* that cleared the class / zone / dwell / size gates. Payload:
|
|
1664
1664
|
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
1665
|
-
* entryId, className, zoneIds,
|
|
1665
|
+
* entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
|
|
1666
1666
|
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
1667
1667
|
* this bus topic drives notifier rules + live UI. See
|
|
1668
1668
|
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
@@ -6448,7 +6448,7 @@ var ZodIssueCode = {
|
|
|
6448
6448
|
var ZodFirstPartyTypeKind;
|
|
6449
6449
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6450
6450
|
//#endregion
|
|
6451
|
-
//#region ../types/dist/sleep-
|
|
6451
|
+
//#region ../types/dist/sleep-DBKu2-U5.mjs
|
|
6452
6452
|
/**
|
|
6453
6453
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6454
6454
|
* window to float samples (D455).
|
|
@@ -8415,13 +8415,30 @@ new Set([
|
|
|
8415
8415
|
"scene",
|
|
8416
8416
|
"motion",
|
|
8417
8417
|
"object",
|
|
8418
|
-
"audio"
|
|
8418
|
+
"audio",
|
|
8419
|
+
"mosaic"
|
|
8419
8420
|
]);
|
|
8420
|
-
|
|
8421
|
+
/**
|
|
8422
|
+
* The owner types that are event tables, in the order the event-media resolver
|
|
8423
|
+
* should consider them. Exported so a consumer asking "is this key an event?"
|
|
8424
|
+
* does not re-spell the list and drift from it.
|
|
8425
|
+
*/
|
|
8426
|
+
var EVENT_OWNER_TYPES = [
|
|
8421
8427
|
"motion",
|
|
8422
8428
|
"object",
|
|
8423
8429
|
"audio"
|
|
8424
|
-
]
|
|
8430
|
+
];
|
|
8431
|
+
/**
|
|
8432
|
+
* The same list as a Zod enum, for the cap inputs that must NAME the table
|
|
8433
|
+
* (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
|
|
8434
|
+
* `(table, id)`).
|
|
8435
|
+
*
|
|
8436
|
+
* Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
|
|
8437
|
+
* table would otherwise be accepted by the codec and refused at the door, with
|
|
8438
|
+
* nothing failing until a caller asked.
|
|
8439
|
+
*/
|
|
8440
|
+
var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
|
|
8441
|
+
new Set(EVENT_OWNER_TYPES);
|
|
8425
8442
|
var EncodeProfileSchema = object({
|
|
8426
8443
|
video: object({
|
|
8427
8444
|
codec: _enum([
|
|
@@ -8460,7 +8477,23 @@ var EncodeProfileSchema = object({
|
|
|
8460
8477
|
"zerolatency",
|
|
8461
8478
|
"film",
|
|
8462
8479
|
"animation"
|
|
8463
|
-
]).optional()
|
|
8480
|
+
]).optional(),
|
|
8481
|
+
/**
|
|
8482
|
+
* ONE slice per access unit.
|
|
8483
|
+
*
|
|
8484
|
+
* `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
|
|
8485
|
+
* the encoder as five NAL slices that share one RTP timestamp and carry one
|
|
8486
|
+
* marker bit. A libwebrtc depacketiser sees five frame-starts and one
|
|
8487
|
+
* frame-end per frame: the first pictures render and the video then freezes
|
|
8488
|
+
* for good while the audio, on its own plane, plays on. Measured on this hub
|
|
8489
|
+
* 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
|
|
8490
|
+
*
|
|
8491
|
+
* A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
|
|
8492
|
+
* `outputArgs` on purpose: an opaque array is part of the sharing key, so two
|
|
8493
|
+
* consumers meaning the same thing spelled differently would stop sharing one
|
|
8494
|
+
* child. Absent means "whatever the encoder does" — today's behaviour.
|
|
8495
|
+
*/
|
|
8496
|
+
singleSlicePerFrame: boolean().optional()
|
|
8464
8497
|
}),
|
|
8465
8498
|
audio: union([literal("passthrough"), object({
|
|
8466
8499
|
codec: _enum([
|
|
@@ -8510,7 +8543,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
|
|
|
8510
8543
|
audio: "passthrough"
|
|
8511
8544
|
};
|
|
8512
8545
|
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
8513
|
-
({ ...BASE_LIVE_EGRESS_PROFILE });
|
|
8546
|
+
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
8514
8547
|
/**
|
|
8515
8548
|
* Deep wiring healthcheck — snapshot of active reachability probes across
|
|
8516
8549
|
* every declared capability + widget of every installed plugin, on every
|
|
@@ -13620,6 +13653,16 @@ method(object({
|
|
|
13620
13653
|
filter: QueryFilterSchema.optional(),
|
|
13621
13654
|
columns: array(string()).readonly().optional()
|
|
13622
13655
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
13656
|
+
namespace: string().optional(),
|
|
13657
|
+
collection: string(),
|
|
13658
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
13659
|
+
* index on the collection. Never empty. */
|
|
13660
|
+
conflict: array(string()).readonly(),
|
|
13661
|
+
record: BulkRecordSchema
|
|
13662
|
+
}), object({
|
|
13663
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
13664
|
+
* row's own id on an update. */
|
|
13665
|
+
id: union([string(), number()]) }), { kind: "mutation" }), method(object({
|
|
13623
13666
|
namespace: string().optional(),
|
|
13624
13667
|
collection: string(),
|
|
13625
13668
|
record: object({
|
|
@@ -13754,6 +13797,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
13754
13797
|
id: union([string(), number()]) }), {
|
|
13755
13798
|
kind: "mutation",
|
|
13756
13799
|
auth: "admin"
|
|
13800
|
+
}), method(object({
|
|
13801
|
+
namespace: string().optional(),
|
|
13802
|
+
collection: string(),
|
|
13803
|
+
conflict: array(string()).readonly(),
|
|
13804
|
+
record: BulkRecordSchema
|
|
13805
|
+
}), object({ id: union([string(), number()]) }), {
|
|
13806
|
+
kind: "mutation",
|
|
13807
|
+
auth: "admin"
|
|
13757
13808
|
}), method(object({
|
|
13758
13809
|
namespace: string().optional(),
|
|
13759
13810
|
collection: string(),
|
|
@@ -20253,8 +20304,8 @@ var TrackPositionSchema = object({
|
|
|
20253
20304
|
var TrackSnapshotSchema = object({
|
|
20254
20305
|
timestamp: number(),
|
|
20255
20306
|
position: TrackPositionSchema,
|
|
20256
|
-
/**
|
|
20257
|
-
|
|
20307
|
+
/** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
|
|
20308
|
+
mediaId: number().int()
|
|
20258
20309
|
});
|
|
20259
20310
|
/**
|
|
20260
20311
|
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
@@ -20858,14 +20909,14 @@ var ObjectEventSchema = object({
|
|
|
20858
20909
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
20859
20910
|
frameWidth: number().optional(),
|
|
20860
20911
|
frameHeight: number().optional(),
|
|
20861
|
-
/**
|
|
20862
|
-
|
|
20863
|
-
/** Design B:
|
|
20912
|
+
/** Media row id of the crop attached to this event (if any) — D482. */
|
|
20913
|
+
mediaId: number().int().optional(),
|
|
20914
|
+
/** Design B: media row id of the track's native-resolution key frame (the
|
|
20864
20915
|
* best-detection full frame). Resolve via the event-media data-plane
|
|
20865
|
-
* (`/addon/<addonId>/event-media/<
|
|
20916
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
|
|
20866
20917
|
* draws `bbox` over the native frame. Absent on legacy rows / non-decoded
|
|
20867
|
-
* sources — consumers fall back to `
|
|
20868
|
-
|
|
20918
|
+
* sources — consumers fall back to `mediaId` (the tight crop). */
|
|
20919
|
+
keyFrameMediaId: number().int().optional(),
|
|
20869
20920
|
/** Populated by B5 (recording playback URL for this event). */
|
|
20870
20921
|
mediaUrl: string().optional(),
|
|
20871
20922
|
/** The parent track's key-event importance [0,1], propagated to every object
|
|
@@ -20915,7 +20966,7 @@ var MediaFileKindEnum = _enum([
|
|
|
20915
20966
|
* hub-main's heap on the way past — for an `<img>` that would have cached it.
|
|
20916
20967
|
*
|
|
20917
20968
|
* `url` points at the `event-media` data plane
|
|
20918
|
-
* (`/addon/<addonId>/event-media/<
|
|
20969
|
+
* (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
|
|
20919
20970
|
* with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
|
|
20920
20971
|
* render a `?variant=thumb`, and streams. The hub gate in front of it requires
|
|
20921
20972
|
* a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
|
|
@@ -20923,10 +20974,13 @@ var MediaFileKindEnum = _enum([
|
|
|
20923
20974
|
* `data-plane-access.ts` for the rule and the one gap it does not close
|
|
20924
20975
|
* (per-device scoping).
|
|
20925
20976
|
*
|
|
20926
|
-
* The URL is built from the row's
|
|
20927
|
-
*
|
|
20977
|
+
* The URL is built from the row's own id, which since D482 says nothing about
|
|
20978
|
+
* the row's owner or kind — and that is the point. The published `kind` is not
|
|
20979
|
+
* the stored one (a track's face/plate crop is stored as `crop` under
|
|
20928
20980
|
* `('face'|'plate', '<prefix>-<trackId>')` and published as
|
|
20929
|
-
* `faceCrop`/`plateCrop
|
|
20981
|
+
* `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
|
|
20982
|
+
* taken from `row.key` verbatim or it 404'd exactly those two rows. An id
|
|
20983
|
+
* cannot be mis-reconstructed, because there is nothing in it to reconstruct.
|
|
20930
20984
|
*
|
|
20931
20985
|
* ## `base64` is TRANSITIONAL and is going away
|
|
20932
20986
|
*
|
|
@@ -20939,7 +20993,19 @@ var MediaFileKindEnum = _enum([
|
|
|
20939
20993
|
* `analytics-query-facade.ts`; nothing else reads it.
|
|
20940
20994
|
*/
|
|
20941
20995
|
var MediaFileSchema = object({
|
|
20942
|
-
|
|
20996
|
+
/**
|
|
20997
|
+
* The media row's OWN id — the rowid SQLite assigned it (D482).
|
|
20998
|
+
*
|
|
20999
|
+
* It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
|
|
21000
|
+
* [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
|
|
21001
|
+
* per-table rowid aliases, so `object:101314` and `motion:101314` are two
|
|
21002
|
+
* different rows that spell the same number, and a track whose
|
|
21003
|
+
* `bestEventId` was an object event was served a motion event's snapshot —
|
|
21004
|
+
* a night-time thumbnail on an afternoon track, with no error anywhere. A
|
|
21005
|
+
* surrogate id cannot name the wrong row's owner, because it names no owner
|
|
21006
|
+
* at all.
|
|
21007
|
+
*/
|
|
21008
|
+
mediaId: number().int(),
|
|
20943
21009
|
kind: MediaFileKindEnum,
|
|
20944
21010
|
sizeBytes: number(),
|
|
20945
21011
|
timestamp: number()
|
|
@@ -21047,7 +21113,7 @@ var RetrainTrackSchema = object({
|
|
|
21047
21113
|
});
|
|
21048
21114
|
/** A frame the picker may offer — an index row, no blob was read to produce it. */
|
|
21049
21115
|
var RetrainFrameCandidateSchema = object({
|
|
21050
|
-
|
|
21116
|
+
mediaId: number().int(),
|
|
21051
21117
|
kind: MediaFileKindEnum,
|
|
21052
21118
|
timestamp: number(),
|
|
21053
21119
|
sizeBytes: number().int(),
|
|
@@ -21061,7 +21127,7 @@ var RetrainFrameSchema = object({
|
|
|
21061
21127
|
deviceId: number(),
|
|
21062
21128
|
trackId: string(),
|
|
21063
21129
|
/** Provenance only. It may already point at nothing — that is expected. */
|
|
21064
|
-
|
|
21130
|
+
sourceMediaId: number().int(),
|
|
21065
21131
|
sourceKind: MediaFileKindEnum,
|
|
21066
21132
|
sizeBytes: number().int(),
|
|
21067
21133
|
width: number().int(),
|
|
@@ -21077,7 +21143,7 @@ var RetrainCopyRefusalSchema = _enum([
|
|
|
21077
21143
|
var RetrainFrameSelectionSchema = object({
|
|
21078
21144
|
copied: array(RetrainFrameSchema).readonly(),
|
|
21079
21145
|
refused: array(object({
|
|
21080
|
-
|
|
21146
|
+
sourceMediaId: number().int(),
|
|
21081
21147
|
reason: RetrainCopyRefusalSchema
|
|
21082
21148
|
})).readonly()
|
|
21083
21149
|
});
|
|
@@ -21085,7 +21151,7 @@ var RetrainFrameListSchema = object({
|
|
|
21085
21151
|
candidates: array(RetrainFrameCandidateSchema).readonly(),
|
|
21086
21152
|
copies: array(RetrainFrameSchema).readonly(),
|
|
21087
21153
|
/** What the page pre-selects — the native key frame when one survives. */
|
|
21088
|
-
|
|
21154
|
+
autoPickMediaId: number().int().optional()
|
|
21089
21155
|
});
|
|
21090
21156
|
/** What the operator asked the assist to look for. */
|
|
21091
21157
|
var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
|
|
@@ -21180,9 +21246,11 @@ var RecentTracksQueryInput = object({
|
|
|
21180
21246
|
});
|
|
21181
21247
|
/**
|
|
21182
21248
|
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
21183
|
-
* `
|
|
21184
|
-
* served by the event-media plane
|
|
21185
|
-
* member visible has been materialised
|
|
21249
|
+
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
21250
|
+
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
21251
|
+
* first frame with a member visible has been materialised (D482 — it was the
|
|
21252
|
+
* row's composite key, which embedded the owner and could name another table's
|
|
21253
|
+
* row once event ids became per-table rowids).
|
|
21186
21254
|
*/
|
|
21187
21255
|
var SummarySchema = object({
|
|
21188
21256
|
id: string(),
|
|
@@ -21191,19 +21259,115 @@ var SummarySchema = object({
|
|
|
21191
21259
|
lastActiveAt: number(),
|
|
21192
21260
|
sealedAt: number().nullable(),
|
|
21193
21261
|
memberCount: number().int().nonnegative(),
|
|
21194
|
-
|
|
21262
|
+
groupShotMediaId: number().int().nullable()
|
|
21195
21263
|
});
|
|
21196
21264
|
var SummariesQueryInput = object({
|
|
21197
21265
|
deviceIds: array(number()).min(1),
|
|
21198
21266
|
since: number().optional(),
|
|
21199
21267
|
until: number().optional(),
|
|
21200
|
-
limit: number().int().min(1).max(200).default(50)
|
|
21268
|
+
limit: number().int().min(1).max(200).default(50),
|
|
21269
|
+
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
21270
|
+
* meaning of "dog" on every summary surface. */
|
|
21271
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
21201
21272
|
});
|
|
21202
|
-
var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
|
|
21203
21273
|
var SummaryDetailSchema = object({
|
|
21204
21274
|
summary: SummarySchema,
|
|
21205
|
-
/**
|
|
21206
|
-
|
|
21275
|
+
/** Members in absorption order, oldest join first. */
|
|
21276
|
+
members: array(object({
|
|
21277
|
+
trackId: string(),
|
|
21278
|
+
/**
|
|
21279
|
+
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
21280
|
+
* and the track no longer exists to fill it.
|
|
21281
|
+
*
|
|
21282
|
+
* The join, not the latest opinion: class voting can re-decide a track's
|
|
21283
|
+
* class afterwards, and a group's composition is the history of who came
|
|
21284
|
+
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
21285
|
+
* dog" — rather than being handed a second, denormalised tally that would
|
|
21286
|
+
* drift from the members it claims to describe.
|
|
21287
|
+
*/
|
|
21288
|
+
className: string().nullable(),
|
|
21289
|
+
/** `primary` is the one member that carries the group's identity. */
|
|
21290
|
+
role: _enum([
|
|
21291
|
+
"primary",
|
|
21292
|
+
"sibling",
|
|
21293
|
+
"child"
|
|
21294
|
+
]).nullable(),
|
|
21295
|
+
joinedAt: number(),
|
|
21296
|
+
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
21297
|
+
* at read time. Absent when nothing resolved, never an empty string. */
|
|
21298
|
+
label: string().optional(),
|
|
21299
|
+
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
21300
|
+
* recognised nobody, and absent for a member whose track has been pruned —
|
|
21301
|
+
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
21302
|
+
subLabel: string().optional()
|
|
21303
|
+
})).readonly()
|
|
21304
|
+
});
|
|
21305
|
+
/**
|
|
21306
|
+
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
21307
|
+
*
|
|
21308
|
+
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
21309
|
+
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
21310
|
+
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
21311
|
+
* are on {@link getSummary}: shipping every member of every group so a client
|
|
21312
|
+
* can count them turns a page of two hundred groups into a thousand records to
|
|
21313
|
+
* draw two hundred badges.
|
|
21314
|
+
*/
|
|
21315
|
+
var SummaryListItemSchema = object({
|
|
21316
|
+
summary: SummarySchema,
|
|
21317
|
+
/** Class counts, most numerous first; `className: null` is a member whose
|
|
21318
|
+
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
21319
|
+
classes: array(object({
|
|
21320
|
+
className: string().nullable(),
|
|
21321
|
+
count: number().int().positive()
|
|
21322
|
+
})).readonly()
|
|
21323
|
+
});
|
|
21324
|
+
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
21325
|
+
/**
|
|
21326
|
+
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
21327
|
+
*
|
|
21328
|
+
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
21329
|
+
* summaries feed that could only answer "the last N for these cameras"
|
|
21330
|
+
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
21331
|
+
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
21332
|
+
* "newest" means, on one screen.
|
|
21333
|
+
*/
|
|
21334
|
+
var RecentSummariesQueryInput = object({
|
|
21335
|
+
/** Devices to merge. An empty array yields an empty page. */
|
|
21336
|
+
deviceIds: array(number()),
|
|
21337
|
+
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
21338
|
+
since: number().optional(),
|
|
21339
|
+
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
21340
|
+
until: number().optional(),
|
|
21341
|
+
limit: number().int().min(1).max(500).default(100),
|
|
21342
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
21343
|
+
cursor: string().optional(),
|
|
21344
|
+
/**
|
|
21345
|
+
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
21346
|
+
* deliberately the same name: the events filter tree emits one list of ticked
|
|
21347
|
+
* taxonomy nodes, and a summaries feed that called it something else would
|
|
21348
|
+
* make the operator's one filter component produce two shapes.
|
|
21349
|
+
*
|
|
21350
|
+
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
21351
|
+
* me the arrivals with a dog" has to return the group of four people who had
|
|
21352
|
+
* one with them; a filter on the group's own fields could only ever answer
|
|
21353
|
+
* about its primary.
|
|
21354
|
+
*
|
|
21355
|
+
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
21356
|
+
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
21357
|
+
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
21358
|
+
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
21359
|
+
* that read only the class would answer "animal" and never "dog".
|
|
21360
|
+
*
|
|
21361
|
+
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
21362
|
+
*/
|
|
21363
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
21364
|
+
});
|
|
21365
|
+
var RecentSummariesPageSchema = object({
|
|
21366
|
+
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
21367
|
+
* {@link listSummaries} — one list shape, so a card renders the same
|
|
21368
|
+
* whichever feed drew it. */
|
|
21369
|
+
summaries: array(SummaryListItemSchema).readonly(),
|
|
21370
|
+
nextCursor: string().nullable()
|
|
21207
21371
|
});
|
|
21208
21372
|
var RecentTracksPageSchema = object({
|
|
21209
21373
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -21617,7 +21781,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21617
21781
|
classes: array(string()).optional(),
|
|
21618
21782
|
/** See {@link ExcludeSourcesDoc}. */
|
|
21619
21783
|
excludeSources: array(TrackSourceSchema).optional()
|
|
21620
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
21784
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
21621
21785
|
kind: "mutation",
|
|
21622
21786
|
auth: "admin"
|
|
21623
21787
|
}), 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({
|
|
@@ -21745,7 +21909,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21745
21909
|
}), method(object({
|
|
21746
21910
|
deviceId: number(),
|
|
21747
21911
|
trackId: string(),
|
|
21748
|
-
|
|
21912
|
+
mediaIds: array(number().int()).min(1)
|
|
21749
21913
|
}), RetrainFrameSelectionSchema, {
|
|
21750
21914
|
kind: "mutation",
|
|
21751
21915
|
auth: "admin"
|
|
@@ -21813,7 +21977,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21813
21977
|
kind: "query",
|
|
21814
21978
|
auth: "admin"
|
|
21815
21979
|
}), method(object({
|
|
21816
|
-
|
|
21980
|
+
/** Which of the three event tables owns the row. */
|
|
21981
|
+
ownerType: EventOwnerTypeSchema,
|
|
21982
|
+
/** The event's rowid in that table (D474: an event id is a number). */
|
|
21983
|
+
eventId: number().int(),
|
|
21817
21984
|
kind: MediaFileKindEnum.optional(),
|
|
21818
21985
|
deviceId: number()
|
|
21819
21986
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
@@ -21824,7 +21991,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21824
21991
|
trackId: string(),
|
|
21825
21992
|
deviceId: number()
|
|
21826
21993
|
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
21827
|
-
|
|
21994
|
+
ownerType: EventOwnerTypeSchema,
|
|
21995
|
+
eventId: number().int(),
|
|
21828
21996
|
deviceId: number()
|
|
21829
21997
|
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
21830
21998
|
kind: "mutation",
|
|
@@ -27025,8 +27193,8 @@ var IdentitySchema = object({
|
|
|
27025
27193
|
id: string(),
|
|
27026
27194
|
name: string(),
|
|
27027
27195
|
sampleCount: number().int().nonnegative(),
|
|
27028
|
-
|
|
27029
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
27196
|
+
coverMediaId: number().int().optional(),
|
|
27197
|
+
/** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
|
|
27030
27198
|
* Lets the UI render the person's face avatar instead of a placeholder icon. */
|
|
27031
27199
|
coverBase64: string().optional()
|
|
27032
27200
|
});
|
|
@@ -27052,8 +27220,8 @@ var IdentitySampleAuditRowSchema = object({
|
|
|
27052
27220
|
enrolledAt: number().int(),
|
|
27053
27221
|
deviceId: number().int().optional(),
|
|
27054
27222
|
source: _enum(["detected", "photo"]),
|
|
27055
|
-
/** The enrolled crop's media
|
|
27056
|
-
|
|
27223
|
+
/** The enrolled crop's media row id, so the panel can show the evidence. */
|
|
27224
|
+
mediaId: number().int().optional(),
|
|
27057
27225
|
/**
|
|
27058
27226
|
* False = the sample is stamped with a DIFFERENT face model, and a cosine
|
|
27059
27227
|
* across feature spaces is a well-formed float with no meaning. Every number
|
|
@@ -27122,15 +27290,15 @@ var FaceInfoSchema = object({
|
|
|
27122
27290
|
*/
|
|
27123
27291
|
cropUrl: string().optional(),
|
|
27124
27292
|
/** Design B: the face bbox (pixel space) on the key frame — lets a detail
|
|
27125
|
-
* view draw the box over the native `
|
|
27293
|
+
* view draw the box over the native `keyFrameMediaId` frame. Absent on
|
|
27126
27294
|
* legacy rows written before design B. */
|
|
27127
27295
|
faceBbox: BoundingBoxSchema.optional(),
|
|
27128
27296
|
/** Design B: MediaStore key of the track's native-resolution key frame.
|
|
27129
27297
|
* Fetch the native JPEG via the event-media data-plane
|
|
27130
|
-
* (`/addon/<addonId>/event-media/<
|
|
27298
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
|
|
27131
27299
|
* track produced no key frame (e.g. native/onboard source) — the UI falls
|
|
27132
27300
|
* back to the inline `base64` face crop. */
|
|
27133
|
-
|
|
27301
|
+
keyFrameMediaId: number().int().optional(),
|
|
27134
27302
|
/** Winning identity-match cosine (0..1) for this face's track, when an
|
|
27135
27303
|
* identity was auto-confirmed. Lets the UI surface WHY a face was assigned
|
|
27136
27304
|
* (confidence badge / low-confidence audit). Absent on legacy rows and on
|
|
@@ -27199,11 +27367,14 @@ var FaceClusterSchema = object({
|
|
|
27199
27367
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
27200
27368
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
27201
27369
|
*
|
|
27202
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
27203
|
-
* media
|
|
27370
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
27371
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
27372
|
+
* access decision.
|
|
27204
27373
|
*/
|
|
27205
27374
|
var MediaFileLiteSchema$1 = object({
|
|
27206
|
-
|
|
27375
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
27376
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
27377
|
+
mediaId: number().int(),
|
|
27207
27378
|
kind: string(),
|
|
27208
27379
|
url: string(),
|
|
27209
27380
|
sizeBytes: number(),
|
|
@@ -27220,7 +27391,7 @@ method(object({
|
|
|
27220
27391
|
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
27221
27392
|
* four times and the viewer holds at `staleTime: 30_000`.
|
|
27222
27393
|
*
|
|
27223
|
-
* Nothing loses its avatar: `
|
|
27394
|
+
* Nothing loses its avatar: `coverMediaId` is already on every row and
|
|
27224
27395
|
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
27225
27396
|
*
|
|
27226
27397
|
* **This is an INPUT field, so it does not reach the addon until the
|
|
@@ -30583,8 +30754,8 @@ var VehicleSchema = object({
|
|
|
30583
30754
|
id: string(),
|
|
30584
30755
|
name: string(),
|
|
30585
30756
|
sampleCount: number().int().nonnegative(),
|
|
30586
|
-
|
|
30587
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
30757
|
+
coverMediaId: number().int().optional(),
|
|
30758
|
+
/** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
|
|
30588
30759
|
coverBase64: string().optional()
|
|
30589
30760
|
});
|
|
30590
30761
|
var VehicleSampleInfoSchema = object({
|
|
@@ -30617,7 +30788,7 @@ var PlateInfoSchema = object({
|
|
|
30617
30788
|
/** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
|
|
30618
30789
|
plateBbox: BoundingBoxSchema.optional(),
|
|
30619
30790
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
30620
|
-
|
|
30791
|
+
keyFrameMediaId: number().int().optional(),
|
|
30621
30792
|
base64: string().optional(),
|
|
30622
30793
|
/**
|
|
30623
30794
|
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
@@ -30638,11 +30809,14 @@ var PlateInfoSchema = object({
|
|
|
30638
30809
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
30639
30810
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
30640
30811
|
*
|
|
30641
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
30642
|
-
* media
|
|
30812
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
30813
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
30814
|
+
* access decision.
|
|
30643
30815
|
*/
|
|
30644
30816
|
var MediaFileLiteSchema = object({
|
|
30645
|
-
|
|
30817
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
30818
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
30819
|
+
mediaId: number().int(),
|
|
30646
30820
|
kind: string(),
|
|
30647
30821
|
url: string(),
|
|
30648
30822
|
sizeBytes: number(),
|
|
@@ -30701,7 +30875,7 @@ method(object({
|
|
|
30701
30875
|
}), method(object({
|
|
30702
30876
|
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
30703
30877
|
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
30704
|
-
* option; `
|
|
30878
|
+
* option; `coverMediaId` + the `event-media` plane carry the picture.
|
|
30705
30879
|
* INPUT field: stripped by the hub router until the train ships, which
|
|
30706
30880
|
* resolves to `false` and is exactly the intended default. */
|
|
30707
30881
|
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
@@ -32270,7 +32444,14 @@ var SceneReferenceSchema = object({
|
|
|
32270
32444
|
modelId: string(),
|
|
32271
32445
|
condition: SceneConditionSchema,
|
|
32272
32446
|
capturedAt: number(),
|
|
32273
|
-
|
|
32447
|
+
/**
|
|
32448
|
+
* The reference thumbnail's media ROW id (D482).
|
|
32449
|
+
*
|
|
32450
|
+
* The name already said `mediaId` while the value was the row's composite
|
|
32451
|
+
* key — a leftover that read as done and was not. It is the row's own id
|
|
32452
|
+
* now, addressed at `/addon/<addonId>/event-media/m/<id>`.
|
|
32453
|
+
*/
|
|
32454
|
+
thumbnailMediaId: number().int().optional(),
|
|
32274
32455
|
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
32275
32456
|
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
32276
32457
|
* normalized rect frame a different piece of world, and the scene would
|
|
@@ -33361,7 +33542,29 @@ var LoggingSettingsPatchSchema = object({
|
|
|
33361
33542
|
* disarmed the channels it did not mention would make the Levels page and
|
|
33362
33543
|
* the Diagnostics page fight over the same value.
|
|
33363
33544
|
*/
|
|
33364
|
-
channels: array(LogChannelWindowPatchSchema).readonly().optional()
|
|
33545
|
+
channels: array(LogChannelWindowPatchSchema).readonly().optional(),
|
|
33546
|
+
/**
|
|
33547
|
+
* How many days the analytics OPS LOG is kept — the audit trail of what
|
|
33548
|
+
* retention actually deleted.
|
|
33549
|
+
*
|
|
33550
|
+
* It lives HERE, on the logging document, and not on the analytics addon's
|
|
33551
|
+
* settings form, on the operator's instruction: every other log-ish window in
|
|
33552
|
+
* this system is configured through this one document, and a retention audit
|
|
33553
|
+
* configured somewhere else is a second place to look when the question is
|
|
33554
|
+
* "what happened to my data".
|
|
33555
|
+
*
|
|
33556
|
+
* That placement has a cost worth stating: this document ships in the
|
|
33557
|
+
* framework closure, so this knob needs a published `@camstack/server` while
|
|
33558
|
+
* the four windows beside it (D485) reach a node on `camstack deploy`.
|
|
33559
|
+
*
|
|
33560
|
+
* `retention-model.ts` argued this one must NOT follow a device window,
|
|
33561
|
+
* because the audit trail is the history of the SWEEP and not of the camera.
|
|
33562
|
+
* That argument stands and is untouched — what changes is that 30 days stops
|
|
33563
|
+
* being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
|
|
33564
|
+
* rather than 0-as-delete: an audit log truncated to nothing is precisely the
|
|
33565
|
+
* state in which the next 9.5 GiB leak cannot be explained.
|
|
33566
|
+
*/
|
|
33567
|
+
opsLogRetentionDays: number().int().min(0).max(3650).optional()
|
|
33365
33568
|
});
|
|
33366
33569
|
/**
|
|
33367
33570
|
* Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
|
|
@@ -33434,6 +33637,14 @@ var LoggingSettingsStateSchema = object({
|
|
|
33434
33637
|
channels: array(LogChannelDescriptorSchema).readonly(),
|
|
33435
33638
|
/** The channels ARMED right now, each with its deadline. */
|
|
33436
33639
|
activeChannels: array(LogChannelWindowStateSchema).readonly(),
|
|
33640
|
+
/**
|
|
33641
|
+
* The ops-log window in days, as it is in force. `0` = kept forever.
|
|
33642
|
+
*
|
|
33643
|
+
* Reported rather than left to the caller's memory of what it wrote: this is
|
|
33644
|
+
* the value the analytics sweep will actually use, and an operator asking how
|
|
33645
|
+
* long their audit trail lives should not have to infer it from a default.
|
|
33646
|
+
*/
|
|
33647
|
+
opsLogRetentionDays: number().int().min(0),
|
|
33437
33648
|
persisted: boolean()
|
|
33438
33649
|
});
|
|
33439
33650
|
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(), {
|
|
@@ -34254,7 +34465,7 @@ var StationaryObjectSchema = object({
|
|
|
34254
34465
|
/** Enrichment label carried from the source track (identity / plate). */
|
|
34255
34466
|
label: string().optional(),
|
|
34256
34467
|
/** Native-resolution key-frame media key for the parked object's best image. */
|
|
34257
|
-
|
|
34468
|
+
keyFrameMediaId: number().int().optional()
|
|
34258
34469
|
});
|
|
34259
34470
|
var CameraOccupancySnapshotSchema = object({
|
|
34260
34471
|
/** Frame timestamp of the inference result that produced this snapshot. */
|
|
@@ -36992,6 +37203,12 @@ Object.freeze({
|
|
|
36992
37203
|
addonId: null,
|
|
36993
37204
|
access: "create"
|
|
36994
37205
|
},
|
|
37206
|
+
"dataStoreProvider.upsert": {
|
|
37207
|
+
capName: "data-store-provider",
|
|
37208
|
+
capScope: "system",
|
|
37209
|
+
addonId: null,
|
|
37210
|
+
access: "create"
|
|
37211
|
+
},
|
|
36995
37212
|
"dayNight.getOptions": {
|
|
36996
37213
|
capName: "day-night",
|
|
36997
37214
|
capScope: "device",
|
|
@@ -39428,6 +39645,12 @@ Object.freeze({
|
|
|
39428
39645
|
addonId: null,
|
|
39429
39646
|
access: "view"
|
|
39430
39647
|
},
|
|
39648
|
+
"pipelineAnalytics.listRecentSummaries": {
|
|
39649
|
+
capName: "pipeline-analytics",
|
|
39650
|
+
capScope: "device",
|
|
39651
|
+
addonId: null,
|
|
39652
|
+
access: "view"
|
|
39653
|
+
},
|
|
39431
39654
|
"pipelineAnalytics.listRecentTracks": {
|
|
39432
39655
|
capName: "pipeline-analytics",
|
|
39433
39656
|
capScope: "device",
|
|
@@ -40856,6 +41079,12 @@ Object.freeze({
|
|
|
40856
41079
|
addonId: null,
|
|
40857
41080
|
access: "create"
|
|
40858
41081
|
},
|
|
41082
|
+
"settingsStore.upsert": {
|
|
41083
|
+
capName: "settings-store",
|
|
41084
|
+
capScope: "system",
|
|
41085
|
+
addonId: null,
|
|
41086
|
+
access: "create"
|
|
41087
|
+
},
|
|
40859
41088
|
"smtpProvider.getStatus": {
|
|
40860
41089
|
capName: "smtp-provider",
|
|
40861
41090
|
capScope: "system",
|
|
@@ -43249,6 +43478,11 @@ Object.freeze({
|
|
|
43249
43478
|
form: "single",
|
|
43250
43479
|
optional: true
|
|
43251
43480
|
}],
|
|
43481
|
+
"pipelineAnalytics.listRecentSummaries": [{
|
|
43482
|
+
name: "deviceIds",
|
|
43483
|
+
form: "array",
|
|
43484
|
+
optional: false
|
|
43485
|
+
}],
|
|
43252
43486
|
"pipelineAnalytics.listRecentTracks": [{
|
|
43253
43487
|
name: "deviceIds",
|
|
43254
43488
|
form: "array",
|
package/dist/addon.mjs
CHANGED
|
@@ -1100,7 +1100,7 @@ var Nodepetkit = class {
|
|
|
1100
1100
|
}
|
|
1101
1101
|
};
|
|
1102
1102
|
//#endregion
|
|
1103
|
-
//#region ../types/dist/event-category-
|
|
1103
|
+
//#region ../types/dist/event-category-ZyX6jcse.mjs
|
|
1104
1104
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
1105
1105
|
EventCategory["SystemBoot"] = "system.boot";
|
|
1106
1106
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -1661,7 +1661,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
1661
1661
|
* a package zone — a newly-appeared stationary object of a package class
|
|
1662
1662
|
* that cleared the class / zone / dwell / size gates. Payload:
|
|
1663
1663
|
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
1664
|
-
* entryId, className, zoneIds,
|
|
1664
|
+
* entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
|
|
1665
1665
|
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
1666
1666
|
* this bus topic drives notifier rules + live UI. See
|
|
1667
1667
|
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
@@ -6447,7 +6447,7 @@ var ZodIssueCode = {
|
|
|
6447
6447
|
var ZodFirstPartyTypeKind;
|
|
6448
6448
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6449
6449
|
//#endregion
|
|
6450
|
-
//#region ../types/dist/sleep-
|
|
6450
|
+
//#region ../types/dist/sleep-DBKu2-U5.mjs
|
|
6451
6451
|
/**
|
|
6452
6452
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6453
6453
|
* window to float samples (D455).
|
|
@@ -8414,13 +8414,30 @@ new Set([
|
|
|
8414
8414
|
"scene",
|
|
8415
8415
|
"motion",
|
|
8416
8416
|
"object",
|
|
8417
|
-
"audio"
|
|
8417
|
+
"audio",
|
|
8418
|
+
"mosaic"
|
|
8418
8419
|
]);
|
|
8419
|
-
|
|
8420
|
+
/**
|
|
8421
|
+
* The owner types that are event tables, in the order the event-media resolver
|
|
8422
|
+
* should consider them. Exported so a consumer asking "is this key an event?"
|
|
8423
|
+
* does not re-spell the list and drift from it.
|
|
8424
|
+
*/
|
|
8425
|
+
var EVENT_OWNER_TYPES = [
|
|
8420
8426
|
"motion",
|
|
8421
8427
|
"object",
|
|
8422
8428
|
"audio"
|
|
8423
|
-
]
|
|
8429
|
+
];
|
|
8430
|
+
/**
|
|
8431
|
+
* The same list as a Zod enum, for the cap inputs that must NAME the table
|
|
8432
|
+
* (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
|
|
8433
|
+
* `(table, id)`).
|
|
8434
|
+
*
|
|
8435
|
+
* Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
|
|
8436
|
+
* table would otherwise be accepted by the codec and refused at the door, with
|
|
8437
|
+
* nothing failing until a caller asked.
|
|
8438
|
+
*/
|
|
8439
|
+
var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
|
|
8440
|
+
new Set(EVENT_OWNER_TYPES);
|
|
8424
8441
|
var EncodeProfileSchema = object({
|
|
8425
8442
|
video: object({
|
|
8426
8443
|
codec: _enum([
|
|
@@ -8459,7 +8476,23 @@ var EncodeProfileSchema = object({
|
|
|
8459
8476
|
"zerolatency",
|
|
8460
8477
|
"film",
|
|
8461
8478
|
"animation"
|
|
8462
|
-
]).optional()
|
|
8479
|
+
]).optional(),
|
|
8480
|
+
/**
|
|
8481
|
+
* ONE slice per access unit.
|
|
8482
|
+
*
|
|
8483
|
+
* `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
|
|
8484
|
+
* the encoder as five NAL slices that share one RTP timestamp and carry one
|
|
8485
|
+
* marker bit. A libwebrtc depacketiser sees five frame-starts and one
|
|
8486
|
+
* frame-end per frame: the first pictures render and the video then freezes
|
|
8487
|
+
* for good while the audio, on its own plane, plays on. Measured on this hub
|
|
8488
|
+
* 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
|
|
8489
|
+
*
|
|
8490
|
+
* A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
|
|
8491
|
+
* `outputArgs` on purpose: an opaque array is part of the sharing key, so two
|
|
8492
|
+
* consumers meaning the same thing spelled differently would stop sharing one
|
|
8493
|
+
* child. Absent means "whatever the encoder does" — today's behaviour.
|
|
8494
|
+
*/
|
|
8495
|
+
singleSlicePerFrame: boolean().optional()
|
|
8463
8496
|
}),
|
|
8464
8497
|
audio: union([literal("passthrough"), object({
|
|
8465
8498
|
codec: _enum([
|
|
@@ -8509,7 +8542,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
|
|
|
8509
8542
|
audio: "passthrough"
|
|
8510
8543
|
};
|
|
8511
8544
|
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
8512
|
-
({ ...BASE_LIVE_EGRESS_PROFILE });
|
|
8545
|
+
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
8513
8546
|
/**
|
|
8514
8547
|
* Deep wiring healthcheck — snapshot of active reachability probes across
|
|
8515
8548
|
* every declared capability + widget of every installed plugin, on every
|
|
@@ -13619,6 +13652,16 @@ method(object({
|
|
|
13619
13652
|
filter: QueryFilterSchema.optional(),
|
|
13620
13653
|
columns: array(string()).readonly().optional()
|
|
13621
13654
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
13655
|
+
namespace: string().optional(),
|
|
13656
|
+
collection: string(),
|
|
13657
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
13658
|
+
* index on the collection. Never empty. */
|
|
13659
|
+
conflict: array(string()).readonly(),
|
|
13660
|
+
record: BulkRecordSchema
|
|
13661
|
+
}), object({
|
|
13662
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
13663
|
+
* row's own id on an update. */
|
|
13664
|
+
id: union([string(), number()]) }), { kind: "mutation" }), method(object({
|
|
13622
13665
|
namespace: string().optional(),
|
|
13623
13666
|
collection: string(),
|
|
13624
13667
|
record: object({
|
|
@@ -13753,6 +13796,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
13753
13796
|
id: union([string(), number()]) }), {
|
|
13754
13797
|
kind: "mutation",
|
|
13755
13798
|
auth: "admin"
|
|
13799
|
+
}), method(object({
|
|
13800
|
+
namespace: string().optional(),
|
|
13801
|
+
collection: string(),
|
|
13802
|
+
conflict: array(string()).readonly(),
|
|
13803
|
+
record: BulkRecordSchema
|
|
13804
|
+
}), object({ id: union([string(), number()]) }), {
|
|
13805
|
+
kind: "mutation",
|
|
13806
|
+
auth: "admin"
|
|
13756
13807
|
}), method(object({
|
|
13757
13808
|
namespace: string().optional(),
|
|
13758
13809
|
collection: string(),
|
|
@@ -20252,8 +20303,8 @@ var TrackPositionSchema = object({
|
|
|
20252
20303
|
var TrackSnapshotSchema = object({
|
|
20253
20304
|
timestamp: number(),
|
|
20254
20305
|
position: TrackPositionSchema,
|
|
20255
|
-
/**
|
|
20256
|
-
|
|
20306
|
+
/** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
|
|
20307
|
+
mediaId: number().int()
|
|
20257
20308
|
});
|
|
20258
20309
|
/**
|
|
20259
20310
|
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
@@ -20857,14 +20908,14 @@ var ObjectEventSchema = object({
|
|
|
20857
20908
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
20858
20909
|
frameWidth: number().optional(),
|
|
20859
20910
|
frameHeight: number().optional(),
|
|
20860
|
-
/**
|
|
20861
|
-
|
|
20862
|
-
/** Design B:
|
|
20911
|
+
/** Media row id of the crop attached to this event (if any) — D482. */
|
|
20912
|
+
mediaId: number().int().optional(),
|
|
20913
|
+
/** Design B: media row id of the track's native-resolution key frame (the
|
|
20863
20914
|
* best-detection full frame). Resolve via the event-media data-plane
|
|
20864
|
-
* (`/addon/<addonId>/event-media/<
|
|
20915
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
|
|
20865
20916
|
* draws `bbox` over the native frame. Absent on legacy rows / non-decoded
|
|
20866
|
-
* sources — consumers fall back to `
|
|
20867
|
-
|
|
20917
|
+
* sources — consumers fall back to `mediaId` (the tight crop). */
|
|
20918
|
+
keyFrameMediaId: number().int().optional(),
|
|
20868
20919
|
/** Populated by B5 (recording playback URL for this event). */
|
|
20869
20920
|
mediaUrl: string().optional(),
|
|
20870
20921
|
/** The parent track's key-event importance [0,1], propagated to every object
|
|
@@ -20914,7 +20965,7 @@ var MediaFileKindEnum = _enum([
|
|
|
20914
20965
|
* hub-main's heap on the way past — for an `<img>` that would have cached it.
|
|
20915
20966
|
*
|
|
20916
20967
|
* `url` points at the `event-media` data plane
|
|
20917
|
-
* (`/addon/<addonId>/event-media/<
|
|
20968
|
+
* (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
|
|
20918
20969
|
* with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
|
|
20919
20970
|
* render a `?variant=thumb`, and streams. The hub gate in front of it requires
|
|
20920
20971
|
* a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
|
|
@@ -20922,10 +20973,13 @@ var MediaFileKindEnum = _enum([
|
|
|
20922
20973
|
* `data-plane-access.ts` for the rule and the one gap it does not close
|
|
20923
20974
|
* (per-device scoping).
|
|
20924
20975
|
*
|
|
20925
|
-
* The URL is built from the row's
|
|
20926
|
-
*
|
|
20976
|
+
* The URL is built from the row's own id, which since D482 says nothing about
|
|
20977
|
+
* the row's owner or kind — and that is the point. The published `kind` is not
|
|
20978
|
+
* the stored one (a track's face/plate crop is stored as `crop` under
|
|
20927
20979
|
* `('face'|'plate', '<prefix>-<trackId>')` and published as
|
|
20928
|
-
* `faceCrop`/`plateCrop
|
|
20980
|
+
* `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
|
|
20981
|
+
* taken from `row.key` verbatim or it 404'd exactly those two rows. An id
|
|
20982
|
+
* cannot be mis-reconstructed, because there is nothing in it to reconstruct.
|
|
20929
20983
|
*
|
|
20930
20984
|
* ## `base64` is TRANSITIONAL and is going away
|
|
20931
20985
|
*
|
|
@@ -20938,7 +20992,19 @@ var MediaFileKindEnum = _enum([
|
|
|
20938
20992
|
* `analytics-query-facade.ts`; nothing else reads it.
|
|
20939
20993
|
*/
|
|
20940
20994
|
var MediaFileSchema = object({
|
|
20941
|
-
|
|
20995
|
+
/**
|
|
20996
|
+
* The media row's OWN id — the rowid SQLite assigned it (D482).
|
|
20997
|
+
*
|
|
20998
|
+
* It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
|
|
20999
|
+
* [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
|
|
21000
|
+
* per-table rowid aliases, so `object:101314` and `motion:101314` are two
|
|
21001
|
+
* different rows that spell the same number, and a track whose
|
|
21002
|
+
* `bestEventId` was an object event was served a motion event's snapshot —
|
|
21003
|
+
* a night-time thumbnail on an afternoon track, with no error anywhere. A
|
|
21004
|
+
* surrogate id cannot name the wrong row's owner, because it names no owner
|
|
21005
|
+
* at all.
|
|
21006
|
+
*/
|
|
21007
|
+
mediaId: number().int(),
|
|
20942
21008
|
kind: MediaFileKindEnum,
|
|
20943
21009
|
sizeBytes: number(),
|
|
20944
21010
|
timestamp: number()
|
|
@@ -21046,7 +21112,7 @@ var RetrainTrackSchema = object({
|
|
|
21046
21112
|
});
|
|
21047
21113
|
/** A frame the picker may offer — an index row, no blob was read to produce it. */
|
|
21048
21114
|
var RetrainFrameCandidateSchema = object({
|
|
21049
|
-
|
|
21115
|
+
mediaId: number().int(),
|
|
21050
21116
|
kind: MediaFileKindEnum,
|
|
21051
21117
|
timestamp: number(),
|
|
21052
21118
|
sizeBytes: number().int(),
|
|
@@ -21060,7 +21126,7 @@ var RetrainFrameSchema = object({
|
|
|
21060
21126
|
deviceId: number(),
|
|
21061
21127
|
trackId: string(),
|
|
21062
21128
|
/** Provenance only. It may already point at nothing — that is expected. */
|
|
21063
|
-
|
|
21129
|
+
sourceMediaId: number().int(),
|
|
21064
21130
|
sourceKind: MediaFileKindEnum,
|
|
21065
21131
|
sizeBytes: number().int(),
|
|
21066
21132
|
width: number().int(),
|
|
@@ -21076,7 +21142,7 @@ var RetrainCopyRefusalSchema = _enum([
|
|
|
21076
21142
|
var RetrainFrameSelectionSchema = object({
|
|
21077
21143
|
copied: array(RetrainFrameSchema).readonly(),
|
|
21078
21144
|
refused: array(object({
|
|
21079
|
-
|
|
21145
|
+
sourceMediaId: number().int(),
|
|
21080
21146
|
reason: RetrainCopyRefusalSchema
|
|
21081
21147
|
})).readonly()
|
|
21082
21148
|
});
|
|
@@ -21084,7 +21150,7 @@ var RetrainFrameListSchema = object({
|
|
|
21084
21150
|
candidates: array(RetrainFrameCandidateSchema).readonly(),
|
|
21085
21151
|
copies: array(RetrainFrameSchema).readonly(),
|
|
21086
21152
|
/** What the page pre-selects — the native key frame when one survives. */
|
|
21087
|
-
|
|
21153
|
+
autoPickMediaId: number().int().optional()
|
|
21088
21154
|
});
|
|
21089
21155
|
/** What the operator asked the assist to look for. */
|
|
21090
21156
|
var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
|
|
@@ -21179,9 +21245,11 @@ var RecentTracksQueryInput = object({
|
|
|
21179
21245
|
});
|
|
21180
21246
|
/**
|
|
21181
21247
|
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
21182
|
-
* `
|
|
21183
|
-
* served by the event-media plane
|
|
21184
|
-
* member visible has been materialised
|
|
21248
|
+
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
21249
|
+
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
21250
|
+
* first frame with a member visible has been materialised (D482 — it was the
|
|
21251
|
+
* row's composite key, which embedded the owner and could name another table's
|
|
21252
|
+
* row once event ids became per-table rowids).
|
|
21185
21253
|
*/
|
|
21186
21254
|
var SummarySchema = object({
|
|
21187
21255
|
id: string(),
|
|
@@ -21190,19 +21258,115 @@ var SummarySchema = object({
|
|
|
21190
21258
|
lastActiveAt: number(),
|
|
21191
21259
|
sealedAt: number().nullable(),
|
|
21192
21260
|
memberCount: number().int().nonnegative(),
|
|
21193
|
-
|
|
21261
|
+
groupShotMediaId: number().int().nullable()
|
|
21194
21262
|
});
|
|
21195
21263
|
var SummariesQueryInput = object({
|
|
21196
21264
|
deviceIds: array(number()).min(1),
|
|
21197
21265
|
since: number().optional(),
|
|
21198
21266
|
until: number().optional(),
|
|
21199
|
-
limit: number().int().min(1).max(200).default(50)
|
|
21267
|
+
limit: number().int().min(1).max(200).default(50),
|
|
21268
|
+
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
21269
|
+
* meaning of "dog" on every summary surface. */
|
|
21270
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
21200
21271
|
});
|
|
21201
|
-
var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
|
|
21202
21272
|
var SummaryDetailSchema = object({
|
|
21203
21273
|
summary: SummarySchema,
|
|
21204
|
-
/**
|
|
21205
|
-
|
|
21274
|
+
/** Members in absorption order, oldest join first. */
|
|
21275
|
+
members: array(object({
|
|
21276
|
+
trackId: string(),
|
|
21277
|
+
/**
|
|
21278
|
+
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
21279
|
+
* and the track no longer exists to fill it.
|
|
21280
|
+
*
|
|
21281
|
+
* The join, not the latest opinion: class voting can re-decide a track's
|
|
21282
|
+
* class afterwards, and a group's composition is the history of who came
|
|
21283
|
+
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
21284
|
+
* dog" — rather than being handed a second, denormalised tally that would
|
|
21285
|
+
* drift from the members it claims to describe.
|
|
21286
|
+
*/
|
|
21287
|
+
className: string().nullable(),
|
|
21288
|
+
/** `primary` is the one member that carries the group's identity. */
|
|
21289
|
+
role: _enum([
|
|
21290
|
+
"primary",
|
|
21291
|
+
"sibling",
|
|
21292
|
+
"child"
|
|
21293
|
+
]).nullable(),
|
|
21294
|
+
joinedAt: number(),
|
|
21295
|
+
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
21296
|
+
* at read time. Absent when nothing resolved, never an empty string. */
|
|
21297
|
+
label: string().optional(),
|
|
21298
|
+
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
21299
|
+
* recognised nobody, and absent for a member whose track has been pruned —
|
|
21300
|
+
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
21301
|
+
subLabel: string().optional()
|
|
21302
|
+
})).readonly()
|
|
21303
|
+
});
|
|
21304
|
+
/**
|
|
21305
|
+
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
21306
|
+
*
|
|
21307
|
+
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
21308
|
+
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
21309
|
+
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
21310
|
+
* are on {@link getSummary}: shipping every member of every group so a client
|
|
21311
|
+
* can count them turns a page of two hundred groups into a thousand records to
|
|
21312
|
+
* draw two hundred badges.
|
|
21313
|
+
*/
|
|
21314
|
+
var SummaryListItemSchema = object({
|
|
21315
|
+
summary: SummarySchema,
|
|
21316
|
+
/** Class counts, most numerous first; `className: null` is a member whose
|
|
21317
|
+
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
21318
|
+
classes: array(object({
|
|
21319
|
+
className: string().nullable(),
|
|
21320
|
+
count: number().int().positive()
|
|
21321
|
+
})).readonly()
|
|
21322
|
+
});
|
|
21323
|
+
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
21324
|
+
/**
|
|
21325
|
+
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
21326
|
+
*
|
|
21327
|
+
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
21328
|
+
* summaries feed that could only answer "the last N for these cameras"
|
|
21329
|
+
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
21330
|
+
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
21331
|
+
* "newest" means, on one screen.
|
|
21332
|
+
*/
|
|
21333
|
+
var RecentSummariesQueryInput = object({
|
|
21334
|
+
/** Devices to merge. An empty array yields an empty page. */
|
|
21335
|
+
deviceIds: array(number()),
|
|
21336
|
+
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
21337
|
+
since: number().optional(),
|
|
21338
|
+
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
21339
|
+
until: number().optional(),
|
|
21340
|
+
limit: number().int().min(1).max(500).default(100),
|
|
21341
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
21342
|
+
cursor: string().optional(),
|
|
21343
|
+
/**
|
|
21344
|
+
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
21345
|
+
* deliberately the same name: the events filter tree emits one list of ticked
|
|
21346
|
+
* taxonomy nodes, and a summaries feed that called it something else would
|
|
21347
|
+
* make the operator's one filter component produce two shapes.
|
|
21348
|
+
*
|
|
21349
|
+
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
21350
|
+
* me the arrivals with a dog" has to return the group of four people who had
|
|
21351
|
+
* one with them; a filter on the group's own fields could only ever answer
|
|
21352
|
+
* about its primary.
|
|
21353
|
+
*
|
|
21354
|
+
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
21355
|
+
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
21356
|
+
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
21357
|
+
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
21358
|
+
* that read only the class would answer "animal" and never "dog".
|
|
21359
|
+
*
|
|
21360
|
+
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
21361
|
+
*/
|
|
21362
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
21363
|
+
});
|
|
21364
|
+
var RecentSummariesPageSchema = object({
|
|
21365
|
+
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
21366
|
+
* {@link listSummaries} — one list shape, so a card renders the same
|
|
21367
|
+
* whichever feed drew it. */
|
|
21368
|
+
summaries: array(SummaryListItemSchema).readonly(),
|
|
21369
|
+
nextCursor: string().nullable()
|
|
21206
21370
|
});
|
|
21207
21371
|
var RecentTracksPageSchema = object({
|
|
21208
21372
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -21616,7 +21780,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21616
21780
|
classes: array(string()).optional(),
|
|
21617
21781
|
/** See {@link ExcludeSourcesDoc}. */
|
|
21618
21782
|
excludeSources: array(TrackSourceSchema).optional()
|
|
21619
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
21783
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
21620
21784
|
kind: "mutation",
|
|
21621
21785
|
auth: "admin"
|
|
21622
21786
|
}), 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({
|
|
@@ -21744,7 +21908,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21744
21908
|
}), method(object({
|
|
21745
21909
|
deviceId: number(),
|
|
21746
21910
|
trackId: string(),
|
|
21747
|
-
|
|
21911
|
+
mediaIds: array(number().int()).min(1)
|
|
21748
21912
|
}), RetrainFrameSelectionSchema, {
|
|
21749
21913
|
kind: "mutation",
|
|
21750
21914
|
auth: "admin"
|
|
@@ -21812,7 +21976,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21812
21976
|
kind: "query",
|
|
21813
21977
|
auth: "admin"
|
|
21814
21978
|
}), method(object({
|
|
21815
|
-
|
|
21979
|
+
/** Which of the three event tables owns the row. */
|
|
21980
|
+
ownerType: EventOwnerTypeSchema,
|
|
21981
|
+
/** The event's rowid in that table (D474: an event id is a number). */
|
|
21982
|
+
eventId: number().int(),
|
|
21816
21983
|
kind: MediaFileKindEnum.optional(),
|
|
21817
21984
|
deviceId: number()
|
|
21818
21985
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
@@ -21823,7 +21990,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21823
21990
|
trackId: string(),
|
|
21824
21991
|
deviceId: number()
|
|
21825
21992
|
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
21826
|
-
|
|
21993
|
+
ownerType: EventOwnerTypeSchema,
|
|
21994
|
+
eventId: number().int(),
|
|
21827
21995
|
deviceId: number()
|
|
21828
21996
|
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
21829
21997
|
kind: "mutation",
|
|
@@ -27024,8 +27192,8 @@ var IdentitySchema = object({
|
|
|
27024
27192
|
id: string(),
|
|
27025
27193
|
name: string(),
|
|
27026
27194
|
sampleCount: number().int().nonnegative(),
|
|
27027
|
-
|
|
27028
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
27195
|
+
coverMediaId: number().int().optional(),
|
|
27196
|
+
/** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
|
|
27029
27197
|
* Lets the UI render the person's face avatar instead of a placeholder icon. */
|
|
27030
27198
|
coverBase64: string().optional()
|
|
27031
27199
|
});
|
|
@@ -27051,8 +27219,8 @@ var IdentitySampleAuditRowSchema = object({
|
|
|
27051
27219
|
enrolledAt: number().int(),
|
|
27052
27220
|
deviceId: number().int().optional(),
|
|
27053
27221
|
source: _enum(["detected", "photo"]),
|
|
27054
|
-
/** The enrolled crop's media
|
|
27055
|
-
|
|
27222
|
+
/** The enrolled crop's media row id, so the panel can show the evidence. */
|
|
27223
|
+
mediaId: number().int().optional(),
|
|
27056
27224
|
/**
|
|
27057
27225
|
* False = the sample is stamped with a DIFFERENT face model, and a cosine
|
|
27058
27226
|
* across feature spaces is a well-formed float with no meaning. Every number
|
|
@@ -27121,15 +27289,15 @@ var FaceInfoSchema = object({
|
|
|
27121
27289
|
*/
|
|
27122
27290
|
cropUrl: string().optional(),
|
|
27123
27291
|
/** Design B: the face bbox (pixel space) on the key frame — lets a detail
|
|
27124
|
-
* view draw the box over the native `
|
|
27292
|
+
* view draw the box over the native `keyFrameMediaId` frame. Absent on
|
|
27125
27293
|
* legacy rows written before design B. */
|
|
27126
27294
|
faceBbox: BoundingBoxSchema.optional(),
|
|
27127
27295
|
/** Design B: MediaStore key of the track's native-resolution key frame.
|
|
27128
27296
|
* Fetch the native JPEG via the event-media data-plane
|
|
27129
|
-
* (`/addon/<addonId>/event-media/<
|
|
27297
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
|
|
27130
27298
|
* track produced no key frame (e.g. native/onboard source) — the UI falls
|
|
27131
27299
|
* back to the inline `base64` face crop. */
|
|
27132
|
-
|
|
27300
|
+
keyFrameMediaId: number().int().optional(),
|
|
27133
27301
|
/** Winning identity-match cosine (0..1) for this face's track, when an
|
|
27134
27302
|
* identity was auto-confirmed. Lets the UI surface WHY a face was assigned
|
|
27135
27303
|
* (confidence badge / low-confidence audit). Absent on legacy rows and on
|
|
@@ -27198,11 +27366,14 @@ var FaceClusterSchema = object({
|
|
|
27198
27366
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
27199
27367
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
27200
27368
|
*
|
|
27201
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
27202
|
-
* media
|
|
27369
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
27370
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
27371
|
+
* access decision.
|
|
27203
27372
|
*/
|
|
27204
27373
|
var MediaFileLiteSchema$1 = object({
|
|
27205
|
-
|
|
27374
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
27375
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
27376
|
+
mediaId: number().int(),
|
|
27206
27377
|
kind: string(),
|
|
27207
27378
|
url: string(),
|
|
27208
27379
|
sizeBytes: number(),
|
|
@@ -27219,7 +27390,7 @@ method(object({
|
|
|
27219
27390
|
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
27220
27391
|
* four times and the viewer holds at `staleTime: 30_000`.
|
|
27221
27392
|
*
|
|
27222
|
-
* Nothing loses its avatar: `
|
|
27393
|
+
* Nothing loses its avatar: `coverMediaId` is already on every row and
|
|
27223
27394
|
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
27224
27395
|
*
|
|
27225
27396
|
* **This is an INPUT field, so it does not reach the addon until the
|
|
@@ -30582,8 +30753,8 @@ var VehicleSchema = object({
|
|
|
30582
30753
|
id: string(),
|
|
30583
30754
|
name: string(),
|
|
30584
30755
|
sampleCount: number().int().nonnegative(),
|
|
30585
|
-
|
|
30586
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
30756
|
+
coverMediaId: number().int().optional(),
|
|
30757
|
+
/** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
|
|
30587
30758
|
coverBase64: string().optional()
|
|
30588
30759
|
});
|
|
30589
30760
|
var VehicleSampleInfoSchema = object({
|
|
@@ -30616,7 +30787,7 @@ var PlateInfoSchema = object({
|
|
|
30616
30787
|
/** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
|
|
30617
30788
|
plateBbox: BoundingBoxSchema.optional(),
|
|
30618
30789
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
30619
|
-
|
|
30790
|
+
keyFrameMediaId: number().int().optional(),
|
|
30620
30791
|
base64: string().optional(),
|
|
30621
30792
|
/**
|
|
30622
30793
|
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
@@ -30637,11 +30808,14 @@ var PlateInfoSchema = object({
|
|
|
30637
30808
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
30638
30809
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
30639
30810
|
*
|
|
30640
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
30641
|
-
* media
|
|
30811
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
30812
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
30813
|
+
* access decision.
|
|
30642
30814
|
*/
|
|
30643
30815
|
var MediaFileLiteSchema = object({
|
|
30644
|
-
|
|
30816
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
30817
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
30818
|
+
mediaId: number().int(),
|
|
30645
30819
|
kind: string(),
|
|
30646
30820
|
url: string(),
|
|
30647
30821
|
sizeBytes: number(),
|
|
@@ -30700,7 +30874,7 @@ method(object({
|
|
|
30700
30874
|
}), method(object({
|
|
30701
30875
|
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
30702
30876
|
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
30703
|
-
* option; `
|
|
30877
|
+
* option; `coverMediaId` + the `event-media` plane carry the picture.
|
|
30704
30878
|
* INPUT field: stripped by the hub router until the train ships, which
|
|
30705
30879
|
* resolves to `false` and is exactly the intended default. */
|
|
30706
30880
|
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
@@ -32269,7 +32443,14 @@ var SceneReferenceSchema = object({
|
|
|
32269
32443
|
modelId: string(),
|
|
32270
32444
|
condition: SceneConditionSchema,
|
|
32271
32445
|
capturedAt: number(),
|
|
32272
|
-
|
|
32446
|
+
/**
|
|
32447
|
+
* The reference thumbnail's media ROW id (D482).
|
|
32448
|
+
*
|
|
32449
|
+
* The name already said `mediaId` while the value was the row's composite
|
|
32450
|
+
* key — a leftover that read as done and was not. It is the row's own id
|
|
32451
|
+
* now, addressed at `/addon/<addonId>/event-media/m/<id>`.
|
|
32452
|
+
*/
|
|
32453
|
+
thumbnailMediaId: number().int().optional(),
|
|
32273
32454
|
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
32274
32455
|
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
32275
32456
|
* normalized rect frame a different piece of world, and the scene would
|
|
@@ -33360,7 +33541,29 @@ var LoggingSettingsPatchSchema = object({
|
|
|
33360
33541
|
* disarmed the channels it did not mention would make the Levels page and
|
|
33361
33542
|
* the Diagnostics page fight over the same value.
|
|
33362
33543
|
*/
|
|
33363
|
-
channels: array(LogChannelWindowPatchSchema).readonly().optional()
|
|
33544
|
+
channels: array(LogChannelWindowPatchSchema).readonly().optional(),
|
|
33545
|
+
/**
|
|
33546
|
+
* How many days the analytics OPS LOG is kept — the audit trail of what
|
|
33547
|
+
* retention actually deleted.
|
|
33548
|
+
*
|
|
33549
|
+
* It lives HERE, on the logging document, and not on the analytics addon's
|
|
33550
|
+
* settings form, on the operator's instruction: every other log-ish window in
|
|
33551
|
+
* this system is configured through this one document, and a retention audit
|
|
33552
|
+
* configured somewhere else is a second place to look when the question is
|
|
33553
|
+
* "what happened to my data".
|
|
33554
|
+
*
|
|
33555
|
+
* That placement has a cost worth stating: this document ships in the
|
|
33556
|
+
* framework closure, so this knob needs a published `@camstack/server` while
|
|
33557
|
+
* the four windows beside it (D485) reach a node on `camstack deploy`.
|
|
33558
|
+
*
|
|
33559
|
+
* `retention-model.ts` argued this one must NOT follow a device window,
|
|
33560
|
+
* because the audit trail is the history of the SWEEP and not of the camera.
|
|
33561
|
+
* That argument stands and is untouched — what changes is that 30 days stops
|
|
33562
|
+
* being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
|
|
33563
|
+
* rather than 0-as-delete: an audit log truncated to nothing is precisely the
|
|
33564
|
+
* state in which the next 9.5 GiB leak cannot be explained.
|
|
33565
|
+
*/
|
|
33566
|
+
opsLogRetentionDays: number().int().min(0).max(3650).optional()
|
|
33364
33567
|
});
|
|
33365
33568
|
/**
|
|
33366
33569
|
* Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
|
|
@@ -33433,6 +33636,14 @@ var LoggingSettingsStateSchema = object({
|
|
|
33433
33636
|
channels: array(LogChannelDescriptorSchema).readonly(),
|
|
33434
33637
|
/** The channels ARMED right now, each with its deadline. */
|
|
33435
33638
|
activeChannels: array(LogChannelWindowStateSchema).readonly(),
|
|
33639
|
+
/**
|
|
33640
|
+
* The ops-log window in days, as it is in force. `0` = kept forever.
|
|
33641
|
+
*
|
|
33642
|
+
* Reported rather than left to the caller's memory of what it wrote: this is
|
|
33643
|
+
* the value the analytics sweep will actually use, and an operator asking how
|
|
33644
|
+
* long their audit trail lives should not have to infer it from a default.
|
|
33645
|
+
*/
|
|
33646
|
+
opsLogRetentionDays: number().int().min(0),
|
|
33436
33647
|
persisted: boolean()
|
|
33437
33648
|
});
|
|
33438
33649
|
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(), {
|
|
@@ -34253,7 +34464,7 @@ var StationaryObjectSchema = object({
|
|
|
34253
34464
|
/** Enrichment label carried from the source track (identity / plate). */
|
|
34254
34465
|
label: string().optional(),
|
|
34255
34466
|
/** Native-resolution key-frame media key for the parked object's best image. */
|
|
34256
|
-
|
|
34467
|
+
keyFrameMediaId: number().int().optional()
|
|
34257
34468
|
});
|
|
34258
34469
|
var CameraOccupancySnapshotSchema = object({
|
|
34259
34470
|
/** Frame timestamp of the inference result that produced this snapshot. */
|
|
@@ -36991,6 +37202,12 @@ Object.freeze({
|
|
|
36991
37202
|
addonId: null,
|
|
36992
37203
|
access: "create"
|
|
36993
37204
|
},
|
|
37205
|
+
"dataStoreProvider.upsert": {
|
|
37206
|
+
capName: "data-store-provider",
|
|
37207
|
+
capScope: "system",
|
|
37208
|
+
addonId: null,
|
|
37209
|
+
access: "create"
|
|
37210
|
+
},
|
|
36994
37211
|
"dayNight.getOptions": {
|
|
36995
37212
|
capName: "day-night",
|
|
36996
37213
|
capScope: "device",
|
|
@@ -39427,6 +39644,12 @@ Object.freeze({
|
|
|
39427
39644
|
addonId: null,
|
|
39428
39645
|
access: "view"
|
|
39429
39646
|
},
|
|
39647
|
+
"pipelineAnalytics.listRecentSummaries": {
|
|
39648
|
+
capName: "pipeline-analytics",
|
|
39649
|
+
capScope: "device",
|
|
39650
|
+
addonId: null,
|
|
39651
|
+
access: "view"
|
|
39652
|
+
},
|
|
39430
39653
|
"pipelineAnalytics.listRecentTracks": {
|
|
39431
39654
|
capName: "pipeline-analytics",
|
|
39432
39655
|
capScope: "device",
|
|
@@ -40855,6 +41078,12 @@ Object.freeze({
|
|
|
40855
41078
|
addonId: null,
|
|
40856
41079
|
access: "create"
|
|
40857
41080
|
},
|
|
41081
|
+
"settingsStore.upsert": {
|
|
41082
|
+
capName: "settings-store",
|
|
41083
|
+
capScope: "system",
|
|
41084
|
+
addonId: null,
|
|
41085
|
+
access: "create"
|
|
41086
|
+
},
|
|
40858
41087
|
"smtpProvider.getStatus": {
|
|
40859
41088
|
capName: "smtp-provider",
|
|
40860
41089
|
capScope: "system",
|
|
@@ -43248,6 +43477,11 @@ Object.freeze({
|
|
|
43248
43477
|
form: "single",
|
|
43249
43478
|
optional: true
|
|
43250
43479
|
}],
|
|
43480
|
+
"pipelineAnalytics.listRecentSummaries": [{
|
|
43481
|
+
name: "deviceIds",
|
|
43482
|
+
form: "array",
|
|
43483
|
+
optional: false
|
|
43484
|
+
}],
|
|
43251
43485
|
"pipelineAnalytics.listRecentTracks": [{
|
|
43252
43486
|
name: "deviceIds",
|
|
43253
43487
|
form: "array",
|
package/package.json
CHANGED