@camstack/system 1.1.22 → 1.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon-runner.js +1 -1
- package/dist/addon-runner.mjs +1 -1
- package/dist/builtins/device-manager/device-aggregation.d.ts +8 -1
- package/dist/builtins/device-manager/device-bindings-store.d.ts +3 -0
- package/dist/builtins/device-manager/device-link-cycle.d.ts +18 -0
- package/dist/builtins/device-manager/device-link-overlay.d.ts +15 -5
- package/dist/builtins/device-manager/device-link-resolver.d.ts +31 -2
- package/dist/builtins/device-manager/device-manager.addon.d.ts +9 -2
- package/dist/builtins/device-manager/device-manager.addon.js +585 -62
- package/dist/builtins/device-manager/device-manager.addon.mjs +586 -63
- package/dist/builtins/device-manager/device-meta-actions.d.ts +21 -0
- package/dist/builtins/device-manager/device-meta-store.d.ts +6 -0
- package/dist/builtins/device-manager/device-meta-types.d.ts +12 -1
- package/dist/builtins/device-manager/device-projection.d.ts +1 -0
- package/dist/builtins/device-manager/device-provider-context.d.ts +4 -0
- package/dist/builtins/device-manager/device-state-mirror.d.ts +13 -5
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{manifest-python-deps-hDWMDe_b.mjs → manifest-python-deps-CPJXzrZt.mjs} +12 -0
- package/dist/{manifest-python-deps-D7iR07uA.js → manifest-python-deps-XWJwKYDx.js} +12 -0
- package/package.json +1 -1
|
@@ -97,6 +97,27 @@ export declare function setDeviceLinks(pctx: ProviderContext, input: Parameters<
|
|
|
97
97
|
* `setIntegrationId`). Idempotent. `null` clears a previous role.
|
|
98
98
|
*/
|
|
99
99
|
export declare function setRole(pctx: ProviderContext, input: Parameters<IDeviceManagerProvider['setRole']>[0]): ReturnType<IDeviceManagerProvider['setRole']>;
|
|
100
|
+
/**
|
|
101
|
+
* Set (or clear) the per-device display override on a device's meta row.
|
|
102
|
+
* Mirrors `setChildLayout` persistence; `null` REMOVES the `display` key
|
|
103
|
+
* entirely (immutable rest-destructure — matches the "absent ⇒ no override"
|
|
104
|
+
* projection contract, never persists `display: undefined`). Override units are
|
|
105
|
+
* normalized at write so the render path always looks up canonical spellings.
|
|
106
|
+
*/
|
|
107
|
+
export declare function setDisplay(pctx: ProviderContext, input: Parameters<IDeviceManagerProvider['setDisplay']>[0]): ReturnType<IDeviceManagerProvider['setDisplay']>;
|
|
108
|
+
/**
|
|
109
|
+
* Read the operator-authored per-role display defaults. Empty record when none
|
|
110
|
+
* set. Not per-device — a plain top-level-key read.
|
|
111
|
+
*/
|
|
112
|
+
export declare function getRoleDisplayDefaults(pctx: ProviderContext, _input: Parameters<IDeviceManagerProvider['getRoleDisplayDefaults']>[0]): ReturnType<IDeviceManagerProvider['getRoleDisplayDefaults']>;
|
|
113
|
+
/**
|
|
114
|
+
* Replace the per-role display defaults whole-record (full replace). Override
|
|
115
|
+
* units are normalized (`normalizeUnit`) at write so the render path always
|
|
116
|
+
* looks up canonical spellings. Single-writer top-level key — no lock, no RMW,
|
|
117
|
+
* no interaction with the `deviceMeta` write lock. Not per-device, so no event
|
|
118
|
+
* is emitted; the UI invalidates its own query on mutate.
|
|
119
|
+
*/
|
|
120
|
+
export declare function setRoleDisplayDefaults(pctx: ProviderContext, input: Parameters<IDeviceManagerProvider['setRoleDisplayDefaults']>[0]): ReturnType<IDeviceManagerProvider['setRoleDisplayDefaults']>;
|
|
100
121
|
/**
|
|
101
122
|
* Batched meta pre-seed. Applies every provided field to the
|
|
102
123
|
* device's meta row in ONE read-modify-write under a single
|
|
@@ -62,6 +62,12 @@ export declare class DeviceMetaStore {
|
|
|
62
62
|
* whose stableId is `${parentStableId}-${sourceKey}`. Null when absent.
|
|
63
63
|
* Pure over a pre-read meta map so a multi-link resolve reads the store once. */
|
|
64
64
|
resolveSourceDeviceId: (parentStableId: string, sourceKey: string, meta: Record<string, PersistedDeviceMeta>) => number | null;
|
|
65
|
+
/** Resolve a GLOBAL link source (P2e) to a live device id: the device whose
|
|
66
|
+
* FULL stableId equals `sourceStableId`, regardless of parent container.
|
|
67
|
+
* First match wins (stableIds are effectively unique cluster-wide — see the
|
|
68
|
+
* `DeviceLinkGlobalSource` docblock). Null when absent. Pure over a
|
|
69
|
+
* pre-read meta map so a multi-link resolve reads the store once. */
|
|
70
|
+
resolveGlobalSourceDeviceId: (sourceStableId: string, meta: Record<string, PersistedDeviceMeta>) => number | null;
|
|
65
71
|
allocateNextDeviceId: () => Promise<number>;
|
|
66
72
|
/** Rebuild the `linkTargets` / `linkDependents` reverse-index maps from the
|
|
67
73
|
* current persisted meta. Called at boot (once the `devicesWithLinks` seed
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChildLayout, DeviceLinks } from '@camstack/types';
|
|
1
|
+
import { ChildLayout, DeviceDisplayOverride, DeviceLinks, RoleDisplayDefault } from '@camstack/types';
|
|
2
2
|
/**
|
|
3
3
|
* Wire shape matching `z.infer<typeof SettingsSchemaWithValuesSchema>` —
|
|
4
4
|
* duplicated as a plain interface because importing the Zod schema across
|
|
@@ -132,6 +132,11 @@ export interface PersistedDeviceMeta {
|
|
|
132
132
|
* Optional: only present for accessory children that carry a known role
|
|
133
133
|
* (e.g. 'numeric-sensor', 'binary-sensor'). `null` clears a previous role. */
|
|
134
134
|
role?: string | null;
|
|
135
|
+
/** Operator-authored per-device display override (icon/label/unit/precision/
|
|
136
|
+
* hidden), set via `setDisplay`. Same create/persist/project/restore
|
|
137
|
+
* lifecycle as `deviceLinks`. Absent ⇒ no override. Applied at render time
|
|
138
|
+
* only — storage stays in source units. */
|
|
139
|
+
display?: DeviceDisplayOverride;
|
|
135
140
|
}
|
|
136
141
|
export interface AddonStore {
|
|
137
142
|
deviceIndex?: Record<string, string[]>;
|
|
@@ -166,4 +171,10 @@ export interface AddonStore {
|
|
|
166
171
|
* the operator forgot to register a label before assigning it.
|
|
167
172
|
*/
|
|
168
173
|
locations?: readonly string[];
|
|
174
|
+
/** Operator-authored per-role display defaults (unit/precision/icon), keyed
|
|
175
|
+
* by `DeviceRole` string. Resolution merges these UNDER any per-device
|
|
176
|
+
* `display` override. Written whole-record by `setRoleDisplayDefaults`
|
|
177
|
+
* (full replace — no read-modify-write, single writer, so it never
|
|
178
|
+
* interacts with the `deviceMeta` write lock). */
|
|
179
|
+
roleDisplayDefaults?: Record<string, RoleDisplayDefault>;
|
|
169
180
|
}
|
|
@@ -47,6 +47,7 @@ export declare function isDeviceRole(value: string): value is DeviceRole;
|
|
|
47
47
|
* never leaks an off-enum string onto the wire shape. */
|
|
48
48
|
export declare function toDeviceRole(value: string | null | undefined): DeviceRole | null;
|
|
49
49
|
export declare function toDeviceInfo(addonId: string, device: IDevice, metadata?: Record<string, unknown> | null, metaRow?: PersistedDeviceMeta | null): {
|
|
50
|
+
display?: import('@camstack/types').DeviceDisplayOverride | undefined;
|
|
50
51
|
deviceLinks?: import('@camstack/types').DeviceLinks | undefined;
|
|
51
52
|
childLayout?: import('@camstack/types').ChildLayout | undefined;
|
|
52
53
|
primaryChildEntityId?: string | null | undefined;
|
|
@@ -14,6 +14,10 @@ export interface ProviderHost {
|
|
|
14
14
|
readonly devicesWithLinks: Set<number>;
|
|
15
15
|
/** Expected link-source stableIds, gating the `registerDevice` rebuild. */
|
|
16
16
|
readonly expectedSourceStableIds: Set<string>;
|
|
17
|
+
/** In-flight `${deviceId}:${cap}` pairs of `resolveLinkedStatus` — the
|
|
18
|
+
* defensive re-entrancy guard that bounds link cycles at resolve time
|
|
19
|
+
* (P2e). A nested resolve of a pair already in flight returns null. */
|
|
20
|
+
readonly linkResolveInFlight: Set<string>;
|
|
17
21
|
/** Drop a removed device's overlay-emit guard entries (state-mirror keyed
|
|
18
22
|
* `${deviceId}:${cap}`). Called from `removeDevice`. */
|
|
19
23
|
dropDeviceOverlays(deviceId: number): void;
|
|
@@ -108,18 +108,26 @@ export declare class DeviceStateMirror {
|
|
|
108
108
|
* Read-time overlay of a cap slice with its cross-device linked values.
|
|
109
109
|
* Returns a cloned raw mirror slice when the (device, cap) pair has no
|
|
110
110
|
* links. Sources are read from the same in-hub stateMirror — sync, no
|
|
111
|
-
* cross-process call.
|
|
112
|
-
*
|
|
111
|
+
* cross-process call. When the raw slice is ABSENT but the cap is a link
|
|
112
|
+
* target, the slice is SYNTHESIZED: the merge base is seeded from the
|
|
113
|
+
* cap's declared `status.empty` default; a failed/empty synthesize
|
|
114
|
+
* returns null (no phantom slices). The disk writer must NOT use this
|
|
115
|
+
* method; it must persist raw provider truth via snapshotForDevice.
|
|
113
116
|
*/
|
|
114
117
|
overlayedSlice(deviceId: number, cap: string): Record<string, unknown> | null;
|
|
115
118
|
/**
|
|
116
119
|
* Like snapshotForDevice but applies the device-link overlay per cap.
|
|
117
120
|
* Used exclusively by the device-state READ methods (getSnapshot,
|
|
118
|
-
* getAllSnapshots) so callers see overlayed values.
|
|
119
|
-
*
|
|
121
|
+
* getAllSnapshots) so callers see overlayed values. SYNTHESIZE-only
|
|
122
|
+
* link-target caps (no base mirror slice) are unioned into the iterated
|
|
123
|
+
* key set so they appear at warm-load — `overlayedSlice` builds them from
|
|
124
|
+
* the cap's `status.empty` (and drops them when nothing resolves). The
|
|
125
|
+
* debounced disk writer must continue to call snapshotForDevice (raw truth).
|
|
120
126
|
*/
|
|
121
127
|
snapshotForDeviceOverlayed(deviceId: number): Record<string, Record<string, unknown>>;
|
|
122
|
-
/** Whole-system mirror dump (overlaid). Backs `deviceState.getAllSnapshots`.
|
|
128
|
+
/** Whole-system mirror dump (overlaid). Backs `deviceState.getAllSnapshots`.
|
|
129
|
+
* Devices that only exist as link TARGETS (no mirror slice yet) are
|
|
130
|
+
* included via the link reverse-index so their synthesized caps appear. */
|
|
123
131
|
allSnapshotsOverlayed(): Record<string, Record<string, Record<string, unknown>>>;
|
|
124
132
|
private emitStateChanged;
|
|
125
133
|
/** Emit DeviceStateChanged for (deviceId, cap) using the OVERLAID slice,
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ const require_builtins_local_auth_local_auth_addon = require("./builtins/local-a
|
|
|
20
20
|
require("./builtins/local-auth/index.js");
|
|
21
21
|
const require_builtins_device_manager_device_manager_addon = require("./builtins/device-manager/device-manager.addon.js");
|
|
22
22
|
require("./builtins/device-manager/index.js");
|
|
23
|
-
const require_manifest_python_deps = require("./manifest-python-deps-
|
|
23
|
+
const require_manifest_python_deps = require("./manifest-python-deps-XWJwKYDx.js");
|
|
24
24
|
const require_custom_action_registry = require("./custom-action-registry-vLYEFTtv.js");
|
|
25
25
|
let _camstack_types_node = require("@camstack/types/node");
|
|
26
26
|
let node_http = require("node:http");
|
package/dist/index.mjs
CHANGED
|
@@ -18,7 +18,7 @@ import { LocalAuthAddon, a as require_ms, c as __esmMin, d as __toCommonJS, f as
|
|
|
18
18
|
import "./builtins/local-auth/index.mjs";
|
|
19
19
|
import { DeviceManagerAddon } from "./builtins/device-manager/device-manager.addon.mjs";
|
|
20
20
|
import "./builtins/device-manager/index.mjs";
|
|
21
|
-
import { $ as buildNativeCapProxy, A as createHubCapForwardService, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, D as localProviderLink, E as ipcParentLink, F as createUdsLogger, G as callWithServiceDiscovery, H as CapRouteResolver, I as createUdsLoggerWithControl, J as UdsLocalTransportServer, K as createLocalTransport, L as LocalChildClient, M as createUdsEventBridge, N as createUdsEventBus, O as HUB_CAP_FWD_ACTION, P as udsChildLogToWorkerEntry, Q as encodeFrame, R as LocalChildRegistry, S as brokerCallForCap, T as ipcChildLink, U as CapRouteError, V as AGENT_CAP_FWD_SERVICE, W as classifyCapRoute, X as localEndpointPath, Y as SocketChannel, Z as FrameDecoder, _ as resolveHwAccel, _t as CapabilityHandle, a as getWorkerDeviceRegistry, b as __resetCapUsageRegistryForTests, bt as resolveAddonClass, c as setHubConnected, ct as NATIVE_PROVIDER_SERVICE_INFIX, d as getMoleculerEventStats, dt as capBareAction, et as buildUdsNativeCapProxy, f as registerEventBusService, ft as capServiceName, g as createKernelHwAccel, gt as DeviceRegistry, h as AddonDepsManager, ht as serializeTypedArrays, i as createUdsAddonContext, it as mountNativeCapService, j as createParentUnownedCallHandler, k as HUB_CAP_FWD_SERVICE, l as EVENT_TOPIC_PREFIX, lt as capActionName, m as subscribePassthrough, mt as deserializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as createAddonService, p as setNodeEventInterest, pt as parseCapAction, q as UdsLocalTransportClient, r as createAddonContext, s as getOrInitReadinessRegistryForClient, st as validateProviderRegistrations, t as installManifestPythonDeps, tt as createBrokerDeviceManagerApi, u as getBrokerEventBus, ut as capActionSuffix, v as createHwAccelService, vt as CapabilityUnavailableError, w as buildLinkChain, x as getCapUsageRegistry, y as CapUsageRegistry, yt as installManifestNativeDeps, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-
|
|
21
|
+
import { $ as buildNativeCapProxy, A as createHubCapForwardService, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, D as localProviderLink, E as ipcParentLink, F as createUdsLogger, G as callWithServiceDiscovery, H as CapRouteResolver, I as createUdsLoggerWithControl, J as UdsLocalTransportServer, K as createLocalTransport, L as LocalChildClient, M as createUdsEventBridge, N as createUdsEventBus, O as HUB_CAP_FWD_ACTION, P as udsChildLogToWorkerEntry, Q as encodeFrame, R as LocalChildRegistry, S as brokerCallForCap, T as ipcChildLink, U as CapRouteError, V as AGENT_CAP_FWD_SERVICE, W as classifyCapRoute, X as localEndpointPath, Y as SocketChannel, Z as FrameDecoder, _ as resolveHwAccel, _t as CapabilityHandle, a as getWorkerDeviceRegistry, b as __resetCapUsageRegistryForTests, bt as resolveAddonClass, c as setHubConnected, ct as NATIVE_PROVIDER_SERVICE_INFIX, d as getMoleculerEventStats, dt as capBareAction, et as buildUdsNativeCapProxy, f as registerEventBusService, ft as capServiceName, g as createKernelHwAccel, gt as DeviceRegistry, h as AddonDepsManager, ht as serializeTypedArrays, i as createUdsAddonContext, it as mountNativeCapService, j as createParentUnownedCallHandler, k as HUB_CAP_FWD_SERVICE, l as EVENT_TOPIC_PREFIX, lt as capActionName, m as subscribePassthrough, mt as deserializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as createAddonService, p as setNodeEventInterest, pt as parseCapAction, q as UdsLocalTransportClient, r as createAddonContext, s as getOrInitReadinessRegistryForClient, st as validateProviderRegistrations, t as installManifestPythonDeps, tt as createBrokerDeviceManagerApi, u as getBrokerEventBus, ut as capActionSuffix, v as createHwAccelService, vt as CapabilityUnavailableError, w as buildLinkChain, x as getCapUsageRegistry, y as CapUsageRegistry, yt as installManifestNativeDeps, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-CPJXzrZt.mjs";
|
|
22
22
|
import { t as CustomActionRegistry } from "./custom-action-registry-BEXwC-oo.mjs";
|
|
23
23
|
import { PYTHON_VERSION, buildBinaryPath, downloadBinary, ensureBinary, ensureFfmpeg, ensurePython, findInPath, getFfmpegDownloadUrl, getPlatformInfo, getPythonDownloadUrl, installPythonPackages, installPythonRequirements } from "@camstack/types/node";
|
|
24
24
|
import { request } from "node:http";
|
|
@@ -1423,6 +1423,18 @@ function createBrokerDeviceManagerApi(opts) {
|
|
|
1423
1423
|
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
1424
1424
|
});
|
|
1425
1425
|
});
|
|
1426
|
+
if (initialMeta.display !== void 0) await callDeviceManager(api, "setDisplay", {
|
|
1427
|
+
deviceId: id,
|
|
1428
|
+
display: initialMeta.display
|
|
1429
|
+
}).catch((err) => {
|
|
1430
|
+
opts.logger.warn("create: setDisplay pre-seed failed", {
|
|
1431
|
+
tags: {
|
|
1432
|
+
stableId,
|
|
1433
|
+
deviceId: id
|
|
1434
|
+
},
|
|
1435
|
+
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
1436
|
+
});
|
|
1437
|
+
});
|
|
1426
1438
|
}
|
|
1427
1439
|
if (Object.keys(config).length > 0) await callDeviceManager(api, "persistConfig", {
|
|
1428
1440
|
deviceId: id,
|
|
@@ -1425,6 +1425,18 @@ function createBrokerDeviceManagerApi(opts) {
|
|
|
1425
1425
|
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
1426
1426
|
});
|
|
1427
1427
|
});
|
|
1428
|
+
if (initialMeta.display !== void 0) await callDeviceManager(api, "setDisplay", {
|
|
1429
|
+
deviceId: id,
|
|
1430
|
+
display: initialMeta.display
|
|
1431
|
+
}).catch((err) => {
|
|
1432
|
+
opts.logger.warn("create: setDisplay pre-seed failed", {
|
|
1433
|
+
tags: {
|
|
1434
|
+
stableId,
|
|
1435
|
+
deviceId: id
|
|
1436
|
+
},
|
|
1437
|
+
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
1438
|
+
});
|
|
1439
|
+
});
|
|
1428
1440
|
}
|
|
1429
1441
|
if (Object.keys(config).length > 0) await callDeviceManager(api, "persistConfig", {
|
|
1430
1442
|
deviceId: id,
|