// The code-mode composition in Node: the stub agent (modules/stub-agent.ts, built here by code mode's // own compiler into modules/stub-agent.wasm) asks code mode, over MCP, to run a program. // node examples/agent.mjs [''] [''] // The code may read one account's PDS publicly (com.atproto.repo.describeRepo with service: a DID). import { readFile, writeFile } from "node:fs/promises"; import { pathToFileURL } from "node:url"; import { loadComposition, runCompose } from "@publicdomainrelay/atlibs/compose/index.js"; import { hostCall } from "@publicdomainrelay/atlibs/run-module/host-call.js"; import { createNodeContext } from "@publicdomainrelay/atlibs/server/index.js"; import { codeMode, compile } from "../js/index.js"; const here = new URL("./", import.meta.url); export const WASM = new URL("modules/stub-agent.wasm", here); /** modules/stub-agent.wasm from modules/stub-agent.ts. */ export async function build() { const built = await compile(await readFile(new URL("modules/stub-agent.ts", here), "utf8")); if (built.error) throw new Error(built.error); await writeFile(WASM, built.binary); return built.binary; } /** Runs the composition's agent with { code, input }; mcp: the handler (default: code mode with the host's call). */ export async function runAgent(ctx, { code, input }, { mcp, allow = ["com.atproto.repo.describeRepo"], call = hostCall({ ctx }) } = {}) { const module = await build(); const spec = JSON.parse(await readFile(new URL("modules/stub-agent.json", here), "utf8")); const manifest = JSON.parse(await readFile(new URL("composition.json", here), "utf8")); const composition = await loadComposition(ctx, manifest, { load: async () => ({ ...spec, module }) }); mcp ??= codeMode({ ctx, call, allow }).handler; return runCompose(ctx, composition, "agent", "run", { input: { code, input } }, { handlers: { mcp } }); } export const EXAMPLE = `export function main(run: Run): void { if (run.start) { print("describing " + run.input.get("did").str); run.query("repo", "com.atproto.repo.describeRepo", Json.object().set("repo", run.input.get("did")), run.input.get("did").str); return; } if (!run.ok) { print(run.error); run.finish(Json.null()); return; } run.finish(Json.object().set("handle", run.output.get("handle")).set("collections", Json.number(run.output.get("collections").items.length))); }`; if (import.meta.url === pathToFileURL(process.argv[1]).href) { const ctx = createNodeContext({ id: "code-mode-example", stateDir: ".state/example" }); const [code = EXAMPLE, input = '{"did":"did:plc:ewvi7nxzyoun6zhxrhs64oiz"}'] = process.argv.slice(2); const ran = await runAgent(ctx, { code, input: JSON.parse(input) }); console.log(JSON.stringify({ stdout: ran.result?.stdout, result: ran.result?.value, error: ran.error }, null, 2)); process.exit(ran.error ? 1 : 0); }