@camstack/system 1.1.10 → 1.1.12
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-merge.d.ts +22 -0
- package/dist/builtins/device-manager/device-aggregation.d.ts +220 -0
- package/dist/builtins/device-manager/device-bindings-store.d.ts +100 -0
- package/dist/builtins/device-manager/device-manager.addon.d.ts +41 -332
- package/dist/builtins/device-manager/device-manager.addon.js +3294 -2860
- package/dist/builtins/device-manager/device-manager.addon.mjs +3294 -2860
- package/dist/builtins/device-manager/device-meta-actions.d.ts +159 -0
- package/dist/builtins/device-manager/device-meta-store.d.ts +72 -0
- package/dist/builtins/device-manager/device-meta-types.d.ts +169 -0
- package/dist/builtins/device-manager/device-projection.d.ts +74 -0
- package/dist/builtins/device-manager/device-provider-context.d.ts +65 -0
- package/dist/builtins/device-manager/device-queries.d.ts +38 -0
- package/dist/builtins/device-manager/device-state-mirror.d.ts +137 -0
- package/dist/builtins/device-manager/device-sync-resolvers.d.ts +41 -0
- package/dist/index.js +216 -1
- package/dist/index.mjs +216 -3
- package/dist/kernel/cap-router-builder.d.ts +78 -0
- package/dist/kernel/index.d.ts +2 -0
- package/dist/{manifest-python-deps-BqId8WrC.mjs → manifest-python-deps-BfJEdXhi.mjs} +11 -3
- package/dist/{manifest-python-deps-Ba_eOEPT.js → manifest-python-deps-Cro19O4u.js} +9 -1
- package/package.json +1 -1
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 { A as createUdsLoggerWithControl, B as createLocalTransport, C as ipcParentLink, D as createUdsEventBus, E as createUdsEventBridge, F as AGENT_CAP_FWD_SERVICE, G as FrameDecoder, H as UdsLocalTransportServer, I as CapRouteResolver, J as buildUdsNativeCapProxy, K as encodeFrame, L as CapRouteError, M as LocalChildRegistry, N as UDS_NO_ROUTE_PREFIX, O as udsChildLogToWorkerEntry, P as AGENT_CAP_FWD_ACTION, Q as mountNativeCapService, R as classifyCapRoute, S as ipcChildLink, T as createParentUnownedCallHandler, U as SocketChannel, V as UdsLocalTransportClient, W as localEndpointPath, Y as createBrokerDeviceManagerApi, _ as __resetCapUsageRegistryForTests, a as getWorkerDeviceRegistry, at as capBareAction, b as brokerTransportLink, c as setHubConnected, ct as deserializeTypedArrays, d as registerEventBusService, dt as CapabilityHandle, et as createAddonService, f as AddonDepsManager, ft as CapabilityUnavailableError, g as CapUsageRegistry, h as createHwAccelService, i as createUdsAddonContext, it as capActionSuffix, j as LocalChildClient, k as createUdsLogger, l as EVENT_TOPIC_PREFIX, lt as serializeTypedArrays, m as resolveHwAccel, mt as resolveAddonClass, n as adaptBrokerToCluster, nt as NATIVE_PROVIDER_SERVICE_INFIX, o as getOrInitReadinessRegistry, ot as capServiceName, p as createKernelHwAccel, pt as installManifestNativeDeps, q as buildNativeCapProxy, r as createAddonContext, rt as capActionName, s as getOrInitReadinessRegistryForClient, st as parseCapAction, t as installManifestPythonDeps, tt as validateProviderRegistrations, u as getBrokerEventBus, ut as DeviceRegistry, v as getCapUsageRegistry, w as localProviderLink, x as buildLinkChain, y as brokerCallForCap, z as callWithServiceDiscovery } from "./manifest-python-deps-
|
|
21
|
+
import { A as createUdsLoggerWithControl, B as createLocalTransport, C as ipcParentLink, D as createUdsEventBus, E as createUdsEventBridge, F as AGENT_CAP_FWD_SERVICE, G as FrameDecoder, H as UdsLocalTransportServer, I as CapRouteResolver, J as buildUdsNativeCapProxy, K as encodeFrame, L as CapRouteError, M as LocalChildRegistry, N as UDS_NO_ROUTE_PREFIX, O as udsChildLogToWorkerEntry, P as AGENT_CAP_FWD_ACTION, Q as mountNativeCapService, R as classifyCapRoute, S as ipcChildLink, T as createParentUnownedCallHandler, U as SocketChannel, V as UdsLocalTransportClient, W as localEndpointPath, Y as createBrokerDeviceManagerApi, _ as __resetCapUsageRegistryForTests, a as getWorkerDeviceRegistry, at as capBareAction, b as brokerTransportLink, c as setHubConnected, ct as deserializeTypedArrays, d as registerEventBusService, dt as CapabilityHandle, et as createAddonService, f as AddonDepsManager, ft as CapabilityUnavailableError, g as CapUsageRegistry, h as createHwAccelService, i as createUdsAddonContext, it as capActionSuffix, j as LocalChildClient, k as createUdsLogger, l as EVENT_TOPIC_PREFIX, lt as serializeTypedArrays, m as resolveHwAccel, mt as resolveAddonClass, n as adaptBrokerToCluster, nt as NATIVE_PROVIDER_SERVICE_INFIX, o as getOrInitReadinessRegistry, ot as capServiceName, p as createKernelHwAccel, pt as installManifestNativeDeps, q as buildNativeCapProxy, r as createAddonContext, rt as capActionName, s as getOrInitReadinessRegistryForClient, st as parseCapAction, t as installManifestPythonDeps, tt as validateProviderRegistrations, u as getBrokerEventBus, ut as DeviceRegistry, v as getCapUsageRegistry, w as localProviderLink, x as buildLinkChain, y as brokerCallForCap, z as callWithServiceDiscovery } from "./manifest-python-deps-BfJEdXhi.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";
|
|
@@ -26,7 +26,7 @@ import * as fs$17 from "node:fs";
|
|
|
26
26
|
import { accessSync, constants, existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
27
27
|
import * as path$39 from "node:path";
|
|
28
28
|
import { dirname, isAbsolute, join, posix, resolve, win32 } from "node:path";
|
|
29
|
-
import { DATAPLANE_SECRET_HEADER, EventCategory, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, asJsonObject, asNumber, asString, createEvent, emitDownForOwnedCaps, errMsg, lifecycleJobSchema, parseJsonObject, parseJsonUnknown, readinessKey, scopeKey } from "@camstack/types";
|
|
29
|
+
import { ALL_CAPABILITY_DEFINITIONS, DATAPLANE_SECRET_HEADER, EventCategory, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, asJsonObject, asNumber, asString, createEvent, emitDownForOwnedCaps, errMsg, expandCapMethods, lifecycleJobSchema, parseJsonObject, parseJsonUnknown, readinessKey, resolveCapMount, scopeKey } from "@camstack/types";
|
|
30
30
|
import { X509Certificate, createHash, randomUUID, timingSafeEqual } from "node:crypto";
|
|
31
31
|
import { execFile, spawn } from "node:child_process";
|
|
32
32
|
import * as util$10 from "node:util";
|
|
@@ -4888,6 +4888,219 @@ var CapabilityRegistry = class CapabilityRegistry {
|
|
|
4888
4888
|
}
|
|
4889
4889
|
};
|
|
4890
4890
|
//#endregion
|
|
4891
|
+
//#region src/kernel/cap-router-builder.ts
|
|
4892
|
+
/**
|
|
4893
|
+
* Runtime cap-router builder (BIG PLAN 2).
|
|
4894
|
+
*
|
|
4895
|
+
* Builds the per-capability tRPC routers DYNAMICALLY at hub boot by
|
|
4896
|
+
* iterating `ALL_CAPABILITY_DEFINITIONS`, instead of importing the
|
|
4897
|
+
* statically codegen'd `createCapRouter_<Cap>` value functions baked into
|
|
4898
|
+
* `@camstack/server`. Moving the CONSTRUCTION here means a capability
|
|
4899
|
+
* update ships via the framework plugin (`@camstack/types` +
|
|
4900
|
+
* `@camstack/system`, live-updated together) WITHOUT a `@camstack/server`
|
|
4901
|
+
* image rebuild.
|
|
4902
|
+
*
|
|
4903
|
+
* Type vs value split:
|
|
4904
|
+
* - The runtime VALUE is built here, generically.
|
|
4905
|
+
* - The static AppRouter TYPE stays codegen'd into `@camstack/types`
|
|
4906
|
+
* (`generated/addon-api.ts`) via the `generated-cap-routers.ts`
|
|
4907
|
+
* per-cap router factory TYPES. The server delegation site assigns
|
|
4908
|
+
* this builder's output to that static type at the single documented
|
|
4909
|
+
* boundary, so the SDK keeps full procedure inference.
|
|
4910
|
+
*
|
|
4911
|
+
* Behaviour MUST stay byte-identical to the codegen output
|
|
4912
|
+
* (`scripts/generate-cap-routers.ts`). The per-method procedure shape is
|
|
4913
|
+
* mechanically derived from each `cap.methods.*` (input/output zod schema
|
|
4914
|
+
* + kind) + the auto-injected `getStatus` / 3 settings-contribution
|
|
4915
|
+
* methods (via `expandCapMethods`). Provider resolution is derived from
|
|
4916
|
+
* the declarative `mount` hint (`resolveCapMount`) — the same decision the
|
|
4917
|
+
* codegen `generate-cap-mounts.ts` baked in.
|
|
4918
|
+
*
|
|
4919
|
+
* This module owns NO tRPC primitives of its own: `@camstack/system`
|
|
4920
|
+
* cannot import the server's `TrpcContext`-bound procedures. The server
|
|
4921
|
+
* passes them in via {@link CapRouterPrimitives} (the `t` half of the
|
|
4922
|
+
* `buildCapRouters(t, services)` contract), keeping the kernel free of any
|
|
4923
|
+
* backend coupling (self-sufficiency invariant).
|
|
4924
|
+
*/
|
|
4925
|
+
/** Auth level → procedure key. Mirrors codegen's AUTH_PROCEDURE_MAP. */
|
|
4926
|
+
function procedureKeyFor(auth) {
|
|
4927
|
+
if (auth === "public") return "public";
|
|
4928
|
+
if (auth === "admin" || auth === "superAdmin") return "admin";
|
|
4929
|
+
return "protected";
|
|
4930
|
+
}
|
|
4931
|
+
/** Zod schema is `z.void()` — input carries no data. Mirrors codegen's isVoidInput. */
|
|
4932
|
+
function isVoidInput(schema) {
|
|
4933
|
+
const def = schema._def;
|
|
4934
|
+
return schema.constructor?.name === "ZodVoid" || def?.type === "void" || def?.typeName === "ZodVoid";
|
|
4935
|
+
}
|
|
4936
|
+
/** Zod schema is `z.object()` — supports `.loose()` for nodeId passthrough. Mirrors codegen's isObjectInput. */
|
|
4937
|
+
function isObjectInput(schema) {
|
|
4938
|
+
const def = schema._def;
|
|
4939
|
+
return schema.constructor?.name === "ZodObject" || def?.type === "object" || def?.typeName === "ZodObject";
|
|
4940
|
+
}
|
|
4941
|
+
/**
|
|
4942
|
+
* Apply `.loose()` to an object input schema when available (Zod 4) so the
|
|
4943
|
+
* router accepts the out-of-band `nodeId` / `addonId` selector keys
|
|
4944
|
+
* without stripping them — matching the codegen's `.input(schema.loose())`.
|
|
4945
|
+
* Falls back to the schema unchanged when `.loose()` is absent.
|
|
4946
|
+
*/
|
|
4947
|
+
function looseSchema(schema) {
|
|
4948
|
+
const loose = schema.loose;
|
|
4949
|
+
return typeof loose === "function" ? loose.call(schema) : schema;
|
|
4950
|
+
}
|
|
4951
|
+
function methodsFor(def) {
|
|
4952
|
+
const effective = expandCapMethods(def);
|
|
4953
|
+
return Object.entries(effective).map(([name, schema]) => {
|
|
4954
|
+
const m = schema;
|
|
4955
|
+
return {
|
|
4956
|
+
name,
|
|
4957
|
+
kind: m.kind ?? "query",
|
|
4958
|
+
auth: m.auth ?? "protected",
|
|
4959
|
+
schema: m,
|
|
4960
|
+
isVoid: isVoidInput(m.input),
|
|
4961
|
+
isObject: isObjectInput(m.input)
|
|
4962
|
+
};
|
|
4963
|
+
});
|
|
4964
|
+
}
|
|
4965
|
+
/** Strip a set of selector keys from an input object, returning a NEW object. */
|
|
4966
|
+
function stripKeys(input, keys) {
|
|
4967
|
+
const src = input ?? {};
|
|
4968
|
+
const rest = {};
|
|
4969
|
+
const picked = {};
|
|
4970
|
+
for (const [k, v] of Object.entries(src)) if (keys.includes(k)) picked[k] = v;
|
|
4971
|
+
else rest[k] = v;
|
|
4972
|
+
return {
|
|
4973
|
+
rest,
|
|
4974
|
+
picked
|
|
4975
|
+
};
|
|
4976
|
+
}
|
|
4977
|
+
/**
|
|
4978
|
+
* Resolve the provider object for a NON-void/object method call, applying
|
|
4979
|
+
* the same local-first → remote-proxy routing the codegen's
|
|
4980
|
+
* `resolveProvider` does. `nodeId` undefined / `'hub'` resolves the local
|
|
4981
|
+
* provider; otherwise it crosses to the named node via the proxy.
|
|
4982
|
+
*/
|
|
4983
|
+
function resolveProviderForCall(capName, nodeId, getLocal, services) {
|
|
4984
|
+
if (!nodeId || nodeId === "hub") {
|
|
4985
|
+
const local = getLocal();
|
|
4986
|
+
if (local !== null && local !== void 0) return local;
|
|
4987
|
+
const proxy = services.remoteProxy(capName, "hub");
|
|
4988
|
+
if (proxy) return proxy;
|
|
4989
|
+
return services.noProvider(capName);
|
|
4990
|
+
}
|
|
4991
|
+
const proxy = services.remoteProxy(capName, nodeId);
|
|
4992
|
+
if (!proxy) return services.noProvider(capName, nodeId);
|
|
4993
|
+
return proxy;
|
|
4994
|
+
}
|
|
4995
|
+
/** Require a local provider (singleton-style, no node routing) or raise. */
|
|
4996
|
+
function requireLocal(capName, getLocal, services) {
|
|
4997
|
+
const p = getLocal();
|
|
4998
|
+
if (p === null || p === void 0) return services.noProvider(capName);
|
|
4999
|
+
return p;
|
|
5000
|
+
}
|
|
5001
|
+
/**
|
|
5002
|
+
* Build a single capability's router (the runtime equivalent of one
|
|
5003
|
+
* codegen'd `createCapRouter_<Cap>`). Each method becomes a typed
|
|
5004
|
+
* procedure with the SAME routing branch the codegen emits.
|
|
5005
|
+
*/
|
|
5006
|
+
function buildOneCapRouter(def, primitives, services) {
|
|
5007
|
+
const capName = def.name;
|
|
5008
|
+
const mount = resolveCapMount(def);
|
|
5009
|
+
const isCollection = mount.kind === "collection";
|
|
5010
|
+
const nodeIdData = def.nodeIdMode === "data";
|
|
5011
|
+
const procedures = {};
|
|
5012
|
+
const getLocal = (ctx, addonId) => services.getLocalProvider(capName, mount.kind, ctx, addonId);
|
|
5013
|
+
for (const method of methodsFor(def)) {
|
|
5014
|
+
const base = primitives.procedures[procedureKeyFor(method.auth)];
|
|
5015
|
+
const inputSchema = method.schema.input;
|
|
5016
|
+
const outputSchema = method.schema.output;
|
|
5017
|
+
if (method.kind === "subscription") {
|
|
5018
|
+
procedures[method.name] = base.input(inputSchema).subscription(({ input, ctx }) => {
|
|
5019
|
+
const provider = requireLocal(capName, () => getLocal(ctx), services);
|
|
5020
|
+
return primitives.iterableSubscription((push) => {
|
|
5021
|
+
const fn = provider[method.name];
|
|
5022
|
+
const unsub = fn?.(input, push);
|
|
5023
|
+
return typeof unsub === "function" ? unsub : () => {};
|
|
5024
|
+
});
|
|
5025
|
+
});
|
|
5026
|
+
continue;
|
|
5027
|
+
}
|
|
5028
|
+
const procKind = method.kind === "mutation" ? "mutation" : "query";
|
|
5029
|
+
if (method.isVoid) {
|
|
5030
|
+
const voidSelector = isCollection ? z.object({
|
|
5031
|
+
nodeId: z.string().optional(),
|
|
5032
|
+
addonId: z.string().optional()
|
|
5033
|
+
}).optional() : z.object({ nodeId: z.string().optional() }).optional();
|
|
5034
|
+
procedures[method.name] = base.input(voidSelector).output(outputSchema)[procKind](({ input, ctx }) => {
|
|
5035
|
+
const sel = input ?? {};
|
|
5036
|
+
return (nodeIdData ? requireLocal(capName, () => getLocal(ctx, isCollection ? sel.addonId : void 0), services) : resolveProviderForCall(capName, sel.nodeId, () => getLocal(ctx, isCollection ? sel.addonId : void 0), services))[method.name]?.();
|
|
5037
|
+
});
|
|
5038
|
+
continue;
|
|
5039
|
+
}
|
|
5040
|
+
if (method.isObject) {
|
|
5041
|
+
const schema = nodeIdData ? inputSchema : looseSchema(inputSchema);
|
|
5042
|
+
procedures[method.name] = base.input(schema).output(outputSchema)[procKind](({ input, ctx }) => {
|
|
5043
|
+
if (nodeIdData) return requireLocal(capName, () => getLocal(ctx), services)[method.name]?.(input);
|
|
5044
|
+
if (isCollection) {
|
|
5045
|
+
const { rest, picked } = stripKeys(input, ["nodeId", "addonId"]);
|
|
5046
|
+
const nodeId = typeof picked.nodeId === "string" ? picked.nodeId : void 0;
|
|
5047
|
+
const addonId = typeof picked.addonId === "string" ? picked.addonId : void 0;
|
|
5048
|
+
return resolveProviderForCall(capName, nodeId, () => getLocal(ctx, addonId), services)[method.name]?.(rest);
|
|
5049
|
+
}
|
|
5050
|
+
const { rest, picked } = stripKeys(input, ["nodeId"]);
|
|
5051
|
+
return resolveProviderForCall(capName, typeof picked.nodeId === "string" ? picked.nodeId : void 0, () => getLocal(ctx), services)[method.name]?.(rest);
|
|
5052
|
+
});
|
|
5053
|
+
continue;
|
|
5054
|
+
}
|
|
5055
|
+
procedures[method.name] = base.input(inputSchema).output(outputSchema)[procKind](({ input, ctx }) => {
|
|
5056
|
+
return requireLocal(capName, () => getLocal(ctx), services)[method.name]?.(input);
|
|
5057
|
+
});
|
|
5058
|
+
}
|
|
5059
|
+
return primitives.router(procedures);
|
|
5060
|
+
}
|
|
5061
|
+
/** kebab-case → camelCase, matching the codegen router-map key naming. */
|
|
5062
|
+
function kebabToCamel(s) {
|
|
5063
|
+
return s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
5064
|
+
}
|
|
5065
|
+
/**
|
|
5066
|
+
* Mount kinds the runtime builder constructs. `service-backed` IS built
|
|
5067
|
+
* (the server supplies the provider via `getLocalProvider`); `custom` and
|
|
5068
|
+
* `skip` are NOT (the server's hand-written override fills the slot for
|
|
5069
|
+
* `custom`; `skip` is never mounted). `hub-only` is built but its remote
|
|
5070
|
+
* leg is `null` — handled by the server's `remoteProxy` returning null for
|
|
5071
|
+
* that cap.
|
|
5072
|
+
*/
|
|
5073
|
+
function isBuilderMounted(kind) {
|
|
5074
|
+
return kind !== "custom" && kind !== "skip";
|
|
5075
|
+
}
|
|
5076
|
+
/**
|
|
5077
|
+
* Build the runtime cap-router map: `{ <camelCapName>: <router> }` for
|
|
5078
|
+
* every capability the builder owns. Caps with `mount.kind` `custom` /
|
|
5079
|
+
* `skip` are omitted (the server overrides / never mounts them). The
|
|
5080
|
+
* server spreads this BEFORE its hand-written overrides + core routers so
|
|
5081
|
+
* override-by-spread precedence is preserved.
|
|
5082
|
+
*/
|
|
5083
|
+
function buildCapRouters(primitives, services) {
|
|
5084
|
+
const out = {};
|
|
5085
|
+
for (const def of ALL_CAPABILITY_DEFINITIONS) {
|
|
5086
|
+
if (!isBuilderMounted(resolveCapMount(def).kind)) continue;
|
|
5087
|
+
const effective = expandCapMethods(def);
|
|
5088
|
+
if (Object.keys(effective).length === 0) continue;
|
|
5089
|
+
out[kebabToCamel(def.name)] = buildOneCapRouter(def, primitives, services);
|
|
5090
|
+
}
|
|
5091
|
+
return out;
|
|
5092
|
+
}
|
|
5093
|
+
/** The set of cap camelNames the builder owns (for drift checks / tests). */
|
|
5094
|
+
function builderMountedCapNames() {
|
|
5095
|
+
const names = [];
|
|
5096
|
+
for (const def of ALL_CAPABILITY_DEFINITIONS) {
|
|
5097
|
+
if (!isBuilderMounted(resolveCapMount(def).kind)) continue;
|
|
5098
|
+
if (Object.keys(expandCapMethods(def)).length === 0) continue;
|
|
5099
|
+
names.push(kebabToCamel(def.name));
|
|
5100
|
+
}
|
|
5101
|
+
return names;
|
|
5102
|
+
}
|
|
5103
|
+
//#endregion
|
|
4891
5104
|
//#region src/kernel/provider-kind-drift.ts
|
|
4892
5105
|
/**
|
|
4893
5106
|
* Compare a runtime registration hint against the authoritative cap
|
|
@@ -92962,4 +93175,4 @@ async function stageFrameworkLockstep(input) {
|
|
|
92962
93175
|
return results;
|
|
92963
93176
|
}
|
|
92964
93177
|
//#endregion
|
|
92965
|
-
export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CustomActionRegistry, DEFAULT_DATA_PATH, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FRAMEWORK_LOCKSTEP, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LifecycleJobEngine, LifecycleStateMachine, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, RESTART_MARKER_FILE, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, __resetCapUsageRegistryForTests, adaptBrokerToCluster, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, callRegisterNodeWithRetry, callWithServiceDiscovery, capActionName, capActionSuffix, capBareAction, capServiceName, classifyCapRoute, clearPendingRestart, clusterSecretMatches, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createFileDataPlaneHandler, createHubService, createHwAccelService, createKernelHwAccel, createLocalTransport, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, detectWorkspacePackagesDir, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, encodeFrame, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensurePython, ensureTlsCert, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcChildLink, ipcParentLink, isAddonDeploySource, isClusterSecretMismatchError, isInfraCapability, isModelDownloaded, isSourceNewer, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, proxyToUpstream, readPendingRestart, readinessKey, registerEventBusService, resolveFilePath, resolveHwAccel, scheduleSelfRestart, scopeKey, scopesAllowDeviceCap, serializeTypedArrays, setHubConnected, stageFrameworkLockstep, stripCamstackDeps, udsChildLogToWorkerEntry, validateProviderRegistrations, writePendingRestart };
|
|
93178
|
+
export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CustomActionRegistry, DEFAULT_DATA_PATH, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FRAMEWORK_LOCKSTEP, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LifecycleJobEngine, LifecycleStateMachine, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, RESTART_MARKER_FILE, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, __resetCapUsageRegistryForTests, adaptBrokerToCluster, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, capActionName, capActionSuffix, capBareAction, capServiceName, classifyCapRoute, clearPendingRestart, clusterSecretMatches, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createFileDataPlaneHandler, createHubService, createHwAccelService, createKernelHwAccel, createLocalTransport, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, detectWorkspacePackagesDir, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, encodeFrame, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensurePython, ensureTlsCert, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcChildLink, ipcParentLink, isAddonDeploySource, isClusterSecretMismatchError, isInfraCapability, isModelDownloaded, isSourceNewer, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, proxyToUpstream, readPendingRestart, readinessKey, registerEventBusService, resolveFilePath, resolveHwAccel, scheduleSelfRestart, scopeKey, scopesAllowDeviceCap, serializeTypedArrays, setHubConnected, stageFrameworkLockstep, stripCamstackDeps, udsChildLogToWorkerEntry, validateProviderRegistrations, writePendingRestart };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { CapabilityMountKind } from '@camstack/types';
|
|
2
|
+
/**
|
|
3
|
+
* A tRPC-procedure-like builder. Mirrors the chainable surface the
|
|
4
|
+
* codegen emits (`procedure.input(...).output(...).query(...)`), kept
|
|
5
|
+
* structural so the server can pass its real `protectedProcedure` /
|
|
6
|
+
* `adminProcedure` / `publicProcedure` without this module importing
|
|
7
|
+
* `@trpc/server` context types.
|
|
8
|
+
*/
|
|
9
|
+
export interface ProcedureBuilder {
|
|
10
|
+
input(schema: unknown): ProcedureBuilder;
|
|
11
|
+
output(schema: unknown): ProcedureBuilder;
|
|
12
|
+
query(resolver: (opts: ProcedureResolverArgs) => unknown): unknown;
|
|
13
|
+
mutation(resolver: (opts: ProcedureResolverArgs) => unknown): unknown;
|
|
14
|
+
subscription(resolver: (opts: ProcedureResolverArgs) => unknown): unknown;
|
|
15
|
+
}
|
|
16
|
+
/** Args object tRPC hands a procedure resolver (input + ctx). */
|
|
17
|
+
export interface ProcedureResolverArgs {
|
|
18
|
+
readonly input: unknown;
|
|
19
|
+
readonly ctx: unknown;
|
|
20
|
+
}
|
|
21
|
+
/** The `t`-half of `buildCapRouters(t, services)`: tRPC primitives the server owns. */
|
|
22
|
+
export interface CapRouterPrimitives {
|
|
23
|
+
/** `t.router` — assembles a `Record<methodName, procedure>` into a router. */
|
|
24
|
+
readonly router: (procedures: Record<string, unknown>) => unknown;
|
|
25
|
+
/** Map of auth level → base procedure (`public`/`protected`/`admin`). */
|
|
26
|
+
readonly procedures: Readonly<Record<'public' | 'protected' | 'admin', ProcedureBuilder>>;
|
|
27
|
+
/**
|
|
28
|
+
* Wrap a push-based subscription into the async-generator tRPC v11
|
|
29
|
+
* expects. Identical to the server's `iterableSubscription`.
|
|
30
|
+
*/
|
|
31
|
+
readonly iterableSubscription: <T>(subscribe: (push: (value: T) => void) => () => void) => AsyncGenerator<T>;
|
|
32
|
+
}
|
|
33
|
+
/** A method the runtime can call on a resolved provider object. */
|
|
34
|
+
type ProviderMethod = (input?: unknown, push?: (value: unknown) => void) => unknown;
|
|
35
|
+
type ResolvedProvider = Readonly<Record<string, ProviderMethod>>;
|
|
36
|
+
/**
|
|
37
|
+
* Per-cap provider getter. `addonId` is only consulted for collection
|
|
38
|
+
* caps (selects a specific provider within the local collection); the
|
|
39
|
+
* server's `services`-backed resolution lives behind this closure so the
|
|
40
|
+
* builder never touches the registry or backend services directly.
|
|
41
|
+
*/
|
|
42
|
+
export type CapProviderGetter = (ctx: unknown, addonId?: string) => ResolvedProvider | null;
|
|
43
|
+
/** Cross-node proxy factory — Moleculer-bridged provider for a remote node. */
|
|
44
|
+
export type RemoteProxyFactory = (capName: string, nodeId: string) => ResolvedProvider | null;
|
|
45
|
+
/**
|
|
46
|
+
* Everything the builder needs from the server to resolve a cap's
|
|
47
|
+
* provider object. The server supplies these closures; the builder owns
|
|
48
|
+
* the procedure shape + routing decision.
|
|
49
|
+
*/
|
|
50
|
+
export interface CapRouterServices {
|
|
51
|
+
/**
|
|
52
|
+
* Resolve the LOCAL provider for a cap given the effective mount kind.
|
|
53
|
+
* Returns null on miss (the procedure surfaces PRECONDITION_FAILED).
|
|
54
|
+
* For `service-backed` caps this calls the server-supplied service
|
|
55
|
+
* provider factory; for `singleton` / `device-native` / `collection`
|
|
56
|
+
* it goes through the registry.
|
|
57
|
+
*/
|
|
58
|
+
readonly getLocalProvider: (capName: string, mountKind: CapabilityMountKind, ctx: unknown, addonId?: string) => ResolvedProvider | null;
|
|
59
|
+
/** Cross-node Moleculer-bridged proxy. */
|
|
60
|
+
readonly remoteProxy: RemoteProxyFactory;
|
|
61
|
+
/** Raise the canonical "no provider" tRPC error (server owns TRPCError). */
|
|
62
|
+
readonly noProvider: (capName: string, nodeId?: string) => never;
|
|
63
|
+
/** Raise the canonical "node routing unavailable" tRPC error. */
|
|
64
|
+
readonly noNodeRouting: (capName: string) => never;
|
|
65
|
+
/** Raise the canonical "bad request: missing field" error. */
|
|
66
|
+
readonly badRequest: (message: string) => never;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Build the runtime cap-router map: `{ <camelCapName>: <router> }` for
|
|
70
|
+
* every capability the builder owns. Caps with `mount.kind` `custom` /
|
|
71
|
+
* `skip` are omitted (the server overrides / never mounts them). The
|
|
72
|
+
* server spreads this BEFORE its hand-written overrides + core routers so
|
|
73
|
+
* override-by-spread precedence is preserved.
|
|
74
|
+
*/
|
|
75
|
+
export declare function buildCapRouters(primitives: CapRouterPrimitives, services: CapRouterServices): Record<string, unknown>;
|
|
76
|
+
/** The set of cap camelNames the builder owns (for drift checks / tests). */
|
|
77
|
+
export declare function builderMountedCapNames(): readonly string[];
|
|
78
|
+
export {};
|
package/dist/kernel/index.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export { RESTART_MARKER_FILE, clearPendingRestart, getRestartMarkerPath, readPen
|
|
|
11
11
|
export type { PendingRestartMarker, RestartKind, ScheduleSelfRestartOptions, } from './restart-coordinator.js';
|
|
12
12
|
export { CapabilityHandle, CapabilityUnavailableError } from './capability-handle.js';
|
|
13
13
|
export { CapabilityRegistry } from './capability-registry.js';
|
|
14
|
+
export { buildCapRouters, builderMountedCapNames } from './cap-router-builder.js';
|
|
15
|
+
export type { CapRouterPrimitives, CapRouterServices, CapProviderGetter, RemoteProxyFactory, ProcedureBuilder, ProcedureResolverArgs, } from './cap-router-builder.js';
|
|
14
16
|
export { describeProviderKindDrift } from './provider-kind-drift.js';
|
|
15
17
|
export type { ProviderKindHint } from './provider-kind-drift.js';
|
|
16
18
|
export type { CapabilityRouter, CapabilityRouterFactory, ConfigReader, } from './capability-registry.js';
|
|
@@ -11,7 +11,7 @@ import { promisify } from "node:util";
|
|
|
11
11
|
import * as os from "node:os";
|
|
12
12
|
import { tmpdir } from "node:os";
|
|
13
13
|
import { unlink } from "node:fs/promises";
|
|
14
|
-
import { DATAPLANE_SECRET_HEADER as DATAPLANE_SECRET_HEADER$1, DeviceType as DeviceType$1, DisposerChain, EventCategory as EventCategory$1, ReadinessRegistry, asJsonObject as asJsonObject$1, asString as asString$1, createDeviceProxy, deviceOpsCapability, emitReadiness, errMsg as errMsg$1, expandCapMethods, scopeKey, sleep as sleep$1 } from "@camstack/types/addon";
|
|
14
|
+
import { DATAPLANE_SECRET_HEADER as DATAPLANE_SECRET_HEADER$1, DeviceType as DeviceType$1, DisposerChain, EventCategory as EventCategory$1, ReadinessRegistry, asJsonObject as asJsonObject$1, asString as asString$1, createDeviceProxy, deviceOpsCapability, emitReadiness, errMsg as errMsg$1, expandCapMethods as expandCapMethods$1, scopeKey, sleep as sleep$1 } from "@camstack/types/addon";
|
|
15
15
|
import { TRPCClientError, createTRPCClient } from "@trpc/client";
|
|
16
16
|
import { connect, createServer as createServer$1 } from "node:net";
|
|
17
17
|
//#region src/kernel/addon-class-resolver.ts
|
|
@@ -925,7 +925,7 @@ var nativeCapReadinessGeneration = typeof crypto !== "undefined" && crypto.rando
|
|
|
925
925
|
function mountNativeCapService(broker, addonId, cap) {
|
|
926
926
|
const serviceName = capServiceName(addonId, cap.name, true);
|
|
927
927
|
if (mountedNativeCapServices.has(serviceName)) return;
|
|
928
|
-
const expandedMethods = expandCapMethods(cap);
|
|
928
|
+
const expandedMethods = expandCapMethods$1(cap);
|
|
929
929
|
if (expandedMethods === void 0 || Object.keys(expandedMethods).length === 0 || typeof broker.createService !== "function") {
|
|
930
930
|
mountedNativeCapServices.add(serviceName);
|
|
931
931
|
return;
|
|
@@ -1288,11 +1288,19 @@ function createBrokerDeviceManagerApi(opts) {
|
|
|
1288
1288
|
deviceId: id,
|
|
1289
1289
|
data: spec.config
|
|
1290
1290
|
}).catch(() => {});
|
|
1291
|
-
const [initialRuntimeState,
|
|
1291
|
+
const [initialRuntimeState, loadedConfig, deviceMeta] = await Promise.all([
|
|
1292
1292
|
callDeviceManager(api, "loadRuntimeState", { deviceId: id }).catch(() => empty),
|
|
1293
1293
|
callDeviceManager(api, "loadConfig", { deviceId: id }).catch(() => empty),
|
|
1294
1294
|
callDeviceManager(api, "loadMeta", { deviceId: id }).catch(() => null)
|
|
1295
1295
|
]);
|
|
1296
|
+
let persistedConfig = loadedConfig;
|
|
1297
|
+
if (!isFirstSpawn && Object.keys(loadedConfig).length === 0 && Object.keys(spec.config).length > 0) {
|
|
1298
|
+
await callDeviceManager(api, "persistConfig", {
|
|
1299
|
+
deviceId: id,
|
|
1300
|
+
data: spec.config
|
|
1301
|
+
}).catch(() => {});
|
|
1302
|
+
persistedConfig = spec.config;
|
|
1303
|
+
}
|
|
1296
1304
|
const childCtx = buildContext(childStableId, id, parent.id, initialRuntimeState, persistedConfig, deviceMeta);
|
|
1297
1305
|
const child = spec.factory(childCtx);
|
|
1298
1306
|
await deviceApi.register(child);
|
|
@@ -1290,11 +1290,19 @@ function createBrokerDeviceManagerApi(opts) {
|
|
|
1290
1290
|
deviceId: id,
|
|
1291
1291
|
data: spec.config
|
|
1292
1292
|
}).catch(() => {});
|
|
1293
|
-
const [initialRuntimeState,
|
|
1293
|
+
const [initialRuntimeState, loadedConfig, deviceMeta] = await Promise.all([
|
|
1294
1294
|
callDeviceManager(api, "loadRuntimeState", { deviceId: id }).catch(() => empty),
|
|
1295
1295
|
callDeviceManager(api, "loadConfig", { deviceId: id }).catch(() => empty),
|
|
1296
1296
|
callDeviceManager(api, "loadMeta", { deviceId: id }).catch(() => null)
|
|
1297
1297
|
]);
|
|
1298
|
+
let persistedConfig = loadedConfig;
|
|
1299
|
+
if (!isFirstSpawn && Object.keys(loadedConfig).length === 0 && Object.keys(spec.config).length > 0) {
|
|
1300
|
+
await callDeviceManager(api, "persistConfig", {
|
|
1301
|
+
deviceId: id,
|
|
1302
|
+
data: spec.config
|
|
1303
|
+
}).catch(() => {});
|
|
1304
|
+
persistedConfig = spec.config;
|
|
1305
|
+
}
|
|
1298
1306
|
const childCtx = buildContext(childStableId, id, parent.id, initialRuntimeState, persistedConfig, deviceMeta);
|
|
1299
1307
|
const child = spec.factory(childCtx);
|
|
1300
1308
|
await deviceApi.register(child);
|