@camstack/addon-provider-tuya 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
|
@@ -819,7 +819,7 @@ async function discoverDevices(options = {}, binder = createDgramBinder()) {
|
|
|
819
819
|
return [...byId.values()];
|
|
820
820
|
}
|
|
821
821
|
//#endregion
|
|
822
|
-
//#region ../types/dist/event-category-
|
|
822
|
+
//#region ../types/dist/event-category-ZyX6jcse.mjs
|
|
823
823
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
824
824
|
EventCategory["SystemBoot"] = "system.boot";
|
|
825
825
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -1380,7 +1380,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
1380
1380
|
* a package zone — a newly-appeared stationary object of a package class
|
|
1381
1381
|
* that cleared the class / zone / dwell / size gates. Payload:
|
|
1382
1382
|
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
1383
|
-
* entryId, className, zoneIds,
|
|
1383
|
+
* entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
|
|
1384
1384
|
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
1385
1385
|
* this bus topic drives notifier rules + live UI. See
|
|
1386
1386
|
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
@@ -6166,7 +6166,7 @@ var ZodIssueCode = {
|
|
|
6166
6166
|
var ZodFirstPartyTypeKind;
|
|
6167
6167
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6168
6168
|
//#endregion
|
|
6169
|
-
//#region ../types/dist/sleep-
|
|
6169
|
+
//#region ../types/dist/sleep-DBKu2-U5.mjs
|
|
6170
6170
|
/**
|
|
6171
6171
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6172
6172
|
* window to float samples (D455).
|
|
@@ -8133,13 +8133,30 @@ new Set([
|
|
|
8133
8133
|
"scene",
|
|
8134
8134
|
"motion",
|
|
8135
8135
|
"object",
|
|
8136
|
-
"audio"
|
|
8136
|
+
"audio",
|
|
8137
|
+
"mosaic"
|
|
8137
8138
|
]);
|
|
8138
|
-
|
|
8139
|
+
/**
|
|
8140
|
+
* The owner types that are event tables, in the order the event-media resolver
|
|
8141
|
+
* should consider them. Exported so a consumer asking "is this key an event?"
|
|
8142
|
+
* does not re-spell the list and drift from it.
|
|
8143
|
+
*/
|
|
8144
|
+
var EVENT_OWNER_TYPES = [
|
|
8139
8145
|
"motion",
|
|
8140
8146
|
"object",
|
|
8141
8147
|
"audio"
|
|
8142
|
-
]
|
|
8148
|
+
];
|
|
8149
|
+
/**
|
|
8150
|
+
* The same list as a Zod enum, for the cap inputs that must NAME the table
|
|
8151
|
+
* (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
|
|
8152
|
+
* `(table, id)`).
|
|
8153
|
+
*
|
|
8154
|
+
* Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
|
|
8155
|
+
* table would otherwise be accepted by the codec and refused at the door, with
|
|
8156
|
+
* nothing failing until a caller asked.
|
|
8157
|
+
*/
|
|
8158
|
+
var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
|
|
8159
|
+
new Set(EVENT_OWNER_TYPES);
|
|
8143
8160
|
var EncodeProfileSchema = object({
|
|
8144
8161
|
video: object({
|
|
8145
8162
|
codec: _enum([
|
|
@@ -8178,7 +8195,23 @@ var EncodeProfileSchema = object({
|
|
|
8178
8195
|
"zerolatency",
|
|
8179
8196
|
"film",
|
|
8180
8197
|
"animation"
|
|
8181
|
-
]).optional()
|
|
8198
|
+
]).optional(),
|
|
8199
|
+
/**
|
|
8200
|
+
* ONE slice per access unit.
|
|
8201
|
+
*
|
|
8202
|
+
* `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
|
|
8203
|
+
* the encoder as five NAL slices that share one RTP timestamp and carry one
|
|
8204
|
+
* marker bit. A libwebrtc depacketiser sees five frame-starts and one
|
|
8205
|
+
* frame-end per frame: the first pictures render and the video then freezes
|
|
8206
|
+
* for good while the audio, on its own plane, plays on. Measured on this hub
|
|
8207
|
+
* 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
|
|
8208
|
+
*
|
|
8209
|
+
* A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
|
|
8210
|
+
* `outputArgs` on purpose: an opaque array is part of the sharing key, so two
|
|
8211
|
+
* consumers meaning the same thing spelled differently would stop sharing one
|
|
8212
|
+
* child. Absent means "whatever the encoder does" — today's behaviour.
|
|
8213
|
+
*/
|
|
8214
|
+
singleSlicePerFrame: boolean().optional()
|
|
8182
8215
|
}),
|
|
8183
8216
|
audio: union([literal("passthrough"), object({
|
|
8184
8217
|
codec: _enum([
|
|
@@ -8228,7 +8261,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
|
|
|
8228
8261
|
audio: "passthrough"
|
|
8229
8262
|
};
|
|
8230
8263
|
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
8231
|
-
({ ...BASE_LIVE_EGRESS_PROFILE });
|
|
8264
|
+
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
8232
8265
|
/**
|
|
8233
8266
|
* Deep wiring healthcheck — snapshot of active reachability probes across
|
|
8234
8267
|
* every declared capability + widget of every installed plugin, on every
|
|
@@ -13338,6 +13371,16 @@ method(object({
|
|
|
13338
13371
|
filter: QueryFilterSchema.optional(),
|
|
13339
13372
|
columns: array(string()).readonly().optional()
|
|
13340
13373
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
13374
|
+
namespace: string().optional(),
|
|
13375
|
+
collection: string(),
|
|
13376
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
13377
|
+
* index on the collection. Never empty. */
|
|
13378
|
+
conflict: array(string()).readonly(),
|
|
13379
|
+
record: BulkRecordSchema
|
|
13380
|
+
}), object({
|
|
13381
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
13382
|
+
* row's own id on an update. */
|
|
13383
|
+
id: union([string(), number()]) }), { kind: "mutation" }), method(object({
|
|
13341
13384
|
namespace: string().optional(),
|
|
13342
13385
|
collection: string(),
|
|
13343
13386
|
record: object({
|
|
@@ -13472,6 +13515,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
13472
13515
|
id: union([string(), number()]) }), {
|
|
13473
13516
|
kind: "mutation",
|
|
13474
13517
|
auth: "admin"
|
|
13518
|
+
}), method(object({
|
|
13519
|
+
namespace: string().optional(),
|
|
13520
|
+
collection: string(),
|
|
13521
|
+
conflict: array(string()).readonly(),
|
|
13522
|
+
record: BulkRecordSchema
|
|
13523
|
+
}), object({ id: union([string(), number()]) }), {
|
|
13524
|
+
kind: "mutation",
|
|
13525
|
+
auth: "admin"
|
|
13475
13526
|
}), method(object({
|
|
13476
13527
|
namespace: string().optional(),
|
|
13477
13528
|
collection: string(),
|
|
@@ -19971,8 +20022,8 @@ var TrackPositionSchema = object({
|
|
|
19971
20022
|
var TrackSnapshotSchema = object({
|
|
19972
20023
|
timestamp: number(),
|
|
19973
20024
|
position: TrackPositionSchema,
|
|
19974
|
-
/**
|
|
19975
|
-
|
|
20025
|
+
/** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
|
|
20026
|
+
mediaId: number().int()
|
|
19976
20027
|
});
|
|
19977
20028
|
/**
|
|
19978
20029
|
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
@@ -20576,14 +20627,14 @@ var ObjectEventSchema = object({
|
|
|
20576
20627
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
20577
20628
|
frameWidth: number().optional(),
|
|
20578
20629
|
frameHeight: number().optional(),
|
|
20579
|
-
/**
|
|
20580
|
-
|
|
20581
|
-
/** Design B:
|
|
20630
|
+
/** Media row id of the crop attached to this event (if any) — D482. */
|
|
20631
|
+
mediaId: number().int().optional(),
|
|
20632
|
+
/** Design B: media row id of the track's native-resolution key frame (the
|
|
20582
20633
|
* best-detection full frame). Resolve via the event-media data-plane
|
|
20583
|
-
* (`/addon/<addonId>/event-media/<
|
|
20634
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
|
|
20584
20635
|
* draws `bbox` over the native frame. Absent on legacy rows / non-decoded
|
|
20585
|
-
* sources — consumers fall back to `
|
|
20586
|
-
|
|
20636
|
+
* sources — consumers fall back to `mediaId` (the tight crop). */
|
|
20637
|
+
keyFrameMediaId: number().int().optional(),
|
|
20587
20638
|
/** Populated by B5 (recording playback URL for this event). */
|
|
20588
20639
|
mediaUrl: string().optional(),
|
|
20589
20640
|
/** The parent track's key-event importance [0,1], propagated to every object
|
|
@@ -20633,7 +20684,7 @@ var MediaFileKindEnum = _enum([
|
|
|
20633
20684
|
* hub-main's heap on the way past — for an `<img>` that would have cached it.
|
|
20634
20685
|
*
|
|
20635
20686
|
* `url` points at the `event-media` data plane
|
|
20636
|
-
* (`/addon/<addonId>/event-media/<
|
|
20687
|
+
* (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
|
|
20637
20688
|
* with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
|
|
20638
20689
|
* render a `?variant=thumb`, and streams. The hub gate in front of it requires
|
|
20639
20690
|
* a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
|
|
@@ -20641,10 +20692,13 @@ var MediaFileKindEnum = _enum([
|
|
|
20641
20692
|
* `data-plane-access.ts` for the rule and the one gap it does not close
|
|
20642
20693
|
* (per-device scoping).
|
|
20643
20694
|
*
|
|
20644
|
-
* The URL is built from the row's
|
|
20645
|
-
*
|
|
20695
|
+
* The URL is built from the row's own id, which since D482 says nothing about
|
|
20696
|
+
* the row's owner or kind — and that is the point. The published `kind` is not
|
|
20697
|
+
* the stored one (a track's face/plate crop is stored as `crop` under
|
|
20646
20698
|
* `('face'|'plate', '<prefix>-<trackId>')` and published as
|
|
20647
|
-
* `faceCrop`/`plateCrop
|
|
20699
|
+
* `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
|
|
20700
|
+
* taken from `row.key` verbatim or it 404'd exactly those two rows. An id
|
|
20701
|
+
* cannot be mis-reconstructed, because there is nothing in it to reconstruct.
|
|
20648
20702
|
*
|
|
20649
20703
|
* ## `base64` is TRANSITIONAL and is going away
|
|
20650
20704
|
*
|
|
@@ -20657,7 +20711,19 @@ var MediaFileKindEnum = _enum([
|
|
|
20657
20711
|
* `analytics-query-facade.ts`; nothing else reads it.
|
|
20658
20712
|
*/
|
|
20659
20713
|
var MediaFileSchema = object({
|
|
20660
|
-
|
|
20714
|
+
/**
|
|
20715
|
+
* The media row's OWN id — the rowid SQLite assigned it (D482).
|
|
20716
|
+
*
|
|
20717
|
+
* It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
|
|
20718
|
+
* [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
|
|
20719
|
+
* per-table rowid aliases, so `object:101314` and `motion:101314` are two
|
|
20720
|
+
* different rows that spell the same number, and a track whose
|
|
20721
|
+
* `bestEventId` was an object event was served a motion event's snapshot —
|
|
20722
|
+
* a night-time thumbnail on an afternoon track, with no error anywhere. A
|
|
20723
|
+
* surrogate id cannot name the wrong row's owner, because it names no owner
|
|
20724
|
+
* at all.
|
|
20725
|
+
*/
|
|
20726
|
+
mediaId: number().int(),
|
|
20661
20727
|
kind: MediaFileKindEnum,
|
|
20662
20728
|
sizeBytes: number(),
|
|
20663
20729
|
timestamp: number()
|
|
@@ -20765,7 +20831,7 @@ var RetrainTrackSchema = object({
|
|
|
20765
20831
|
});
|
|
20766
20832
|
/** A frame the picker may offer — an index row, no blob was read to produce it. */
|
|
20767
20833
|
var RetrainFrameCandidateSchema = object({
|
|
20768
|
-
|
|
20834
|
+
mediaId: number().int(),
|
|
20769
20835
|
kind: MediaFileKindEnum,
|
|
20770
20836
|
timestamp: number(),
|
|
20771
20837
|
sizeBytes: number().int(),
|
|
@@ -20779,7 +20845,7 @@ var RetrainFrameSchema = object({
|
|
|
20779
20845
|
deviceId: number(),
|
|
20780
20846
|
trackId: string(),
|
|
20781
20847
|
/** Provenance only. It may already point at nothing — that is expected. */
|
|
20782
|
-
|
|
20848
|
+
sourceMediaId: number().int(),
|
|
20783
20849
|
sourceKind: MediaFileKindEnum,
|
|
20784
20850
|
sizeBytes: number().int(),
|
|
20785
20851
|
width: number().int(),
|
|
@@ -20795,7 +20861,7 @@ var RetrainCopyRefusalSchema = _enum([
|
|
|
20795
20861
|
var RetrainFrameSelectionSchema = object({
|
|
20796
20862
|
copied: array(RetrainFrameSchema).readonly(),
|
|
20797
20863
|
refused: array(object({
|
|
20798
|
-
|
|
20864
|
+
sourceMediaId: number().int(),
|
|
20799
20865
|
reason: RetrainCopyRefusalSchema
|
|
20800
20866
|
})).readonly()
|
|
20801
20867
|
});
|
|
@@ -20803,7 +20869,7 @@ var RetrainFrameListSchema = object({
|
|
|
20803
20869
|
candidates: array(RetrainFrameCandidateSchema).readonly(),
|
|
20804
20870
|
copies: array(RetrainFrameSchema).readonly(),
|
|
20805
20871
|
/** What the page pre-selects — the native key frame when one survives. */
|
|
20806
|
-
|
|
20872
|
+
autoPickMediaId: number().int().optional()
|
|
20807
20873
|
});
|
|
20808
20874
|
/** What the operator asked the assist to look for. */
|
|
20809
20875
|
var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
|
|
@@ -20898,9 +20964,11 @@ var RecentTracksQueryInput = object({
|
|
|
20898
20964
|
});
|
|
20899
20965
|
/**
|
|
20900
20966
|
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
20901
|
-
* `
|
|
20902
|
-
* served by the event-media plane
|
|
20903
|
-
* member visible has been materialised
|
|
20967
|
+
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
20968
|
+
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
20969
|
+
* first frame with a member visible has been materialised (D482 — it was the
|
|
20970
|
+
* row's composite key, which embedded the owner and could name another table's
|
|
20971
|
+
* row once event ids became per-table rowids).
|
|
20904
20972
|
*/
|
|
20905
20973
|
var SummarySchema = object({
|
|
20906
20974
|
id: string(),
|
|
@@ -20909,19 +20977,115 @@ var SummarySchema = object({
|
|
|
20909
20977
|
lastActiveAt: number(),
|
|
20910
20978
|
sealedAt: number().nullable(),
|
|
20911
20979
|
memberCount: number().int().nonnegative(),
|
|
20912
|
-
|
|
20980
|
+
groupShotMediaId: number().int().nullable()
|
|
20913
20981
|
});
|
|
20914
20982
|
var SummariesQueryInput = object({
|
|
20915
20983
|
deviceIds: array(number()).min(1),
|
|
20916
20984
|
since: number().optional(),
|
|
20917
20985
|
until: number().optional(),
|
|
20918
|
-
limit: number().int().min(1).max(200).default(50)
|
|
20986
|
+
limit: number().int().min(1).max(200).default(50),
|
|
20987
|
+
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
20988
|
+
* meaning of "dog" on every summary surface. */
|
|
20989
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
20919
20990
|
});
|
|
20920
|
-
var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
|
|
20921
20991
|
var SummaryDetailSchema = object({
|
|
20922
20992
|
summary: SummarySchema,
|
|
20923
|
-
/**
|
|
20924
|
-
|
|
20993
|
+
/** Members in absorption order, oldest join first. */
|
|
20994
|
+
members: array(object({
|
|
20995
|
+
trackId: string(),
|
|
20996
|
+
/**
|
|
20997
|
+
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
20998
|
+
* and the track no longer exists to fill it.
|
|
20999
|
+
*
|
|
21000
|
+
* The join, not the latest opinion: class voting can re-decide a track's
|
|
21001
|
+
* class afterwards, and a group's composition is the history of who came
|
|
21002
|
+
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
21003
|
+
* dog" — rather than being handed a second, denormalised tally that would
|
|
21004
|
+
* drift from the members it claims to describe.
|
|
21005
|
+
*/
|
|
21006
|
+
className: string().nullable(),
|
|
21007
|
+
/** `primary` is the one member that carries the group's identity. */
|
|
21008
|
+
role: _enum([
|
|
21009
|
+
"primary",
|
|
21010
|
+
"sibling",
|
|
21011
|
+
"child"
|
|
21012
|
+
]).nullable(),
|
|
21013
|
+
joinedAt: number(),
|
|
21014
|
+
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
21015
|
+
* at read time. Absent when nothing resolved, never an empty string. */
|
|
21016
|
+
label: string().optional(),
|
|
21017
|
+
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
21018
|
+
* recognised nobody, and absent for a member whose track has been pruned —
|
|
21019
|
+
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
21020
|
+
subLabel: string().optional()
|
|
21021
|
+
})).readonly()
|
|
21022
|
+
});
|
|
21023
|
+
/**
|
|
21024
|
+
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
21025
|
+
*
|
|
21026
|
+
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
21027
|
+
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
21028
|
+
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
21029
|
+
* are on {@link getSummary}: shipping every member of every group so a client
|
|
21030
|
+
* can count them turns a page of two hundred groups into a thousand records to
|
|
21031
|
+
* draw two hundred badges.
|
|
21032
|
+
*/
|
|
21033
|
+
var SummaryListItemSchema = object({
|
|
21034
|
+
summary: SummarySchema,
|
|
21035
|
+
/** Class counts, most numerous first; `className: null` is a member whose
|
|
21036
|
+
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
21037
|
+
classes: array(object({
|
|
21038
|
+
className: string().nullable(),
|
|
21039
|
+
count: number().int().positive()
|
|
21040
|
+
})).readonly()
|
|
21041
|
+
});
|
|
21042
|
+
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
21043
|
+
/**
|
|
21044
|
+
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
21045
|
+
*
|
|
21046
|
+
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
21047
|
+
* summaries feed that could only answer "the last N for these cameras"
|
|
21048
|
+
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
21049
|
+
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
21050
|
+
* "newest" means, on one screen.
|
|
21051
|
+
*/
|
|
21052
|
+
var RecentSummariesQueryInput = object({
|
|
21053
|
+
/** Devices to merge. An empty array yields an empty page. */
|
|
21054
|
+
deviceIds: array(number()),
|
|
21055
|
+
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
21056
|
+
since: number().optional(),
|
|
21057
|
+
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
21058
|
+
until: number().optional(),
|
|
21059
|
+
limit: number().int().min(1).max(500).default(100),
|
|
21060
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
21061
|
+
cursor: string().optional(),
|
|
21062
|
+
/**
|
|
21063
|
+
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
21064
|
+
* deliberately the same name: the events filter tree emits one list of ticked
|
|
21065
|
+
* taxonomy nodes, and a summaries feed that called it something else would
|
|
21066
|
+
* make the operator's one filter component produce two shapes.
|
|
21067
|
+
*
|
|
21068
|
+
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
21069
|
+
* me the arrivals with a dog" has to return the group of four people who had
|
|
21070
|
+
* one with them; a filter on the group's own fields could only ever answer
|
|
21071
|
+
* about its primary.
|
|
21072
|
+
*
|
|
21073
|
+
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
21074
|
+
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
21075
|
+
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
21076
|
+
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
21077
|
+
* that read only the class would answer "animal" and never "dog".
|
|
21078
|
+
*
|
|
21079
|
+
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
21080
|
+
*/
|
|
21081
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
21082
|
+
});
|
|
21083
|
+
var RecentSummariesPageSchema = object({
|
|
21084
|
+
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
21085
|
+
* {@link listSummaries} — one list shape, so a card renders the same
|
|
21086
|
+
* whichever feed drew it. */
|
|
21087
|
+
summaries: array(SummaryListItemSchema).readonly(),
|
|
21088
|
+
nextCursor: string().nullable()
|
|
20925
21089
|
});
|
|
20926
21090
|
var RecentTracksPageSchema = object({
|
|
20927
21091
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -21335,7 +21499,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21335
21499
|
classes: array(string()).optional(),
|
|
21336
21500
|
/** See {@link ExcludeSourcesDoc}. */
|
|
21337
21501
|
excludeSources: array(TrackSourceSchema).optional()
|
|
21338
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
21502
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
21339
21503
|
kind: "mutation",
|
|
21340
21504
|
auth: "admin"
|
|
21341
21505
|
}), 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({
|
|
@@ -21463,7 +21627,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21463
21627
|
}), method(object({
|
|
21464
21628
|
deviceId: number(),
|
|
21465
21629
|
trackId: string(),
|
|
21466
|
-
|
|
21630
|
+
mediaIds: array(number().int()).min(1)
|
|
21467
21631
|
}), RetrainFrameSelectionSchema, {
|
|
21468
21632
|
kind: "mutation",
|
|
21469
21633
|
auth: "admin"
|
|
@@ -21531,7 +21695,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21531
21695
|
kind: "query",
|
|
21532
21696
|
auth: "admin"
|
|
21533
21697
|
}), method(object({
|
|
21534
|
-
|
|
21698
|
+
/** Which of the three event tables owns the row. */
|
|
21699
|
+
ownerType: EventOwnerTypeSchema,
|
|
21700
|
+
/** The event's rowid in that table (D474: an event id is a number). */
|
|
21701
|
+
eventId: number().int(),
|
|
21535
21702
|
kind: MediaFileKindEnum.optional(),
|
|
21536
21703
|
deviceId: number()
|
|
21537
21704
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
@@ -21542,7 +21709,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21542
21709
|
trackId: string(),
|
|
21543
21710
|
deviceId: number()
|
|
21544
21711
|
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
21545
|
-
|
|
21712
|
+
ownerType: EventOwnerTypeSchema,
|
|
21713
|
+
eventId: number().int(),
|
|
21546
21714
|
deviceId: number()
|
|
21547
21715
|
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
21548
21716
|
kind: "mutation",
|
|
@@ -26743,8 +26911,8 @@ var IdentitySchema = object({
|
|
|
26743
26911
|
id: string(),
|
|
26744
26912
|
name: string(),
|
|
26745
26913
|
sampleCount: number().int().nonnegative(),
|
|
26746
|
-
|
|
26747
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
26914
|
+
coverMediaId: number().int().optional(),
|
|
26915
|
+
/** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
|
|
26748
26916
|
* Lets the UI render the person's face avatar instead of a placeholder icon. */
|
|
26749
26917
|
coverBase64: string().optional()
|
|
26750
26918
|
});
|
|
@@ -26770,8 +26938,8 @@ var IdentitySampleAuditRowSchema = object({
|
|
|
26770
26938
|
enrolledAt: number().int(),
|
|
26771
26939
|
deviceId: number().int().optional(),
|
|
26772
26940
|
source: _enum(["detected", "photo"]),
|
|
26773
|
-
/** The enrolled crop's media
|
|
26774
|
-
|
|
26941
|
+
/** The enrolled crop's media row id, so the panel can show the evidence. */
|
|
26942
|
+
mediaId: number().int().optional(),
|
|
26775
26943
|
/**
|
|
26776
26944
|
* False = the sample is stamped with a DIFFERENT face model, and a cosine
|
|
26777
26945
|
* across feature spaces is a well-formed float with no meaning. Every number
|
|
@@ -26840,15 +27008,15 @@ var FaceInfoSchema = object({
|
|
|
26840
27008
|
*/
|
|
26841
27009
|
cropUrl: string().optional(),
|
|
26842
27010
|
/** Design B: the face bbox (pixel space) on the key frame — lets a detail
|
|
26843
|
-
* view draw the box over the native `
|
|
27011
|
+
* view draw the box over the native `keyFrameMediaId` frame. Absent on
|
|
26844
27012
|
* legacy rows written before design B. */
|
|
26845
27013
|
faceBbox: BoundingBoxSchema.optional(),
|
|
26846
27014
|
/** Design B: MediaStore key of the track's native-resolution key frame.
|
|
26847
27015
|
* Fetch the native JPEG via the event-media data-plane
|
|
26848
|
-
* (`/addon/<addonId>/event-media/<
|
|
27016
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
|
|
26849
27017
|
* track produced no key frame (e.g. native/onboard source) — the UI falls
|
|
26850
27018
|
* back to the inline `base64` face crop. */
|
|
26851
|
-
|
|
27019
|
+
keyFrameMediaId: number().int().optional(),
|
|
26852
27020
|
/** Winning identity-match cosine (0..1) for this face's track, when an
|
|
26853
27021
|
* identity was auto-confirmed. Lets the UI surface WHY a face was assigned
|
|
26854
27022
|
* (confidence badge / low-confidence audit). Absent on legacy rows and on
|
|
@@ -26917,11 +27085,14 @@ var FaceClusterSchema = object({
|
|
|
26917
27085
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
26918
27086
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
26919
27087
|
*
|
|
26920
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
26921
|
-
* media
|
|
27088
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
27089
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
27090
|
+
* access decision.
|
|
26922
27091
|
*/
|
|
26923
27092
|
var MediaFileLiteSchema$1 = object({
|
|
26924
|
-
|
|
27093
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
27094
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
27095
|
+
mediaId: number().int(),
|
|
26925
27096
|
kind: string(),
|
|
26926
27097
|
url: string(),
|
|
26927
27098
|
sizeBytes: number(),
|
|
@@ -26938,7 +27109,7 @@ method(object({
|
|
|
26938
27109
|
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
26939
27110
|
* four times and the viewer holds at `staleTime: 30_000`.
|
|
26940
27111
|
*
|
|
26941
|
-
* Nothing loses its avatar: `
|
|
27112
|
+
* Nothing loses its avatar: `coverMediaId` is already on every row and
|
|
26942
27113
|
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
26943
27114
|
*
|
|
26944
27115
|
* **This is an INPUT field, so it does not reach the addon until the
|
|
@@ -30301,8 +30472,8 @@ var VehicleSchema = object({
|
|
|
30301
30472
|
id: string(),
|
|
30302
30473
|
name: string(),
|
|
30303
30474
|
sampleCount: number().int().nonnegative(),
|
|
30304
|
-
|
|
30305
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
30475
|
+
coverMediaId: number().int().optional(),
|
|
30476
|
+
/** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
|
|
30306
30477
|
coverBase64: string().optional()
|
|
30307
30478
|
});
|
|
30308
30479
|
var VehicleSampleInfoSchema = object({
|
|
@@ -30335,7 +30506,7 @@ var PlateInfoSchema = object({
|
|
|
30335
30506
|
/** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
|
|
30336
30507
|
plateBbox: BoundingBoxSchema.optional(),
|
|
30337
30508
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
30338
|
-
|
|
30509
|
+
keyFrameMediaId: number().int().optional(),
|
|
30339
30510
|
base64: string().optional(),
|
|
30340
30511
|
/**
|
|
30341
30512
|
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
@@ -30356,11 +30527,14 @@ var PlateInfoSchema = object({
|
|
|
30356
30527
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
30357
30528
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
30358
30529
|
*
|
|
30359
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
30360
|
-
* media
|
|
30530
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
30531
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
30532
|
+
* access decision.
|
|
30361
30533
|
*/
|
|
30362
30534
|
var MediaFileLiteSchema = object({
|
|
30363
|
-
|
|
30535
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
30536
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
30537
|
+
mediaId: number().int(),
|
|
30364
30538
|
kind: string(),
|
|
30365
30539
|
url: string(),
|
|
30366
30540
|
sizeBytes: number(),
|
|
@@ -30419,7 +30593,7 @@ method(object({
|
|
|
30419
30593
|
}), method(object({
|
|
30420
30594
|
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
30421
30595
|
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
30422
|
-
* option; `
|
|
30596
|
+
* option; `coverMediaId` + the `event-media` plane carry the picture.
|
|
30423
30597
|
* INPUT field: stripped by the hub router until the train ships, which
|
|
30424
30598
|
* resolves to `false` and is exactly the intended default. */
|
|
30425
30599
|
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
@@ -31988,7 +32162,14 @@ var SceneReferenceSchema = object({
|
|
|
31988
32162
|
modelId: string(),
|
|
31989
32163
|
condition: SceneConditionSchema,
|
|
31990
32164
|
capturedAt: number(),
|
|
31991
|
-
|
|
32165
|
+
/**
|
|
32166
|
+
* The reference thumbnail's media ROW id (D482).
|
|
32167
|
+
*
|
|
32168
|
+
* The name already said `mediaId` while the value was the row's composite
|
|
32169
|
+
* key — a leftover that read as done and was not. It is the row's own id
|
|
32170
|
+
* now, addressed at `/addon/<addonId>/event-media/m/<id>`.
|
|
32171
|
+
*/
|
|
32172
|
+
thumbnailMediaId: number().int().optional(),
|
|
31992
32173
|
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
31993
32174
|
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
31994
32175
|
* normalized rect frame a different piece of world, and the scene would
|
|
@@ -33079,7 +33260,29 @@ var LoggingSettingsPatchSchema = object({
|
|
|
33079
33260
|
* disarmed the channels it did not mention would make the Levels page and
|
|
33080
33261
|
* the Diagnostics page fight over the same value.
|
|
33081
33262
|
*/
|
|
33082
|
-
channels: array(LogChannelWindowPatchSchema).readonly().optional()
|
|
33263
|
+
channels: array(LogChannelWindowPatchSchema).readonly().optional(),
|
|
33264
|
+
/**
|
|
33265
|
+
* How many days the analytics OPS LOG is kept — the audit trail of what
|
|
33266
|
+
* retention actually deleted.
|
|
33267
|
+
*
|
|
33268
|
+
* It lives HERE, on the logging document, and not on the analytics addon's
|
|
33269
|
+
* settings form, on the operator's instruction: every other log-ish window in
|
|
33270
|
+
* this system is configured through this one document, and a retention audit
|
|
33271
|
+
* configured somewhere else is a second place to look when the question is
|
|
33272
|
+
* "what happened to my data".
|
|
33273
|
+
*
|
|
33274
|
+
* That placement has a cost worth stating: this document ships in the
|
|
33275
|
+
* framework closure, so this knob needs a published `@camstack/server` while
|
|
33276
|
+
* the four windows beside it (D485) reach a node on `camstack deploy`.
|
|
33277
|
+
*
|
|
33278
|
+
* `retention-model.ts` argued this one must NOT follow a device window,
|
|
33279
|
+
* because the audit trail is the history of the SWEEP and not of the camera.
|
|
33280
|
+
* That argument stands and is untouched — what changes is that 30 days stops
|
|
33281
|
+
* being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
|
|
33282
|
+
* rather than 0-as-delete: an audit log truncated to nothing is precisely the
|
|
33283
|
+
* state in which the next 9.5 GiB leak cannot be explained.
|
|
33284
|
+
*/
|
|
33285
|
+
opsLogRetentionDays: number().int().min(0).max(3650).optional()
|
|
33083
33286
|
});
|
|
33084
33287
|
/**
|
|
33085
33288
|
* Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
|
|
@@ -33152,6 +33355,14 @@ var LoggingSettingsStateSchema = object({
|
|
|
33152
33355
|
channels: array(LogChannelDescriptorSchema).readonly(),
|
|
33153
33356
|
/** The channels ARMED right now, each with its deadline. */
|
|
33154
33357
|
activeChannels: array(LogChannelWindowStateSchema).readonly(),
|
|
33358
|
+
/**
|
|
33359
|
+
* The ops-log window in days, as it is in force. `0` = kept forever.
|
|
33360
|
+
*
|
|
33361
|
+
* Reported rather than left to the caller's memory of what it wrote: this is
|
|
33362
|
+
* the value the analytics sweep will actually use, and an operator asking how
|
|
33363
|
+
* long their audit trail lives should not have to infer it from a default.
|
|
33364
|
+
*/
|
|
33365
|
+
opsLogRetentionDays: number().int().min(0),
|
|
33155
33366
|
persisted: boolean()
|
|
33156
33367
|
});
|
|
33157
33368
|
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(), {
|
|
@@ -33972,7 +34183,7 @@ var StationaryObjectSchema = object({
|
|
|
33972
34183
|
/** Enrichment label carried from the source track (identity / plate). */
|
|
33973
34184
|
label: string().optional(),
|
|
33974
34185
|
/** Native-resolution key-frame media key for the parked object's best image. */
|
|
33975
|
-
|
|
34186
|
+
keyFrameMediaId: number().int().optional()
|
|
33976
34187
|
});
|
|
33977
34188
|
var CameraOccupancySnapshotSchema = object({
|
|
33978
34189
|
/** Frame timestamp of the inference result that produced this snapshot. */
|
|
@@ -36710,6 +36921,12 @@ Object.freeze({
|
|
|
36710
36921
|
addonId: null,
|
|
36711
36922
|
access: "create"
|
|
36712
36923
|
},
|
|
36924
|
+
"dataStoreProvider.upsert": {
|
|
36925
|
+
capName: "data-store-provider",
|
|
36926
|
+
capScope: "system",
|
|
36927
|
+
addonId: null,
|
|
36928
|
+
access: "create"
|
|
36929
|
+
},
|
|
36713
36930
|
"dayNight.getOptions": {
|
|
36714
36931
|
capName: "day-night",
|
|
36715
36932
|
capScope: "device",
|
|
@@ -39146,6 +39363,12 @@ Object.freeze({
|
|
|
39146
39363
|
addonId: null,
|
|
39147
39364
|
access: "view"
|
|
39148
39365
|
},
|
|
39366
|
+
"pipelineAnalytics.listRecentSummaries": {
|
|
39367
|
+
capName: "pipeline-analytics",
|
|
39368
|
+
capScope: "device",
|
|
39369
|
+
addonId: null,
|
|
39370
|
+
access: "view"
|
|
39371
|
+
},
|
|
39149
39372
|
"pipelineAnalytics.listRecentTracks": {
|
|
39150
39373
|
capName: "pipeline-analytics",
|
|
39151
39374
|
capScope: "device",
|
|
@@ -40574,6 +40797,12 @@ Object.freeze({
|
|
|
40574
40797
|
addonId: null,
|
|
40575
40798
|
access: "create"
|
|
40576
40799
|
},
|
|
40800
|
+
"settingsStore.upsert": {
|
|
40801
|
+
capName: "settings-store",
|
|
40802
|
+
capScope: "system",
|
|
40803
|
+
addonId: null,
|
|
40804
|
+
access: "create"
|
|
40805
|
+
},
|
|
40577
40806
|
"smtpProvider.getStatus": {
|
|
40578
40807
|
capName: "smtp-provider",
|
|
40579
40808
|
capScope: "system",
|
|
@@ -42967,6 +43196,11 @@ Object.freeze({
|
|
|
42967
43196
|
form: "single",
|
|
42968
43197
|
optional: true
|
|
42969
43198
|
}],
|
|
43199
|
+
"pipelineAnalytics.listRecentSummaries": [{
|
|
43200
|
+
name: "deviceIds",
|
|
43201
|
+
form: "array",
|
|
43202
|
+
optional: false
|
|
43203
|
+
}],
|
|
42970
43204
|
"pipelineAnalytics.listRecentTracks": [{
|
|
42971
43205
|
name: "deviceIds",
|
|
42972
43206
|
form: "array",
|
package/dist/addon.mjs
CHANGED
|
@@ -818,7 +818,7 @@ async function discoverDevices(options = {}, binder = createDgramBinder()) {
|
|
|
818
818
|
return [...byId.values()];
|
|
819
819
|
}
|
|
820
820
|
//#endregion
|
|
821
|
-
//#region ../types/dist/event-category-
|
|
821
|
+
//#region ../types/dist/event-category-ZyX6jcse.mjs
|
|
822
822
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
823
823
|
EventCategory["SystemBoot"] = "system.boot";
|
|
824
824
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -1379,7 +1379,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
1379
1379
|
* a package zone — a newly-appeared stationary object of a package class
|
|
1380
1380
|
* that cleared the class / zone / dwell / size gates. Payload:
|
|
1381
1381
|
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
1382
|
-
* entryId, className, zoneIds,
|
|
1382
|
+
* entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
|
|
1383
1383
|
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
1384
1384
|
* this bus topic drives notifier rules + live UI. See
|
|
1385
1385
|
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
@@ -6165,7 +6165,7 @@ var ZodIssueCode = {
|
|
|
6165
6165
|
var ZodFirstPartyTypeKind;
|
|
6166
6166
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6167
6167
|
//#endregion
|
|
6168
|
-
//#region ../types/dist/sleep-
|
|
6168
|
+
//#region ../types/dist/sleep-DBKu2-U5.mjs
|
|
6169
6169
|
/**
|
|
6170
6170
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6171
6171
|
* window to float samples (D455).
|
|
@@ -8132,13 +8132,30 @@ new Set([
|
|
|
8132
8132
|
"scene",
|
|
8133
8133
|
"motion",
|
|
8134
8134
|
"object",
|
|
8135
|
-
"audio"
|
|
8135
|
+
"audio",
|
|
8136
|
+
"mosaic"
|
|
8136
8137
|
]);
|
|
8137
|
-
|
|
8138
|
+
/**
|
|
8139
|
+
* The owner types that are event tables, in the order the event-media resolver
|
|
8140
|
+
* should consider them. Exported so a consumer asking "is this key an event?"
|
|
8141
|
+
* does not re-spell the list and drift from it.
|
|
8142
|
+
*/
|
|
8143
|
+
var EVENT_OWNER_TYPES = [
|
|
8138
8144
|
"motion",
|
|
8139
8145
|
"object",
|
|
8140
8146
|
"audio"
|
|
8141
|
-
]
|
|
8147
|
+
];
|
|
8148
|
+
/**
|
|
8149
|
+
* The same list as a Zod enum, for the cap inputs that must NAME the table
|
|
8150
|
+
* (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
|
|
8151
|
+
* `(table, id)`).
|
|
8152
|
+
*
|
|
8153
|
+
* Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
|
|
8154
|
+
* table would otherwise be accepted by the codec and refused at the door, with
|
|
8155
|
+
* nothing failing until a caller asked.
|
|
8156
|
+
*/
|
|
8157
|
+
var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
|
|
8158
|
+
new Set(EVENT_OWNER_TYPES);
|
|
8142
8159
|
var EncodeProfileSchema = object({
|
|
8143
8160
|
video: object({
|
|
8144
8161
|
codec: _enum([
|
|
@@ -8177,7 +8194,23 @@ var EncodeProfileSchema = object({
|
|
|
8177
8194
|
"zerolatency",
|
|
8178
8195
|
"film",
|
|
8179
8196
|
"animation"
|
|
8180
|
-
]).optional()
|
|
8197
|
+
]).optional(),
|
|
8198
|
+
/**
|
|
8199
|
+
* ONE slice per access unit.
|
|
8200
|
+
*
|
|
8201
|
+
* `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
|
|
8202
|
+
* the encoder as five NAL slices that share one RTP timestamp and carry one
|
|
8203
|
+
* marker bit. A libwebrtc depacketiser sees five frame-starts and one
|
|
8204
|
+
* frame-end per frame: the first pictures render and the video then freezes
|
|
8205
|
+
* for good while the audio, on its own plane, plays on. Measured on this hub
|
|
8206
|
+
* 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
|
|
8207
|
+
*
|
|
8208
|
+
* A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
|
|
8209
|
+
* `outputArgs` on purpose: an opaque array is part of the sharing key, so two
|
|
8210
|
+
* consumers meaning the same thing spelled differently would stop sharing one
|
|
8211
|
+
* child. Absent means "whatever the encoder does" — today's behaviour.
|
|
8212
|
+
*/
|
|
8213
|
+
singleSlicePerFrame: boolean().optional()
|
|
8181
8214
|
}),
|
|
8182
8215
|
audio: union([literal("passthrough"), object({
|
|
8183
8216
|
codec: _enum([
|
|
@@ -8227,7 +8260,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
|
|
|
8227
8260
|
audio: "passthrough"
|
|
8228
8261
|
};
|
|
8229
8262
|
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
8230
|
-
({ ...BASE_LIVE_EGRESS_PROFILE });
|
|
8263
|
+
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
8231
8264
|
/**
|
|
8232
8265
|
* Deep wiring healthcheck — snapshot of active reachability probes across
|
|
8233
8266
|
* every declared capability + widget of every installed plugin, on every
|
|
@@ -13337,6 +13370,16 @@ method(object({
|
|
|
13337
13370
|
filter: QueryFilterSchema.optional(),
|
|
13338
13371
|
columns: array(string()).readonly().optional()
|
|
13339
13372
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
13373
|
+
namespace: string().optional(),
|
|
13374
|
+
collection: string(),
|
|
13375
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
13376
|
+
* index on the collection. Never empty. */
|
|
13377
|
+
conflict: array(string()).readonly(),
|
|
13378
|
+
record: BulkRecordSchema
|
|
13379
|
+
}), object({
|
|
13380
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
13381
|
+
* row's own id on an update. */
|
|
13382
|
+
id: union([string(), number()]) }), { kind: "mutation" }), method(object({
|
|
13340
13383
|
namespace: string().optional(),
|
|
13341
13384
|
collection: string(),
|
|
13342
13385
|
record: object({
|
|
@@ -13471,6 +13514,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
13471
13514
|
id: union([string(), number()]) }), {
|
|
13472
13515
|
kind: "mutation",
|
|
13473
13516
|
auth: "admin"
|
|
13517
|
+
}), method(object({
|
|
13518
|
+
namespace: string().optional(),
|
|
13519
|
+
collection: string(),
|
|
13520
|
+
conflict: array(string()).readonly(),
|
|
13521
|
+
record: BulkRecordSchema
|
|
13522
|
+
}), object({ id: union([string(), number()]) }), {
|
|
13523
|
+
kind: "mutation",
|
|
13524
|
+
auth: "admin"
|
|
13474
13525
|
}), method(object({
|
|
13475
13526
|
namespace: string().optional(),
|
|
13476
13527
|
collection: string(),
|
|
@@ -19970,8 +20021,8 @@ var TrackPositionSchema = object({
|
|
|
19970
20021
|
var TrackSnapshotSchema = object({
|
|
19971
20022
|
timestamp: number(),
|
|
19972
20023
|
position: TrackPositionSchema,
|
|
19973
|
-
/**
|
|
19974
|
-
|
|
20024
|
+
/** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
|
|
20025
|
+
mediaId: number().int()
|
|
19975
20026
|
});
|
|
19976
20027
|
/**
|
|
19977
20028
|
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
@@ -20575,14 +20626,14 @@ var ObjectEventSchema = object({
|
|
|
20575
20626
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
20576
20627
|
frameWidth: number().optional(),
|
|
20577
20628
|
frameHeight: number().optional(),
|
|
20578
|
-
/**
|
|
20579
|
-
|
|
20580
|
-
/** Design B:
|
|
20629
|
+
/** Media row id of the crop attached to this event (if any) — D482. */
|
|
20630
|
+
mediaId: number().int().optional(),
|
|
20631
|
+
/** Design B: media row id of the track's native-resolution key frame (the
|
|
20581
20632
|
* best-detection full frame). Resolve via the event-media data-plane
|
|
20582
|
-
* (`/addon/<addonId>/event-media/<
|
|
20633
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
|
|
20583
20634
|
* draws `bbox` over the native frame. Absent on legacy rows / non-decoded
|
|
20584
|
-
* sources — consumers fall back to `
|
|
20585
|
-
|
|
20635
|
+
* sources — consumers fall back to `mediaId` (the tight crop). */
|
|
20636
|
+
keyFrameMediaId: number().int().optional(),
|
|
20586
20637
|
/** Populated by B5 (recording playback URL for this event). */
|
|
20587
20638
|
mediaUrl: string().optional(),
|
|
20588
20639
|
/** The parent track's key-event importance [0,1], propagated to every object
|
|
@@ -20632,7 +20683,7 @@ var MediaFileKindEnum = _enum([
|
|
|
20632
20683
|
* hub-main's heap on the way past — for an `<img>` that would have cached it.
|
|
20633
20684
|
*
|
|
20634
20685
|
* `url` points at the `event-media` data plane
|
|
20635
|
-
* (`/addon/<addonId>/event-media/<
|
|
20686
|
+
* (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
|
|
20636
20687
|
* with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
|
|
20637
20688
|
* render a `?variant=thumb`, and streams. The hub gate in front of it requires
|
|
20638
20689
|
* a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
|
|
@@ -20640,10 +20691,13 @@ var MediaFileKindEnum = _enum([
|
|
|
20640
20691
|
* `data-plane-access.ts` for the rule and the one gap it does not close
|
|
20641
20692
|
* (per-device scoping).
|
|
20642
20693
|
*
|
|
20643
|
-
* The URL is built from the row's
|
|
20644
|
-
*
|
|
20694
|
+
* The URL is built from the row's own id, which since D482 says nothing about
|
|
20695
|
+
* the row's owner or kind — and that is the point. The published `kind` is not
|
|
20696
|
+
* the stored one (a track's face/plate crop is stored as `crop` under
|
|
20645
20697
|
* `('face'|'plate', '<prefix>-<trackId>')` and published as
|
|
20646
|
-
* `faceCrop`/`plateCrop
|
|
20698
|
+
* `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
|
|
20699
|
+
* taken from `row.key` verbatim or it 404'd exactly those two rows. An id
|
|
20700
|
+
* cannot be mis-reconstructed, because there is nothing in it to reconstruct.
|
|
20647
20701
|
*
|
|
20648
20702
|
* ## `base64` is TRANSITIONAL and is going away
|
|
20649
20703
|
*
|
|
@@ -20656,7 +20710,19 @@ var MediaFileKindEnum = _enum([
|
|
|
20656
20710
|
* `analytics-query-facade.ts`; nothing else reads it.
|
|
20657
20711
|
*/
|
|
20658
20712
|
var MediaFileSchema = object({
|
|
20659
|
-
|
|
20713
|
+
/**
|
|
20714
|
+
* The media row's OWN id — the rowid SQLite assigned it (D482).
|
|
20715
|
+
*
|
|
20716
|
+
* It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
|
|
20717
|
+
* [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
|
|
20718
|
+
* per-table rowid aliases, so `object:101314` and `motion:101314` are two
|
|
20719
|
+
* different rows that spell the same number, and a track whose
|
|
20720
|
+
* `bestEventId` was an object event was served a motion event's snapshot —
|
|
20721
|
+
* a night-time thumbnail on an afternoon track, with no error anywhere. A
|
|
20722
|
+
* surrogate id cannot name the wrong row's owner, because it names no owner
|
|
20723
|
+
* at all.
|
|
20724
|
+
*/
|
|
20725
|
+
mediaId: number().int(),
|
|
20660
20726
|
kind: MediaFileKindEnum,
|
|
20661
20727
|
sizeBytes: number(),
|
|
20662
20728
|
timestamp: number()
|
|
@@ -20764,7 +20830,7 @@ var RetrainTrackSchema = object({
|
|
|
20764
20830
|
});
|
|
20765
20831
|
/** A frame the picker may offer — an index row, no blob was read to produce it. */
|
|
20766
20832
|
var RetrainFrameCandidateSchema = object({
|
|
20767
|
-
|
|
20833
|
+
mediaId: number().int(),
|
|
20768
20834
|
kind: MediaFileKindEnum,
|
|
20769
20835
|
timestamp: number(),
|
|
20770
20836
|
sizeBytes: number().int(),
|
|
@@ -20778,7 +20844,7 @@ var RetrainFrameSchema = object({
|
|
|
20778
20844
|
deviceId: number(),
|
|
20779
20845
|
trackId: string(),
|
|
20780
20846
|
/** Provenance only. It may already point at nothing — that is expected. */
|
|
20781
|
-
|
|
20847
|
+
sourceMediaId: number().int(),
|
|
20782
20848
|
sourceKind: MediaFileKindEnum,
|
|
20783
20849
|
sizeBytes: number().int(),
|
|
20784
20850
|
width: number().int(),
|
|
@@ -20794,7 +20860,7 @@ var RetrainCopyRefusalSchema = _enum([
|
|
|
20794
20860
|
var RetrainFrameSelectionSchema = object({
|
|
20795
20861
|
copied: array(RetrainFrameSchema).readonly(),
|
|
20796
20862
|
refused: array(object({
|
|
20797
|
-
|
|
20863
|
+
sourceMediaId: number().int(),
|
|
20798
20864
|
reason: RetrainCopyRefusalSchema
|
|
20799
20865
|
})).readonly()
|
|
20800
20866
|
});
|
|
@@ -20802,7 +20868,7 @@ var RetrainFrameListSchema = object({
|
|
|
20802
20868
|
candidates: array(RetrainFrameCandidateSchema).readonly(),
|
|
20803
20869
|
copies: array(RetrainFrameSchema).readonly(),
|
|
20804
20870
|
/** What the page pre-selects — the native key frame when one survives. */
|
|
20805
|
-
|
|
20871
|
+
autoPickMediaId: number().int().optional()
|
|
20806
20872
|
});
|
|
20807
20873
|
/** What the operator asked the assist to look for. */
|
|
20808
20874
|
var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
|
|
@@ -20897,9 +20963,11 @@ var RecentTracksQueryInput = object({
|
|
|
20897
20963
|
});
|
|
20898
20964
|
/**
|
|
20899
20965
|
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
20900
|
-
* `
|
|
20901
|
-
* served by the event-media plane
|
|
20902
|
-
* member visible has been materialised
|
|
20966
|
+
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
20967
|
+
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
20968
|
+
* first frame with a member visible has been materialised (D482 — it was the
|
|
20969
|
+
* row's composite key, which embedded the owner and could name another table's
|
|
20970
|
+
* row once event ids became per-table rowids).
|
|
20903
20971
|
*/
|
|
20904
20972
|
var SummarySchema = object({
|
|
20905
20973
|
id: string(),
|
|
@@ -20908,19 +20976,115 @@ var SummarySchema = object({
|
|
|
20908
20976
|
lastActiveAt: number(),
|
|
20909
20977
|
sealedAt: number().nullable(),
|
|
20910
20978
|
memberCount: number().int().nonnegative(),
|
|
20911
|
-
|
|
20979
|
+
groupShotMediaId: number().int().nullable()
|
|
20912
20980
|
});
|
|
20913
20981
|
var SummariesQueryInput = object({
|
|
20914
20982
|
deviceIds: array(number()).min(1),
|
|
20915
20983
|
since: number().optional(),
|
|
20916
20984
|
until: number().optional(),
|
|
20917
|
-
limit: number().int().min(1).max(200).default(50)
|
|
20985
|
+
limit: number().int().min(1).max(200).default(50),
|
|
20986
|
+
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
20987
|
+
* meaning of "dog" on every summary surface. */
|
|
20988
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
20918
20989
|
});
|
|
20919
|
-
var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
|
|
20920
20990
|
var SummaryDetailSchema = object({
|
|
20921
20991
|
summary: SummarySchema,
|
|
20922
|
-
/**
|
|
20923
|
-
|
|
20992
|
+
/** Members in absorption order, oldest join first. */
|
|
20993
|
+
members: array(object({
|
|
20994
|
+
trackId: string(),
|
|
20995
|
+
/**
|
|
20996
|
+
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
20997
|
+
* and the track no longer exists to fill it.
|
|
20998
|
+
*
|
|
20999
|
+
* The join, not the latest opinion: class voting can re-decide a track's
|
|
21000
|
+
* class afterwards, and a group's composition is the history of who came
|
|
21001
|
+
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
21002
|
+
* dog" — rather than being handed a second, denormalised tally that would
|
|
21003
|
+
* drift from the members it claims to describe.
|
|
21004
|
+
*/
|
|
21005
|
+
className: string().nullable(),
|
|
21006
|
+
/** `primary` is the one member that carries the group's identity. */
|
|
21007
|
+
role: _enum([
|
|
21008
|
+
"primary",
|
|
21009
|
+
"sibling",
|
|
21010
|
+
"child"
|
|
21011
|
+
]).nullable(),
|
|
21012
|
+
joinedAt: number(),
|
|
21013
|
+
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
21014
|
+
* at read time. Absent when nothing resolved, never an empty string. */
|
|
21015
|
+
label: string().optional(),
|
|
21016
|
+
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
21017
|
+
* recognised nobody, and absent for a member whose track has been pruned —
|
|
21018
|
+
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
21019
|
+
subLabel: string().optional()
|
|
21020
|
+
})).readonly()
|
|
21021
|
+
});
|
|
21022
|
+
/**
|
|
21023
|
+
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
21024
|
+
*
|
|
21025
|
+
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
21026
|
+
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
21027
|
+
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
21028
|
+
* are on {@link getSummary}: shipping every member of every group so a client
|
|
21029
|
+
* can count them turns a page of two hundred groups into a thousand records to
|
|
21030
|
+
* draw two hundred badges.
|
|
21031
|
+
*/
|
|
21032
|
+
var SummaryListItemSchema = object({
|
|
21033
|
+
summary: SummarySchema,
|
|
21034
|
+
/** Class counts, most numerous first; `className: null` is a member whose
|
|
21035
|
+
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
21036
|
+
classes: array(object({
|
|
21037
|
+
className: string().nullable(),
|
|
21038
|
+
count: number().int().positive()
|
|
21039
|
+
})).readonly()
|
|
21040
|
+
});
|
|
21041
|
+
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
21042
|
+
/**
|
|
21043
|
+
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
21044
|
+
*
|
|
21045
|
+
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
21046
|
+
* summaries feed that could only answer "the last N for these cameras"
|
|
21047
|
+
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
21048
|
+
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
21049
|
+
* "newest" means, on one screen.
|
|
21050
|
+
*/
|
|
21051
|
+
var RecentSummariesQueryInput = object({
|
|
21052
|
+
/** Devices to merge. An empty array yields an empty page. */
|
|
21053
|
+
deviceIds: array(number()),
|
|
21054
|
+
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
21055
|
+
since: number().optional(),
|
|
21056
|
+
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
21057
|
+
until: number().optional(),
|
|
21058
|
+
limit: number().int().min(1).max(500).default(100),
|
|
21059
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
21060
|
+
cursor: string().optional(),
|
|
21061
|
+
/**
|
|
21062
|
+
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
21063
|
+
* deliberately the same name: the events filter tree emits one list of ticked
|
|
21064
|
+
* taxonomy nodes, and a summaries feed that called it something else would
|
|
21065
|
+
* make the operator's one filter component produce two shapes.
|
|
21066
|
+
*
|
|
21067
|
+
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
21068
|
+
* me the arrivals with a dog" has to return the group of four people who had
|
|
21069
|
+
* one with them; a filter on the group's own fields could only ever answer
|
|
21070
|
+
* about its primary.
|
|
21071
|
+
*
|
|
21072
|
+
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
21073
|
+
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
21074
|
+
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
21075
|
+
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
21076
|
+
* that read only the class would answer "animal" and never "dog".
|
|
21077
|
+
*
|
|
21078
|
+
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
21079
|
+
*/
|
|
21080
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
21081
|
+
});
|
|
21082
|
+
var RecentSummariesPageSchema = object({
|
|
21083
|
+
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
21084
|
+
* {@link listSummaries} — one list shape, so a card renders the same
|
|
21085
|
+
* whichever feed drew it. */
|
|
21086
|
+
summaries: array(SummaryListItemSchema).readonly(),
|
|
21087
|
+
nextCursor: string().nullable()
|
|
20924
21088
|
});
|
|
20925
21089
|
var RecentTracksPageSchema = object({
|
|
20926
21090
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -21334,7 +21498,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21334
21498
|
classes: array(string()).optional(),
|
|
21335
21499
|
/** See {@link ExcludeSourcesDoc}. */
|
|
21336
21500
|
excludeSources: array(TrackSourceSchema).optional()
|
|
21337
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
21501
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
21338
21502
|
kind: "mutation",
|
|
21339
21503
|
auth: "admin"
|
|
21340
21504
|
}), 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({
|
|
@@ -21462,7 +21626,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21462
21626
|
}), method(object({
|
|
21463
21627
|
deviceId: number(),
|
|
21464
21628
|
trackId: string(),
|
|
21465
|
-
|
|
21629
|
+
mediaIds: array(number().int()).min(1)
|
|
21466
21630
|
}), RetrainFrameSelectionSchema, {
|
|
21467
21631
|
kind: "mutation",
|
|
21468
21632
|
auth: "admin"
|
|
@@ -21530,7 +21694,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21530
21694
|
kind: "query",
|
|
21531
21695
|
auth: "admin"
|
|
21532
21696
|
}), method(object({
|
|
21533
|
-
|
|
21697
|
+
/** Which of the three event tables owns the row. */
|
|
21698
|
+
ownerType: EventOwnerTypeSchema,
|
|
21699
|
+
/** The event's rowid in that table (D474: an event id is a number). */
|
|
21700
|
+
eventId: number().int(),
|
|
21534
21701
|
kind: MediaFileKindEnum.optional(),
|
|
21535
21702
|
deviceId: number()
|
|
21536
21703
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
@@ -21541,7 +21708,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21541
21708
|
trackId: string(),
|
|
21542
21709
|
deviceId: number()
|
|
21543
21710
|
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
21544
|
-
|
|
21711
|
+
ownerType: EventOwnerTypeSchema,
|
|
21712
|
+
eventId: number().int(),
|
|
21545
21713
|
deviceId: number()
|
|
21546
21714
|
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
21547
21715
|
kind: "mutation",
|
|
@@ -26742,8 +26910,8 @@ var IdentitySchema = object({
|
|
|
26742
26910
|
id: string(),
|
|
26743
26911
|
name: string(),
|
|
26744
26912
|
sampleCount: number().int().nonnegative(),
|
|
26745
|
-
|
|
26746
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
26913
|
+
coverMediaId: number().int().optional(),
|
|
26914
|
+
/** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
|
|
26747
26915
|
* Lets the UI render the person's face avatar instead of a placeholder icon. */
|
|
26748
26916
|
coverBase64: string().optional()
|
|
26749
26917
|
});
|
|
@@ -26769,8 +26937,8 @@ var IdentitySampleAuditRowSchema = object({
|
|
|
26769
26937
|
enrolledAt: number().int(),
|
|
26770
26938
|
deviceId: number().int().optional(),
|
|
26771
26939
|
source: _enum(["detected", "photo"]),
|
|
26772
|
-
/** The enrolled crop's media
|
|
26773
|
-
|
|
26940
|
+
/** The enrolled crop's media row id, so the panel can show the evidence. */
|
|
26941
|
+
mediaId: number().int().optional(),
|
|
26774
26942
|
/**
|
|
26775
26943
|
* False = the sample is stamped with a DIFFERENT face model, and a cosine
|
|
26776
26944
|
* across feature spaces is a well-formed float with no meaning. Every number
|
|
@@ -26839,15 +27007,15 @@ var FaceInfoSchema = object({
|
|
|
26839
27007
|
*/
|
|
26840
27008
|
cropUrl: string().optional(),
|
|
26841
27009
|
/** Design B: the face bbox (pixel space) on the key frame — lets a detail
|
|
26842
|
-
* view draw the box over the native `
|
|
27010
|
+
* view draw the box over the native `keyFrameMediaId` frame. Absent on
|
|
26843
27011
|
* legacy rows written before design B. */
|
|
26844
27012
|
faceBbox: BoundingBoxSchema.optional(),
|
|
26845
27013
|
/** Design B: MediaStore key of the track's native-resolution key frame.
|
|
26846
27014
|
* Fetch the native JPEG via the event-media data-plane
|
|
26847
|
-
* (`/addon/<addonId>/event-media/<
|
|
27015
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
|
|
26848
27016
|
* track produced no key frame (e.g. native/onboard source) — the UI falls
|
|
26849
27017
|
* back to the inline `base64` face crop. */
|
|
26850
|
-
|
|
27018
|
+
keyFrameMediaId: number().int().optional(),
|
|
26851
27019
|
/** Winning identity-match cosine (0..1) for this face's track, when an
|
|
26852
27020
|
* identity was auto-confirmed. Lets the UI surface WHY a face was assigned
|
|
26853
27021
|
* (confidence badge / low-confidence audit). Absent on legacy rows and on
|
|
@@ -26916,11 +27084,14 @@ var FaceClusterSchema = object({
|
|
|
26916
27084
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
26917
27085
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
26918
27086
|
*
|
|
26919
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
26920
|
-
* media
|
|
27087
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
27088
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
27089
|
+
* access decision.
|
|
26921
27090
|
*/
|
|
26922
27091
|
var MediaFileLiteSchema$1 = object({
|
|
26923
|
-
|
|
27092
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
27093
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
27094
|
+
mediaId: number().int(),
|
|
26924
27095
|
kind: string(),
|
|
26925
27096
|
url: string(),
|
|
26926
27097
|
sizeBytes: number(),
|
|
@@ -26937,7 +27108,7 @@ method(object({
|
|
|
26937
27108
|
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
26938
27109
|
* four times and the viewer holds at `staleTime: 30_000`.
|
|
26939
27110
|
*
|
|
26940
|
-
* Nothing loses its avatar: `
|
|
27111
|
+
* Nothing loses its avatar: `coverMediaId` is already on every row and
|
|
26941
27112
|
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
26942
27113
|
*
|
|
26943
27114
|
* **This is an INPUT field, so it does not reach the addon until the
|
|
@@ -30300,8 +30471,8 @@ var VehicleSchema = object({
|
|
|
30300
30471
|
id: string(),
|
|
30301
30472
|
name: string(),
|
|
30302
30473
|
sampleCount: number().int().nonnegative(),
|
|
30303
|
-
|
|
30304
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
30474
|
+
coverMediaId: number().int().optional(),
|
|
30475
|
+
/** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
|
|
30305
30476
|
coverBase64: string().optional()
|
|
30306
30477
|
});
|
|
30307
30478
|
var VehicleSampleInfoSchema = object({
|
|
@@ -30334,7 +30505,7 @@ var PlateInfoSchema = object({
|
|
|
30334
30505
|
/** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
|
|
30335
30506
|
plateBbox: BoundingBoxSchema.optional(),
|
|
30336
30507
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
30337
|
-
|
|
30508
|
+
keyFrameMediaId: number().int().optional(),
|
|
30338
30509
|
base64: string().optional(),
|
|
30339
30510
|
/**
|
|
30340
30511
|
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
@@ -30355,11 +30526,14 @@ var PlateInfoSchema = object({
|
|
|
30355
30526
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
30356
30527
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
30357
30528
|
*
|
|
30358
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
30359
|
-
* media
|
|
30529
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
30530
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
30531
|
+
* access decision.
|
|
30360
30532
|
*/
|
|
30361
30533
|
var MediaFileLiteSchema = object({
|
|
30362
|
-
|
|
30534
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
30535
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
30536
|
+
mediaId: number().int(),
|
|
30363
30537
|
kind: string(),
|
|
30364
30538
|
url: string(),
|
|
30365
30539
|
sizeBytes: number(),
|
|
@@ -30418,7 +30592,7 @@ method(object({
|
|
|
30418
30592
|
}), method(object({
|
|
30419
30593
|
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
30420
30594
|
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
30421
|
-
* option; `
|
|
30595
|
+
* option; `coverMediaId` + the `event-media` plane carry the picture.
|
|
30422
30596
|
* INPUT field: stripped by the hub router until the train ships, which
|
|
30423
30597
|
* resolves to `false` and is exactly the intended default. */
|
|
30424
30598
|
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
@@ -31987,7 +32161,14 @@ var SceneReferenceSchema = object({
|
|
|
31987
32161
|
modelId: string(),
|
|
31988
32162
|
condition: SceneConditionSchema,
|
|
31989
32163
|
capturedAt: number(),
|
|
31990
|
-
|
|
32164
|
+
/**
|
|
32165
|
+
* The reference thumbnail's media ROW id (D482).
|
|
32166
|
+
*
|
|
32167
|
+
* The name already said `mediaId` while the value was the row's composite
|
|
32168
|
+
* key — a leftover that read as done and was not. It is the row's own id
|
|
32169
|
+
* now, addressed at `/addon/<addonId>/event-media/m/<id>`.
|
|
32170
|
+
*/
|
|
32171
|
+
thumbnailMediaId: number().int().optional(),
|
|
31991
32172
|
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
31992
32173
|
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
31993
32174
|
* normalized rect frame a different piece of world, and the scene would
|
|
@@ -33078,7 +33259,29 @@ var LoggingSettingsPatchSchema = object({
|
|
|
33078
33259
|
* disarmed the channels it did not mention would make the Levels page and
|
|
33079
33260
|
* the Diagnostics page fight over the same value.
|
|
33080
33261
|
*/
|
|
33081
|
-
channels: array(LogChannelWindowPatchSchema).readonly().optional()
|
|
33262
|
+
channels: array(LogChannelWindowPatchSchema).readonly().optional(),
|
|
33263
|
+
/**
|
|
33264
|
+
* How many days the analytics OPS LOG is kept — the audit trail of what
|
|
33265
|
+
* retention actually deleted.
|
|
33266
|
+
*
|
|
33267
|
+
* It lives HERE, on the logging document, and not on the analytics addon's
|
|
33268
|
+
* settings form, on the operator's instruction: every other log-ish window in
|
|
33269
|
+
* this system is configured through this one document, and a retention audit
|
|
33270
|
+
* configured somewhere else is a second place to look when the question is
|
|
33271
|
+
* "what happened to my data".
|
|
33272
|
+
*
|
|
33273
|
+
* That placement has a cost worth stating: this document ships in the
|
|
33274
|
+
* framework closure, so this knob needs a published `@camstack/server` while
|
|
33275
|
+
* the four windows beside it (D485) reach a node on `camstack deploy`.
|
|
33276
|
+
*
|
|
33277
|
+
* `retention-model.ts` argued this one must NOT follow a device window,
|
|
33278
|
+
* because the audit trail is the history of the SWEEP and not of the camera.
|
|
33279
|
+
* That argument stands and is untouched — what changes is that 30 days stops
|
|
33280
|
+
* being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
|
|
33281
|
+
* rather than 0-as-delete: an audit log truncated to nothing is precisely the
|
|
33282
|
+
* state in which the next 9.5 GiB leak cannot be explained.
|
|
33283
|
+
*/
|
|
33284
|
+
opsLogRetentionDays: number().int().min(0).max(3650).optional()
|
|
33082
33285
|
});
|
|
33083
33286
|
/**
|
|
33084
33287
|
* Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
|
|
@@ -33151,6 +33354,14 @@ var LoggingSettingsStateSchema = object({
|
|
|
33151
33354
|
channels: array(LogChannelDescriptorSchema).readonly(),
|
|
33152
33355
|
/** The channels ARMED right now, each with its deadline. */
|
|
33153
33356
|
activeChannels: array(LogChannelWindowStateSchema).readonly(),
|
|
33357
|
+
/**
|
|
33358
|
+
* The ops-log window in days, as it is in force. `0` = kept forever.
|
|
33359
|
+
*
|
|
33360
|
+
* Reported rather than left to the caller's memory of what it wrote: this is
|
|
33361
|
+
* the value the analytics sweep will actually use, and an operator asking how
|
|
33362
|
+
* long their audit trail lives should not have to infer it from a default.
|
|
33363
|
+
*/
|
|
33364
|
+
opsLogRetentionDays: number().int().min(0),
|
|
33154
33365
|
persisted: boolean()
|
|
33155
33366
|
});
|
|
33156
33367
|
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(), {
|
|
@@ -33971,7 +34182,7 @@ var StationaryObjectSchema = object({
|
|
|
33971
34182
|
/** Enrichment label carried from the source track (identity / plate). */
|
|
33972
34183
|
label: string().optional(),
|
|
33973
34184
|
/** Native-resolution key-frame media key for the parked object's best image. */
|
|
33974
|
-
|
|
34185
|
+
keyFrameMediaId: number().int().optional()
|
|
33975
34186
|
});
|
|
33976
34187
|
var CameraOccupancySnapshotSchema = object({
|
|
33977
34188
|
/** Frame timestamp of the inference result that produced this snapshot. */
|
|
@@ -36709,6 +36920,12 @@ Object.freeze({
|
|
|
36709
36920
|
addonId: null,
|
|
36710
36921
|
access: "create"
|
|
36711
36922
|
},
|
|
36923
|
+
"dataStoreProvider.upsert": {
|
|
36924
|
+
capName: "data-store-provider",
|
|
36925
|
+
capScope: "system",
|
|
36926
|
+
addonId: null,
|
|
36927
|
+
access: "create"
|
|
36928
|
+
},
|
|
36712
36929
|
"dayNight.getOptions": {
|
|
36713
36930
|
capName: "day-night",
|
|
36714
36931
|
capScope: "device",
|
|
@@ -39145,6 +39362,12 @@ Object.freeze({
|
|
|
39145
39362
|
addonId: null,
|
|
39146
39363
|
access: "view"
|
|
39147
39364
|
},
|
|
39365
|
+
"pipelineAnalytics.listRecentSummaries": {
|
|
39366
|
+
capName: "pipeline-analytics",
|
|
39367
|
+
capScope: "device",
|
|
39368
|
+
addonId: null,
|
|
39369
|
+
access: "view"
|
|
39370
|
+
},
|
|
39148
39371
|
"pipelineAnalytics.listRecentTracks": {
|
|
39149
39372
|
capName: "pipeline-analytics",
|
|
39150
39373
|
capScope: "device",
|
|
@@ -40573,6 +40796,12 @@ Object.freeze({
|
|
|
40573
40796
|
addonId: null,
|
|
40574
40797
|
access: "create"
|
|
40575
40798
|
},
|
|
40799
|
+
"settingsStore.upsert": {
|
|
40800
|
+
capName: "settings-store",
|
|
40801
|
+
capScope: "system",
|
|
40802
|
+
addonId: null,
|
|
40803
|
+
access: "create"
|
|
40804
|
+
},
|
|
40576
40805
|
"smtpProvider.getStatus": {
|
|
40577
40806
|
capName: "smtp-provider",
|
|
40578
40807
|
capScope: "system",
|
|
@@ -42966,6 +43195,11 @@ Object.freeze({
|
|
|
42966
43195
|
form: "single",
|
|
42967
43196
|
optional: true
|
|
42968
43197
|
}],
|
|
43198
|
+
"pipelineAnalytics.listRecentSummaries": [{
|
|
43199
|
+
name: "deviceIds",
|
|
43200
|
+
form: "array",
|
|
43201
|
+
optional: false
|
|
43202
|
+
}],
|
|
42969
43203
|
"pipelineAnalytics.listRecentTracks": [{
|
|
42970
43204
|
name: "deviceIds",
|
|
42971
43205
|
form: "array",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-tuya",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.101",
|
|
4
4
|
"description": "Tuya / Smart Life device-provider addon for CamStack — account-onboarded (Tuya IoT cloud fetch of device localKeys) + LOCAL DP control via the @apocaliss92/nodetuya encrypted-LAN client, exposing switch / water-heater-family kettle entities",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|