@camstack/types 1.2.33 → 1.2.35

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.
@@ -1,70 +1,5 @@
1
1
  import { t as EventCategory } from "./event-category-41fKf-q9.mjs";
2
2
  import { z } from "zod";
3
- //#region src/disposer-chain.ts
4
- var DisposerChain = class {
5
- disposers = [];
6
- disposed = false;
7
- onError;
8
- constructor(opts = {}) {
9
- this.onError = opts.onError ?? ((err, index) => {
10
- console.error(`[DisposerChain] disposer #${index} threw`, err);
11
- });
12
- }
13
- /**
14
- * Register a teardown callback. Returns an unregister function so
15
- * callers can drop a single disposer without disposing the whole
16
- * chain.
17
- *
18
- * If the chain has already been disposed, the callback runs immediately
19
- * (sync) — this matches the “register-after-shutdown” edge case where
20
- * an addon's late initialization races with kernel restart.
21
- */
22
- add(fn) {
23
- if (this.disposed) {
24
- try {
25
- const result = fn();
26
- if (result && typeof result.then === "function") result.catch((err) => this.onError(err, -1));
27
- } catch (err) {
28
- this.onError(err, -1);
29
- }
30
- return () => void 0;
31
- }
32
- this.disposers.push(fn);
33
- return () => {
34
- const idx = this.disposers.indexOf(fn);
35
- if (idx >= 0) this.disposers.splice(idx, 1);
36
- };
37
- }
38
- /** True after `dispose()` has been called at least once. */
39
- get isDisposed() {
40
- return this.disposed;
41
- }
42
- /** Number of disposers currently registered. */
43
- get size() {
44
- return this.disposers.length;
45
- }
46
- /**
47
- * Run every registered disposer in LIFO order. Idempotent: subsequent
48
- * calls do nothing. Awaits async disposers so callers can sequence
49
- * shutdown → restart correctly.
50
- */
51
- async dispose() {
52
- if (this.disposed) return;
53
- this.disposed = true;
54
- const drain = this.disposers.slice().toReversed();
55
- this.disposers = [];
56
- for (let i = 0; i < drain.length; i++) {
57
- const fn = drain[i];
58
- try {
59
- const result = fn();
60
- if (result && typeof result.then === "function") await result;
61
- } catch (err) {
62
- this.onError(err, drain.length - 1 - i);
63
- }
64
- }
65
- }
66
- };
67
- //#endregion
68
3
  //#region src/interfaces/config-ui.ts
69
4
  /** Predefined tabs with standard label, icon, and sort order.
70
5
  *
@@ -1084,6 +1019,80 @@ function normalizeAddonInitResult(result) {
1084
1019
  return result;
1085
1020
  }
1086
1021
  //#endregion
1022
+ //#region src/disposer-chain.ts
1023
+ var DisposerChain = class {
1024
+ disposers = [];
1025
+ disposed = false;
1026
+ onError;
1027
+ constructor(opts = {}) {
1028
+ this.onError = opts.onError ?? ((err, index) => {
1029
+ console.error(`[DisposerChain] disposer #${index} threw`, err);
1030
+ });
1031
+ }
1032
+ /**
1033
+ * Register a teardown callback. Returns an unregister function so
1034
+ * callers can drop a single disposer without disposing the whole
1035
+ * chain.
1036
+ *
1037
+ * If the chain has already been disposed, the callback runs immediately
1038
+ * (sync) — this matches the “register-after-shutdown” edge case where
1039
+ * an addon's late initialization races with kernel restart.
1040
+ */
1041
+ add(fn) {
1042
+ if (this.disposed) {
1043
+ try {
1044
+ const result = fn();
1045
+ if (result && typeof result.then === "function") result.catch((err) => this.onError(err, -1));
1046
+ } catch (err) {
1047
+ this.onError(err, -1);
1048
+ }
1049
+ return () => void 0;
1050
+ }
1051
+ this.disposers.push(fn);
1052
+ return () => {
1053
+ const idx = this.disposers.indexOf(fn);
1054
+ if (idx >= 0) this.disposers.splice(idx, 1);
1055
+ };
1056
+ }
1057
+ /** True after `dispose()` has been called at least once. */
1058
+ get isDisposed() {
1059
+ return this.disposed;
1060
+ }
1061
+ /** Number of disposers currently registered. */
1062
+ get size() {
1063
+ return this.disposers.length;
1064
+ }
1065
+ /**
1066
+ * Run every registered disposer in LIFO order. Idempotent: subsequent
1067
+ * calls do nothing. Awaits async disposers so callers can sequence
1068
+ * shutdown → restart correctly.
1069
+ */
1070
+ async dispose() {
1071
+ if (this.disposed) return;
1072
+ this.disposed = true;
1073
+ const drain = this.disposers.slice().toReversed();
1074
+ this.disposers = [];
1075
+ for (let i = 0; i < drain.length; i++) {
1076
+ const fn = drain[i];
1077
+ try {
1078
+ const result = fn();
1079
+ if (result && typeof result.then === "function") await result;
1080
+ } catch (err) {
1081
+ this.onError(err, drain.length - 1 - i);
1082
+ }
1083
+ }
1084
+ }
1085
+ };
1086
+ //#endregion
1087
+ //#region src/interfaces/addon-data-plane.ts
1088
+ /**
1089
+ * Per-listener shared-secret header the hub injects on every reverse-proxied
1090
+ * data-plane request and the addon's framework wrapper validates — so only the
1091
+ * hub can reach the addon's `127.0.0.1` listener. Defined here (shared by the
1092
+ * core proxy and the kernel listener) to keep both off a kernel↔core import.
1093
+ */
1094
+ var DATAPLANE_SECRET_HEADER = "x-camstack-dataplane-secret";
1095
+ //#endregion
1087
1096
  //#region src/capabilities/schemas/streaming-shared.ts
1088
1097
  /** Shared Zod schemas used across streaming capabilities. */
1089
1098
  var CamProfileSchema = z.enum([
@@ -1898,15 +1907,6 @@ function emitDownForOwnedCaps(registry, owned) {
1898
1907
  for (const { capName, scope } of owned) registry.emitDown(capName, scope);
1899
1908
  }
1900
1909
  //#endregion
1901
- //#region src/interfaces/addon-data-plane.ts
1902
- /**
1903
- * Per-listener shared-secret header the hub injects on every reverse-proxied
1904
- * data-plane request and the addon's framework wrapper validates — so only the
1905
- * hub can reach the addon's `127.0.0.1` listener. Defined here (shared by the
1906
- * core proxy and the kernel listener) to keep both off a kernel↔core import.
1907
- */
1908
- var DATAPLANE_SECRET_HEADER = "x-camstack-dataplane-secret";
1909
- //#endregion
1910
1910
  //#region src/cap-call-context.ts
1911
1911
  /**
1912
1912
  * Per-call node pinning for `ctx.api` capability calls.
@@ -1948,171 +1948,180 @@ function readNodePin(context) {
1948
1948
  return typeof value === "string" ? value : void 0;
1949
1949
  }
1950
1950
  //#endregion
1951
- //#region src/utils/json-safe.ts
1951
+ //#region src/capabilities/capability-definition.ts
1952
1952
  /**
1953
- * Type-safe JSON parsing helpers.
1953
+ * Generic types for capability definitions.
1954
1954
  *
1955
- * `JSON.parse` is typed as `any` in lib.es5.d.ts, which triggers
1956
- * `no-unsafe-*` ESLint rules and destroys downstream inference. These
1957
- * wrappers return `unknown` — callers narrow structurally via type
1958
- * guards, `typeof` checks, or helpers like `asRecord`/`asString`.
1955
+ * A capability is defined with Zod schemas for methods, events, and settings.
1956
+ * TypeScript types are inferred via z.infer<> — zero duplication.
1957
+ *
1958
+ * Pattern:
1959
+ * 1. Define Zod schemas for data, methods, settings
1960
+ * 2. Export const capabilityDef = { ... } satisfies CapabilityDefinition
1961
+ * 3. Export type IProvider = InferProvider<typeof capabilityDef>
1962
+ * 4. Addon implements IProvider
1963
+ * 5. Registry auto-mounts tRPC router from definition.methods
1959
1964
  */
1960
1965
  /**
1961
- * Parse JSON and return it as `unknown` — the only entry point for untrusted JSON.
1962
- *
1963
- * The optional generic overload `parseJsonUnknown<T>(text)` returns `T` for
1964
- * call sites that know the shape at parse time (e.g. MQTT payloads with a
1965
- * known protocol schema). This is a **type-level bridge only** — no runtime
1966
- * validation is performed. Callers that need runtime validation should parse
1967
- * as `unknown` and narrow via Zod or structural guards.
1966
+ * Resolve the EFFECTIVE mount hint for a cap — the explicit `mount` when
1967
+ * present, else the scope/mode/deviceNative-derived default. Single source
1968
+ * of truth shared by the runtime builder and any codegen that needs the
1969
+ * same classification, so the two can never disagree.
1968
1970
  */
1969
- function parseJsonUnknown(text) {
1970
- return JSON.parse(text);
1971
- }
1972
- /** Narrow an unknown value to a plain `Record<string, unknown>` or return null. */
1973
- function asJsonObject(value) {
1974
- if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
1975
- return { ...value };
1976
- }
1977
- /** Narrow an unknown value to a `readonly unknown[]` or return an empty array. */
1978
- function asJsonArray(value) {
1979
- return Array.isArray(value) ? value : [];
1980
- }
1981
- /** Safe string extraction from an unknown record field. */
1982
- function asString(value, fallback = "") {
1983
- return typeof value === "string" ? value : fallback;
1984
- }
1985
- /** Safe number extraction from an unknown record field. */
1986
- function asNumber(value, fallback = 0) {
1987
- return typeof value === "number" ? value : fallback;
1988
- }
1989
- /** Safe boolean extraction from an unknown record field. */
1990
- function asBoolean(value, fallback = false) {
1991
- return typeof value === "boolean" ? value : fallback;
1992
- }
1993
- /** Parse JSON + narrow to object in one step. */
1994
- function parseJsonObject(text) {
1995
- try {
1996
- return asJsonObject(parseJsonUnknown(text));
1997
- } catch {
1998
- return null;
1999
- }
2000
- }
2001
- /** Parse JSON + narrow to array in one step. */
2002
- function parseJsonArray(text) {
2003
- try {
2004
- const parsed = parseJsonUnknown(text);
2005
- return Array.isArray(parsed) ? parsed : null;
2006
- } catch {
2007
- return null;
2008
- }
1971
+ function resolveCapMount(def) {
1972
+ if (def.mount) return def.mount;
1973
+ if (def.deviceNative === true) return { kind: "device-native" };
1974
+ if (def.mode === "collection") return { kind: "collection" };
1975
+ return { kind: "singleton" };
2009
1976
  }
2010
- //#endregion
2011
- //#region src/generated/device-scoped-caps.ts
2012
1977
  /**
2013
- * AUTO-GENERATED by scripts/generate-device-scoped-caps.ts DO NOT EDIT.
1978
+ * Output schema shared by the contribution + live methods.
2014
1979
  *
2015
- * Every `scope: 'device'` capability name, as plain data — so a forked runner
2016
- * can answer "may a rule actuate this?" without importing the schema barrel
2017
- * (~144MB RSS per runner, D28).
1980
+ * Mirrors the `ConfigUISchemaWithValues` shape (sections[] + optional
1981
+ * tabs[]) without importing from `../interfaces/config-ui.js` — a
1982
+ * concrete-but-lenient Zod object keeps tRPC output inference happy
1983
+ * (using `z.unknown()` here collapses unrelated router branches to
1984
+ * `unknown` when the generator re-inlines the huge AppRouter type).
2018
1985
  *
2019
- * Coverage: 80 device-scoped capabilities.
1986
+ * `.passthrough()` on sections/fields accepts whatever FormBuilder
1987
+ * extensions the caller adds (showWhen, displayScale, …) without
1988
+ * rebuilding every time a new field kind is introduced.
2020
1989
  */
2021
- var DEVICE_SCOPED_CAPS = new Set([
2022
- "accessories",
2023
- "air-quality-sensor",
2024
- "alarm-panel",
2025
- "ambient-light-sensor",
2026
- "audio-analysis",
2027
- "audio-metrics",
2028
- "automation-control",
2029
- "battery",
2030
- "binary",
2031
- "brightness",
2032
- "button",
2033
- "camera-credentials",
2034
- "camera-pipeline-config",
2035
- "camera-streams",
2036
- "carbon-monoxide",
2037
- "climate-control",
2038
- "color",
2039
- "connectivity",
2040
- "consumables",
2041
- "contact",
2042
- "control",
2043
- "cover",
2044
- "day-night",
2045
- "detection-pipeline",
2046
- "device-discovery",
2047
- "device-ops",
2048
- "device-status",
2049
- "doorbell",
2050
- "enum-sensor",
2051
- "event-emitter",
2052
- "events",
2053
- "fan-control",
2054
- "feature-probe",
2055
- "flood",
2056
- "gas",
2057
- "humidifier",
2058
- "humidity-sensor",
2059
- "image",
2060
- "image-settings",
2061
- "intercom",
2062
- "lawn-mower-control",
2063
- "lock-control",
2064
- "media-player",
2065
- "motion",
2066
- "motion-detection",
2067
- "motion-trigger",
2068
- "motion-zones",
2069
- "native-object-detection",
2070
- "notifier",
2071
- "numeric-sensor",
2072
- "osd",
2073
- "pet-feeder",
2074
- "pipeline-analytics",
2075
- "power-meter",
2076
- "presence",
2077
- "pressure-sensor",
2078
- "privacy-mask",
2079
- "ptz",
2080
- "ptz-autotrack",
2081
- "reboot",
2082
- "scene-monitor",
2083
- "script-runner",
2084
- "smoke",
2085
- "snapshot",
2086
- "stream-catalog",
2087
- "stream-params",
2088
- "switch",
2089
- "tamper",
2090
- "temperature-sensor",
2091
- "update",
2092
- "vacuum-control",
2093
- "valve",
2094
- "vibration",
2095
- "videoclips",
2096
- "water-heater",
2097
- "weather",
2098
- "webrtc-session",
2099
- "zone-analytics",
2100
- "zone-rules",
2101
- "zones"
2102
- ]);
1990
+ var ContributionSectionSchema = z.object({
1991
+ id: z.string(),
1992
+ title: z.string(),
1993
+ description: z.string().optional(),
1994
+ style: z.enum(["card", "accordion"]).optional(),
1995
+ defaultCollapsed: z.boolean().optional(),
1996
+ columns: z.union([
1997
+ z.literal(1),
1998
+ z.literal(2),
1999
+ z.literal(3),
2000
+ z.literal(4)
2001
+ ]).optional(),
2002
+ tab: z.string().optional(),
2003
+ location: z.enum(["settings", "top-tab"]).optional(),
2004
+ order: z.number().optional(),
2005
+ fields: z.array(z.any())
2006
+ });
2007
+ var ContributionTabSchema = z.object({
2008
+ id: z.string(),
2009
+ label: z.string(),
2010
+ icon: z.string(),
2011
+ order: z.number().optional()
2012
+ });
2013
+ var ContributionOutputSchema = z.object({
2014
+ tabs: z.array(ContributionTabSchema).optional(),
2015
+ sections: z.array(ContributionSectionSchema)
2016
+ }).nullable();
2017
+ var DEVICE_SETTINGS_CONTRIBUTION_METHODS = {
2018
+ getDeviceSettingsContribution: {
2019
+ input: z.object({ deviceId: z.number() }),
2020
+ output: ContributionOutputSchema,
2021
+ kind: "query",
2022
+ auth: "protected"
2023
+ },
2024
+ getDeviceLiveContribution: {
2025
+ input: z.object({ deviceId: z.number() }),
2026
+ output: ContributionOutputSchema,
2027
+ kind: "query",
2028
+ auth: "protected"
2029
+ },
2030
+ applyDeviceSettingsPatch: {
2031
+ input: z.object({
2032
+ deviceId: z.number(),
2033
+ patch: z.record(z.string(), z.unknown())
2034
+ }),
2035
+ output: z.object({ success: z.literal(true) }),
2036
+ kind: "mutation",
2037
+ auth: "admin"
2038
+ }
2039
+ };
2103
2040
  /**
2104
- * True when `capName` is a device capability.
2041
+ * Schema for the `getStatus` method auto-injected when a cap declares
2042
+ * `status`. The runtime shape of the output is the cap's own
2043
+ * `status.schema` — but at codegen time we need a concrete Zod to emit
2044
+ * a typed tRPC route, so we keep the output as `z.unknown().nullable()`
2045
+ * here and tighten it on the client side via the generated
2046
+ * `CapStatusTypeMap` (see `scripts/generate-cap-status-types.ts`).
2047
+ */
2048
+ var DEVICE_STATUS_METHOD = { getStatus: {
2049
+ input: z.object({ deviceId: z.number() }),
2050
+ output: z.unknown().nullable(),
2051
+ kind: "query",
2052
+ auth: "protected"
2053
+ } };
2054
+ /**
2055
+ * Expand a cap def's methods map with every auto-injected method:
2056
+ * - `exposesDeviceSettings: true` → 3 contribution methods
2057
+ * - `status: {...}` → `getStatus`
2105
2058
  *
2106
- * This is the ONLY boundary on what a notification rule may actuate. A rule can
2107
- * be authored by a non-admin and the runner executes with the addon's
2108
- * privileges, so an unbounded action would be an arbitrary RPC channel with a
2109
- * privilege escalation attached. Device scope excludes the system caps
2110
- * (`device-manager.removeDevice` and friends) by construction.
2059
+ * Callers walk `expandCapMethods(def)` instead of `def.methods` when
2060
+ * they need the effective runtime method surface (Moleculer actions,
2061
+ * proxy shape, tRPC router entries). The cap def stays the single
2062
+ * source of truth. Providers still declare their concrete `methods`
2063
+ * block; the expansion happens at every consumption point, so there's
2064
+ * no accidental divergence between the declared surface and what's
2065
+ * actually mounted.
2111
2066
  */
2112
- function isDeviceScopedCap(capName) {
2113
- return DEVICE_SCOPED_CAPS.has(capName);
2067
+ function expandCapMethods(def) {
2068
+ let out = def.methods;
2069
+ if (def.exposesDeviceSettings) out = {
2070
+ ...DEVICE_SETTINGS_CONTRIBUTION_METHODS,
2071
+ ...out
2072
+ };
2073
+ if (def.status) out = {
2074
+ ...DEVICE_STATUS_METHOD,
2075
+ ...out
2076
+ };
2077
+ return out;
2078
+ }
2079
+ function method(input, output, options) {
2080
+ return {
2081
+ input,
2082
+ output,
2083
+ kind: options?.kind ?? "query",
2084
+ auth: options?.auth ?? "protected",
2085
+ ...options?.access !== void 0 ? { access: options.access } : {},
2086
+ ...options?.caller !== void 0 ? { caller: options.caller } : {},
2087
+ timeoutMs: options?.timeoutMs
2088
+ };
2089
+ }
2090
+ /**
2091
+ * A wrapper/system-only method: served exclusively by the cap's system-level
2092
+ * provider (`InferProvider`), and OPTIONAL on `InferNativeProvider` so per-device
2093
+ * driver natives don't stub out a wrapper concern (e.g. a cross-device cache
2094
+ * overview). The `systemOnly: true` literal is what `InferNativeProvider` keys on.
2095
+ */
2096
+ function systemMethod(input, output, options) {
2097
+ return {
2098
+ ...method(input, output, options),
2099
+ systemOnly: true
2100
+ };
2101
+ }
2102
+ /** Shorthand to define an event schema */
2103
+ function event(data) {
2104
+ return { data };
2105
+ }
2106
+ /** Type guard: does this cap declare the D14 device-config archetype? */
2107
+ function isDeviceConfigCap(def) {
2108
+ return def?.deviceConfig !== void 0;
2114
2109
  }
2115
2110
  //#endregion
2111
+ //#region src/capabilities/admin-ui.cap.ts
2112
+ var StaticDirOutputSchema$1 = z.object({ staticDir: z.string() });
2113
+ var VersionOutputSchema$1 = z.object({ version: z.string() });
2114
+ var adminUiCapability = {
2115
+ name: "admin-ui",
2116
+ scope: "system",
2117
+ mode: "singleton",
2118
+ internal: true,
2119
+ methods: {
2120
+ getStaticDir: method(z.void(), StaticDirOutputSchema$1),
2121
+ getVersion: method(z.void(), VersionOutputSchema$1)
2122
+ }
2123
+ };
2124
+ //#endregion
2116
2125
  //#region src/device/device-type.ts
2117
2126
  var DeviceType = /* @__PURE__ */ function(DeviceType) {
2118
2127
  DeviceType["Camera"] = "camera";
@@ -2439,165 +2448,144 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
2439
2448
  return DeviceRole;
2440
2449
  }({});
2441
2450
  //#endregion
2442
- //#region src/capabilities/capability-definition.ts
2443
- /**
2444
- * Generic types for capability definitions.
2445
- *
2446
- * A capability is defined with Zod schemas for methods, events, and settings.
2447
- * TypeScript types are inferred via z.infer<> — zero duplication.
2448
- *
2449
- * Pattern:
2450
- * 1. Define Zod schemas for data, methods, settings
2451
- * 2. Export const capabilityDef = { ... } satisfies CapabilityDefinition
2452
- * 3. Export type IProvider = InferProvider<typeof capabilityDef>
2453
- * 4. Addon implements IProvider
2454
- * 5. Registry auto-mounts tRPC router from definition.methods
2455
- */
2451
+ //#region src/capabilities/viewer-ui.cap.ts
2452
+ var StaticDirOutputSchema = z.object({ staticDir: z.string() });
2453
+ var VersionOutputSchema = z.object({ version: z.string() });
2456
2454
  /**
2457
- * Resolve the EFFECTIVE mount hint for a cap the explicit `mount` when
2458
- * present, else the scope/mode/deviceNative-derived default. Single source
2459
- * of truth shared by the runtime builder and any codegen that needs the
2460
- * same classification, so the two can never disagree.
2455
+ * viewer-ui serves the CamStack VIEWER web build (the Expo/React-Native
2456
+ * universal client's PWA export) from the hub, alongside admin-ui. Mirrors
2457
+ * `admin-ui` exactly: a singleton, server-internal cap exposing the static
2458
+ * dist directory + build version so `main.ts` can mount the SPA under a
2459
+ * dedicated prefix.
2461
2460
  */
2462
- function resolveCapMount(def) {
2463
- if (def.mount) return def.mount;
2464
- if (def.deviceNative === true) return { kind: "device-native" };
2465
- if (def.mode === "collection") return { kind: "collection" };
2466
- return { kind: "singleton" };
2467
- }
2461
+ var viewerUiCapability = {
2462
+ name: "viewer-ui",
2463
+ scope: "system",
2464
+ mode: "singleton",
2465
+ internal: true,
2466
+ methods: {
2467
+ getStaticDir: method(z.void(), StaticDirOutputSchema),
2468
+ getVersion: method(z.void(), VersionOutputSchema)
2469
+ }
2470
+ };
2471
+ //#endregion
2472
+ //#region src/capabilities/device-ops.cap.ts
2468
2473
  /**
2469
- * Output schema shared by the contribution + live methods.
2470
- *
2471
- * Mirrors the `ConfigUISchemaWithValues` shape (sections[] + optional
2472
- * tabs[]) without importing from `../interfaces/config-ui.js` — a
2473
- * concrete-but-lenient Zod object keeps tRPC output inference happy
2474
- * (using `z.unknown()` here collapses unrelated router branches to
2475
- * `unknown` when the generator re-inlines the huge AppRouter type).
2474
+ * device-ops device-scoped cap that unifies the per-IDevice operations
2475
+ * previously routed through the `.device-ops` Moleculer bridge service.
2476
2476
  *
2477
- * `.passthrough()` on sections/fields accepts whatever FormBuilder
2478
- * extensions the caller adds (showWhen, displayScale, …) without
2479
- * rebuilding every time a new field kind is introduced.
2477
+ * Each worker that hosts live `IDevice` instances auto-registers a native
2478
+ * provider for this cap (per device) backed by its local
2479
+ * `DeviceRegistry`. Hub-side callers reach it transparently through
2480
+ * `ctx.fetchDevice(id).deviceOps.*` — the DeviceProxy injects
2481
+ * `deviceId` + `nodeId` and dispatches through the standard cap-router,
2482
+ * so there's no parallel bridge path anymore.
2483
+ *
2484
+ * The surface is intentionally small — every method corresponds to a
2485
+ * single action on the live `IDevice` (or `ICameraDevice` for
2486
+ * `getStreamSources`). Richer orchestration (enable/disable with
2487
+ * integration plumbing, bulk updates) stays in the `device-manager` cap;
2488
+ * `device-ops` is the per-device primitive the device-manager routes to.
2480
2489
  */
2481
- var ContributionSectionSchema = z.object({
2482
- id: z.string(),
2483
- title: z.string(),
2484
- description: z.string().optional(),
2485
- style: z.enum(["card", "accordion"]).optional(),
2486
- defaultCollapsed: z.boolean().optional(),
2487
- columns: z.union([
2488
- z.literal(1),
2489
- z.literal(2),
2490
- z.literal(3),
2491
- z.literal(4)
2492
- ]).optional(),
2493
- tab: z.string().optional(),
2494
- location: z.enum(["settings", "top-tab"]).optional(),
2495
- order: z.number().optional(),
2496
- fields: z.array(z.any())
2497
- });
2498
- var ContributionTabSchema = z.object({
2490
+ var StreamSourceEntrySchema = z.object({
2499
2491
  id: z.string(),
2500
2492
  label: z.string(),
2501
- icon: z.string(),
2502
- order: z.number().optional()
2493
+ protocol: z.enum([
2494
+ "rtsp",
2495
+ "rtmp",
2496
+ "annexb",
2497
+ "http-mjpeg",
2498
+ "webrtc",
2499
+ "custom"
2500
+ ]),
2501
+ url: z.string().optional(),
2502
+ resolution: z.object({
2503
+ width: z.number(),
2504
+ height: z.number()
2505
+ }).optional(),
2506
+ fps: z.number().optional(),
2507
+ bitrate: z.number().optional(),
2508
+ codec: z.string().optional(),
2509
+ profileHint: CamProfileSchema.optional(),
2510
+ sdp: z.string().optional()
2503
2511
  });
2504
- var ContributionOutputSchema = z.object({
2505
- tabs: z.array(ContributionTabSchema).optional(),
2506
- sections: z.array(ContributionSectionSchema)
2507
- }).nullable();
2508
- var DEVICE_SETTINGS_CONTRIBUTION_METHODS = {
2509
- getDeviceSettingsContribution: {
2510
- input: z.object({ deviceId: z.number() }),
2511
- output: ContributionOutputSchema,
2512
- kind: "query",
2513
- auth: "protected"
2514
- },
2515
- getDeviceLiveContribution: {
2516
- input: z.object({ deviceId: z.number() }),
2517
- output: ContributionOutputSchema,
2518
- kind: "query",
2519
- auth: "protected"
2520
- },
2521
- applyDeviceSettingsPatch: {
2522
- input: z.object({
2512
+ var ConfigEntrySchema = z.object({
2513
+ key: z.string(),
2514
+ value: z.unknown()
2515
+ });
2516
+ var RawStateResultSchema = z.object({
2517
+ /** Originating provider id, e.g. 'homeassistant' | 'reolink' | 'hikvision'. */
2518
+ source: z.string(),
2519
+ /** Opaque, DISPLAY-SAFE upstream blob (no secrets/PII). */
2520
+ data: z.record(z.string(), z.unknown())
2521
+ });
2522
+ var deviceOpsCapability = {
2523
+ name: "device-ops",
2524
+ scope: "device",
2525
+ deviceNative: true,
2526
+ mode: "singleton",
2527
+ methods: {
2528
+ /**
2529
+ * Return stream sources for camera-like devices. Non-camera devices
2530
+ * return an empty array (the bridge did the same; preserved for compat).
2531
+ */
2532
+ getStreamSources: method(z.object({ deviceId: z.number() }), z.array(StreamSourceEntrySchema)),
2533
+ /**
2534
+ * Return the device's config entries (key + current value). Used by
2535
+ * the device-manager aggregator when reading the driver's schema+values.
2536
+ */
2537
+ getConfigEntries: method(z.object({ deviceId: z.number() }), z.array(ConfigEntrySchema)),
2538
+ /**
2539
+ * Bulk-apply a config patch via `IDevice.config.setAll`. Covers the
2540
+ * updateConfig / setStreamProfileMap / enable-as-config paths from
2541
+ * the old bridge.
2542
+ */
2543
+ setConfig: method(z.object({
2523
2544
  deviceId: z.number(),
2524
- patch: z.record(z.string(), z.unknown())
2525
- }),
2526
- output: z.object({ success: z.literal(true) }),
2527
- kind: "mutation",
2528
- auth: "admin"
2545
+ values: z.record(z.string(), z.unknown())
2546
+ }), z.void(), { kind: "mutation" }),
2547
+ /**
2548
+ * Invoke a device custom action on a forked/remote device (the
2549
+ * cross-process transport for `IDevice.runDeviceAction`). Mirrors
2550
+ * `setConfig` — the device-manager calls this when the device is not
2551
+ * hub-local.
2552
+ */
2553
+ runAction: method(z.object({
2554
+ deviceId: z.number(),
2555
+ action: z.string().min(1),
2556
+ input: z.unknown()
2557
+ }), z.unknown(), { kind: "mutation" }),
2558
+ /**
2559
+ * Invoke `IDevice.removeDevice()` so the driver can release resources
2560
+ * (close sockets, stop background tasks, …). The device-manager still
2561
+ * performs its own persistence cleanup before/after this call.
2562
+ */
2563
+ removeDevice: method(z.object({ deviceId: z.number() }), z.void(), { kind: "mutation" }),
2564
+ /**
2565
+ * Build the ConfigUISchema (FormBuilder input shape) from the device's
2566
+ * Zod config schema. Runs on the worker that owns the IDevice so the
2567
+ * Zod types stay local (they're function references, not
2568
+ * serializable). Returns a fully JSON-serializable schema with
2569
+ * sections/fields the admin UI renders directly.
2570
+ *
2571
+ * Needed because the hub-side `device-manager.getSettingsSchema`
2572
+ * couldn't reach forked-worker devices — it had no registry entry
2573
+ * and no cross-process lookup, so the UI silently rendered an empty
2574
+ * settings panel for every worker-owned device.
2575
+ *
2576
+ * Returns `null` when the device isn't found on this worker.
2577
+ */
2578
+ getSettingsSchema: method(z.object({ deviceId: z.number() }), z.unknown().nullable()),
2579
+ /**
2580
+ * Opt-in: return the device's RAW upstream state (the provider's
2581
+ * cached values) as a display-safe `{ source, data }` blob. Returns
2582
+ * `null` when the device exposes no raw state — the State panel hides
2583
+ * its Raw toggle in that case. One-shot (read the provider's existing
2584
+ * cache; no upstream round-trip).
2585
+ */
2586
+ getRawState: method(z.object({ deviceId: z.number() }), RawStateResultSchema.nullable(), { auth: "protected" })
2529
2587
  }
2530
2588
  };
2531
- /**
2532
- * Schema for the `getStatus` method auto-injected when a cap declares
2533
- * `status`. The runtime shape of the output is the cap's own
2534
- * `status.schema` — but at codegen time we need a concrete Zod to emit
2535
- * a typed tRPC route, so we keep the output as `z.unknown().nullable()`
2536
- * here and tighten it on the client side via the generated
2537
- * `CapStatusTypeMap` (see `scripts/generate-cap-status-types.ts`).
2538
- */
2539
- var DEVICE_STATUS_METHOD = { getStatus: {
2540
- input: z.object({ deviceId: z.number() }),
2541
- output: z.unknown().nullable(),
2542
- kind: "query",
2543
- auth: "protected"
2544
- } };
2545
- /**
2546
- * Expand a cap def's methods map with every auto-injected method:
2547
- * - `exposesDeviceSettings: true` → 3 contribution methods
2548
- * - `status: {...}` → `getStatus`
2549
- *
2550
- * Callers walk `expandCapMethods(def)` instead of `def.methods` when
2551
- * they need the effective runtime method surface (Moleculer actions,
2552
- * proxy shape, tRPC router entries). The cap def stays the single
2553
- * source of truth. Providers still declare their concrete `methods`
2554
- * block; the expansion happens at every consumption point, so there's
2555
- * no accidental divergence between the declared surface and what's
2556
- * actually mounted.
2557
- */
2558
- function expandCapMethods(def) {
2559
- let out = def.methods;
2560
- if (def.exposesDeviceSettings) out = {
2561
- ...DEVICE_SETTINGS_CONTRIBUTION_METHODS,
2562
- ...out
2563
- };
2564
- if (def.status) out = {
2565
- ...DEVICE_STATUS_METHOD,
2566
- ...out
2567
- };
2568
- return out;
2569
- }
2570
- function method(input, output, options) {
2571
- return {
2572
- input,
2573
- output,
2574
- kind: options?.kind ?? "query",
2575
- auth: options?.auth ?? "protected",
2576
- ...options?.access !== void 0 ? { access: options.access } : {},
2577
- ...options?.caller !== void 0 ? { caller: options.caller } : {},
2578
- timeoutMs: options?.timeoutMs
2579
- };
2580
- }
2581
- /**
2582
- * A wrapper/system-only method: served exclusively by the cap's system-level
2583
- * provider (`InferProvider`), and OPTIONAL on `InferNativeProvider` so per-device
2584
- * driver natives don't stub out a wrapper concern (e.g. a cross-device cache
2585
- * overview). The `systemOnly: true` literal is what `InferNativeProvider` keys on.
2586
- */
2587
- function systemMethod(input, output, options) {
2588
- return {
2589
- ...method(input, output, options),
2590
- systemOnly: true
2591
- };
2592
- }
2593
- /** Shorthand to define an event schema */
2594
- function event(data) {
2595
- return { data };
2596
- }
2597
- /** Type guard: does this cap declare the D14 device-config archetype? */
2598
- function isDeviceConfigCap(def) {
2599
- return def?.deviceConfig !== void 0;
2600
- }
2601
2589
  //#endregion
2602
2590
  //#region src/device/device-state-handle.ts
2603
2591
  var DEVICE_STATE_EVENT_CATEGORY = "device.state-changed";
@@ -3120,7 +3108,9 @@ function createDeviceProxy(api, binding, opts) {
3120
3108
  getHistory: (input) => dispatch("notification-rules", "notificationRules", "getHistory", "query", input),
3121
3109
  listSnoozes: (input) => dispatch("notification-rules", "notificationRules", "listSnoozes", "query", input),
3122
3110
  createSnooze: (input) => dispatch("notification-rules", "notificationRules", "createSnooze", "mutation", input),
3123
- cancelSnooze: (input) => dispatch("notification-rules", "notificationRules", "cancelSnooze", "mutation", input)
3111
+ cancelSnooze: (input) => dispatch("notification-rules", "notificationRules", "cancelSnooze", "mutation", input),
3112
+ getAlarmConfig: (input) => dispatch("notification-rules", "notificationRules", "getAlarmConfig", "query", input),
3113
+ setAlarmConfig: (input) => dispatch("notification-rules", "notificationRules", "setAlarmConfig", "mutation", input)
3124
3114
  },
3125
3115
  notifier: {
3126
3116
  send: (input) => dispatch("notifier", "notifier", "send", "mutation", input),
@@ -3445,158 +3435,170 @@ function createDeviceProxy(api, binding, opts) {
3445
3435
  };
3446
3436
  }
3447
3437
  //#endregion
3448
- //#region src/capabilities/admin-ui.cap.ts
3449
- var StaticDirOutputSchema$1 = z.object({ staticDir: z.string() });
3450
- var VersionOutputSchema$1 = z.object({ version: z.string() });
3451
- var adminUiCapability = {
3452
- name: "admin-ui",
3453
- scope: "system",
3454
- mode: "singleton",
3455
- internal: true,
3456
- methods: {
3457
- getStaticDir: method(z.void(), StaticDirOutputSchema$1),
3458
- getVersion: method(z.void(), VersionOutputSchema$1)
3459
- }
3460
- };
3461
- //#endregion
3462
- //#region src/capabilities/viewer-ui.cap.ts
3463
- var StaticDirOutputSchema = z.object({ staticDir: z.string() });
3464
- var VersionOutputSchema = z.object({ version: z.string() });
3438
+ //#region src/generated/device-scoped-caps.ts
3465
3439
  /**
3466
- * viewer-ui serves the CamStack VIEWER web build (the Expo/React-Native
3467
- * universal client's PWA export) from the hub, alongside admin-ui. Mirrors
3468
- * `admin-ui` exactly: a singleton, server-internal cap exposing the static
3469
- * dist directory + build version so `main.ts` can mount the SPA under a
3470
- * dedicated prefix.
3440
+ * AUTO-GENERATED by scripts/generate-device-scoped-caps.ts DO NOT EDIT.
3441
+ *
3442
+ * Every `scope: 'device'` capability name, as plain data so a forked runner
3443
+ * can answer "may a rule actuate this?" without importing the schema barrel
3444
+ * (~144MB RSS per runner, D28).
3445
+ *
3446
+ * Coverage: 80 device-scoped capabilities.
3471
3447
  */
3472
- var viewerUiCapability = {
3473
- name: "viewer-ui",
3474
- scope: "system",
3475
- mode: "singleton",
3476
- internal: true,
3477
- methods: {
3478
- getStaticDir: method(z.void(), StaticDirOutputSchema),
3479
- getVersion: method(z.void(), VersionOutputSchema)
3480
- }
3481
- };
3448
+ var DEVICE_SCOPED_CAPS = new Set([
3449
+ "accessories",
3450
+ "air-quality-sensor",
3451
+ "alarm-panel",
3452
+ "ambient-light-sensor",
3453
+ "audio-analysis",
3454
+ "audio-metrics",
3455
+ "automation-control",
3456
+ "battery",
3457
+ "binary",
3458
+ "brightness",
3459
+ "button",
3460
+ "camera-credentials",
3461
+ "camera-pipeline-config",
3462
+ "camera-streams",
3463
+ "carbon-monoxide",
3464
+ "climate-control",
3465
+ "color",
3466
+ "connectivity",
3467
+ "consumables",
3468
+ "contact",
3469
+ "control",
3470
+ "cover",
3471
+ "day-night",
3472
+ "detection-pipeline",
3473
+ "device-discovery",
3474
+ "device-ops",
3475
+ "device-status",
3476
+ "doorbell",
3477
+ "enum-sensor",
3478
+ "event-emitter",
3479
+ "events",
3480
+ "fan-control",
3481
+ "feature-probe",
3482
+ "flood",
3483
+ "gas",
3484
+ "humidifier",
3485
+ "humidity-sensor",
3486
+ "image",
3487
+ "image-settings",
3488
+ "intercom",
3489
+ "lawn-mower-control",
3490
+ "lock-control",
3491
+ "media-player",
3492
+ "motion",
3493
+ "motion-detection",
3494
+ "motion-trigger",
3495
+ "motion-zones",
3496
+ "native-object-detection",
3497
+ "notifier",
3498
+ "numeric-sensor",
3499
+ "osd",
3500
+ "pet-feeder",
3501
+ "pipeline-analytics",
3502
+ "power-meter",
3503
+ "presence",
3504
+ "pressure-sensor",
3505
+ "privacy-mask",
3506
+ "ptz",
3507
+ "ptz-autotrack",
3508
+ "reboot",
3509
+ "scene-monitor",
3510
+ "script-runner",
3511
+ "smoke",
3512
+ "snapshot",
3513
+ "stream-catalog",
3514
+ "stream-params",
3515
+ "switch",
3516
+ "tamper",
3517
+ "temperature-sensor",
3518
+ "update",
3519
+ "vacuum-control",
3520
+ "valve",
3521
+ "vibration",
3522
+ "videoclips",
3523
+ "water-heater",
3524
+ "weather",
3525
+ "webrtc-session",
3526
+ "zone-analytics",
3527
+ "zone-rules",
3528
+ "zones"
3529
+ ]);
3530
+ /**
3531
+ * True when `capName` is a device capability.
3532
+ *
3533
+ * This is the ONLY boundary on what a notification rule may actuate. A rule can
3534
+ * be authored by a non-admin and the runner executes with the addon's
3535
+ * privileges, so an unbounded action would be an arbitrary RPC channel with a
3536
+ * privilege escalation attached. Device scope excludes the system caps
3537
+ * (`device-manager.removeDevice` and friends) by construction.
3538
+ */
3539
+ function isDeviceScopedCap(capName) {
3540
+ return DEVICE_SCOPED_CAPS.has(capName);
3541
+ }
3482
3542
  //#endregion
3483
- //#region src/capabilities/device-ops.cap.ts
3543
+ //#region src/utils/json-safe.ts
3484
3544
  /**
3485
- * device-ops device-scoped cap that unifies the per-IDevice operations
3486
- * previously routed through the `.device-ops` Moleculer bridge service.
3545
+ * Type-safe JSON parsing helpers.
3487
3546
  *
3488
- * Each worker that hosts live `IDevice` instances auto-registers a native
3489
- * provider for this cap (per device) backed by its local
3490
- * `DeviceRegistry`. Hub-side callers reach it transparently through
3491
- * `ctx.fetchDevice(id).deviceOps.*` the DeviceProxy injects
3492
- * `deviceId` + `nodeId` and dispatches through the standard cap-router,
3493
- * so there's no parallel bridge path anymore.
3547
+ * `JSON.parse` is typed as `any` in lib.es5.d.ts, which triggers
3548
+ * `no-unsafe-*` ESLint rules and destroys downstream inference. These
3549
+ * wrappers return `unknown` callers narrow structurally via type
3550
+ * guards, `typeof` checks, or helpers like `asRecord`/`asString`.
3551
+ */
3552
+ /**
3553
+ * Parse JSON and return it as `unknown` — the only entry point for untrusted JSON.
3494
3554
  *
3495
- * The surface is intentionally small every method corresponds to a
3496
- * single action on the live `IDevice` (or `ICameraDevice` for
3497
- * `getStreamSources`). Richer orchestration (enable/disable with
3498
- * integration plumbing, bulk updates) stays in the `device-manager` cap;
3499
- * `device-ops` is the per-device primitive the device-manager routes to.
3555
+ * The optional generic overload `parseJsonUnknown<T>(text)` returns `T` for
3556
+ * call sites that know the shape at parse time (e.g. MQTT payloads with a
3557
+ * known protocol schema). This is a **type-level bridge only** — no runtime
3558
+ * validation is performed. Callers that need runtime validation should parse
3559
+ * as `unknown` and narrow via Zod or structural guards.
3500
3560
  */
3501
- var StreamSourceEntrySchema = z.object({
3502
- id: z.string(),
3503
- label: z.string(),
3504
- protocol: z.enum([
3505
- "rtsp",
3506
- "rtmp",
3507
- "annexb",
3508
- "http-mjpeg",
3509
- "webrtc",
3510
- "custom"
3511
- ]),
3512
- url: z.string().optional(),
3513
- resolution: z.object({
3514
- width: z.number(),
3515
- height: z.number()
3516
- }).optional(),
3517
- fps: z.number().optional(),
3518
- bitrate: z.number().optional(),
3519
- codec: z.string().optional(),
3520
- profileHint: CamProfileSchema.optional(),
3521
- sdp: z.string().optional()
3522
- });
3523
- var ConfigEntrySchema = z.object({
3524
- key: z.string(),
3525
- value: z.unknown()
3526
- });
3527
- var RawStateResultSchema = z.object({
3528
- /** Originating provider id, e.g. 'homeassistant' | 'reolink' | 'hikvision'. */
3529
- source: z.string(),
3530
- /** Opaque, DISPLAY-SAFE upstream blob (no secrets/PII). */
3531
- data: z.record(z.string(), z.unknown())
3532
- });
3533
- var deviceOpsCapability = {
3534
- name: "device-ops",
3535
- scope: "device",
3536
- deviceNative: true,
3537
- mode: "singleton",
3538
- methods: {
3539
- /**
3540
- * Return stream sources for camera-like devices. Non-camera devices
3541
- * return an empty array (the bridge did the same; preserved for compat).
3542
- */
3543
- getStreamSources: method(z.object({ deviceId: z.number() }), z.array(StreamSourceEntrySchema)),
3544
- /**
3545
- * Return the device's config entries (key + current value). Used by
3546
- * the device-manager aggregator when reading the driver's schema+values.
3547
- */
3548
- getConfigEntries: method(z.object({ deviceId: z.number() }), z.array(ConfigEntrySchema)),
3549
- /**
3550
- * Bulk-apply a config patch via `IDevice.config.setAll`. Covers the
3551
- * updateConfig / setStreamProfileMap / enable-as-config paths from
3552
- * the old bridge.
3553
- */
3554
- setConfig: method(z.object({
3555
- deviceId: z.number(),
3556
- values: z.record(z.string(), z.unknown())
3557
- }), z.void(), { kind: "mutation" }),
3558
- /**
3559
- * Invoke a device custom action on a forked/remote device (the
3560
- * cross-process transport for `IDevice.runDeviceAction`). Mirrors
3561
- * `setConfig` — the device-manager calls this when the device is not
3562
- * hub-local.
3563
- */
3564
- runAction: method(z.object({
3565
- deviceId: z.number(),
3566
- action: z.string().min(1),
3567
- input: z.unknown()
3568
- }), z.unknown(), { kind: "mutation" }),
3569
- /**
3570
- * Invoke `IDevice.removeDevice()` so the driver can release resources
3571
- * (close sockets, stop background tasks, …). The device-manager still
3572
- * performs its own persistence cleanup before/after this call.
3573
- */
3574
- removeDevice: method(z.object({ deviceId: z.number() }), z.void(), { kind: "mutation" }),
3575
- /**
3576
- * Build the ConfigUISchema (FormBuilder input shape) from the device's
3577
- * Zod config schema. Runs on the worker that owns the IDevice so the
3578
- * Zod types stay local (they're function references, not
3579
- * serializable). Returns a fully JSON-serializable schema with
3580
- * sections/fields the admin UI renders directly.
3581
- *
3582
- * Needed because the hub-side `device-manager.getSettingsSchema`
3583
- * couldn't reach forked-worker devices — it had no registry entry
3584
- * and no cross-process lookup, so the UI silently rendered an empty
3585
- * settings panel for every worker-owned device.
3586
- *
3587
- * Returns `null` when the device isn't found on this worker.
3588
- */
3589
- getSettingsSchema: method(z.object({ deviceId: z.number() }), z.unknown().nullable()),
3590
- /**
3591
- * Opt-in: return the device's RAW upstream state (the provider's
3592
- * cached values) as a display-safe `{ source, data }` blob. Returns
3593
- * `null` when the device exposes no raw state — the State panel hides
3594
- * its Raw toggle in that case. One-shot (read the provider's existing
3595
- * cache; no upstream round-trip).
3596
- */
3597
- getRawState: method(z.object({ deviceId: z.number() }), RawStateResultSchema.nullable(), { auth: "protected" })
3561
+ function parseJsonUnknown(text) {
3562
+ return JSON.parse(text);
3563
+ }
3564
+ /** Narrow an unknown value to a plain `Record<string, unknown>` or return null. */
3565
+ function asJsonObject(value) {
3566
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
3567
+ return { ...value };
3568
+ }
3569
+ /** Narrow an unknown value to a `readonly unknown[]` or return an empty array. */
3570
+ function asJsonArray(value) {
3571
+ return Array.isArray(value) ? value : [];
3572
+ }
3573
+ /** Safe string extraction from an unknown record field. */
3574
+ function asString(value, fallback = "") {
3575
+ return typeof value === "string" ? value : fallback;
3576
+ }
3577
+ /** Safe number extraction from an unknown record field. */
3578
+ function asNumber(value, fallback = 0) {
3579
+ return typeof value === "number" ? value : fallback;
3580
+ }
3581
+ /** Safe boolean extraction from an unknown record field. */
3582
+ function asBoolean(value, fallback = false) {
3583
+ return typeof value === "boolean" ? value : fallback;
3584
+ }
3585
+ /** Parse JSON + narrow to object in one step. */
3586
+ function parseJsonObject(text) {
3587
+ try {
3588
+ return asJsonObject(parseJsonUnknown(text));
3589
+ } catch {
3590
+ return null;
3598
3591
  }
3599
- };
3592
+ }
3593
+ /** Parse JSON + narrow to array in one step. */
3594
+ function parseJsonArray(text) {
3595
+ try {
3596
+ const parsed = parseJsonUnknown(text);
3597
+ return Array.isArray(parsed) ? parsed : null;
3598
+ } catch {
3599
+ return null;
3600
+ }
3601
+ }
3600
3602
  //#endregion
3601
3603
  //#region src/utils/sleep.ts
3602
3604
  /**
@@ -3651,4 +3653,4 @@ function sleepCancellable(ms, signal) {
3651
3653
  });
3652
3654
  }
3653
3655
  //#endregion
3654
- export { FrameHandleSchema as $, parseJsonArray as A, readinessKey as B, DEVICE_SCOPED_CAPS as C, hydrateSchema as Ct, asJsonObject as D, asJsonArray as E, readNodePin as F, CamProfileSchema as G, BrokerStatsSchema as H, DATAPLANE_SECRET_HEADER as I, CameraStreamSchema as J, CamStreamKindSchema as K, ReadinessRegistry as L, parseJsonUnknown as M, CAP_NODE_PIN_CONTEXT_KEY as N, asNumber as O, nodePin as P, FrameHandleFormatSchema as Q, ReadinessTimeoutError as R, DeviceType as S, collectHydratedFieldValues as St, asBoolean as T, DisposerChain as Tt, BrokerStatusSchema as U, scopeKey as V, CAM_PROFILE_ORDER as W, DecodedFrameSchema as X, DecodedAudioChunkSchema as Y, EncodedPacketSchema as Z, resolveCapMount as _, emitReadiness as _t, viewerUiCapability as a, SubscribeAudioChunksInputSchema as at, DeviceFeature as b, WELL_KNOWN_TAB_MAP as bt, createLazyTrpcSource as c, SubscribeFramesResultSchema as ct, DEVICE_SETTINGS_CONTRIBUTION_METHODS as d, parseProfileBrokerId as dt, ProfileRtspEntrySchema as et, DEVICE_STATUS_METHOD as f, selectAssignedProfileSlots as ft, method as g, createEvent as gt, isDeviceConfigCap as h, createDurableState as ht, deviceOpsCapability as i, StreamSourceSchema as it, parseJsonObject as j, asString as k, createMirrorSource as l, makeProfileBrokerId as lt, expandCapMethods as m, normalizeAddonInitResult as mt, sleepCancellable as n, ProfileSlotStatusSchema as nt, adminUiCapability as o, SubscribeAudioChunksResultSchema as ot, event as p, BaseAddon as pt, CamStreamResolutionSchema as q, RawStateResultSchema as r, StreamSourceEntrySchema$1 as rt, createDeviceProxy as s, SubscribeFramesInputSchema as st, sleep as t, ProfileSlotSchema as tt, createSliceHandle as u, makeSourceBrokerId as ut, systemMethod as v, isEvent as vt, isDeviceScopedCap as w, resolveHydratedFieldValue as wt, DeviceRole as x, collectHydratedFieldEntries as xt, ChargingStatus as y, WELL_KNOWN_TABS as yt, emitDownForOwnedCaps as z };
3656
+ export { ProfileRtspEntrySchema as $, method as A, scopeKey as B, DeviceType as C, collectHydratedFieldValues as Ct, event as D, DEVICE_STATUS_METHOD as E, readNodePin as F, CamStreamKindSchema as G, BrokerStatusSchema as H, ReadinessRegistry as I, DecodedAudioChunkSchema as J, CamStreamResolutionSchema as K, ReadinessTimeoutError as L, systemMethod as M, CAP_NODE_PIN_CONTEXT_KEY as N, expandCapMethods as O, nodePin as P, FrameHandleSchema as Q, emitDownForOwnedCaps as R, DeviceRole as S, collectHydratedFieldEntries as St, DEVICE_SETTINGS_CONTRIBUTION_METHODS as T, resolveHydratedFieldValue as Tt, CAM_PROFILE_ORDER as U, BrokerStatsSchema as V, CamProfileSchema as W, EncodedPacketSchema as X, DecodedFrameSchema as Y, FrameHandleFormatSchema as Z, RawStateResultSchema as _, createEvent as _t, asJsonObject as a, SubscribeAudioChunksResultSchema as at, ChargingStatus as b, WELL_KNOWN_TABS as bt, parseJsonArray as c, makeProfileBrokerId as ct, DEVICE_SCOPED_CAPS as d, selectAssignedProfileSlots as dt, ProfileSlotSchema as et, isDeviceScopedCap as f, DATAPLANE_SECRET_HEADER as ft, createSliceHandle as g, createDurableState as gt, createMirrorSource as h, normalizeAddonInitResult as ht, asJsonArray as i, SubscribeAudioChunksInputSchema as it, resolveCapMount as j, isDeviceConfigCap as k, parseJsonObject as l, makeSourceBrokerId as lt, createLazyTrpcSource as m, BaseAddon as mt, sleepCancellable as n, StreamSourceEntrySchema$1 as nt, asNumber as o, SubscribeFramesInputSchema as ot, createDeviceProxy as p, DisposerChain as pt, CameraStreamSchema as q, asBoolean as r, StreamSourceSchema as rt, asString as s, SubscribeFramesResultSchema as st, sleep as t, ProfileSlotStatusSchema as tt, parseJsonUnknown as u, parseProfileBrokerId as ut, deviceOpsCapability as v, emitReadiness as vt, adminUiCapability as w, hydrateSchema as wt, DeviceFeature as x, WELL_KNOWN_TAB_MAP as xt, viewerUiCapability as y, isEvent as yt, readinessKey as z };