A tool call names the machine it is for, every answer says which machine answered, and a holder's
runtime serves its seat's verbs (novox/hq ADR 0159) A module on several machines served one subject in one queue group, so a call reached whichever instance answered first and nobody could ask one machine's instance. Now each instance also serves its subject with its machine as the last token, `<module>.<tool>@<node>` addresses it, and every answer carries the machine that gave it: the console lists `node` on every module tool, strips it into the subject, and appends "answered by <node>" to the answer; `mesh call` prints it. And a seat's verbs are served by whoever claims the seat: the credential names the claimed seats and the verbs each promises, the runtime serves each verb with the module's tool of the same name on the seat's own subject, and the bus — which admits only the holder's subscription — decides where that serving is real. Design 33 §3 and §4, built.
This commit is contained in:
+38
-3
@@ -86,7 +86,7 @@ test("a person calls a tool and gets the module's own answer, unshaped", async (
|
||||
const person = await connectNats({ url, module: "person.ada" });
|
||||
try {
|
||||
const answer = await callTool(person, "shop.price", { of: "a hat" });
|
||||
assert.deepEqual(answer, { of: "a hat", cost: 12 });
|
||||
assert.deepEqual(answer.result, { of: "a hat", cost: 12 });
|
||||
} finally {
|
||||
await person.close();
|
||||
await mesh.close();
|
||||
@@ -140,11 +140,46 @@ test("a role's tool is reached through the seat, and a module's own name is neve
|
||||
assert.equal(toolKey("mesh-controller.other", roles), "mesh-controller.other", "a verb the seat does not declare is a module's");
|
||||
assert.equal(toolKey("shop.price", roles), "shop.price");
|
||||
const answer = await callTool(person, "mesh-controller.status", {}, roles);
|
||||
assert.deepEqual(answer, { output: "all quiet", ok: true });
|
||||
assert.deepEqual(answer.result, { output: "all quiet", ok: true });
|
||||
const direct = await callTool(person, "seat:mesh-controller.status", {});
|
||||
assert.deepEqual(direct, { output: "all quiet", ok: true });
|
||||
assert.deepEqual(direct.result, { output: "all quiet", ok: true });
|
||||
} finally {
|
||||
await person.close();
|
||||
await mesh.close();
|
||||
}
|
||||
});
|
||||
|
||||
// A module on two machines (novox/hq ADR 0159): a call names the machine and reaches that instance
|
||||
// and no other; a call that names none reaches one of them and says which; a seat's verb is served
|
||||
// by the claimant's tool of the same name on the seat's own subject.
|
||||
test("a tool call names the machine it is for, and every answer says which machine answered", async (t) => {
|
||||
if (!url) return t.skip("MESH_TEST_NATS unset");
|
||||
const onAnchor = await connectNats({ url: url!, module: "store", node: "anchor" });
|
||||
const onHome = await connectNats({ url: url!, module: "store", node: "home-server" });
|
||||
const asker = await connectNats({ url: url!, module: "console", node: "workstation" });
|
||||
try {
|
||||
await onAnchor.handle("databases", async () => ({ at: "anchor" }));
|
||||
await onHome.handle("databases", async () => ({ at: "home-server" }));
|
||||
|
||||
const home = await callTool(asker, "store.databases@home-server", {});
|
||||
assert.deepEqual(home.result, { at: "home-server" });
|
||||
assert.equal(home.node, "home-server");
|
||||
const anchor = await callTool(asker, "store.databases@anchor", {});
|
||||
assert.deepEqual(anchor.result, { at: "anchor" });
|
||||
assert.equal(anchor.node, "anchor");
|
||||
|
||||
const whichever = await callTool(asker, "store.databases", {});
|
||||
assert.ok(["anchor", "home-server"].includes(whichever.node ?? ""), `an unnamed call still says who answered: ${whichever.node}`);
|
||||
assert.deepEqual(whichever.result, { at: whichever.node });
|
||||
|
||||
// A seat's verb, served by the claimant on the seat's subject; a mesh seat's is flat.
|
||||
await onAnchor.handleSubject("mesh.seat.mesh-store.tool.databases", async () => ({ seat: "mesh-store", at: "anchor" }));
|
||||
const viaSeat = await callTool(asker, "seat:mesh-store.databases", {});
|
||||
assert.deepEqual(viaSeat.result, { seat: "mesh-store", at: "anchor" });
|
||||
assert.equal(viaSeat.node, "anchor");
|
||||
} finally {
|
||||
await onAnchor.close();
|
||||
await onHome.close();
|
||||
await asker.close();
|
||||
}
|
||||
});
|
||||
|
||||
+5
-2
@@ -99,8 +99,11 @@ test("a host initialises, lists the mesh's tools and calls one", async (t) => {
|
||||
"the modules' tools and the roles', named the way a person names them");
|
||||
const price = listed[1];
|
||||
assert.ok(price.inputSchema, "a tool with no schema is one an agent cannot call");
|
||||
// A module's bare property map arrives as a schema an agent can read, its words kept.
|
||||
assert.deepEqual(price.inputSchema, { type: "object", properties: { of: { type: "string" } } });
|
||||
// A module's bare property map arrives as a schema an agent can read, its words kept — and
|
||||
// `node`, the machine to ask when the module runs on several (novox/hq ADR 0159), beside them.
|
||||
assert.deepEqual(price.inputSchema.properties.of, { type: "string" });
|
||||
assert.equal(price.inputSchema.properties.node.type, "string", "a module's tool takes the machine to ask");
|
||||
assert.ok(!listed[0].inputSchema.properties?.node, "a seat's verb takes no machine; the seat's scope decides");
|
||||
// Silence is named: the module the catalogue holds and nothing answered for.
|
||||
assert.deepEqual(byId.get(2)!.result._meta.notAnswering, ["ghost"]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user