@camstack/types 1.2.41 → 1.2.43
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/canonical-hash-7nfBbEqR.mjs +35 -0
- package/dist/canonical-hash-BcZHRHIx.js +40 -0
- package/dist/cap-call-context.d.ts +26 -0
- package/dist/capabilities/index.d.ts +5 -5
- package/dist/capabilities/notification-rules.cap.d.ts +41 -0
- package/dist/capabilities/pipeline-analytics.cap.d.ts +92 -4
- package/dist/capabilities/pipeline-orchestrator.cap.d.ts +149 -0
- package/dist/capabilities/pipeline-runner.cap.d.ts +119 -1
- package/dist/capabilities/platform-probe.cap.d.ts +3 -3
- package/dist/capabilities/privacy-mask.cap.d.ts +69 -9
- package/dist/capabilities/recording.cap.d.ts +30 -0
- package/dist/capabilities/snapshot.cap.d.ts +1 -1
- package/dist/capabilities/stream-broker.cap.d.ts +304 -0
- package/dist/capabilities/stream-params.cap.d.ts +8 -4
- package/dist/device/device-profile.d.ts +12 -4
- package/dist/device/system-mirror.d.ts +11 -0
- package/dist/encode-profile.d.ts +2 -0
- package/dist/ffmpeg/encode-defaults.d.ts +107 -0
- package/dist/ffmpeg/hwaccel.d.ts +98 -0
- package/dist/ffmpeg/invocation.d.ts +348 -0
- package/dist/ffmpeg/process.d.ts +135 -0
- package/dist/ffmpeg/sharing-key.d.ts +91 -0
- package/dist/generated/addon-api.d.ts +92 -4
- package/dist/generated/device-proxy.d.ts +2 -2
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/system-proxy.d.ts +2 -2
- package/dist/index.d.ts +7 -0
- package/dist/index.js +2069 -42
- package/dist/index.mjs +2006 -43
- package/dist/interfaces/camera-switches.d.ts +375 -0
- package/dist/interfaces/inference-engine.d.ts +24 -3
- package/dist/interfaces/ops-log.d.ts +4 -0
- package/dist/interfaces/pipeline-runner-capability.d.ts +9 -1
- package/dist/node.d.ts +2 -0
- package/dist/node.js +270 -36
- package/dist/node.mjs +269 -36
- package/dist/pipeline/native-lease.d.ts +150 -0
- package/dist/{sleep-DTce7-ch.js → sleep-Bx9IIoT0.js} +43 -1
- package/dist/{sleep-CXimb854.mjs → sleep-DtstvzWm.mjs} +38 -2
- package/dist/utils/addon-id.d.ts +30 -0
- package/package.json +1 -1
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-camera FUNCTION SWITCHES — the one coherent on/off surface over the
|
|
3
|
+
* pipeline functions an operator thinks in terms of.
|
|
4
|
+
*
|
|
5
|
+
* ## This file adds no state
|
|
6
|
+
*
|
|
7
|
+
* Every switch here is a VIEW onto an authority that already existed
|
|
8
|
+
* ([D62](../../../../docs/decisions/adr-0062.md)). The whole point of the
|
|
9
|
+
* group is that there is exactly one place each function is turned off, and
|
|
10
|
+
* the group routes to it:
|
|
11
|
+
*
|
|
12
|
+
* | Switch | Authority | Proven "off stops the work" gate |
|
|
13
|
+
* | --- | --- | --- |
|
|
14
|
+
* | `stream-broker` | `deviceManager.setDisabled` | `StreamBrokerManager.reconcileAllCatalogs` releases the brokers; `ensureBroker` refuses re-creation |
|
|
15
|
+
* | `object-detection` | `deviceManager.setWrapperActive('detection-pipeline')` | `PipelineSettingsStore.resolvePipelineForDevice` returns `{ steps: [], audio: null }` |
|
|
16
|
+
* | `audio-analysis` | `deviceManager.setWrapperActive('audio-analysis')` | `AudioSubscriptionController.subscribeAudioStream` returns `null` before opening the stream |
|
|
17
|
+
* | `recording` | `recording.setDeviceConfig` → `RecordingConfig.enabled` | `band-decision.shouldRecord` returns false; the controller detaches the device |
|
|
18
|
+
* | `notifications` | `notificationRules.setDeviceMuted` | `NotificationCenter.evaluateAndEnqueue` returns before any rule is evaluated |
|
|
19
|
+
* | `privacy-mask` | `privacyMask.setMask({ enabled })` → the CAMERA | the camera blanks the masked regions itself; every stream and recording carries the black boxes |
|
|
20
|
+
* | `device-audio` | `privacyMask.setAudioEnabled` → the CAMERA | the camera stops encoding an audio track at all; every consumer sees silent video |
|
|
21
|
+
*
|
|
22
|
+
* ## The two switches whose authority is not on this server
|
|
23
|
+
*
|
|
24
|
+
* `privacy-mask` and `device-audio` write the CAMERA. That is not a loophole
|
|
25
|
+
* in "the group stores nothing" — it is the purest form of it: the camera
|
|
26
|
+
* holds the fact, every read is a read-through, and there is no server-side
|
|
27
|
+
* copy that could drift. Their availability therefore cannot come from
|
|
28
|
+
* `listBindableCapsForDeviceType` (a device-NATIVE cap carries no wrappers and
|
|
29
|
+
* is filtered out there); it comes from the cap's own camera-probed
|
|
30
|
+
* `privacyMask.getOptions()`, which is strictly more honest — it answers for
|
|
31
|
+
* THIS camera rather than for the device type
|
|
32
|
+
* ([D74](../../../../docs/decisions/adr-0074.md)).
|
|
33
|
+
*
|
|
34
|
+
* ## `privacy-mask` is the one row whose ON is not "the function is working"
|
|
35
|
+
*
|
|
36
|
+
* Every other switch means *this camera's function is doing its job*, so
|
|
37
|
+
* `enabled: false` is a thing an operator took away. `privacy-mask` means **the
|
|
38
|
+
* MASK is active** — `enabled: true` is video deliberately obscured. The
|
|
39
|
+
* polarity is not a choice made here: `addon-export-hap`'s privacy `Switch`
|
|
40
|
+
* (`builders/privacy-switch.ts`) already mirrors `patch.enabled` verbatim, and
|
|
41
|
+
* a HomeKit toggle that disagreed with the app's toggle for the same camera is
|
|
42
|
+
* worse than either surface not having one.
|
|
43
|
+
*
|
|
44
|
+
* Two consequences follow and both are load-bearing:
|
|
45
|
+
*
|
|
46
|
+
* - **It never counts as `switchedOff`.** `countsAsSwitchedOff` is `false` for
|
|
47
|
+
* exactly this row. With the polarity above, every camera that has NOT drawn
|
|
48
|
+
* a privacy mask would otherwise report `switchedOff: ['privacy-mask']` — the
|
|
49
|
+
* normal, healthy state of most cameras rendered as an operator disablement.
|
|
50
|
+
* - **Its cost line names BOTH directions.** `costWhenOff` is rendered
|
|
51
|
+
* unconditionally by both clients, so for this row it has to read correctly
|
|
52
|
+
* whichever way the switch is sitting.
|
|
53
|
+
*
|
|
54
|
+
* The wrapper-binding pair is not a new idea: `legacy-migrations.ts` already
|
|
55
|
+
* migrated the legacy `audioEnabled` / `pipelineEnabled` /
|
|
56
|
+
* `motionDetectionEnabled` booleans ONTO `setWrapperActive`. The group is the
|
|
57
|
+
* surface that decision never got.
|
|
58
|
+
*
|
|
59
|
+
* ## Two rules that are load-bearing
|
|
60
|
+
*
|
|
61
|
+
* - **Recording's switch is `enabled`, never the bands.** `bands` is the only
|
|
62
|
+
* authored intent and `mode` is derived from it (`deriveRecordingMode`).
|
|
63
|
+
* Expressing "off" by clearing bands destroys the operator's schedule and
|
|
64
|
+
* turning the camera back on would then silently record nothing.
|
|
65
|
+
* - **A switch that is off must be reported as off**, not merely produce
|
|
66
|
+
* nothing. {@link CameraSwitch.enabled} is what a status surface renders as
|
|
67
|
+
* "disabled by an operator" instead of "broken" — see
|
|
68
|
+
* `CameraStatus.switchedOff`.
|
|
69
|
+
*/
|
|
70
|
+
import { z } from 'zod';
|
|
71
|
+
/**
|
|
72
|
+
* The functions the operator named — five on 2026-08-05, plus the camera's own
|
|
73
|
+
* microphone on 2026-08-07. Deliberately NOT one id per pipeline step: face
|
|
74
|
+
* recognition and plate/LPR are per-step toggles on
|
|
75
|
+
* `pipelineOrchestrator.setCameraStepToggle` and belong in the pipeline
|
|
76
|
+
* editor, not in a safety group.
|
|
77
|
+
*/
|
|
78
|
+
export declare const CameraSwitchIdSchema: z.ZodEnum<{
|
|
79
|
+
"privacy-mask": "privacy-mask";
|
|
80
|
+
"audio-analysis": "audio-analysis";
|
|
81
|
+
recording: "recording";
|
|
82
|
+
"stream-broker": "stream-broker";
|
|
83
|
+
notifications: "notifications";
|
|
84
|
+
"object-detection": "object-detection";
|
|
85
|
+
"device-audio": "device-audio";
|
|
86
|
+
}>;
|
|
87
|
+
export type CameraSwitchId = z.infer<typeof CameraSwitchIdSchema>;
|
|
88
|
+
/**
|
|
89
|
+
* Stable render order — broadest blast radius first, and a source before the
|
|
90
|
+
* thing that consumes it. `device-audio` sits ABOVE `audio-analysis` because
|
|
91
|
+
* turning the microphone off leaves the analyzer with nothing to analyse; the
|
|
92
|
+
* reverse is not true.
|
|
93
|
+
*
|
|
94
|
+
* `privacy-mask` sits directly ABOVE `device-audio` because they are literal
|
|
95
|
+
* siblings — one cap, one device plane, video then audio — and NOT above
|
|
96
|
+
* `object-detection` despite feeding it: a mask blanks REGIONS, so its blast
|
|
97
|
+
* radius is partial, and the "broadest first" rule does not rank a partial
|
|
98
|
+
* control above a whole-function one.
|
|
99
|
+
*/
|
|
100
|
+
export declare const CAMERA_SWITCH_ORDER: readonly CameraSwitchId[];
|
|
101
|
+
/**
|
|
102
|
+
* WHERE the switch's state actually lives. A discriminated union rather than a
|
|
103
|
+
* string so both the writer (the orchestrator's `setCameraSwitch`) and any
|
|
104
|
+
* reader can exhaustively narrow — and so "the group added a parallel map" is
|
|
105
|
+
* a compile error rather than a review comment.
|
|
106
|
+
*/
|
|
107
|
+
export declare const CameraSwitchAuthoritySchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
108
|
+
kind: z.ZodLiteral<"device-disabled">;
|
|
109
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
110
|
+
kind: z.ZodLiteral<"wrapper-binding">;
|
|
111
|
+
capName: z.ZodString;
|
|
112
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
113
|
+
kind: z.ZodLiteral<"recording-config">;
|
|
114
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
115
|
+
kind: z.ZodLiteral<"notification-mute">;
|
|
116
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
117
|
+
kind: z.ZodLiteral<"camera-audio">;
|
|
118
|
+
capName: z.ZodString;
|
|
119
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
120
|
+
kind: z.ZodLiteral<"camera-mask">;
|
|
121
|
+
capName: z.ZodString;
|
|
122
|
+
}, z.core.$strip>], "kind">;
|
|
123
|
+
export type CameraSwitchAuthority = z.infer<typeof CameraSwitchAuthoritySchema>;
|
|
124
|
+
/**
|
|
125
|
+
* Why a switch is not offered for this camera. Rendered instead of the
|
|
126
|
+
* control, never as a dead control — an absent function and a broken one must
|
|
127
|
+
* not look the same.
|
|
128
|
+
*/
|
|
129
|
+
export declare const CameraSwitchUnavailableReasonSchema: z.ZodEnum<{
|
|
130
|
+
"no-provider": "no-provider";
|
|
131
|
+
"source-unreachable": "source-unreachable";
|
|
132
|
+
"not-configured": "not-configured";
|
|
133
|
+
}>;
|
|
134
|
+
export type CameraSwitchUnavailableReason = z.infer<typeof CameraSwitchUnavailableReasonSchema>;
|
|
135
|
+
/**
|
|
136
|
+
* One switch, resolved for one camera.
|
|
137
|
+
*
|
|
138
|
+
* `label` and `costWhenOff` travel ON THE WIRE rather than being looked up
|
|
139
|
+
* client-side: the viewer is a separate repository that does not import
|
|
140
|
+
* `@camstack/types`, and a cost line duplicated in two clients is a cost line
|
|
141
|
+
* that will disagree with itself. Five rows per camera is nothing.
|
|
142
|
+
*/
|
|
143
|
+
export declare const CameraSwitchSchema: z.ZodObject<{
|
|
144
|
+
id: z.ZodEnum<{
|
|
145
|
+
"privacy-mask": "privacy-mask";
|
|
146
|
+
"audio-analysis": "audio-analysis";
|
|
147
|
+
recording: "recording";
|
|
148
|
+
"stream-broker": "stream-broker";
|
|
149
|
+
notifications: "notifications";
|
|
150
|
+
"object-detection": "object-detection";
|
|
151
|
+
"device-audio": "device-audio";
|
|
152
|
+
}>;
|
|
153
|
+
label: z.ZodString;
|
|
154
|
+
costWhenOff: z.ZodString;
|
|
155
|
+
available: z.ZodBoolean;
|
|
156
|
+
unavailableReason: z.ZodOptional<z.ZodEnum<{
|
|
157
|
+
"no-provider": "no-provider";
|
|
158
|
+
"source-unreachable": "source-unreachable";
|
|
159
|
+
"not-configured": "not-configured";
|
|
160
|
+
}>>;
|
|
161
|
+
enabled: z.ZodBoolean;
|
|
162
|
+
authority: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
163
|
+
kind: z.ZodLiteral<"device-disabled">;
|
|
164
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
165
|
+
kind: z.ZodLiteral<"wrapper-binding">;
|
|
166
|
+
capName: z.ZodString;
|
|
167
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
168
|
+
kind: z.ZodLiteral<"recording-config">;
|
|
169
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
170
|
+
kind: z.ZodLiteral<"notification-mute">;
|
|
171
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
172
|
+
kind: z.ZodLiteral<"camera-audio">;
|
|
173
|
+
capName: z.ZodString;
|
|
174
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
175
|
+
kind: z.ZodLiteral<"camera-mask">;
|
|
176
|
+
capName: z.ZodString;
|
|
177
|
+
}, z.core.$strip>], "kind">;
|
|
178
|
+
}, z.core.$strip>;
|
|
179
|
+
export type CameraSwitch = z.infer<typeof CameraSwitchSchema>;
|
|
180
|
+
/** The whole group for one camera. */
|
|
181
|
+
export declare const CameraSwitchGroupSchema: z.ZodObject<{
|
|
182
|
+
deviceId: z.ZodNumber;
|
|
183
|
+
switches: z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
184
|
+
id: z.ZodEnum<{
|
|
185
|
+
"privacy-mask": "privacy-mask";
|
|
186
|
+
"audio-analysis": "audio-analysis";
|
|
187
|
+
recording: "recording";
|
|
188
|
+
"stream-broker": "stream-broker";
|
|
189
|
+
notifications: "notifications";
|
|
190
|
+
"object-detection": "object-detection";
|
|
191
|
+
"device-audio": "device-audio";
|
|
192
|
+
}>;
|
|
193
|
+
label: z.ZodString;
|
|
194
|
+
costWhenOff: z.ZodString;
|
|
195
|
+
available: z.ZodBoolean;
|
|
196
|
+
unavailableReason: z.ZodOptional<z.ZodEnum<{
|
|
197
|
+
"no-provider": "no-provider";
|
|
198
|
+
"source-unreachable": "source-unreachable";
|
|
199
|
+
"not-configured": "not-configured";
|
|
200
|
+
}>>;
|
|
201
|
+
enabled: z.ZodBoolean;
|
|
202
|
+
authority: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
203
|
+
kind: z.ZodLiteral<"device-disabled">;
|
|
204
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
205
|
+
kind: z.ZodLiteral<"wrapper-binding">;
|
|
206
|
+
capName: z.ZodString;
|
|
207
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
208
|
+
kind: z.ZodLiteral<"recording-config">;
|
|
209
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
210
|
+
kind: z.ZodLiteral<"notification-mute">;
|
|
211
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
212
|
+
kind: z.ZodLiteral<"camera-audio">;
|
|
213
|
+
capName: z.ZodString;
|
|
214
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
215
|
+
kind: z.ZodLiteral<"camera-mask">;
|
|
216
|
+
capName: z.ZodString;
|
|
217
|
+
}, z.core.$strip>], "kind">;
|
|
218
|
+
}, z.core.$strip>>>;
|
|
219
|
+
fetchedAt: z.ZodNumber;
|
|
220
|
+
}, z.core.$strip>;
|
|
221
|
+
export type CameraSwitchGroup = z.infer<typeof CameraSwitchGroupSchema>;
|
|
222
|
+
/**
|
|
223
|
+
* The wrapper capability each wrapper-backed switch controls. Named constants
|
|
224
|
+
* because the same strings appear in `legacy-migrations.ts`, in
|
|
225
|
+
* `isCapActiveForDevice` call sites and in the fake harness — a typo in any of
|
|
226
|
+
* them is a switch that silently writes a binding nobody reads.
|
|
227
|
+
*/
|
|
228
|
+
export declare const DETECTION_PIPELINE_CAP_NAME = "detection-pipeline";
|
|
229
|
+
export declare const AUDIO_ANALYSIS_CAP_NAME = "audio-analysis";
|
|
230
|
+
/**
|
|
231
|
+
* The device-NATIVE cap that owns what the camera does not capture — masked
|
|
232
|
+
* video regions and, since 2026-08-07, the microphone. Named here because the
|
|
233
|
+
* `camera-audio` authority, the orchestrator's gather and the fake harness all
|
|
234
|
+
* have to agree on it.
|
|
235
|
+
*/
|
|
236
|
+
export declare const PRIVACY_MASK_CAP_NAME = "privacy-mask";
|
|
237
|
+
/** Static half of a switch: everything that does not depend on a device. */
|
|
238
|
+
export interface CameraSwitchDescriptor {
|
|
239
|
+
readonly id: CameraSwitchId;
|
|
240
|
+
readonly label: string;
|
|
241
|
+
readonly costWhenOff: string;
|
|
242
|
+
readonly authority: CameraSwitchAuthority;
|
|
243
|
+
/**
|
|
244
|
+
* May `enabled: false` on this row appear in {@link switchedOffIds}?
|
|
245
|
+
*
|
|
246
|
+
* `true` for every switch that means "this camera's function is doing its
|
|
247
|
+
* job", where OFF is something a person took away and a status surface must
|
|
248
|
+
* render as disabled rather than broken.
|
|
249
|
+
*
|
|
250
|
+
* `false` for `privacy-mask` alone, and only because its polarity is
|
|
251
|
+
* inverted: OFF there means the mask is not obscuring anything, which is the
|
|
252
|
+
* ordinary state of nearly every camera. Reporting it would put a
|
|
253
|
+
* `switchedOff` badge on healthy cameras and drown the badge that matters.
|
|
254
|
+
*/
|
|
255
|
+
readonly countsAsSwitchedOff: boolean;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* THE catalog. One entry per switch; the cost lines are the operator-facing
|
|
259
|
+
* contract and are written to be true rather than reassuring.
|
|
260
|
+
*/
|
|
261
|
+
export declare const CAMERA_SWITCH_CATALOG: Readonly<Record<CameraSwitchId, CameraSwitchDescriptor>>;
|
|
262
|
+
/**
|
|
263
|
+
* Everything the pure derivation needs, gathered by the caller. A `null`
|
|
264
|
+
* sub-state means the owning source did not answer — which produces
|
|
265
|
+
* `available: false` with `source-unreachable`, NEVER a control defaulted to
|
|
266
|
+
* "on". Guessing a switch is on when we could not read it is how an operator
|
|
267
|
+
* learns a function is off a week later.
|
|
268
|
+
*/
|
|
269
|
+
export interface CameraSwitchDerivationInput {
|
|
270
|
+
readonly deviceId: number;
|
|
271
|
+
/** `deviceManager` soft-disable flag for this device. */
|
|
272
|
+
readonly deviceDisabled: boolean;
|
|
273
|
+
/**
|
|
274
|
+
* Capability names bindable for this device's TYPE
|
|
275
|
+
* (`deviceManager.listBindableCapsForDeviceType`). This is what makes the
|
|
276
|
+
* group derived rather than hardcoded: a deployment with no audio analyzer
|
|
277
|
+
* has no `audio-analysis` here, so no audio switch is rendered.
|
|
278
|
+
* `null` = the lookup failed.
|
|
279
|
+
*/
|
|
280
|
+
readonly bindableCapNames: readonly string[] | null;
|
|
281
|
+
/**
|
|
282
|
+
* Capability names currently bound `kind: 'wrapped'` for this device
|
|
283
|
+
* (`deviceManager.getBindings`). Absence IS how a deactivated wrapper is
|
|
284
|
+
* represented — there is no `active: false` row.
|
|
285
|
+
*/
|
|
286
|
+
readonly activeWrapperCapNames: readonly string[] | null;
|
|
287
|
+
/** `RecordingConfig.enabled`; `null` when the recording cap did not answer. */
|
|
288
|
+
readonly recordingEnabled: boolean | null;
|
|
289
|
+
/** `notificationRules` per-camera mute; `null` when the cap did not answer. */
|
|
290
|
+
readonly notificationsMuted: boolean | null;
|
|
291
|
+
/**
|
|
292
|
+
* The camera's own microphone, read through the `privacy-mask` native cap.
|
|
293
|
+
* `null` = the cap is bound to this camera but did not answer.
|
|
294
|
+
*
|
|
295
|
+
* A camera with no `privacy-mask` provider at all is `{ supported: false }`,
|
|
296
|
+
* not `null` — "this camera has no such control" and "we could not read it"
|
|
297
|
+
* are different answers and the operator is shown different copy for each.
|
|
298
|
+
*/
|
|
299
|
+
readonly deviceAudio: DeviceAudioSwitchState | null;
|
|
300
|
+
/**
|
|
301
|
+
* The camera's own VIDEO privacy mask, read through the same `privacy-mask`
|
|
302
|
+
* native cap and the same pair of round trips as {@link deviceAudio} — one
|
|
303
|
+
* `getOptions` + one `getStatus` answer both, so the second switch is free.
|
|
304
|
+
*
|
|
305
|
+
* `null` = the cap is bound to this camera but did not answer.
|
|
306
|
+
*/
|
|
307
|
+
readonly privacyMask: PrivacyMaskSwitchState | null;
|
|
308
|
+
}
|
|
309
|
+
/** What the camera-probed audio switch reported for one camera. */
|
|
310
|
+
export interface DeviceAudioSwitchState {
|
|
311
|
+
/**
|
|
312
|
+
* `privacyMask.getOptions().supportsAudioMute` — camera-probed, never a
|
|
313
|
+
* device-type guess. A camera that does not expose the control renders no
|
|
314
|
+
* switch rather than a toggle that silently does nothing.
|
|
315
|
+
*/
|
|
316
|
+
readonly supported: boolean;
|
|
317
|
+
/**
|
|
318
|
+
* `privacyMask.getStatus().audioEnabled` — the camera's current answer.
|
|
319
|
+
* `null` when unsupported, or when supported but unreadable; the second
|
|
320
|
+
* case yields `source-unreachable`, never a control defaulted to "on".
|
|
321
|
+
*/
|
|
322
|
+
readonly enabled: boolean | null;
|
|
323
|
+
}
|
|
324
|
+
/** What the camera-probed VIDEO privacy mask reported for one camera. */
|
|
325
|
+
export interface PrivacyMaskSwitchState {
|
|
326
|
+
/**
|
|
327
|
+
* Can this camera store privacy zones at all? Derived from the probed
|
|
328
|
+
* `getOptions()`: `maxRegions > 0` AND at least one supported shape kind.
|
|
329
|
+
* Reolink answers `maxNum: 0` / `supportedShapes: []` honestly on models
|
|
330
|
+
* that cannot, and that must render no control rather than a toggle whose
|
|
331
|
+
* write the camera discards.
|
|
332
|
+
*/
|
|
333
|
+
readonly supported: boolean;
|
|
334
|
+
/**
|
|
335
|
+
* How many zones are actually drawn on the camera right now
|
|
336
|
+
* (`getStatus().regions.length`). `null` = supported, but the status could
|
|
337
|
+
* not be read.
|
|
338
|
+
*
|
|
339
|
+
* **Zero is not "off", it is "nothing to switch".** Toggling the master
|
|
340
|
+
* enable with no zones changes not one pixel — the dead control D62 exists
|
|
341
|
+
* to remove — so it resolves to `not-configured`, which tells the operator
|
|
342
|
+
* to go and draw one instead of leaving them pressing a button.
|
|
343
|
+
*/
|
|
344
|
+
readonly configuredRegions: number | null;
|
|
345
|
+
/**
|
|
346
|
+
* `getStatus().enabled` — the camera's master mask flag, `true` when the
|
|
347
|
+
* zones are being blanked. `null` when unreadable; never defaulted.
|
|
348
|
+
*/
|
|
349
|
+
readonly enabled: boolean | null;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Pure derivation of the whole group. No I/O — the orchestrator gathers, this
|
|
353
|
+
* decides, so the decision is testable without a hub.
|
|
354
|
+
*
|
|
355
|
+
* Order is {@link CAMERA_SWITCH_ORDER}; unavailable switches are RETURNED
|
|
356
|
+
* rather than filtered out, so a client can explain the gap instead of
|
|
357
|
+
* silently rendering four buttons where another camera shows five.
|
|
358
|
+
*/
|
|
359
|
+
export declare function deriveCameraSwitches(input: CameraSwitchDerivationInput): readonly CameraSwitch[];
|
|
360
|
+
/**
|
|
361
|
+
* The ids an operator has switched OFF, for a status surface.
|
|
362
|
+
*
|
|
363
|
+
* This is the answer to "a disabled function must be visible as DISABLED, not
|
|
364
|
+
* merely quiet": a camera reporting zero detections with
|
|
365
|
+
* `switchedOff: ['object-detection']` was turned off; the same camera with an
|
|
366
|
+
* empty list is broken. Unavailable switches never appear — a function nobody
|
|
367
|
+
* provides was not switched off by anyone.
|
|
368
|
+
*
|
|
369
|
+
* `privacy-mask` never appears either, whichever way it is sitting, because its
|
|
370
|
+
* ON means "the mask is active" rather than "the function works"
|
|
371
|
+
* ({@link CameraSwitchDescriptor.countsAsSwitchedOff}). Without that filter the
|
|
372
|
+
* ordinary state of every camera nobody has masked would carry a
|
|
373
|
+
* "switched off" badge, and the badge that matters would be lost in it.
|
|
374
|
+
*/
|
|
375
|
+
export declare function switchedOffIds(switches: readonly CameraSwitch[]): readonly CameraSwitchId[];
|
|
@@ -16,16 +16,36 @@ import type { RawFrameFormat } from '../types/io.js';
|
|
|
16
16
|
* raw buffer to JPEG internally rather than throwing — `infer()` must
|
|
17
17
|
* always succeed for either kind.
|
|
18
18
|
*/
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Fields every `InferenceInput` variant carries regardless of pixel transport.
|
|
21
|
+
*/
|
|
22
|
+
interface InferenceInputCommon {
|
|
23
|
+
/**
|
|
24
|
+
* The camera this frame belongs to — **diagnostic only**. It changes no
|
|
25
|
+
* dispatch decision, no deadline and no shed rule; it exists so an inference
|
|
26
|
+
* failure inside a SHARED pool can name the camera that paid for it.
|
|
27
|
+
*
|
|
28
|
+
* A `SharedInferencePool` serves every camera on its
|
|
29
|
+
* `(node, runtime, device)`, so its `inference request timed out` and
|
|
30
|
+
* `worker saturated` lines could describe the pool and nothing else — and
|
|
31
|
+
* "why is 617 worse than 615?" is the question those lines always get asked.
|
|
32
|
+
*
|
|
33
|
+
* Omitted by callers with no camera (commands, model loads, the benchmark);
|
|
34
|
+
* the failure line then carries no `deviceId` tag rather than a fabricated
|
|
35
|
+
* one.
|
|
36
|
+
*/
|
|
37
|
+
readonly deviceId?: number;
|
|
38
|
+
}
|
|
39
|
+
export type InferenceInput = ({
|
|
20
40
|
readonly kind: 'jpeg';
|
|
21
41
|
readonly data: Buffer;
|
|
22
|
-
} | {
|
|
42
|
+
} & InferenceInputCommon) | ({
|
|
23
43
|
readonly kind: 'raw';
|
|
24
44
|
readonly data: Buffer;
|
|
25
45
|
readonly width: number;
|
|
26
46
|
readonly height: number;
|
|
27
47
|
readonly format: RawFrameFormat;
|
|
28
|
-
};
|
|
48
|
+
} & InferenceInputCommon);
|
|
29
49
|
export interface IInferenceEngine {
|
|
30
50
|
readonly runtime: DetectionRuntime;
|
|
31
51
|
readonly device: DetectionDevice;
|
|
@@ -34,3 +54,4 @@ export interface IInferenceEngine {
|
|
|
34
54
|
run?(input: Float32Array, inputShape: readonly number[]): Promise<Float32Array>;
|
|
35
55
|
dispose(): Promise<void>;
|
|
36
56
|
}
|
|
57
|
+
export {};
|
|
@@ -23,6 +23,7 @@ export declare const OpsLogOpSchema: z.ZodEnum<{
|
|
|
23
23
|
rescan: "rescan";
|
|
24
24
|
"retention-run": "retention-run";
|
|
25
25
|
relocate: "relocate";
|
|
26
|
+
"orphan-audit": "orphan-audit";
|
|
26
27
|
}>;
|
|
27
28
|
export type OpsLogOp = z.infer<typeof OpsLogOpSchema>;
|
|
28
29
|
/** Why the operation ran. */
|
|
@@ -31,6 +32,7 @@ export declare const OpsLogReasonSchema: z.ZodEnum<{
|
|
|
31
32
|
operator: "operator";
|
|
32
33
|
retention: "retention";
|
|
33
34
|
quota: "quota";
|
|
35
|
+
maintenance: "maintenance";
|
|
34
36
|
}>;
|
|
35
37
|
export type OpsLogReason = z.infer<typeof OpsLogReasonSchema>;
|
|
36
38
|
/** One audit row, shared verbatim by both domains. */
|
|
@@ -47,12 +49,14 @@ export declare const OpsLogEntrySchema: z.ZodObject<{
|
|
|
47
49
|
rescan: "rescan";
|
|
48
50
|
"retention-run": "retention-run";
|
|
49
51
|
relocate: "relocate";
|
|
52
|
+
"orphan-audit": "orphan-audit";
|
|
50
53
|
}>;
|
|
51
54
|
reason: z.ZodEnum<{
|
|
52
55
|
manual: "manual";
|
|
53
56
|
operator: "operator";
|
|
54
57
|
retention: "retention";
|
|
55
58
|
quota: "quota";
|
|
59
|
+
maintenance: "maintenance";
|
|
56
60
|
}>;
|
|
57
61
|
deviceId: z.ZodNullable<z.ZodNumber>;
|
|
58
62
|
nodeId: z.ZodString;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { OrchestratorMetrics, CameraMetrics } from './api-shared.js';
|
|
2
1
|
import type { PipelineStepInputOutput } from '../capabilities/pipeline-executor.cap.js';
|
|
3
2
|
import type { Zone } from '../capabilities/zones.cap.js';
|
|
4
3
|
import type { PipelinePhaseMode } from '../device/device-profile.js';
|
|
4
|
+
import type { CameraMetrics, OrchestratorMetrics } from './api-shared.js';
|
|
5
5
|
/**
|
|
6
6
|
* Camera assignment payload sent by the pipeline-orchestrator to a runner
|
|
7
7
|
* via `attachCamera`. Carries everything the runner needs to subscribe to
|
|
@@ -204,4 +204,12 @@ export interface IPipelineRunnerProvider {
|
|
|
204
204
|
* `null` when neither `frameHandle` nor `cropJpeg` resolves to a crop.
|
|
205
205
|
*/
|
|
206
206
|
runDetailSubtree(input: import('../capabilities/pipeline-runner.cap.js').RunDetailSubtreeInput): Promise<import('../capabilities/pipeline-runner.cap.js').RunDetailSubtreeResult | null>;
|
|
207
|
+
/**
|
|
208
|
+
* Run ONE enrichment step against caller-supplied pixels with NO camera
|
|
209
|
+
* session — no attach, no handle, no device affinity. See
|
|
210
|
+
* `pipelineRunnerCapability.runStatelessStep`
|
|
211
|
+
* (`capabilities/pipeline-runner.cap.ts`) for the full contract, including
|
|
212
|
+
* why the model pin is refused rather than substituted.
|
|
213
|
+
*/
|
|
214
|
+
runStatelessStep(input: import('../capabilities/pipeline-runner.cap.js').RunStatelessStepInput): Promise<import('../capabilities/pipeline-runner.cap.js').RunStatelessStepResult>;
|
|
207
215
|
}
|
package/dist/node.d.ts
CHANGED
|
@@ -6,3 +6,5 @@ export { FilesystemStorageProvider } from './storage/filesystem-storage-provider
|
|
|
6
6
|
export { canonicalHash } from './utils/canonical-hash.js';
|
|
7
7
|
export { canonicalDeviceFingerprint, diffExportTargets, resolveExportFingerprint, } from './utils/export-reconciler.js';
|
|
8
8
|
export type { DeviceExportShape, ExportDelta, ExportTargetEntry, } from './utils/export-reconciler.js';
|
|
9
|
+
export { FfmpegProcess } from './ffmpeg/process.js';
|
|
10
|
+
export type { FfmpegProcessOptions, FfmpegExit, FfmpegExitClass } from './ffmpeg/process.js';
|