@camstack/server 1.1.25 → 1.1.27

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.
@@ -4,16 +4,16 @@ exports.createHwAccelRouter = createHwAccelRouter;
4
4
  /**
5
5
  * Hwaccel router — fixed core API (not a capability).
6
6
  *
7
- * Thin wrapper around the per-node `$hwaccel.resolve` Moleculer
8
- * service. The hub-local instance (same process) serves the default
9
- * `resolve` call; the per-node `resolveForNode` action targets any
10
- * node in the cluster — used by the admin UI pipeline / NodeDetail
11
- * pages to show the hwaccel backends available on each agent.
7
+ * Repointed (S3 consolidation) onto the `platform-probe` capability — the SOLE
8
+ * cross-node-pinnable hwaccel surface instead of the retired `$hwaccel`
9
+ * Moleculer service. The hub-local instance is resolved via
10
+ * `capabilityRegistry.getSingleton('platform-probe')`; any other cluster node
11
+ * via `moleculer.createCapabilityProxy('platform-probe', nodeId)` (the same
12
+ * node-routing the codegen'd cap routers use). Used by the admin UI pipeline /
13
+ * NodeDetail pages to show which hardware backend each node will use.
12
14
  *
13
- * Cross-node behaviour: `resolveForNode({ nodeId })` forwards via
14
- * `broker.call('$hwaccel.resolve', params, { nodeID })`. Every node
15
- * (hub + forked worker + remote agent) registers `$hwaccel` at
16
- * bootstrap, so any reachable nodeId works.
15
+ * The tRPC input/output shapes are UNCHANGED for clients (`{prefer}` in,
16
+ * `{preferred, rationale}` out) no SDK break.
17
17
  */
18
18
  const zod_1 = require("zod");
19
19
  const trpc_middleware_js_1 = require("../trpc/trpc.middleware.js");
@@ -33,33 +33,69 @@ const HwAccelPreferSchema = zod_1.z
33
33
  .union([HwAccelBackendSchema, zod_1.z.literal('none')])
34
34
  .nullable()
35
35
  .optional();
36
+ // `preferred` is a plain string array (not the decode-backend enum) to match
37
+ // the `platform-probe` cap's own resolution schema: the resolver only ever
38
+ // emits decode backends, but a narrow enum would reject any future addition and
39
+ // force a cast at the cap boundary.
36
40
  const HwAccelResolutionSchema = zod_1.z.object({
37
- preferred: zod_1.z.array(HwAccelBackendSchema).readonly(),
41
+ preferred: zod_1.z.array(zod_1.z.string()).readonly(),
38
42
  rationale: zod_1.z.string(),
39
43
  });
40
- function createHwAccelRouter(broker) {
44
+ /**
45
+ * Resolve hwaccel on a specific cluster node through the `platform-probe` cap
46
+ * proxy. `createCapabilityProxy` returns `Record<string, (params) =>
47
+ * Promise<unknown>> | null`; rather than casting that to the provider type
48
+ * (the webrtc-session mount does — repo rule forbids it), we call the proxy's
49
+ * `resolveHwAccel` and narrow its result through the cap's Zod OUTPUT schema.
50
+ * A missing proxy (node unreachable), a missing method, a malformed response,
51
+ * or a thrown call all degrade to an EXPLAINED empty list rather than
52
+ * corrupting the typed API surface.
53
+ */
54
+ async function resolveHwAccelOnNode(moleculer, nodeId, prefer) {
55
+ const proxy = moleculer?.createCapabilityProxy('platform-probe', nodeId) ?? null;
56
+ const resolveFn = proxy?.['resolveHwAccel'];
57
+ if (!resolveFn) {
58
+ return { preferred: [], rationale: `node ${nodeId} unreachable` };
59
+ }
60
+ try {
61
+ const raw = await resolveFn({ prefer });
62
+ const parsed = HwAccelResolutionSchema.safeParse(raw);
63
+ if (!parsed.success) {
64
+ return { preferred: [], rationale: `invalid probe response from ${nodeId}` };
65
+ }
66
+ return parsed.data;
67
+ }
68
+ catch (err) {
69
+ const msg = err instanceof Error ? err.message : String(err);
70
+ return { preferred: [], rationale: `resolve failed: ${msg}` };
71
+ }
72
+ }
73
+ function listAvailableNodeIds(moleculer) {
74
+ const broker = moleculer?.broker ?? null;
75
+ if (!broker)
76
+ return [];
77
+ const withRegistry = broker;
78
+ return withRegistry.registry.getNodeList({ onlyAvailable: true }).map((n) => n.id);
79
+ }
80
+ function createHwAccelRouter(capabilityRegistry, moleculer) {
41
81
  return (0, trpc_middleware_js_1.trpcRouter)({
42
- /** Probe the current hub process. */
82
+ /** Probe the current hub process via the local `platform-probe` singleton. */
43
83
  resolve: trpc_middleware_js_1.adminProcedure
44
84
  .input(zod_1.z.object({ prefer: HwAccelPreferSchema }).optional())
45
85
  .output(HwAccelResolutionSchema)
46
86
  .query(async ({ input }) => {
47
- if (!broker)
48
- throw new Error('Moleculer broker not available');
49
- const params = { prefer: input?.prefer ?? null };
50
- return broker.call('$hwaccel.resolve', params);
87
+ const provider = capabilityRegistry?.getSingleton('platform-probe') ?? null;
88
+ if (!provider) {
89
+ return { preferred: [], rationale: 'platform-probe capability not available' };
90
+ }
91
+ return provider.resolveHwAccel({ prefer: input?.prefer ?? null });
51
92
  }),
52
93
  /** Probe a specific node in the cluster — used by per-agent UI cards. */
53
94
  resolveForNode: trpc_middleware_js_1.adminProcedure
54
95
  .input(zod_1.z.object({ nodeId: zod_1.z.string(), prefer: HwAccelPreferSchema }))
55
96
  .output(HwAccelResolutionSchema)
56
97
  .query(async ({ input }) => {
57
- if (!broker)
58
- throw new Error('Moleculer broker not available');
59
- const params = { prefer: input.prefer ?? null };
60
- return broker.call('$hwaccel.resolve', params, {
61
- nodeID: input.nodeId,
62
- });
98
+ return resolveHwAccelOnNode(moleculer, input.nodeId, input.prefer ?? null);
63
99
  }),
64
100
  /** List every node currently reachable and the hwaccel each resolves to. */
65
101
  resolveAll: trpc_middleware_js_1.adminProcedure
@@ -68,24 +104,11 @@ function createHwAccelRouter(broker) {
68
104
  resolution: HwAccelResolutionSchema,
69
105
  })))
70
106
  .query(async () => {
71
- if (!broker)
72
- throw new Error('Moleculer broker not available');
73
- const registry = broker.registry;
74
- const nodes = registry.getNodeList({ onlyAvailable: true });
75
- const results = await Promise.all(nodes.map(async (n) => {
76
- try {
77
- const resolution = (await broker.call('$hwaccel.resolve', { prefer: null }, { nodeID: n.id }));
78
- return { nodeId: n.id, resolution };
79
- }
80
- catch (err) {
81
- const msg = err instanceof Error ? err.message : String(err);
82
- return {
83
- nodeId: n.id,
84
- resolution: { preferred: [], rationale: `resolve failed: ${msg}` },
85
- };
86
- }
87
- }));
88
- return results;
107
+ const nodeIds = listAvailableNodeIds(moleculer);
108
+ return Promise.all(nodeIds.map(async (nodeId) => ({
109
+ nodeId,
110
+ resolution: await resolveHwAccelOnNode(moleculer, nodeId, null),
111
+ })));
89
112
  }),
90
113
  });
91
114
  }
@@ -2,7 +2,7 @@
2
2
  // AUTO-GENERATED by scripts/generate-cap-mounts.ts — DO NOT EDIT
3
3
  // Re-run: npx tsx scripts/generate-cap-mounts.ts
4
4
  //
5
- // Mounted: 130 Skipped (legacy): 6
5
+ // Mounted: 131 Skipped (legacy): 6
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.LEGACY_SHAPE_SKIP = void 0;
8
8
  exports.mountAllCaps = mountAllCaps;
@@ -294,6 +294,7 @@ function mountAllCaps(services) {
294
294
  return entries[0]?.[1] ?? null;
295
295
  }, remoteCapProxy),
296
296
  osd: (0, generated_cap_routers_js_1.createCapRouter_osd)((_ctx) => (0, cap_mount_helpers_js_1.requireDeviceScoped)(reg, 'osd'), remoteCapProxy),
297
+ petFeeder: (0, generated_cap_routers_js_1.createCapRouter_petFeeder)((_ctx) => (0, cap_mount_helpers_js_1.requireDeviceScoped)(reg, 'pet-feeder'), remoteCapProxy),
297
298
  pipelineAnalytics: (0, generated_cap_routers_js_1.createCapRouter_pipelineAnalytics)((_ctx) => reg?.getSingleton('pipeline-analytics') ?? null, remoteCapProxy),
298
299
  pipelineExecutor: (0, generated_cap_routers_js_1.createCapRouter_pipelineExecutor)((_ctx) => reg?.getSingleton('pipeline-executor') ??
299
300
  null, remoteCapProxy),