@camstack/types 1.2.236 → 1.2.238
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 +1 -1
- package/dist/addon.mjs +1 -1
- package/dist/capabilities/capability-definition.d.ts +41 -1
- package/dist/capabilities/index.d.ts +4 -4
- package/dist/capabilities/recording-export.cap.d.ts +437 -20
- package/dist/capabilities/videoclips.cap.d.ts +142 -12
- package/dist/generated/addon-api.d.ts +7 -0
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/method-device-selectors.d.ts +1 -1
- package/dist/index.js +495 -33
- package/dist/index.mjs +499 -43
- package/dist/{sleep-CaB_hL5g.mjs → sleep-BVhJDJka.mjs} +15 -2
- package/dist/{sleep-Cqxm5OIN.js → sleep-C0n7gucP.js} +20 -1
- package/package.json +1 -1
|
@@ -6,13 +6,14 @@ import { type InferProvider } from './capability-definition.js';
|
|
|
6
6
|
*
|
|
7
7
|
* A device-scoped wrapper COLLECTION (D549 decision 2, D554): every provider a
|
|
8
8
|
* camera has is a SOURCE, and they are listed beside each other — never one
|
|
9
|
-
* substituted for another
|
|
10
|
-
* the RECORDER — the addon that owns the
|
|
11
|
-
* composes the analytics event log (markers + thumbnails,
|
|
12
|
-
* with the recorder's own `getPlaybackManifest
|
|
13
|
-
* existing footage, never a separate file. A camera that
|
|
14
|
-
* clips (Reolink SD card, a hub's storage, HKSV) adds
|
|
15
|
-
* ALONGSIDE that one.
|
|
9
|
+
* substituted for another, and none of them privileged by name. One source,
|
|
10
|
+
* `analytics`, is registered by the RECORDER — the addon that owns the
|
|
11
|
+
* footage, D560 — and composes the analytics event log (markers + thumbnails,
|
|
12
|
+
* read over `ctx.api`) with the recorder's own `getPlaybackManifest`: a clip
|
|
13
|
+
* is a time-WINDOW over existing footage, never a separate file. A camera that
|
|
14
|
+
* exposes NATIVE onboard clips (Reolink SD card, a hub's storage, HKSV) adds
|
|
15
|
+
* its own catalog ALONGSIDE that one. (`defaultActive` above is the CAP's
|
|
16
|
+
* auto-bind to cameras, not a ranking among these sources — there is none.)
|
|
16
17
|
*
|
|
17
18
|
* The mount stays per-device (`resolveCapMount` → `device-scoped`), and a
|
|
18
19
|
* device's SOURCES are its BINDINGS: `deviceManager.getBindings(deviceId)` is
|
|
@@ -22,10 +23,17 @@ import { type InferProvider } from './capability-definition.js';
|
|
|
22
23
|
* native provider, as the hub-local registration and as an
|
|
23
24
|
* `<addonId>@<nodeId>` one (D554 amended 2026-09-20).
|
|
24
25
|
*
|
|
25
|
-
* `listClips` is asked of ONE provider at a time
|
|
26
|
-
* ({@link videoclipsCapability.methods.listClips} `provider
|
|
27
|
-
*
|
|
28
|
-
*
|
|
26
|
+
* `listClips` is asked of ONE provider at a time, and NAMING it is REQUIRED
|
|
27
|
+
* ({@link videoclipsCapability.methods.listClips} `provider`, D554 amended). It is not
|
|
28
|
+
* a union over everything a camera has: *"l'utilizzatore è uno solo"*. There
|
|
29
|
+
* is no default, because a collection cap's binding set is DERIVED and PLURAL
|
|
30
|
+
* (D554 amended, `getBindings` step 0) — "the bound one" does not exist to
|
|
31
|
+
* resolve to, and the one thing that could take its place is a second
|
|
32
|
+
* authority naming a provider per camera, which D554 decision 3 rejected.
|
|
33
|
+
* The pick is a SURFACE's to make, from the {@link ClipSourceSchema} rows it
|
|
34
|
+
* already holds, and it says which one it made (D569 § 1–3).
|
|
35
|
+
* {@link videoclipsCapability.methods.listSources} is the method that fans out
|
|
36
|
+
* — one row per source, by construction.
|
|
29
37
|
* {@link videoclipsCapability.methods.getClipPlayback} dispatches by the
|
|
30
38
|
* source namespace inside the clip id, which is why ids are self-contained.
|
|
31
39
|
*
|
|
@@ -169,6 +177,68 @@ export type ClipPlayback = z.infer<typeof ClipPlaybackSchema>;
|
|
|
169
177
|
* which days it asked for and got nothing — "no clips" would be a lie about a
|
|
170
178
|
* card that is full of them.
|
|
171
179
|
*/
|
|
180
|
+
/**
|
|
181
|
+
* The operator's authorisation to WAKE a sleeping camera for one clip read.
|
|
182
|
+
*
|
|
183
|
+
* ONE value, absent by default, and it is a `force`-shaped operator signal in
|
|
184
|
+
* exactly the sense `snapshot-wake-gate.ts` uses the word: *"`snapshot.getSnapshot`'s
|
|
185
|
+
* `force` flag, and nothing else… a background caller must never set it…
|
|
186
|
+
* Stale but honest beats woken"*. A scheduler, a retry, a reconcile and a
|
|
187
|
+
* prefetch never set it; a surface sets it only behind the same confirm the
|
|
188
|
+
* "Wake and refresh" gesture uses, and it is refused below 15 % battery
|
|
189
|
+
* exactly as that gesture is.
|
|
190
|
+
*
|
|
191
|
+
* The gate is decided BEFORE `getApi()`, because on UDP the login IS the wake
|
|
192
|
+
* (D549) — a read that opened a session and then checked would have woken the
|
|
193
|
+
* camera to find out it was not allowed to.
|
|
194
|
+
*
|
|
195
|
+
* **One authorised yes is one wake.** `next-natural` — take the clip the next
|
|
196
|
+
* time the camera is awake for its own reasons — is deliberately not a member:
|
|
197
|
+
* it was proposed, it is free on the battery, and the operator declined it on
|
|
198
|
+
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."*,
|
|
199
|
+
* D558 "Considered and not taken").
|
|
200
|
+
*/
|
|
201
|
+
export declare const ClipWakeSchema: z.ZodEnum<{
|
|
202
|
+
authorised: "authorised";
|
|
203
|
+
}>;
|
|
204
|
+
export type ClipWake = z.infer<typeof ClipWakeSchema>;
|
|
205
|
+
/**
|
|
206
|
+
* Hard ceiling on ONE {@link videoclipsCapability.methods.readClipBytes} — the
|
|
207
|
+
* same 50 MiB `RECORDING_EXPORT_MAX_READ_BYTES` uses, and for the same second
|
|
208
|
+
* reason: the envelope is unary, so a base64 payload is held whole (~1.33× its
|
|
209
|
+
* size) in the provider AND in the caller, on a hub this repo has already
|
|
210
|
+
* OOM'd once (D9/D18).
|
|
211
|
+
*
|
|
212
|
+
* Measured clips sit far below it — 92 KB–2.29 MB for a sub twin, 455 KB for a
|
|
213
|
+
* 16 s main clip — so the bound bites rarely. "Rarely" is not "never": a long
|
|
214
|
+
* 4K main twin can exceed it, and above the bound the provider REFUSES with
|
|
215
|
+
* the size in the message, never truncates. Half a video is worse than an
|
|
216
|
+
* honest refusal.
|
|
217
|
+
*
|
|
218
|
+
* The clean follow-on is a CHUNKED read so a `high` twin of a long clip stops
|
|
219
|
+
* being refusable at all. That is a later slice, named here so the bound is
|
|
220
|
+
* not mistaken for a design ceiling.
|
|
221
|
+
*/
|
|
222
|
+
export declare const VIDEOCLIPS_MAX_READ_BYTES: number;
|
|
223
|
+
/**
|
|
224
|
+
* A clip's finished bytes, inline — the twin of `recordingExport.readExportBytes`.
|
|
225
|
+
*
|
|
226
|
+
* `bytes` is the DECODED length, so nobody infers it from the base64 length,
|
|
227
|
+
* and `served` says which twin the caller actually got.
|
|
228
|
+
*/
|
|
229
|
+
export declare const ClipBytesSchema: z.ZodObject<{
|
|
230
|
+
base64: z.ZodString;
|
|
231
|
+
contentType: z.ZodString;
|
|
232
|
+
name: z.ZodString;
|
|
233
|
+
bytes: z.ZodNumber;
|
|
234
|
+
served: z.ZodEnum<{
|
|
235
|
+
high: "high";
|
|
236
|
+
mid: "mid";
|
|
237
|
+
low: "low";
|
|
238
|
+
}>;
|
|
239
|
+
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
240
|
+
}, z.core.$strip>;
|
|
241
|
+
export type ClipBytes = z.infer<typeof ClipBytesSchema>;
|
|
172
242
|
export declare const ClipSourceAvailabilitySchema: z.ZodObject<{
|
|
173
243
|
state: z.ZodEnum<{
|
|
174
244
|
ok: "ok";
|
|
@@ -259,7 +329,7 @@ export declare const videoclipsCapability: {
|
|
|
259
329
|
since: z.ZodNumber;
|
|
260
330
|
until: z.ZodNumber;
|
|
261
331
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
262
|
-
provider: z.
|
|
332
|
+
provider: z.ZodString;
|
|
263
333
|
}, z.core.$strip>, z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
264
334
|
id: z.ZodString;
|
|
265
335
|
source: z.ZodString;
|
|
@@ -358,6 +428,66 @@ export declare const videoclipsCapability: {
|
|
|
358
428
|
playbackEndpoints: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
359
429
|
token: z.ZodOptional<z.ZodString>;
|
|
360
430
|
}, z.core.$strip>, "query">;
|
|
431
|
+
/**
|
|
432
|
+
* This clip's BYTES, base64, bounded — the by-handle read a clip EXPORT
|
|
433
|
+
* pulls once (D558).
|
|
434
|
+
*
|
|
435
|
+
* `getClipPlayback` is the right answer for a player: it hands back a URL
|
|
436
|
+
* on a plane the hub serves `access:'authenticated'`, which a browser and a
|
|
437
|
+
* viewer session satisfy. It is the wrong answer for another ADDON. There
|
|
438
|
+
* is no addon→addon byte transport in this framework — `AddonDataPlane`
|
|
439
|
+
* only lets an addon SERVE, on `127.0.0.1` behind a per-listener secret
|
|
440
|
+
* only the hub may present — so a recorder that wants a camera's clip
|
|
441
|
+
* cannot fetch that URL. This method is the one seam that exists for it,
|
|
442
|
+
* and it is deliberately the same shape (and the same bound) as
|
|
443
|
+
* `recordingExport.readExportBytes`, which exists for the mirror-image
|
|
444
|
+
* reason.
|
|
445
|
+
*
|
|
446
|
+
* Routing needs no `provider` pin: the id is source-prefixed and
|
|
447
|
+
* self-contained, so `device-collection-dispatch.ts` rule 3 hands the call
|
|
448
|
+
* to the source that claims it — and an id nobody claims is REFUSED rather
|
|
449
|
+
* than answered by another source.
|
|
450
|
+
*
|
|
451
|
+
* The producer reuses the fetch path it already has, completion rules
|
|
452
|
+
* included: a clip is taken by cmd 5 and finished on a short idle window
|
|
453
|
+
* whose result is PROVED against the catalog row's own span, retried once
|
|
454
|
+
* when it comes up materially short, and served-and-named when it is still
|
|
455
|
+
* short (D568). A second fetch with different completion rules is exactly
|
|
456
|
+
* the second authority D558 refuses to create.
|
|
457
|
+
*
|
|
458
|
+
* Every refusal THROWS with its reason and none of them is silent — the
|
|
459
|
+
* sleep gate (decided before `getApi()`, liftable only by
|
|
460
|
+
* {@link ClipWakeSchema}), a catalog row nobody claims, a clip with no
|
|
461
|
+
* bytes behind it, a mux that failed, and the size bound. The caller turns
|
|
462
|
+
* that reason into an operator-facing one; a truncated file is never an
|
|
463
|
+
* answer.
|
|
464
|
+
*/
|
|
465
|
+
readonly readClipBytes: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
|
|
466
|
+
deviceId: z.ZodNumber;
|
|
467
|
+
clipId: z.ZodString;
|
|
468
|
+
profile: z.ZodOptional<z.ZodEnum<{
|
|
469
|
+
high: "high";
|
|
470
|
+
mid: "mid";
|
|
471
|
+
low: "low";
|
|
472
|
+
}>>;
|
|
473
|
+
maxBytes: z.ZodOptional<z.ZodNumber>;
|
|
474
|
+
wake: z.ZodOptional<z.ZodEnum<{
|
|
475
|
+
authorised: "authorised";
|
|
476
|
+
}>>;
|
|
477
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
478
|
+
base64: z.ZodString;
|
|
479
|
+
contentType: z.ZodString;
|
|
480
|
+
name: z.ZodString;
|
|
481
|
+
bytes: z.ZodNumber;
|
|
482
|
+
served: z.ZodEnum<{
|
|
483
|
+
high: "high";
|
|
484
|
+
mid: "mid";
|
|
485
|
+
low: "low";
|
|
486
|
+
}>;
|
|
487
|
+
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
488
|
+
}, z.core.$strip>, "query"> & {
|
|
489
|
+
readonly providerOptional: true;
|
|
490
|
+
};
|
|
361
491
|
};
|
|
362
492
|
};
|
|
363
493
|
export type IVideoclipsProvider = InferProvider<typeof videoclipsCapability>;
|
|
@@ -9080,6 +9080,13 @@ export type AppRouter = TrpcCoreRouter<{
|
|
|
9080
9080
|
output: z.infer<typeof videoclipsCapability.methods.getClipPlayback.output>;
|
|
9081
9081
|
meta: object;
|
|
9082
9082
|
}>;
|
|
9083
|
+
readClipBytes: TRPCQueryProcedure<{
|
|
9084
|
+
input: {
|
|
9085
|
+
[x: string]: unknown;
|
|
9086
|
+
} & z.input<typeof videoclipsCapability.methods.readClipBytes.input>;
|
|
9087
|
+
output: z.infer<typeof videoclipsCapability.methods.readClipBytes.output>;
|
|
9088
|
+
meta: object;
|
|
9089
|
+
}>;
|
|
9083
9090
|
}>>;
|
|
9084
9091
|
viewerUi: TRPCBuiltRouter<{
|
|
9085
9092
|
ctx: TrpcContext;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* scope+access check inside `protectedProcedure` (see
|
|
7
7
|
* `server/backend/src/api/trpc/trpc.middleware.ts`).
|
|
8
8
|
*
|
|
9
|
-
* Coverage:
|
|
9
|
+
* Coverage: 1059 method paths across 131 capabilities.
|
|
10
10
|
*/
|
|
11
11
|
import type { CapabilityMethodAccess } from '../capabilities/capability-definition.js';
|
|
12
12
|
export interface MethodAccessRecord {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* system-scope cap that takes a deviceId was previously never device-filtered
|
|
7
7
|
* — see the generator header).
|
|
8
8
|
*
|
|
9
|
-
* Coverage:
|
|
9
|
+
* Coverage: 391 methods carry a device reference, of which
|
|
10
10
|
* 141 are on SYSTEM-scope caps.
|
|
11
11
|
*
|
|
12
12
|
* Top-level fields, number arrays, and one-level arrays of objects carrying
|