@camstack/system 1.1.11 → 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/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-1zTy3vXe.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-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 {};
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/system",
3
- "version": "1.1.11",
3
+ "version": "1.1.12",
4
4
  "description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
5
5
  "keywords": [
6
6
  "camstack",