collectToolsEach: each registration is given its own environment (hq ADR 0192)
A node's runtime serves many modules in one process; a module's composed paths and words must reach its own tools and no other's. The runtime knows which bundle made which registration, so it says which environment each contributor gets. collectTools(env) is unchanged. 0.1.3.
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@novox/mesh-sdk",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.3",
|
||||
"description": "The stable spine a Novox Mesh module's own code builds against.",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@@ -49,6 +49,27 @@ export function collectTools(env: NodeJS.ProcessEnv = process.env): { module: st
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect every registered module's tools, each contributor given ITS OWN environment (novox/hq ADR
|
||||
* 0192): `envFor` is asked with the registration's module and its index in registration order, and
|
||||
* whatever it answers is all that contributor sees. A node's runtime serves many modules in one
|
||||
* process, and a module's paths and words must reach its own tools and no other's — so the runtime
|
||||
* that knows which bundle made which registration says which environment each gets, and the shared
|
||||
* `collectTools(env)` stays what it was for a runtime serving one module.
|
||||
*/
|
||||
export function collectToolsEach(
|
||||
envFor: (module: string, index: number) => NodeJS.ProcessEnv,
|
||||
): { module: string; tools: ToolDefinition[] }[] {
|
||||
return registrations.map(({ module, contribute }, index) => {
|
||||
try {
|
||||
return { module, tools: contribute(envFor(module, index)) };
|
||||
} catch (err) {
|
||||
console.error(`[tools] ${module}: contributor failed, exposing none: ${err}`);
|
||||
return { module, tools: [] };
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** List the tools every registered module exposes — for discovery, without invoking anything. */
|
||||
export function listTools(env: NodeJS.ProcessEnv = process.env): { module: string; name: string; description: string }[] {
|
||||
return collectTools(env).flatMap(({ module, tools }) =>
|
||||
|
||||
+16
-1
@@ -5,7 +5,7 @@ import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { compareVersions } from "../dist/primitives/index.js";
|
||||
import { registerModuleTools, collectTools, resetTools, serveTools, listTools, invokeTool } from "../dist/tools/index.js";
|
||||
import { registerModuleTools, collectTools, collectToolsEach, resetTools, serveTools, listTools, invokeTool } from "../dist/tools/index.js";
|
||||
import { runProvisioner } from "../dist/provisioner/index.js";
|
||||
import { emit, on, type Event } from "../dist/events/index.js";
|
||||
import { useBroker } from "../dist/messaging/index.js";
|
||||
@@ -482,3 +482,18 @@ async function waitFor(cond: () => boolean, ms: number): Promise<void> {
|
||||
await new Promise((r) => setTimeout(r, 10));
|
||||
}
|
||||
}
|
||||
|
||||
test("each registration is given the environment asked for it, and sees no other's (ADR 0192)", () => {
|
||||
resetTools();
|
||||
const seen: Record<string, unknown> = {};
|
||||
registerModuleTools("alpha", (env) => { seen.alpha = { ...env }; return [{ name: "a", description: "", input: {}, run: async () => env.ALPHA_FILE }]; });
|
||||
registerModuleTools("beta", (env) => { seen.beta = { ...env }; return [{ name: "b", description: "", input: {}, run: async () => env.BETA_URL }]; });
|
||||
const envs: Record<string, NodeJS.ProcessEnv> = { alpha: { ALPHA_FILE: "/a/config.json" }, beta: { BETA_URL: "http://127.0.0.1:3000" } };
|
||||
const asked: string[] = [];
|
||||
const got = collectToolsEach((module, index) => { asked.push(`${module}#${index}`); return envs[module] ?? {}; });
|
||||
assert.deepEqual(got.map((g) => g.module), ["alpha", "beta"]);
|
||||
assert.deepEqual(asked, ["alpha#0", "beta#1"]);
|
||||
assert.deepEqual(seen.alpha, { ALPHA_FILE: "/a/config.json" });
|
||||
assert.deepEqual(seen.beta, { BETA_URL: "http://127.0.0.1:3000" });
|
||||
resetTools();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user