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

johnandersen777.bsky.social/atlibs-code-mode

0
0
main
182 lines · 11.0 KB Raw History
// Offline: compile + run, the MCP protocol (and the official SDK client over Streamable HTTP), the
// sandbox's limits and escape attempts, the code's calls, and the host-call and Node CLI ways in.
import assert from "node:assert/strict";
import { execFile } from "node:child_process";
import { mkdtemp, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { test } from "node:test";
import { fileURLToPath } from "node:url";
import { promisify } from "node:util";

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

import { hostCall } from "@publicdomainrelay/atlibs/run-module/host-call.js";
import { runModule } from "@publicdomainrelay/atlibs/run-module/index.js";
import { createNodeContext } from "@publicdomainrelay/atlibs/server/index.js";
import { build } from "../examples/agent.mjs";
import { MESSAGE, SOURCE_MAX, TOOL, codeMode, compile, streamableHttp } from "../js/index.js";

const ctx = createNodeContext({ id: "code-mode-test", stateDir: await mkdtemp(join(tmpdir(), "code-mode-test-")), wasmTimeoutMs: 1000 });
let id = 0;
const rpc = (mcp, method, params) => mcp.message({ jsonrpc: "2.0", id: ++id, method, params });
// tools/call -> { isError, ...the text's JSON }
const run = async (code, { input, ...options } = {}) => {
	const { result } = await rpc(codeMode({ ctx, ...options }), "tools/call", { name: TOOL, arguments: { code, input } });
	return { isError: result.isError === true, ...JSON.parse(result.content[0].text) };
};

test("compiles and runs: stdout, input and result", async () => {
	const out = await run('export function main(run: Run): void { print("hello"); print(run.input.get("who").str); run.finish(Json.object().set("n", Json.number(run.input.get("n").num * 2))); }', { input: { who: "agent", n: 21 } });
	assert.deepEqual(out, { isError: false, stdout: "hello\nagent\n", result: { n: 42 } });
});

test("Json accessors: length, has, kind checks, keys and items", async () => {
	const code = `export function main(run: Run): void {
  const records = run.input.get("records");
  const names: string[] = [];
  for (let i = 0; i < records.length; i++) names.push(records.at(i).get("name").str);
  const o = run.input.get("o");
  const none = run.input.get("none");
  run.finish(Json.object()
    .set("n", Json.number(records.length))
    .set("names", Json.string(names.join(",")))
    .set("keys", Json.number(o.length))
    .set("first", Json.string(o.keys[0]))
    .set("has", Json.bool(o.has("b") && !o.has("z")))
    .set("chars", Json.number(run.input.get("s").length))
    .set("kinds", Json.bool(records.isArray && o.isObject && run.input.get("s").isString && o.get("a").isNumber && o.get("b").isBool && none.isNull && none.length == 0)));
}`;
	const out = await run(code, { input: { records: [{ name: "a" }, { name: "b" }, { name: "c" }], o: { a: 1, b: true }, s: "hello" } });
	assert.deepEqual(out, { isError: false, stdout: "", result: { n: 3, names: "a,b,c", keys: 2, first: "a", has: true, chars: 5, kinds: true } });
});

test("the tool description documents the accessors", async () => {
	const { result } = await rpc(codeMode({ ctx }), "tools/list");
	for (const word of [".length", "has(key)", ".keys", ".items", ".isArray"]) assert.ok(result.tools[0].description.includes(word), word);
});

test("a compile error is the compiler's log, with the agent's own line numbers", async () => {
	const out = await run("export function main(run: Run): void {\n  let x: i32 = \"no\";\n}");
	assert.equal(out.isError, true);
	assert.match(out.error, /^compile: [\s\S]*code\.ts\(2,/);
});

test("MCP: initialize, ping, tools/list, notifications and errors", async () => {
	const mcp = codeMode({ ctx });
	const init = await rpc(mcp, "initialize", { protocolVersion: "2025-06-18", capabilities: {}, clientInfo: { name: "t", version: "0" } });
	assert.deepEqual(init.result.capabilities, { tools: {} });
	assert.equal(init.result.protocolVersion, "2025-06-18");
	assert.equal((await rpc(mcp, "initialize", { protocolVersion: "1999-01-01" })).result.protocolVersion, "2025-11-25");
	assert.deepEqual((await rpc(mcp, "ping")).result, {});
	const [tool] = (await rpc(mcp, "tools/list")).result.tools;
	assert.equal(tool.name, TOOL);
	assert.deepEqual(tool.inputSchema.required, ["code"]);
	assert.equal(await mcp.message({ jsonrpc: "2.0", method: "notifications/initialized" }), null);
	assert.equal(await mcp.message({ jsonrpc: "2.0", id: 9, result: {} }), null);
	assert.equal((await rpc(mcp, "resources/list")).error.code, -32601);
	assert.equal((await rpc(mcp, "tools/call", { name: "rm_rf" })).error.code, -32602);
	assert.equal((await mcp.message({ id: 1, method: "ping" })).error.code, -32600);
});

test("the official MCP SDK client, over Streamable HTTP", async () => {
	const handle = streamableHttp(codeMode({ ctx }).message);
	const transport = new StreamableHTTPClientTransport(new URL("http://code-mode.invalid/mcp"), { fetch: (url, init) => handle(new Request(url, init)) });
	const client = new Client({ name: "sdk-test", version: "0.0.0" });
	await client.connect(transport);
	assert.equal(client.getServerVersion().name, "atlibs-code-mode");
	assert.deepEqual((await client.listTools()).tools.map((t) => t.name), [TOOL]);
	const called = await client.callTool({ name: TOOL, arguments: { code: 'export function main(run: Run): void { print("via sdk"); }' } });
	assert.deepEqual(JSON.parse(called.content[0].text), { stdout: "via sdk\n", result: null });
	await client.close();
	assert.equal((await handle(new Request("http://x/mcp"))).status, 405);
	assert.equal((await handle(new Request("http://x/mcp", { method: "POST", body: "{" }))).status, 400);
});

test("sandbox: no imports, so no host functions and no Math.random", async () => {
	const external = await run('@external("env", "readFile") declare function readFile(): i32;\nexport function main(run: Run): void { readFile(); }');
	assert.match(external.error, /imports are not allowed: env\.readFile/);
	assert.match((await run("export function main(run: Run): void { print(Math.random().toString()); }")).error, /imports are not allowed: env\.seed/);
	// nothing but the prelude and the code is readable: no files, no host modules
	assert.match((await run('import { readFileSync } from "fs";\nexport function main(run: Run): void {}')).error, /File '~lib\/fs\.ts' not found/);
	assert.match((await run('import { x } from "../../../../etc/passwd";\nexport function main(run: Run): void {}')).error, /not found/);
});

test("sandbox: an infinite loop is stopped at the host's per-event limit", async () => {
	const started = Date.now();
	const out = await run("export function main(run: Run): void { while (true) {} }");
	assert.match(out.error, /^WASM_TIMEOUT/);
	assert.ok(Date.now() - started < 10000);
});

test("sandbox: memory is capped at the host's 1024 pages", async () => {
	const out = await run('export function main(run: Run): void { const a: string[] = []; while (true) a.push("x".repeat(65536)); }');
	assert.match(out.error, /^WASM_TRAP/);
});

test("sandbox: stdout is bounded", async () => {
	const out = await run('export function main(run: Run): void { for (let i = 0; i < 100000; i++) print("0123456789"); }');
	assert.equal(out.stdout.length, 65536);
});

test("the compiler: a crash, a runaway and a huge source cost a worker, not the host", async () => {
	// asc calls process.exit(1) on this stack overflow; in its worker that ends only the worker
	const crash = await run("function f<T>(n: i32): i32 { return n ? f<T[]>(n - 1) : 0; }\nexport function main(run: Run): void { f<i32>(3); }");
	assert.match(crash.error, /compiler crashed/);
	assert.deepEqual(await compile("export function main(run: Run): void {}", { timeoutMs: 1 }), { error: "compile ran longer than 1 ms" });
	assert.match((await run("x".repeat(SOURCE_MAX + 1))).error, /exceeds/);
});

test("calls: through the host's call, held to allow; none by default", async () => {
	const seen = [];
	const call = async (nsid, request) => (seen.push([nsid, request.params]), { handle: "alice.test" });
	const code = `export function main(run: Run): void {
		if (run.start) { run.query("a", "com.atproto.repo.describeRepo", Json.object().set("repo", Json.string("did:plc:alice"))); run.query("b", "com.atproto.server.createSession", Json.object()); return; }
		print(run.id + " " + (run.ok ? run.output.get("handle").str : run.error));
	}`;
	const allowed = await run(code, { call, allow: ["com.atproto.repo.describeRepo"] });
	assert.deepEqual(seen, [["com.atproto.repo.describeRepo", { repo: "did:plc:alice" }]]);
	assert.deepEqual(allowed.stdout.split("\n").sort(), ["", "a alice.test", "b Module does not allow com.atproto.server.createSession"]);
	assert.match((await run(code, { call })).stdout, /a Module does not allow com\.atproto\.repo\.describeRepo/);
});

test("state and stdout carry across events", async () => {
	const call = async () => ({ n: 1 });
	const out = await run(`export function main(run: Run): void {
		const n = run.state.isNull ? 0 : <i32>run.state.get("n").num;
		print("event " + n.toString());
		if (n == 3) { run.finish(Json.number(n)); return; }
		run.state = Json.object().set("n", Json.number(n + 1));
		run.call("c" + n.toString(), "com.example.tick", Json.object());
	}`, { call, allow: ["com.example.tick"] });
	assert.deepEqual(out, { isError: false, stdout: "event 0\nevent 1\nevent 2\nevent 3\n", result: 3 });
});

// a module that calls com.fedfork.exec.mcp.message directly (no hook): the stub agent without its hook
const direct = async () => {
	const dir = await mkdtemp(join(tmpdir(), "code-mode-direct-"));
	const wasm = join(dir, "stub-agent.wasm");
	const bytes = await build();
	await writeFile(wasm, bytes);
	await writeFile(join(dir, "stub-agent.json"), JSON.stringify({ name: "Stub agent", calls: [MESSAGE] }));
	return { dir, wasm, module: { name: "Stub agent", module: bytes, calls: [MESSAGE] } };
};
const program = { code: 'export function main(run: Run): void { print("direct"); run.finish(Json.bool(true)); }' };
const text = (ran) => JSON.parse(ran.result.value.result.content[0].text);

test("hostCall's calls: a module lists the NSID and the host serves it", async () => {
	const { module } = await direct();
	const call = hostCall({ ctx, calls: codeMode({ ctx }).calls });
	const ran = await runModule(ctx, module, "run", { input: program }, call, { provides: [MESSAGE] });
	assert.equal(ran.error, undefined);
	assert.deepEqual(text(ran), { stdout: "direct\n", result: true });
});

test("atlibs' Node CLI loads it as a transport (ATLIBS_TRANSPORTS=js/cli.mjs)", async () => {
	const { dir, wasm } = await direct();
	const cli = fileURLToPath(import.meta.resolve("@publicdomainrelay/atlibs/server/cli.mjs"));
	const env = { PATH: process.env.PATH, ATLIBS_TRANSPORTS: fileURLToPath(new URL("../js/cli.mjs", import.meta.url)), ATLIBS_SERVER_STATE: join(dir, "state") };
	const { stdout } = await promisify(execFile)(process.execPath, [cli, "run", wasm, join(dir, "stub-agent.json"), "run", JSON.stringify({ input: program })], { env });
	assert.deepEqual(text(JSON.parse(stdout)), { stdout: "direct\n", result: true });
});