Merge pull request 'collectToolsEach: each registration is given its own environment (hq ADR 0192)' (#12) from feat/0192-each-registration-its-own-env into main
mesh/delivery held for a person: merged without a passing check: only a person decides that it goes on
mesh/delivery held for a person: merged without a passing check: only a person decides that it goes on
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@novox/mesh-sdk",
|
"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.",
|
"description": "The stable spine a Novox Mesh module's own code builds against.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"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. */
|
/** 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 }[] {
|
export function listTools(env: NodeJS.ProcessEnv = process.env): { module: string; name: string; description: string }[] {
|
||||||
return collectTools(env).flatMap(({ module, tools }) =>
|
return collectTools(env).flatMap(({ module, tools }) =>
|
||||||
|
|||||||
+16
-1
@@ -5,7 +5,7 @@ import { tmpdir } from "node:os";
|
|||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
|
|
||||||
import { compareVersions } from "../dist/primitives/index.js";
|
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 { runProvisioner } from "../dist/provisioner/index.js";
|
||||||
import { emit, on, type Event } from "../dist/events/index.js";
|
import { emit, on, type Event } from "../dist/events/index.js";
|
||||||
import { useBroker } from "../dist/messaging/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));
|
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