~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/atlibs-code-mode

0
0
main
50 lines · 2.8 KB Raw History
// 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 ['<AssemblyScript>'] ['<input json>']
// 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);
}