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:
+15
-5
@@ -20,7 +20,7 @@ import { readFile } from "node:fs/promises";
|
||||
|
||||
import type { Broker } from "@novox/mesh-sdk/messaging";
|
||||
|
||||
import { connectNats, type Credential } from "./broker-nats.js";
|
||||
import { connectNats, type Answered, type Credential } from "./broker-nats.js";
|
||||
import { TOOLS_VERB, type ToolsAnswer } from "./runtime.js";
|
||||
|
||||
/** Where the catalogue answers which modules the mesh holds. */
|
||||
@@ -201,13 +201,23 @@ export async function toolsOn(bus: Broker): Promise<Listing> {
|
||||
|
||||
/** Call one tool. The key is `<module>.<tool>`, which is what a person types and what the account
|
||||
* permits — one vocabulary, so a refusal names the thing they asked for. */
|
||||
export async function callTool(bus: Broker, key: string, args: unknown, seats?: Seats): Promise<unknown> {
|
||||
if (!key.includes(".")) {
|
||||
/** Call a tool and learn which machine answered (novox/hq ADR 0159). `<module>.<tool>@<node>` asks
|
||||
* the instance on one machine; without it, whichever instance answers first does, and the answer
|
||||
* says which. */
|
||||
export async function callTool(bus: Broker, key: string, args: unknown, seats?: Seats): Promise<Answered<unknown>> {
|
||||
const at = key.indexOf("@");
|
||||
const name = at < 0 ? key : key.slice(0, at);
|
||||
const node = at < 0 ? "" : key.slice(at + 1);
|
||||
if (!name.includes(".")) {
|
||||
throw new Error(
|
||||
`"${key}" does not name a tool: write <module>.<tool>, as \`mesh tools\` lists them`,
|
||||
`"${key}" does not name a tool: write <module>.<tool>, as \`mesh tools\` lists them, ` +
|
||||
"or <module>.<tool>@<node> for the instance on one machine",
|
||||
);
|
||||
}
|
||||
return bus.request<unknown, unknown>(toolKey(key, seats), args ?? {});
|
||||
const resolved = toolKey(name, seats) + (node ? `@${node}` : "");
|
||||
const asking = bus as Broker & { ask?: <Req, Res>(k: string, b: Req) => Promise<Answered<Res>> };
|
||||
if (typeof asking.ask === "function") return asking.ask<unknown, unknown>(resolved, args ?? {});
|
||||
return { result: await bus.request<unknown, unknown>(resolved, args ?? {}) };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user