@camstack/addon-pipeline 1.2.43 → 1.2.44

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.
Files changed (37) hide show
  1. package/dist/audio-analyzer/index.js +1 -1
  2. package/dist/audio-analyzer/index.mjs +1 -1
  3. package/dist/detection-pipeline/index.js +157 -81
  4. package/dist/detection-pipeline/index.mjs +157 -81
  5. package/dist/{dist-UHbKZiSa.js → dist-BuFE5rOK.js} +724 -39
  6. package/dist/{dist-B-VVBzrL.mjs → dist-DOu93i_g.mjs} +659 -40
  7. package/dist/{event-loop-stall-monitor-DfKdC7G4.mjs → event-loop-stall-monitor-CShgQE6l.mjs} +40 -2
  8. package/dist/{event-loop-stall-monitor-C7_L6vHO.js → event-loop-stall-monitor-L08yG6bB.js} +40 -2
  9. package/dist/motion-wasm/index.js +1 -1
  10. package/dist/motion-wasm/index.mjs +1 -1
  11. package/dist/pipeline-runner/index.js +342 -69
  12. package/dist/pipeline-runner/index.mjs +342 -69
  13. package/dist/recorder/index.js +189 -6
  14. package/dist/recorder/index.mjs +189 -6
  15. package/dist/session-decode/decode-worker-child.js +197 -24
  16. package/dist/session-decode/decode-worker-child.mjs +197 -24
  17. package/dist/stream-broker/_stub.js +2 -2
  18. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-D7iQbuKY.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DiXoZnou.mjs} +2 -2
  19. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BRc-m6W-.mjs +26 -0
  20. package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-54IklEep.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-B_hakWAb.mjs} +1 -1
  21. package/dist/stream-broker/{hostInit-CKYS9yZO.mjs → hostInit-khRXMnjl.mjs} +2 -2
  22. package/dist/stream-broker/index.js +3952 -1103
  23. package/dist/stream-broker/index.mjs +3953 -1104
  24. package/dist/stream-broker/remoteEntry.js +1 -1
  25. package/dist/worker-protocol-BOXlUhWO.mjs +244 -0
  26. package/dist/worker-protocol-VURr0nUh.js +279 -0
  27. package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-DxZ75vB8.js → MaskShapeCanvas-DI4BY7W2-DHZuYYjH.js} +1 -1
  28. package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-BBY2Ztz5.js → MotionZonesSettings-NcxxQN8r-jFDOzPCD.js} +1 -1
  29. package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-BC-3QmHa.js → PrivacyMaskSettings-APgPLF7p-BPBXgIX8.js} +1 -1
  30. package/embed-dist/assets/{index-on1wyOnd.js → index-4CtQAybX.js} +12 -12
  31. package/embed-dist/assets/index-DC63og2c.css +2 -0
  32. package/embed-dist/index.html +2 -2
  33. package/package.json +1 -1
  34. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CCC9fqHH.mjs +0 -26
  35. package/dist/worker-protocol-D7RzZIla.mjs +0 -77
  36. package/dist/worker-protocol-DextwlTX.js +0 -94
  37. package/embed-dist/assets/index-CGdwTcwE.css +0 -2
@@ -30,7 +30,7 @@ async function d(e) {
30
30
  }
31
31
  }
32
32
  async function f() {
33
- return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-D7iQbuKY.mjs")).catch((e) => {
33
+ return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DiXoZnou.mjs")).catch((e) => {
34
34
  throw l = void 0, e;
35
35
  }), l;
36
36
  }
@@ -0,0 +1,244 @@
1
+ import { g as NativeLeaseSettingsSchema, h as NativeLeaseAdmissionSchema, l as DEFAULT_NATIVE_LEASE_SETTINGS } from "./dist-DOu93i_g.mjs";
2
+ //#region src/session-decode/native-lease-config.ts
3
+ /**
4
+ * Resolution of the native-frame lease knobs for one decode worker.
5
+ *
6
+ * ## Where the values come from
7
+ *
8
+ * The knobs are cluster-wide `pipeline-orchestrator` settings
9
+ * (`@camstack/types` → `pipeline/native-lease.ts`). The pipeline-runner reads
10
+ * them over the hub-routed `addon-settings` cap
11
+ * (`pipeline-runner/native-lease-settings-source.ts`) and injects the ones the
12
+ * operator actually SET into the child's environment at `fork` time
13
+ * ({@link nativeLeaseSettingEnv}, consumed by `fork-decode-worker.ts`). The
14
+ * child resolves them at module load ({@link resolveNativeLeaseKnobs}).
15
+ *
16
+ * Env-on-fork rather than an init message on purpose: the lease store and the
17
+ * demand gate are constructed with the worker, before the first `start` message
18
+ * arrives, and a knob that can change after construction is a knob that has two
19
+ * values during a session.
20
+ *
21
+ * ## Precedence — setting > env > default
22
+ *
23
+ * 1. **setting** — the operator set the knob in the orchestrator's global
24
+ * settings. Wins, because a value someone deliberately chose in the UI must
25
+ * not be silently overruled by a shell variable nobody can see from there.
26
+ * 2. **env** — {@link NATIVE_LEASE_ENV_VARS}, the pre-settings mechanism, kept
27
+ * as an emergency / dev override. It applies only while the corresponding
28
+ * setting is UNSET. "Unset" includes a knob sitting AT its shipped default:
29
+ * `addon-settings.getGlobalSettings` hydrates an unstored field with the
30
+ * schema default and offers no way to tell the two apart, so treating the
31
+ * default as a choice would have retired every env var on the day this
32
+ * shipped. Move the slider off the default and the setting takes over; move
33
+ * it back and the env var returns. See `readNativeLeaseOverride`.
34
+ * 3. **default** — {@link DEFAULT_NATIVE_LEASE_SETTINGS}, byte-for-byte the
35
+ * constants the worker shipped with.
36
+ *
37
+ * A value that fails its bounds at ANY level falls through to the next one
38
+ * rather than being clamped: clamping turns a typo into a number nobody chose,
39
+ * and this one governs how much RAM a busy camera holds.
40
+ *
41
+ * The GPU surface ring (`CAMSTACK_SESSION_NATIVE_CROP_RING`) is deliberately
42
+ * NOT here — see its docblock in `decode-worker-child.ts` for why it stays
43
+ * env-only.
44
+ */
45
+ /** Every knob, in the order the spawn line names them. */
46
+ var NATIVE_LEASE_KNOBS = [
47
+ "ttlMs",
48
+ "budgetMb",
49
+ "activityMs",
50
+ "admission"
51
+ ];
52
+ /** Emergency / dev override env vars (pre-settings; lowest precedence but the default). */
53
+ var NATIVE_LEASE_ENV_VARS = {
54
+ ttlMs: "CAMSTACK_SESSION_NATIVE_LEASE_TTL_MS",
55
+ budgetMb: "CAMSTACK_SESSION_NATIVE_LEASE_BUDGET_MB",
56
+ activityMs: "CAMSTACK_SESSION_NATIVE_LEASE_ACTIVITY_MS",
57
+ admission: "CAMSTACK_SESSION_NATIVE_LEASE_ADMISSION"
58
+ };
59
+ /**
60
+ * Env vars the PARENT writes at fork time to carry an operator setting into the
61
+ * child. Distinct names from {@link NATIVE_LEASE_ENV_VARS} so the child can tell
62
+ * "the operator chose this" from "a shell variable set this" and log the source
63
+ * honestly — with one shared name that distinction is unrecoverable.
64
+ */
65
+ var NATIVE_LEASE_SETTING_ENV_VARS = {
66
+ ttlMs: "CAMSTACK_SESSION_NATIVE_LEASE_TTL_MS_SETTING",
67
+ budgetMb: "CAMSTACK_SESSION_NATIVE_LEASE_BUDGET_MB_SETTING",
68
+ activityMs: "CAMSTACK_SESSION_NATIVE_LEASE_ACTIVITY_MS_SETTING",
69
+ admission: "CAMSTACK_SESSION_NATIVE_LEASE_ADMISSION_SETTING"
70
+ };
71
+ /**
72
+ * Parse one env value through the knob's own Zod bound. Returns `null` for
73
+ * absent, non-numeric, or out-of-bounds input — the caller then falls through
74
+ * to the next precedence level.
75
+ */
76
+ function parseKnob(knob, raw) {
77
+ if (raw === void 0 || raw.trim() === "") return null;
78
+ const parsed = NativeLeaseSettingsSchema.shape[knob].safeParse(Number(raw));
79
+ return parsed.success ? parsed.data : null;
80
+ }
81
+ /** {@link parseKnob} for the one knob whose value is a word, not a number. */
82
+ function parseAdmission(raw) {
83
+ if (raw === void 0) return null;
84
+ const parsed = NativeLeaseAdmissionSchema.safeParse(raw.trim());
85
+ return parsed.success ? parsed.data : null;
86
+ }
87
+ /** Resolve one NUMERIC knob across the three precedence levels. */
88
+ function resolveKnob(knob, env) {
89
+ const fromSetting = parseKnob(knob, env[NATIVE_LEASE_SETTING_ENV_VARS[knob]]);
90
+ if (fromSetting !== null) return {
91
+ value: fromSetting,
92
+ source: "setting"
93
+ };
94
+ const fromEnv = parseKnob(knob, env[NATIVE_LEASE_ENV_VARS[knob]]);
95
+ if (fromEnv !== null) return {
96
+ value: fromEnv,
97
+ source: "env"
98
+ };
99
+ return {
100
+ value: DEFAULT_NATIVE_LEASE_SETTINGS[knob],
101
+ source: "default"
102
+ };
103
+ }
104
+ /** {@link resolveKnob} for `admission`. Same precedence, different parser. */
105
+ function resolveAdmission(env) {
106
+ const fromSetting = parseAdmission(env[NATIVE_LEASE_SETTING_ENV_VARS.admission]);
107
+ if (fromSetting !== null) return {
108
+ value: fromSetting,
109
+ source: "setting"
110
+ };
111
+ const fromEnv = parseAdmission(env[NATIVE_LEASE_ENV_VARS.admission]);
112
+ if (fromEnv !== null) return {
113
+ value: fromEnv,
114
+ source: "env"
115
+ };
116
+ return {
117
+ value: DEFAULT_NATIVE_LEASE_SETTINGS.admission,
118
+ source: "default"
119
+ };
120
+ }
121
+ /** Resolve all four lease knobs from an environment. Pure. */
122
+ function resolveNativeLeaseKnobs(env) {
123
+ const ttlMs = resolveKnob("ttlMs", env);
124
+ const budgetMb = resolveKnob("budgetMb", env);
125
+ const activityMs = resolveKnob("activityMs", env);
126
+ const admission = resolveAdmission(env);
127
+ return {
128
+ values: {
129
+ ttlMs: ttlMs.value,
130
+ budgetMb: budgetMb.value,
131
+ activityMs: activityMs.value,
132
+ admission: admission.value
133
+ },
134
+ sources: {
135
+ ttlMs: ttlMs.source,
136
+ budgetMb: budgetMb.source,
137
+ activityMs: activityMs.source,
138
+ admission: admission.source
139
+ }
140
+ };
141
+ }
142
+ /**
143
+ * The env fragment the parent merges into a decode worker's `fork` environment.
144
+ * Emits ONLY the knobs the operator actually set — an empty result leaves the
145
+ * env override fully functional, which is the whole point of the distinction.
146
+ */
147
+ function nativeLeaseSettingEnv(override) {
148
+ const out = {};
149
+ for (const knob of NATIVE_LEASE_KNOBS) {
150
+ const value = override[knob];
151
+ if (value !== void 0) out[NATIVE_LEASE_SETTING_ENV_VARS[knob]] = String(value);
152
+ }
153
+ return out;
154
+ }
155
+ /**
156
+ * The one-line spawn diagnostic. Names the effective value AND its source for
157
+ * every knob: without the source, a log saying `ttlMs=2800` cannot distinguish
158
+ * "the operator's setting arrived" from "someone left a shell variable set", and
159
+ * a setting that silently fails to arrive is exactly the failure the distinct
160
+ * env-var names exist to make visible.
161
+ */
162
+ function formatNativeLeaseKnobs(resolved) {
163
+ const part = (knob) => `${knob}=${resolved.values[knob]} source=${resolved.sources[knob]}`;
164
+ return `native lease knobs — ${NATIVE_LEASE_KNOBS.map(part).join("; ")}`;
165
+ }
166
+ //#endregion
167
+ //#region src/session-decode/worker-protocol.ts
168
+ /**
169
+ * Classify a worker diagnostic line into a {@link WorkerLogLevel}. Failure /
170
+ * fault lines surface at `warn` (visible at the default log level so a
171
+ * native-crop failure is finally seen in `addons.getLogs`); routine
172
+ * provenance / transition / lifecycle lines stay `debug`. Pure + exported so
173
+ * the mapping is unit-testable without spawning a worker.
174
+ */
175
+ function logLevelForLine(line) {
176
+ return /\b(fail(?:ed|ure)?|error|exception|unhandled rejection|corrupt|EIO|EINVAL)\b/i.test(line) ? "warn" : "debug";
177
+ }
178
+ function isRecord(value) {
179
+ return typeof value === "object" && value !== null;
180
+ }
181
+ function isFiniteNumber(value) {
182
+ return typeof value === "number" && Number.isFinite(value);
183
+ }
184
+ function isWorkerFrameFormat(value) {
185
+ return value === "rgb" || value === "gray";
186
+ }
187
+ function isWorkerLogLevel(value) {
188
+ return value === "debug" || value === "info" || value === "warn" || value === "error";
189
+ }
190
+ function isWorkerCropRegion(value) {
191
+ return isRecord(value) && isFiniteNumber(value.left) && isFiniteNumber(value.top) && isFiniteNumber(value.width) && isFiniteNumber(value.height);
192
+ }
193
+ function isWorkerResizeTarget(value) {
194
+ return isRecord(value) && isFiniteNumber(value.width) && isFiniteNumber(value.height);
195
+ }
196
+ function isFrameImageOptions(value) {
197
+ if (!isRecord(value)) return false;
198
+ if (value.crop !== void 0 && !isWorkerCropRegion(value.crop)) return false;
199
+ if (value.resize !== void 0 && !isWorkerResizeTarget(value.resize)) return false;
200
+ if (value.format !== void 0 && !isWorkerFrameFormat(value.format)) return false;
201
+ return true;
202
+ }
203
+ function isNormalizedBbox(value) {
204
+ return isRecord(value) && isFiniteNumber(value.x) && isFiniteNumber(value.y) && isFiniteNumber(value.w) && isFiniteNumber(value.h);
205
+ }
206
+ function isVideoFrameSource(value) {
207
+ return isRecord(value) && typeof value.restreamUrl === "string" && isFiniteNumber(value.deviceId) && typeof value.codec === "string";
208
+ }
209
+ function isVideoFrameGenOptions(value) {
210
+ if (!isRecord(value)) return false;
211
+ if (value.fps !== void 0 && !isFiniteNumber(value.fps)) return false;
212
+ if (value.format !== void 0 && !isWorkerFrameFormat(value.format)) return false;
213
+ return true;
214
+ }
215
+ /** Discriminated-union guard for {@link WorkerRequest} — no `as` casts. */
216
+ function isWorkerRequest(value) {
217
+ if (!isRecord(value)) return false;
218
+ switch (value.kind) {
219
+ case "start": return isVideoFrameSource(value.source) && isVideoFrameGenOptions(value.opts);
220
+ case "pull": return true;
221
+ case "toBuffer": return isFiniteNumber(value.frameId) && (value.opts === void 0 || isFrameImageOptions(value.opts));
222
+ case "nativeCrop": return isFiniteNumber(value.requestId) && isFiniteNumber(value.frameId) && isNormalizedBbox(value.bbox) && (value.maxWidth === void 0 || isFiniteNumber(value.maxWidth));
223
+ case "releaseNativeLease":
224
+ case "markInferred": return isFiniteNumber(value.frameId);
225
+ case "stop": return true;
226
+ default: return false;
227
+ }
228
+ }
229
+ /** Discriminated-union guard for {@link WorkerReply} — no `as` casts. */
230
+ function isWorkerReply(value) {
231
+ if (!isRecord(value)) return false;
232
+ switch (value.kind) {
233
+ case "frame": return isFiniteNumber(value.frameId) && isFiniteNumber(value.timestamp) && isFiniteNumber(value.width) && isFiniteNumber(value.height) && isWorkerFrameFormat(value.format);
234
+ case "buffer": return isFiniteNumber(value.frameId) && value.bytes instanceof Uint8Array;
235
+ case "nativeCropResult": return isFiniteNumber(value.requestId) && value.bytes instanceof Uint8Array && isFiniteNumber(value.width) && isFiniteNumber(value.height);
236
+ case "nativeCropMiss": return isFiniteNumber(value.requestId) && (value.reason === void 0 || typeof value.reason === "string");
237
+ case "ended": return true;
238
+ case "error": return typeof value.message === "string" && (value.frameId === void 0 || isFiniteNumber(value.frameId));
239
+ case "log": return isWorkerLogLevel(value.level) && typeof value.message === "string";
240
+ default: return false;
241
+ }
242
+ }
243
+ //#endregion
244
+ export { nativeLeaseSettingEnv as a, formatNativeLeaseKnobs as i, isWorkerRequest as n, resolveNativeLeaseKnobs as o, logLevelForLine as r, isWorkerReply as t };
@@ -0,0 +1,279 @@
1
+ const require_dist = require("./dist-BuFE5rOK.js");
2
+ //#region src/session-decode/native-lease-config.ts
3
+ /**
4
+ * Resolution of the native-frame lease knobs for one decode worker.
5
+ *
6
+ * ## Where the values come from
7
+ *
8
+ * The knobs are cluster-wide `pipeline-orchestrator` settings
9
+ * (`@camstack/types` → `pipeline/native-lease.ts`). The pipeline-runner reads
10
+ * them over the hub-routed `addon-settings` cap
11
+ * (`pipeline-runner/native-lease-settings-source.ts`) and injects the ones the
12
+ * operator actually SET into the child's environment at `fork` time
13
+ * ({@link nativeLeaseSettingEnv}, consumed by `fork-decode-worker.ts`). The
14
+ * child resolves them at module load ({@link resolveNativeLeaseKnobs}).
15
+ *
16
+ * Env-on-fork rather than an init message on purpose: the lease store and the
17
+ * demand gate are constructed with the worker, before the first `start` message
18
+ * arrives, and a knob that can change after construction is a knob that has two
19
+ * values during a session.
20
+ *
21
+ * ## Precedence — setting > env > default
22
+ *
23
+ * 1. **setting** — the operator set the knob in the orchestrator's global
24
+ * settings. Wins, because a value someone deliberately chose in the UI must
25
+ * not be silently overruled by a shell variable nobody can see from there.
26
+ * 2. **env** — {@link NATIVE_LEASE_ENV_VARS}, the pre-settings mechanism, kept
27
+ * as an emergency / dev override. It applies only while the corresponding
28
+ * setting is UNSET. "Unset" includes a knob sitting AT its shipped default:
29
+ * `addon-settings.getGlobalSettings` hydrates an unstored field with the
30
+ * schema default and offers no way to tell the two apart, so treating the
31
+ * default as a choice would have retired every env var on the day this
32
+ * shipped. Move the slider off the default and the setting takes over; move
33
+ * it back and the env var returns. See `readNativeLeaseOverride`.
34
+ * 3. **default** — {@link DEFAULT_NATIVE_LEASE_SETTINGS}, byte-for-byte the
35
+ * constants the worker shipped with.
36
+ *
37
+ * A value that fails its bounds at ANY level falls through to the next one
38
+ * rather than being clamped: clamping turns a typo into a number nobody chose,
39
+ * and this one governs how much RAM a busy camera holds.
40
+ *
41
+ * The GPU surface ring (`CAMSTACK_SESSION_NATIVE_CROP_RING`) is deliberately
42
+ * NOT here — see its docblock in `decode-worker-child.ts` for why it stays
43
+ * env-only.
44
+ */
45
+ /** Every knob, in the order the spawn line names them. */
46
+ var NATIVE_LEASE_KNOBS = [
47
+ "ttlMs",
48
+ "budgetMb",
49
+ "activityMs",
50
+ "admission"
51
+ ];
52
+ /** Emergency / dev override env vars (pre-settings; lowest precedence but the default). */
53
+ var NATIVE_LEASE_ENV_VARS = {
54
+ ttlMs: "CAMSTACK_SESSION_NATIVE_LEASE_TTL_MS",
55
+ budgetMb: "CAMSTACK_SESSION_NATIVE_LEASE_BUDGET_MB",
56
+ activityMs: "CAMSTACK_SESSION_NATIVE_LEASE_ACTIVITY_MS",
57
+ admission: "CAMSTACK_SESSION_NATIVE_LEASE_ADMISSION"
58
+ };
59
+ /**
60
+ * Env vars the PARENT writes at fork time to carry an operator setting into the
61
+ * child. Distinct names from {@link NATIVE_LEASE_ENV_VARS} so the child can tell
62
+ * "the operator chose this" from "a shell variable set this" and log the source
63
+ * honestly — with one shared name that distinction is unrecoverable.
64
+ */
65
+ var NATIVE_LEASE_SETTING_ENV_VARS = {
66
+ ttlMs: "CAMSTACK_SESSION_NATIVE_LEASE_TTL_MS_SETTING",
67
+ budgetMb: "CAMSTACK_SESSION_NATIVE_LEASE_BUDGET_MB_SETTING",
68
+ activityMs: "CAMSTACK_SESSION_NATIVE_LEASE_ACTIVITY_MS_SETTING",
69
+ admission: "CAMSTACK_SESSION_NATIVE_LEASE_ADMISSION_SETTING"
70
+ };
71
+ /**
72
+ * Parse one env value through the knob's own Zod bound. Returns `null` for
73
+ * absent, non-numeric, or out-of-bounds input — the caller then falls through
74
+ * to the next precedence level.
75
+ */
76
+ function parseKnob(knob, raw) {
77
+ if (raw === void 0 || raw.trim() === "") return null;
78
+ const parsed = require_dist.NativeLeaseSettingsSchema.shape[knob].safeParse(Number(raw));
79
+ return parsed.success ? parsed.data : null;
80
+ }
81
+ /** {@link parseKnob} for the one knob whose value is a word, not a number. */
82
+ function parseAdmission(raw) {
83
+ if (raw === void 0) return null;
84
+ const parsed = require_dist.NativeLeaseAdmissionSchema.safeParse(raw.trim());
85
+ return parsed.success ? parsed.data : null;
86
+ }
87
+ /** Resolve one NUMERIC knob across the three precedence levels. */
88
+ function resolveKnob(knob, env) {
89
+ const fromSetting = parseKnob(knob, env[NATIVE_LEASE_SETTING_ENV_VARS[knob]]);
90
+ if (fromSetting !== null) return {
91
+ value: fromSetting,
92
+ source: "setting"
93
+ };
94
+ const fromEnv = parseKnob(knob, env[NATIVE_LEASE_ENV_VARS[knob]]);
95
+ if (fromEnv !== null) return {
96
+ value: fromEnv,
97
+ source: "env"
98
+ };
99
+ return {
100
+ value: require_dist.DEFAULT_NATIVE_LEASE_SETTINGS[knob],
101
+ source: "default"
102
+ };
103
+ }
104
+ /** {@link resolveKnob} for `admission`. Same precedence, different parser. */
105
+ function resolveAdmission(env) {
106
+ const fromSetting = parseAdmission(env[NATIVE_LEASE_SETTING_ENV_VARS.admission]);
107
+ if (fromSetting !== null) return {
108
+ value: fromSetting,
109
+ source: "setting"
110
+ };
111
+ const fromEnv = parseAdmission(env[NATIVE_LEASE_ENV_VARS.admission]);
112
+ if (fromEnv !== null) return {
113
+ value: fromEnv,
114
+ source: "env"
115
+ };
116
+ return {
117
+ value: require_dist.DEFAULT_NATIVE_LEASE_SETTINGS.admission,
118
+ source: "default"
119
+ };
120
+ }
121
+ /** Resolve all four lease knobs from an environment. Pure. */
122
+ function resolveNativeLeaseKnobs(env) {
123
+ const ttlMs = resolveKnob("ttlMs", env);
124
+ const budgetMb = resolveKnob("budgetMb", env);
125
+ const activityMs = resolveKnob("activityMs", env);
126
+ const admission = resolveAdmission(env);
127
+ return {
128
+ values: {
129
+ ttlMs: ttlMs.value,
130
+ budgetMb: budgetMb.value,
131
+ activityMs: activityMs.value,
132
+ admission: admission.value
133
+ },
134
+ sources: {
135
+ ttlMs: ttlMs.source,
136
+ budgetMb: budgetMb.source,
137
+ activityMs: activityMs.source,
138
+ admission: admission.source
139
+ }
140
+ };
141
+ }
142
+ /**
143
+ * The env fragment the parent merges into a decode worker's `fork` environment.
144
+ * Emits ONLY the knobs the operator actually set — an empty result leaves the
145
+ * env override fully functional, which is the whole point of the distinction.
146
+ */
147
+ function nativeLeaseSettingEnv(override) {
148
+ const out = {};
149
+ for (const knob of NATIVE_LEASE_KNOBS) {
150
+ const value = override[knob];
151
+ if (value !== void 0) out[NATIVE_LEASE_SETTING_ENV_VARS[knob]] = String(value);
152
+ }
153
+ return out;
154
+ }
155
+ /**
156
+ * The one-line spawn diagnostic. Names the effective value AND its source for
157
+ * every knob: without the source, a log saying `ttlMs=2800` cannot distinguish
158
+ * "the operator's setting arrived" from "someone left a shell variable set", and
159
+ * a setting that silently fails to arrive is exactly the failure the distinct
160
+ * env-var names exist to make visible.
161
+ */
162
+ function formatNativeLeaseKnobs(resolved) {
163
+ const part = (knob) => `${knob}=${resolved.values[knob]} source=${resolved.sources[knob]}`;
164
+ return `native lease knobs — ${NATIVE_LEASE_KNOBS.map(part).join("; ")}`;
165
+ }
166
+ //#endregion
167
+ //#region src/session-decode/worker-protocol.ts
168
+ /**
169
+ * Classify a worker diagnostic line into a {@link WorkerLogLevel}. Failure /
170
+ * fault lines surface at `warn` (visible at the default log level so a
171
+ * native-crop failure is finally seen in `addons.getLogs`); routine
172
+ * provenance / transition / lifecycle lines stay `debug`. Pure + exported so
173
+ * the mapping is unit-testable without spawning a worker.
174
+ */
175
+ function logLevelForLine(line) {
176
+ return /\b(fail(?:ed|ure)?|error|exception|unhandled rejection|corrupt|EIO|EINVAL)\b/i.test(line) ? "warn" : "debug";
177
+ }
178
+ function isRecord(value) {
179
+ return typeof value === "object" && value !== null;
180
+ }
181
+ function isFiniteNumber(value) {
182
+ return typeof value === "number" && Number.isFinite(value);
183
+ }
184
+ function isWorkerFrameFormat(value) {
185
+ return value === "rgb" || value === "gray";
186
+ }
187
+ function isWorkerLogLevel(value) {
188
+ return value === "debug" || value === "info" || value === "warn" || value === "error";
189
+ }
190
+ function isWorkerCropRegion(value) {
191
+ return isRecord(value) && isFiniteNumber(value.left) && isFiniteNumber(value.top) && isFiniteNumber(value.width) && isFiniteNumber(value.height);
192
+ }
193
+ function isWorkerResizeTarget(value) {
194
+ return isRecord(value) && isFiniteNumber(value.width) && isFiniteNumber(value.height);
195
+ }
196
+ function isFrameImageOptions(value) {
197
+ if (!isRecord(value)) return false;
198
+ if (value.crop !== void 0 && !isWorkerCropRegion(value.crop)) return false;
199
+ if (value.resize !== void 0 && !isWorkerResizeTarget(value.resize)) return false;
200
+ if (value.format !== void 0 && !isWorkerFrameFormat(value.format)) return false;
201
+ return true;
202
+ }
203
+ function isNormalizedBbox(value) {
204
+ return isRecord(value) && isFiniteNumber(value.x) && isFiniteNumber(value.y) && isFiniteNumber(value.w) && isFiniteNumber(value.h);
205
+ }
206
+ function isVideoFrameSource(value) {
207
+ return isRecord(value) && typeof value.restreamUrl === "string" && isFiniteNumber(value.deviceId) && typeof value.codec === "string";
208
+ }
209
+ function isVideoFrameGenOptions(value) {
210
+ if (!isRecord(value)) return false;
211
+ if (value.fps !== void 0 && !isFiniteNumber(value.fps)) return false;
212
+ if (value.format !== void 0 && !isWorkerFrameFormat(value.format)) return false;
213
+ return true;
214
+ }
215
+ /** Discriminated-union guard for {@link WorkerRequest} — no `as` casts. */
216
+ function isWorkerRequest(value) {
217
+ if (!isRecord(value)) return false;
218
+ switch (value.kind) {
219
+ case "start": return isVideoFrameSource(value.source) && isVideoFrameGenOptions(value.opts);
220
+ case "pull": return true;
221
+ case "toBuffer": return isFiniteNumber(value.frameId) && (value.opts === void 0 || isFrameImageOptions(value.opts));
222
+ case "nativeCrop": return isFiniteNumber(value.requestId) && isFiniteNumber(value.frameId) && isNormalizedBbox(value.bbox) && (value.maxWidth === void 0 || isFiniteNumber(value.maxWidth));
223
+ case "releaseNativeLease":
224
+ case "markInferred": return isFiniteNumber(value.frameId);
225
+ case "stop": return true;
226
+ default: return false;
227
+ }
228
+ }
229
+ /** Discriminated-union guard for {@link WorkerReply} — no `as` casts. */
230
+ function isWorkerReply(value) {
231
+ if (!isRecord(value)) return false;
232
+ switch (value.kind) {
233
+ case "frame": return isFiniteNumber(value.frameId) && isFiniteNumber(value.timestamp) && isFiniteNumber(value.width) && isFiniteNumber(value.height) && isWorkerFrameFormat(value.format);
234
+ case "buffer": return isFiniteNumber(value.frameId) && value.bytes instanceof Uint8Array;
235
+ case "nativeCropResult": return isFiniteNumber(value.requestId) && value.bytes instanceof Uint8Array && isFiniteNumber(value.width) && isFiniteNumber(value.height);
236
+ case "nativeCropMiss": return isFiniteNumber(value.requestId) && (value.reason === void 0 || typeof value.reason === "string");
237
+ case "ended": return true;
238
+ case "error": return typeof value.message === "string" && (value.frameId === void 0 || isFiniteNumber(value.frameId));
239
+ case "log": return isWorkerLogLevel(value.level) && typeof value.message === "string";
240
+ default: return false;
241
+ }
242
+ }
243
+ //#endregion
244
+ Object.defineProperty(exports, "formatNativeLeaseKnobs", {
245
+ enumerable: true,
246
+ get: function() {
247
+ return formatNativeLeaseKnobs;
248
+ }
249
+ });
250
+ Object.defineProperty(exports, "isWorkerReply", {
251
+ enumerable: true,
252
+ get: function() {
253
+ return isWorkerReply;
254
+ }
255
+ });
256
+ Object.defineProperty(exports, "isWorkerRequest", {
257
+ enumerable: true,
258
+ get: function() {
259
+ return isWorkerRequest;
260
+ }
261
+ });
262
+ Object.defineProperty(exports, "logLevelForLine", {
263
+ enumerable: true,
264
+ get: function() {
265
+ return logLevelForLine;
266
+ }
267
+ });
268
+ Object.defineProperty(exports, "nativeLeaseSettingEnv", {
269
+ enumerable: true,
270
+ get: function() {
271
+ return nativeLeaseSettingEnv;
272
+ }
273
+ });
274
+ Object.defineProperty(exports, "resolveNativeLeaseKnobs", {
275
+ enumerable: true,
276
+ get: function() {
277
+ return resolveNativeLeaseKnobs;
278
+ }
279
+ });
@@ -1,4 +1,4 @@
1
- import{d as e,f as t,g as n,h as r,m as i,p as a}from"./index-on1wyOnd.js";var o=n(t()),s=n(e(),1),c=Math.PI/180;function l(){return typeof window<`u`&&({}.toString.call(window)===`[object Window]`||{}.toString.call(window)===`[object global]`)}var u=typeof global<`u`?global:typeof window<`u`?window:typeof WorkerGlobalScope<`u`?self:{},d={_global:u,version:`10.3.0`,isBrowser:l(),isUnminified:/param/.test(function(e){}.toString()),dblClickWindow:400,getAngle(e){return d.angleDeg?e*c:e},enableTrace:!1,pointerEventsEnabled:!0,autoDrawEnabled:!0,hitOnDragEnabled:!1,capturePointerEventsEnabled:!1,_mouseListenClick:!1,_touchListenClick:!1,_pointerListenClick:!1,_mouseInDblClickWindow:!1,_touchInDblClickWindow:!1,_pointerInDblClickWindow:!1,_mouseDblClickPointerId:null,_touchDblClickPointerId:null,_pointerDblClickPointerId:null,_renderBackend:`web`,legacyTextRendering:!1,pixelRatio:typeof window<`u`&&window.devicePixelRatio||1,dragDistance:3,angleDeg:!0,showWarnings:!0,dragButtons:[0,1],isDragging(){return d.DD.isDragging},isTransforming(){return d.Transformer?.isTransforming()??!1},isDragReady(){return!!d.DD.node},releaseCanvasOnDestroy:!0,document:u.document,_injectGlobal(e){u.Konva!==void 0&&console.error(`Several Konva instances detected. It is not recommended to use multiple Konva instances in the same environment.`),u.Konva=e}},f=e=>{d[e.prototype.getClassName()]=e};d._injectGlobal(d);var p=`Konva.js unsupported environment.
1
+ import{d as e,f as t,g as n,h as r,m as i,p as a}from"./index-4CtQAybX.js";var o=n(t()),s=n(e(),1),c=Math.PI/180;function l(){return typeof window<`u`&&({}.toString.call(window)===`[object Window]`||{}.toString.call(window)===`[object global]`)}var u=typeof global<`u`?global:typeof window<`u`?window:typeof WorkerGlobalScope<`u`?self:{},d={_global:u,version:`10.3.0`,isBrowser:l(),isUnminified:/param/.test(function(e){}.toString()),dblClickWindow:400,getAngle(e){return d.angleDeg?e*c:e},enableTrace:!1,pointerEventsEnabled:!0,autoDrawEnabled:!0,hitOnDragEnabled:!1,capturePointerEventsEnabled:!1,_mouseListenClick:!1,_touchListenClick:!1,_pointerListenClick:!1,_mouseInDblClickWindow:!1,_touchInDblClickWindow:!1,_pointerInDblClickWindow:!1,_mouseDblClickPointerId:null,_touchDblClickPointerId:null,_pointerDblClickPointerId:null,_renderBackend:`web`,legacyTextRendering:!1,pixelRatio:typeof window<`u`&&window.devicePixelRatio||1,dragDistance:3,angleDeg:!0,showWarnings:!0,dragButtons:[0,1],isDragging(){return d.DD.isDragging},isTransforming(){return d.Transformer?.isTransforming()??!1},isDragReady(){return!!d.DD.node},releaseCanvasOnDestroy:!0,document:u.document,_injectGlobal(e){u.Konva!==void 0&&console.error(`Several Konva instances detected. It is not recommended to use multiple Konva instances in the same environment.`),u.Konva=e}},f=e=>{d[e.prototype.getClassName()]=e};d._injectGlobal(d);var p=`Konva.js unsupported environment.
2
2
 
3
3
  Looks like you are trying to use Konva.js in Node.js environment. because "document" object is undefined.
4
4
 
@@ -1 +1 @@
1
- import{a as e,c as t,d as n,f as r,g as i,l as a,o,r as s,s as c,u as l}from"./index-on1wyOnd.js";import{MaskShapeCanvas as u}from"./MaskShapeCanvas-DI4BY7W2-DxZ75vB8.js";var d=i(r(),1),f=i(n(),1),p=o(`grid-2x2`,[[`path`,{d:`M12 3v18`,key:`108xh3`}],[`path`,{d:`M3 12h18`,key:`1i2n21`}],[`rect`,{x:`3`,y:`3`,width:`18`,height:`18`,rx:`2`,key:`h1oib`}]]),m=110,h=`motion-zones`,g=0,_=[1,2,3],v=1,y=`rounded-md border border-border bg-surface px-2 py-1 text-[11px] font-medium text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,b=`rounded-md border border-primary/50 bg-primary/15 px-2.5 py-1 text-[11px] font-medium text-primary hover:bg-primary/25 disabled:opacity-40 transition-colors`;function x(e,t,n){let r=t*n,i=Array.from({length:r});for(let t=0;t<r;t+=1)i[t]=e[t]===!0;return i}function S(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n+=1)if(e[n]!==t[n])return!1;return!0}function C(e,t){return Math.ceil(e/t)}function w(e,t,n){return Math.min(n-1,Math.floor((e+.5)/t*n))}function T(e,t,n,r){let i=C(t,r),a=C(n,r),o=Array.from({length:i*a},()=>!1);for(let r=0;r<n;r+=1){let s=w(r,n,a);for(let n=0;n<t;n+=1)e[r*t+n]===!0&&(o[s*i+w(n,t,i)]=!0)}return o}function E(e,t,n,r){let i=C(t,r),a=C(n,r),o=Array.from({length:t*n},()=>!1);for(let r=0;r<n;r+=1){let s=w(r,n,a);for(let n=0;n<t;n+=1)o[r*t+n]=e[s*i+w(n,t,i)]===!0}return o}function D({deviceId:n}){let r=t(l().trpcClient,n),[i,o]=(0,d.useState)(null),[w,D]=(0,d.useState)(!1),[O,k]=(0,d.useState)(null),[A,j]=(0,d.useState)(null),[M,N]=(0,d.useState)(v),[P,F]=(0,d.useState)(!1),[I,L]=(0,d.useState)(!1),R=(0,d.useRef)(!1);(0,d.useEffect)(()=>{if(!r)return;let e=!1;return R.current=!1,o(null),D(!1),k(null),j(null),N(v),L(!1),(async()=>{try{let t=await r.motionZones?.getOptions({});if(e)return;if(!t)throw Error(`device proxy not ready`);if(o(t),R.current)return;let n=await r.motionZones?.getStatus({});if(e)return;if(!n)throw Error(`device proxy not ready`);R.current=!0;let i=n.regions.find(e=>e.shape.kind===`grid`),a=x(i?i.shape.cells:[],t.grid.width,t.grid.height);j(a),k(T(a,t.grid.width,t.grid.height,v))}catch(t){if(e)return;c(t)?D(!0):console.error(`Motion Zones load failed`,t)}})(),()=>{e=!0}},[r]);let z=i?i.grid.width:0,B=i?i.grid.height:0,V=C(z,M),H=C(B,M),U=(0,d.useMemo)(()=>O&&i?E(O,z,B,M):null,[O,i,z,B,M]),W=(0,d.useMemo)(()=>U!==null&&A!==null&&!S(U,A),[U,A]),G=(0,d.useMemo)(()=>U?U.reduce((e,t)=>t?e+1:e,0):0,[U]),K=z*B,q=V*H,J=(0,d.useCallback)(e=>{q>0&&k(Array.from({length:q},()=>e))},[q]),Y=(0,d.useCallback)(()=>{k(e=>e&&e.map(e=>!e))},[]),X=(0,d.useCallback)(()=>{A&&i&&k(T(A,z,B,M))},[A,i,z,B,M]),Z=(0,d.useCallback)(e=>{e===M||!i||k(t=>{if(!t)return N(e),t;let n=T(E(t,z,B,M),z,B,e);return N(e),n})},[M,i,z,B]),Q=(0,d.useMemo)(()=>i&&O?[{id:g,shape:{kind:`grid`,gridWidth:V,gridHeight:H,cells:[...O]}}]:[],[i,O,V,H]),$=(0,d.useCallback)((e,t)=>{t.kind===`grid`&&k(t.cells)},[]),ee=(0,d.useCallback)(async()=>{if(!(!r||!O||!i)){F(!0);try{let e=E(O,i.grid.width,i.grid.height,M),t={kind:`grid`,gridWidth:i.grid.width,gridHeight:i.grid.height,cells:e};await r.motionZones?.setZone({patch:{regions:[{id:g,enabled:!0,shape:t}]}});let n=await r.motionZones?.getStatus({});if(n){let e=n.regions.find(e=>e.shape.kind===`grid`),t=x(e?e.shape.cells:[],i.grid.width,i.grid.height);j(t),k(T(t,i.grid.width,i.grid.height,M))}}catch(e){console.error(`Motion Zones save failed`,e)}finally{F(!1)}}},[r,O,i,M]);a((0,d.useMemo)(()=>I&&!w&&i&&O?{id:h,order:m,node:(0,f.jsx)(u,{transparent:!0,items:Q,supportedShapes:[`grid`],grid:{width:V,height:H},selectedId:g,onSelect:()=>{},onShapeChange:$,onDrawComplete:()=>{},drawingKind:null})}:null,[I,w,i,O,Q,$,V,H]));let te=!w&&i!==null&&O!==null;return r?(0,f.jsx)(e,{title:`Motion Zones`,icon:(0,f.jsx)(p,{className:`h-3.5 w-3.5 text-foreground-subtle`}),children:(0,f.jsx)(`div`,{className:`flex flex-col gap-3`,children:w?(0,f.jsx)(`p`,{className:`${s} leading-relaxed`,children:`This camera doesn't expose an on-board motion zones grid.`}):te?(0,f.jsxs)(f.Fragment,{children:[(0,f.jsxs)(`p`,{className:`${s} leading-relaxed`,children:[`Toggle `,(0,f.jsx)(`strong`,{className:`text-foreground`,children:`Edit grid`}),` to paint the region directly on the live frame, then `,(0,f.jsx)(`strong`,{className:`text-foreground`,children:`Save`}),` to push the mask to the camera. Pick a bigger`,` `,(0,f.jsx)(`strong`,{className:`text-foreground`,children:`Cell size`}),` for quicker, broad-stroke painting — it's resampled to the camera's native `,i.grid.width,`×`,i.grid.height,` grid on save (×1 is the finest).`]}),(0,f.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,f.jsx)(`button`,{type:`button`,onClick:()=>L(e=>!e),disabled:P,"aria-pressed":I,className:I?b:y,children:I?`Done editing`:`Edit grid`}),(0,f.jsx)(`button`,{type:`button`,onClick:()=>J(!0),disabled:P,className:y,children:`All on`}),(0,f.jsx)(`button`,{type:`button`,onClick:()=>J(!1),disabled:P,className:y,children:`All off`}),(0,f.jsx)(`button`,{type:`button`,onClick:Y,disabled:P,className:y,children:`Invert`}),(0,f.jsxs)(`div`,{className:`flex items-center gap-1 ml-1`,role:`group`,"aria-label":`Cell size`,children:[(0,f.jsx)(`span`,{className:`${s} mr-0.5`,children:`Cell size`}),_.map(e=>(0,f.jsxs)(`button`,{type:`button`,onClick:()=>Z(e),disabled:P,"aria-pressed":M===e,title:e===1?`Camera grid ${z}×${B} (finest)`:`${C(z,e)}×${C(B,e)} painting grid · cells ×${e} bigger`,className:M===e?b:y,children:[`×`,e]},e))]}),(0,f.jsxs)(`span`,{className:`${s} ml-1 tabular-nums`,children:[G,` / `,K,` cells · `,i.grid.width,`×`,i.grid.height,M===1?``:` · paint ${V}×${H}`]}),(0,f.jsx)(`span`,{className:`flex-1`}),(0,f.jsx)(`button`,{type:`button`,onClick:X,disabled:P||!W,className:`rounded-md border border-border bg-surface px-2 py-1 text-[11px] text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,children:`Revert`}),(0,f.jsx)(`button`,{type:`button`,onClick:()=>void ee(),disabled:P||!W,className:b,children:P?`Saving…`:`Save`})]})]}):(0,f.jsx)(`p`,{className:`${s} leading-relaxed`,children:`Loading the camera's grid…`})})}):null}export{D as MotionZonesSettings};
1
+ import{a as e,c as t,d as n,f as r,g as i,l as a,o,r as s,s as c,u as l}from"./index-4CtQAybX.js";import{MaskShapeCanvas as u}from"./MaskShapeCanvas-DI4BY7W2-DHZuYYjH.js";var d=i(r(),1),f=i(n(),1),p=o(`grid-2x2`,[[`path`,{d:`M12 3v18`,key:`108xh3`}],[`path`,{d:`M3 12h18`,key:`1i2n21`}],[`rect`,{x:`3`,y:`3`,width:`18`,height:`18`,rx:`2`,key:`h1oib`}]]),m=110,h=`motion-zones`,g=0,_=[1,2,3],v=1,y=`rounded-md border border-border bg-surface px-2 py-1 text-[11px] font-medium text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,b=`rounded-md border border-primary/50 bg-primary/15 px-2.5 py-1 text-[11px] font-medium text-primary hover:bg-primary/25 disabled:opacity-40 transition-colors`;function x(e,t,n){let r=t*n,i=Array.from({length:r});for(let t=0;t<r;t+=1)i[t]=e[t]===!0;return i}function S(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n+=1)if(e[n]!==t[n])return!1;return!0}function C(e,t){return Math.ceil(e/t)}function w(e,t,n){return Math.min(n-1,Math.floor((e+.5)/t*n))}function T(e,t,n,r){let i=C(t,r),a=C(n,r),o=Array.from({length:i*a},()=>!1);for(let r=0;r<n;r+=1){let s=w(r,n,a);for(let n=0;n<t;n+=1)e[r*t+n]===!0&&(o[s*i+w(n,t,i)]=!0)}return o}function E(e,t,n,r){let i=C(t,r),a=C(n,r),o=Array.from({length:t*n},()=>!1);for(let r=0;r<n;r+=1){let s=w(r,n,a);for(let n=0;n<t;n+=1)o[r*t+n]=e[s*i+w(n,t,i)]===!0}return o}function D({deviceId:n}){let r=t(l().trpcClient,n),[i,o]=(0,d.useState)(null),[w,D]=(0,d.useState)(!1),[O,k]=(0,d.useState)(null),[A,j]=(0,d.useState)(null),[M,N]=(0,d.useState)(v),[P,F]=(0,d.useState)(!1),[I,L]=(0,d.useState)(!1),R=(0,d.useRef)(!1);(0,d.useEffect)(()=>{if(!r)return;let e=!1;return R.current=!1,o(null),D(!1),k(null),j(null),N(v),L(!1),(async()=>{try{let t=await r.motionZones?.getOptions({});if(e)return;if(!t)throw Error(`device proxy not ready`);if(o(t),R.current)return;let n=await r.motionZones?.getStatus({});if(e)return;if(!n)throw Error(`device proxy not ready`);R.current=!0;let i=n.regions.find(e=>e.shape.kind===`grid`),a=x(i?i.shape.cells:[],t.grid.width,t.grid.height);j(a),k(T(a,t.grid.width,t.grid.height,v))}catch(t){if(e)return;c(t)?D(!0):console.error(`Motion Zones load failed`,t)}})(),()=>{e=!0}},[r]);let z=i?i.grid.width:0,B=i?i.grid.height:0,V=C(z,M),H=C(B,M),U=(0,d.useMemo)(()=>O&&i?E(O,z,B,M):null,[O,i,z,B,M]),W=(0,d.useMemo)(()=>U!==null&&A!==null&&!S(U,A),[U,A]),G=(0,d.useMemo)(()=>U?U.reduce((e,t)=>t?e+1:e,0):0,[U]),K=z*B,q=V*H,J=(0,d.useCallback)(e=>{q>0&&k(Array.from({length:q},()=>e))},[q]),Y=(0,d.useCallback)(()=>{k(e=>e&&e.map(e=>!e))},[]),X=(0,d.useCallback)(()=>{A&&i&&k(T(A,z,B,M))},[A,i,z,B,M]),Z=(0,d.useCallback)(e=>{e===M||!i||k(t=>{if(!t)return N(e),t;let n=T(E(t,z,B,M),z,B,e);return N(e),n})},[M,i,z,B]),Q=(0,d.useMemo)(()=>i&&O?[{id:g,shape:{kind:`grid`,gridWidth:V,gridHeight:H,cells:[...O]}}]:[],[i,O,V,H]),$=(0,d.useCallback)((e,t)=>{t.kind===`grid`&&k(t.cells)},[]),ee=(0,d.useCallback)(async()=>{if(!(!r||!O||!i)){F(!0);try{let e=E(O,i.grid.width,i.grid.height,M),t={kind:`grid`,gridWidth:i.grid.width,gridHeight:i.grid.height,cells:e};await r.motionZones?.setZone({patch:{regions:[{id:g,enabled:!0,shape:t}]}});let n=await r.motionZones?.getStatus({});if(n){let e=n.regions.find(e=>e.shape.kind===`grid`),t=x(e?e.shape.cells:[],i.grid.width,i.grid.height);j(t),k(T(t,i.grid.width,i.grid.height,M))}}catch(e){console.error(`Motion Zones save failed`,e)}finally{F(!1)}}},[r,O,i,M]);a((0,d.useMemo)(()=>I&&!w&&i&&O?{id:h,order:m,node:(0,f.jsx)(u,{transparent:!0,items:Q,supportedShapes:[`grid`],grid:{width:V,height:H},selectedId:g,onSelect:()=>{},onShapeChange:$,onDrawComplete:()=>{},drawingKind:null})}:null,[I,w,i,O,Q,$,V,H]));let te=!w&&i!==null&&O!==null;return r?(0,f.jsx)(e,{title:`Motion Zones`,icon:(0,f.jsx)(p,{className:`h-3.5 w-3.5 text-foreground-subtle`}),children:(0,f.jsx)(`div`,{className:`flex flex-col gap-3`,children:w?(0,f.jsx)(`p`,{className:`${s} leading-relaxed`,children:`This camera doesn't expose an on-board motion zones grid.`}):te?(0,f.jsxs)(f.Fragment,{children:[(0,f.jsxs)(`p`,{className:`${s} leading-relaxed`,children:[`Toggle `,(0,f.jsx)(`strong`,{className:`text-foreground`,children:`Edit grid`}),` to paint the region directly on the live frame, then `,(0,f.jsx)(`strong`,{className:`text-foreground`,children:`Save`}),` to push the mask to the camera. Pick a bigger`,` `,(0,f.jsx)(`strong`,{className:`text-foreground`,children:`Cell size`}),` for quicker, broad-stroke painting — it's resampled to the camera's native `,i.grid.width,`×`,i.grid.height,` grid on save (×1 is the finest).`]}),(0,f.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,f.jsx)(`button`,{type:`button`,onClick:()=>L(e=>!e),disabled:P,"aria-pressed":I,className:I?b:y,children:I?`Done editing`:`Edit grid`}),(0,f.jsx)(`button`,{type:`button`,onClick:()=>J(!0),disabled:P,className:y,children:`All on`}),(0,f.jsx)(`button`,{type:`button`,onClick:()=>J(!1),disabled:P,className:y,children:`All off`}),(0,f.jsx)(`button`,{type:`button`,onClick:Y,disabled:P,className:y,children:`Invert`}),(0,f.jsxs)(`div`,{className:`flex items-center gap-1 ml-1`,role:`group`,"aria-label":`Cell size`,children:[(0,f.jsx)(`span`,{className:`${s} mr-0.5`,children:`Cell size`}),_.map(e=>(0,f.jsxs)(`button`,{type:`button`,onClick:()=>Z(e),disabled:P,"aria-pressed":M===e,title:e===1?`Camera grid ${z}×${B} (finest)`:`${C(z,e)}×${C(B,e)} painting grid · cells ×${e} bigger`,className:M===e?b:y,children:[`×`,e]},e))]}),(0,f.jsxs)(`span`,{className:`${s} ml-1 tabular-nums`,children:[G,` / `,K,` cells · `,i.grid.width,`×`,i.grid.height,M===1?``:` · paint ${V}×${H}`]}),(0,f.jsx)(`span`,{className:`flex-1`}),(0,f.jsx)(`button`,{type:`button`,onClick:X,disabled:P||!W,className:`rounded-md border border-border bg-surface px-2 py-1 text-[11px] text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,children:`Revert`}),(0,f.jsx)(`button`,{type:`button`,onClick:()=>void ee(),disabled:P||!W,className:b,children:P?`Saving…`:`Save`})]})]}):(0,f.jsx)(`p`,{className:`${s} leading-relaxed`,children:`Loading the camera's grid…`})})}):null}export{D as MotionZonesSettings};
@@ -1 +1 @@
1
- import{a as e,c as t,d as n,f as r,g as i,i as a,l as o,n as s,o as c,r as l,s as u,t as d,u as ee}from"./index-on1wyOnd.js";import{MaskShapeCanvas as te}from"./MaskShapeCanvas-DI4BY7W2-DxZ75vB8.js";var f=i(r(),1),p=i(n(),1),m=c(`hexagon`,[[`path`,{d:`M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z`,key:`yt0hxn`}]]),h=120,g=`privacy-mask`,_=`rounded-md border border-border bg-surface px-2 py-1 text-[11px] font-medium text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,v=`rounded-md border border-primary/50 bg-primary/15 px-2.5 py-1 text-[11px] font-medium text-primary hover:bg-primary/25 disabled:opacity-40 transition-colors`;function y(e){return e.kind===`rect`||e.kind===`polygon`?e:null}function b(e){let t=new Set(e.map(e=>e.id)),n=0;for(;t.has(n);)n+=1;return n}function x(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n+=1)if(JSON.stringify(e[n])!==JSON.stringify(t[n]))return!1;return!0}function S({deviceId:n}){let r=t(ee().trpcClient,n),[i,c]=(0,f.useState)(null),[S,C]=(0,f.useState)(!1),[w,T]=(0,f.useState)(null),[E,D]=(0,f.useState)(null),[O,k]=(0,f.useState)(!1),[A,j]=(0,f.useState)(!1),[M,N]=(0,f.useState)(null),[P,F]=(0,f.useState)(null),I=(0,f.useRef)(!1);(0,f.useEffect)(()=>{if(!r)return;let e=!1;return I.current=!1,c(null),C(!1),T(null),D(null),j(!1),N(null),F(null),(async()=>{try{let t=await r.privacyMask?.getOptions({});if(e)return;if(!t)throw Error(`device proxy not ready`);if(c(t),I.current)return;let n=await r.privacyMask?.getStatus({});if(e)return;if(!n)throw Error(`device proxy not ready`);I.current=!0;let i={enabled:n.enabled,regions:n.regions};D(i),T(i)}catch(t){if(e)return;u(t)?C(!0):console.error(`Privacy Mask load failed`,t)}})(),()=>{e=!0}},[r]);let L=(0,f.useMemo)(()=>w!==null&&E!==null&&(w.enabled!==E.enabled||!x(w.regions,E.regions)),[w,E]),R=w?w.regions.length:0,z=i?i.maxRegions:0,B=(0,f.useRef)(0);(0,f.useEffect)(()=>{B.current=z},[z]);let V=z>0&&R>=z,H=(0,f.useCallback)(()=>{T(e=>e&&{...e,enabled:!e.enabled})},[]),U=(0,f.useCallback)(e=>{N(typeof e==`number`?e:null)},[]),W=(0,f.useMemo)(()=>w?w.regions.map(e=>({id:e.id,shape:e.shape,enabled:e.enabled,label:`Zone ${String(e.id)}`})):[],[w]),G=(0,f.useCallback)((e,t)=>{let n=y(t);n&&T(t=>t&&{...t,regions:t.regions.map(t=>t.id===e?{...t,shape:n}:t)})},[]),K=(0,f.useCallback)(e=>{let t=y(e);t&&(F(null),T(e=>{if(!e)return e;let n=B.current;if(n>0&&e.regions.length>=n)return e;let r=b(e.regions),i={id:r,enabled:!0,shape:t};return N(r),{...e,regions:[...e.regions,i]}}))},[]),q=(0,f.useCallback)(e=>{j(!0),N(null),F(e)},[]),J=(0,f.useCallback)(e=>{j(!0),F(null),N(e)},[]),Y=(0,f.useCallback)(e=>{N(t=>t===e?null:t),T(t=>t&&{...t,regions:t.regions.filter(t=>t.id!==e)})},[]),X=(0,f.useCallback)(()=>{F(null),N(null),E&&T({enabled:E.enabled,regions:E.regions})},[E]),Z=(0,f.useCallback)(async()=>{if(!(!r||!w)){k(!0);try{await r.privacyMask?.setMask({patch:{enabled:w.enabled,regions:[...w.regions]}});let e=await r.privacyMask?.getStatus({});if(e){let t={enabled:e.enabled,regions:e.regions};D(t),T(t)}}catch(e){console.error(`Privacy Mask save failed`,e)}finally{k(!1)}}},[r,w]),ne=(0,f.useCallback)(()=>{j(e=>(e&&(F(null),N(null)),!e))},[]),Q=i?.supportedShapes??[];o((0,f.useMemo)(()=>A&&!S&&i&&w?{id:g,order:h,node:(0,p.jsx)(te,{transparent:!0,items:W,supportedShapes:Q,polygonVertices:i.polygonVertices,selectedId:M,onSelect:U,onShapeChange:G,onDrawComplete:K,drawingKind:P})}:null,[A,S,i,w,W,Q,M,U,G,K,P]));let re=i?.supportedShapes.includes(`rect`)??!1,ie=i?.supportedShapes.includes(`polygon`)??!1,$=i!==null&&(i.maxRegions<=0||i.supportedShapes.length===0),ae=!S&&!$&&i!==null&&w!==null;return r?(0,p.jsx)(e,{title:`Privacy Mask`,icon:(0,p.jsx)(d,{className:`h-3.5 w-3.5 text-foreground-subtle`}),children:(0,p.jsx)(`div`,{className:`flex flex-col gap-3`,children:S||$?(0,p.jsx)(`p`,{className:`${l} leading-relaxed`,children:`This camera doesn't support an on-board privacy mask.`}):ae?(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(`p`,{className:`${l} leading-relaxed`,children:[`Toggle `,(0,p.jsx)(`strong`,{className:`text-foreground`,children:`Edit mask`}),` to draw blanked-out zones on the live frame, then `,(0,p.jsx)(`strong`,{className:`text-foreground`,children:`Save`}),` to push them to the camera. Drag a rectangle to move, its corner to resize; drag polygon vertices, click an edge midpoint to add one, or right-click a vertex to remove it.`]}),(0,p.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,p.jsx)(`button`,{type:`button`,onClick:ne,disabled:O,"aria-pressed":A,className:A?v:_,children:A?`Done editing`:`Edit mask`}),(0,p.jsx)(`button`,{type:`button`,onClick:H,disabled:O,"aria-pressed":w.enabled,className:w.enabled?v:_,children:w.enabled?`Mask on`:`Mask off`}),re&&(0,p.jsx)(`button`,{type:`button`,onClick:()=>q(`rect`),disabled:O||V,"aria-pressed":P===`rect`,className:P===`rect`?v:_,title:V?`Maximum zones reached`:`Add a rectangle zone`,children:`+ Rect`}),ie&&(0,p.jsx)(`button`,{type:`button`,onClick:()=>q(`polygon`),disabled:O||V,"aria-pressed":P===`polygon`,className:P===`polygon`?v:_,title:V?`Maximum zones reached`:`Add a polygon zone`,children:`+ Polygon`}),(0,p.jsxs)(`span`,{className:`${l} ml-1 tabular-nums`,children:[R,` / `,z,` zones`]}),(0,p.jsx)(`span`,{className:`flex-1`}),(0,p.jsx)(`button`,{type:`button`,onClick:X,disabled:O||!L,className:`rounded-md border border-border bg-surface px-2 py-1 text-[11px] text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,children:`Revert`}),(0,p.jsx)(`button`,{type:`button`,onClick:()=>void Z(),disabled:O||!L,className:v,children:O?`Saving…`:`Save`})]}),R>0?(0,p.jsx)(`div`,{className:`flex flex-col gap-1`,children:w.regions.map(e=>{let t=M===e.id,n=e.shape.kind===`polygon`?m:s;return(0,p.jsxs)(`div`,{className:`flex items-center gap-2 rounded-md border px-2 py-1 transition-colors ${t?`border-primary/50 bg-primary/10`:`border-border bg-surface`}`,children:[(0,p.jsxs)(`button`,{type:`button`,onClick:()=>J(e.id),disabled:O,className:`flex flex-1 items-center gap-2 text-left text-[11px] font-medium text-foreground-subtle hover:text-foreground disabled:opacity-40 transition-colors`,children:[(0,p.jsx)(n,{className:`h-3.5 w-3.5 shrink-0`}),(0,p.jsxs)(`span`,{children:[`Zone `,e.id]}),(0,p.jsx)(`span`,{className:`text-foreground-faint capitalize`,children:e.shape.kind})]}),(0,p.jsx)(`button`,{type:`button`,onClick:()=>Y(e.id),disabled:O,"aria-label":`Delete zone ${String(e.id)}`,title:`Delete zone`,className:`inline-flex h-6 w-6 items-center justify-center rounded border border-border bg-surface text-foreground-subtle hover:border-red-400/40 hover:bg-red-500/10 hover:text-red-400 disabled:opacity-40 transition-colors`,children:(0,p.jsx)(a,{className:`h-3.5 w-3.5`})})]},e.id)})}):null]}):(0,p.jsx)(`p`,{className:`${l} leading-relaxed`,children:`Loading the camera's privacy mask…`})})}):null}export{S as PrivacyMaskSettings};
1
+ import{a as e,c as t,d as n,f as r,g as i,i as a,l as o,n as s,o as c,r as l,s as u,t as d,u as ee}from"./index-4CtQAybX.js";import{MaskShapeCanvas as te}from"./MaskShapeCanvas-DI4BY7W2-DHZuYYjH.js";var f=i(r(),1),p=i(n(),1),m=c(`hexagon`,[[`path`,{d:`M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z`,key:`yt0hxn`}]]),h=120,g=`privacy-mask`,_=`rounded-md border border-border bg-surface px-2 py-1 text-[11px] font-medium text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,v=`rounded-md border border-primary/50 bg-primary/15 px-2.5 py-1 text-[11px] font-medium text-primary hover:bg-primary/25 disabled:opacity-40 transition-colors`;function y(e){return e.kind===`rect`||e.kind===`polygon`?e:null}function b(e){let t=new Set(e.map(e=>e.id)),n=0;for(;t.has(n);)n+=1;return n}function x(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n+=1)if(JSON.stringify(e[n])!==JSON.stringify(t[n]))return!1;return!0}function S({deviceId:n}){let r=t(ee().trpcClient,n),[i,c]=(0,f.useState)(null),[S,C]=(0,f.useState)(!1),[w,T]=(0,f.useState)(null),[E,D]=(0,f.useState)(null),[O,k]=(0,f.useState)(!1),[A,j]=(0,f.useState)(!1),[M,N]=(0,f.useState)(null),[P,F]=(0,f.useState)(null),I=(0,f.useRef)(!1);(0,f.useEffect)(()=>{if(!r)return;let e=!1;return I.current=!1,c(null),C(!1),T(null),D(null),j(!1),N(null),F(null),(async()=>{try{let t=await r.privacyMask?.getOptions({});if(e)return;if(!t)throw Error(`device proxy not ready`);if(c(t),I.current)return;let n=await r.privacyMask?.getStatus({});if(e)return;if(!n)throw Error(`device proxy not ready`);I.current=!0;let i={enabled:n.enabled,regions:n.regions};D(i),T(i)}catch(t){if(e)return;u(t)?C(!0):console.error(`Privacy Mask load failed`,t)}})(),()=>{e=!0}},[r]);let L=(0,f.useMemo)(()=>w!==null&&E!==null&&(w.enabled!==E.enabled||!x(w.regions,E.regions)),[w,E]),R=w?w.regions.length:0,z=i?i.maxRegions:0,B=(0,f.useRef)(0);(0,f.useEffect)(()=>{B.current=z},[z]);let V=z>0&&R>=z,H=(0,f.useCallback)(()=>{T(e=>e&&{...e,enabled:!e.enabled})},[]),U=(0,f.useCallback)(e=>{N(typeof e==`number`?e:null)},[]),W=(0,f.useMemo)(()=>w?w.regions.map(e=>({id:e.id,shape:e.shape,enabled:e.enabled,label:`Zone ${String(e.id)}`})):[],[w]),G=(0,f.useCallback)((e,t)=>{let n=y(t);n&&T(t=>t&&{...t,regions:t.regions.map(t=>t.id===e?{...t,shape:n}:t)})},[]),K=(0,f.useCallback)(e=>{let t=y(e);t&&(F(null),T(e=>{if(!e)return e;let n=B.current;if(n>0&&e.regions.length>=n)return e;let r=b(e.regions),i={id:r,enabled:!0,shape:t};return N(r),{...e,regions:[...e.regions,i]}}))},[]),q=(0,f.useCallback)(e=>{j(!0),N(null),F(e)},[]),J=(0,f.useCallback)(e=>{j(!0),F(null),N(e)},[]),Y=(0,f.useCallback)(e=>{N(t=>t===e?null:t),T(t=>t&&{...t,regions:t.regions.filter(t=>t.id!==e)})},[]),X=(0,f.useCallback)(()=>{F(null),N(null),E&&T({enabled:E.enabled,regions:E.regions})},[E]),Z=(0,f.useCallback)(async()=>{if(!(!r||!w)){k(!0);try{await r.privacyMask?.setMask({patch:{enabled:w.enabled,regions:[...w.regions]}});let e=await r.privacyMask?.getStatus({});if(e){let t={enabled:e.enabled,regions:e.regions};D(t),T(t)}}catch(e){console.error(`Privacy Mask save failed`,e)}finally{k(!1)}}},[r,w]),ne=(0,f.useCallback)(()=>{j(e=>(e&&(F(null),N(null)),!e))},[]),Q=i?.supportedShapes??[];o((0,f.useMemo)(()=>A&&!S&&i&&w?{id:g,order:h,node:(0,p.jsx)(te,{transparent:!0,items:W,supportedShapes:Q,polygonVertices:i.polygonVertices,selectedId:M,onSelect:U,onShapeChange:G,onDrawComplete:K,drawingKind:P})}:null,[A,S,i,w,W,Q,M,U,G,K,P]));let re=i?.supportedShapes.includes(`rect`)??!1,ie=i?.supportedShapes.includes(`polygon`)??!1,$=i!==null&&(i.maxRegions<=0||i.supportedShapes.length===0),ae=!S&&!$&&i!==null&&w!==null;return r?(0,p.jsx)(e,{title:`Privacy Mask`,icon:(0,p.jsx)(d,{className:`h-3.5 w-3.5 text-foreground-subtle`}),children:(0,p.jsx)(`div`,{className:`flex flex-col gap-3`,children:S||$?(0,p.jsx)(`p`,{className:`${l} leading-relaxed`,children:`This camera doesn't support an on-board privacy mask.`}):ae?(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(`p`,{className:`${l} leading-relaxed`,children:[`Toggle `,(0,p.jsx)(`strong`,{className:`text-foreground`,children:`Edit mask`}),` to draw blanked-out zones on the live frame, then `,(0,p.jsx)(`strong`,{className:`text-foreground`,children:`Save`}),` to push them to the camera. Drag a rectangle to move, its corner to resize; drag polygon vertices, click an edge midpoint to add one, or right-click a vertex to remove it.`]}),(0,p.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,p.jsx)(`button`,{type:`button`,onClick:ne,disabled:O,"aria-pressed":A,className:A?v:_,children:A?`Done editing`:`Edit mask`}),(0,p.jsx)(`button`,{type:`button`,onClick:H,disabled:O,"aria-pressed":w.enabled,className:w.enabled?v:_,children:w.enabled?`Mask on`:`Mask off`}),re&&(0,p.jsx)(`button`,{type:`button`,onClick:()=>q(`rect`),disabled:O||V,"aria-pressed":P===`rect`,className:P===`rect`?v:_,title:V?`Maximum zones reached`:`Add a rectangle zone`,children:`+ Rect`}),ie&&(0,p.jsx)(`button`,{type:`button`,onClick:()=>q(`polygon`),disabled:O||V,"aria-pressed":P===`polygon`,className:P===`polygon`?v:_,title:V?`Maximum zones reached`:`Add a polygon zone`,children:`+ Polygon`}),(0,p.jsxs)(`span`,{className:`${l} ml-1 tabular-nums`,children:[R,` / `,z,` zones`]}),(0,p.jsx)(`span`,{className:`flex-1`}),(0,p.jsx)(`button`,{type:`button`,onClick:X,disabled:O||!L,className:`rounded-md border border-border bg-surface px-2 py-1 text-[11px] text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,children:`Revert`}),(0,p.jsx)(`button`,{type:`button`,onClick:()=>void Z(),disabled:O||!L,className:v,children:O?`Saving…`:`Save`})]}),R>0?(0,p.jsx)(`div`,{className:`flex flex-col gap-1`,children:w.regions.map(e=>{let t=M===e.id,n=e.shape.kind===`polygon`?m:s;return(0,p.jsxs)(`div`,{className:`flex items-center gap-2 rounded-md border px-2 py-1 transition-colors ${t?`border-primary/50 bg-primary/10`:`border-border bg-surface`}`,children:[(0,p.jsxs)(`button`,{type:`button`,onClick:()=>J(e.id),disabled:O,className:`flex flex-1 items-center gap-2 text-left text-[11px] font-medium text-foreground-subtle hover:text-foreground disabled:opacity-40 transition-colors`,children:[(0,p.jsx)(n,{className:`h-3.5 w-3.5 shrink-0`}),(0,p.jsxs)(`span`,{children:[`Zone `,e.id]}),(0,p.jsx)(`span`,{className:`text-foreground-faint capitalize`,children:e.shape.kind})]}),(0,p.jsx)(`button`,{type:`button`,onClick:()=>Y(e.id),disabled:O,"aria-label":`Delete zone ${String(e.id)}`,title:`Delete zone`,className:`inline-flex h-6 w-6 items-center justify-center rounded border border-border bg-surface text-foreground-subtle hover:border-red-400/40 hover:bg-red-500/10 hover:text-red-400 disabled:opacity-40 transition-colors`,children:(0,p.jsx)(a,{className:`h-3.5 w-3.5`})})]},e.id)})}):null]}):(0,p.jsx)(`p`,{className:`${l} leading-relaxed`,children:`Loading the camera's privacy mask…`})})}):null}export{S as PrivacyMaskSettings};