A launched bundle is told the module it serves (hq ADR 0193) #35

Merged
mesh-admin merged 1 commits from feat/0193-a-launched-bundle-is-told-its-module into main 2026-10-03 19:08:06 +00:00
3 changed files with 37 additions and 1 deletions
+2 -1
View File
@@ -161,7 +161,8 @@ export async function runTools(opts: RuntimeOptions): Promise<() => void> {
const path = resolve(entry); const path = resolve(entry);
try { try {
if (launches(path)) { if (launches(path)) {
const child = await launch(module, path, envFor(module)); // Told the module it serves it as, so a seat's verbs are the seat's (ADR 0193).
const child = await launch(module, path, { ...envFor(module), MESH_SERVED_MODULE: module });
children.push(child.stop); children.push(child.stop);
for (const r of child.registrations) launched.push({ ...r, owner: module }); for (const r of child.registrations) launched.push({ ...r, owner: module });
continue; continue;
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/env node
// A launched bundle registering its seat before its own tools, served through the SDK's loop
// (novox/hq ADR 0193): which is the seat's and which the module's comes from the name it is given.
import { registerModuleTools } from "@novox/mesh-sdk/tools";
import { serveRegisteredOverStdio } from "@novox/mesh-sdk/stdio";
registerModuleTools("node-shelf", () => [{ name: "list", description: "the shelf", input: {}, run: async () => ({ shelf: ["x"] }) }]);
registerModuleTools("theta", (env) => [{ name: "own", description: "theta's", input: {}, run: async () => ({ theta: env.THETA_WORD ?? null }) }]);
await serveRegisteredOverStdio();
+27
View File
@@ -289,3 +289,30 @@ test("each bundle is given its own environment and none of another's, imported o
resetTools(); resetTools();
} }
}); });
test("a launched bundle is told the module it serves, so its seat's verbs stay the seat's (ADR 0193)", async (t) => {
if (!url) return t.skip("MESH_TEST_NATS unset");
resetTools();
const mesh = await aMesh();
await mesh.issue(membershipOf("theta", "anchor", { seats: { "node-shelf": ["list"] } }));
const credential = { url, node: "anchor", module: "node-tools" };
const nodeTools = await connectNats(credential);
const asker = await connectNats({ url, module: "console", node: "workstation" });
const log = console.log;
let stop = () => {};
try {
console.log = () => {};
stop = await runTools({ broker: nodeTools, credential, envs: new Map([["theta", { THETA_WORD: "given" }]]),
serves: [{ module: "theta", entrypoints: [fixture("served-seat-first.mjs")] }] });
console.log = log;
assert.deepEqual((await callTool(asker, "theta.own@anchor", {})).result, { theta: "given" });
assert.deepEqual((await callTool(asker, "seat:node-shelf.list@anchor", {})).result, { shelf: ["x"] });
} finally {
console.log = log;
stop();
await asker.close();
await nodeTools.close();
await mesh.close();
resetTools();
}
});