diff --git a/apps/server/src/harness/atomic/adapter.ts b/apps/server/src/harness/atomic/adapter.ts index 47db1b66d..b35009f07 100644 --- a/apps/server/src/harness/atomic/adapter.ts +++ b/apps/server/src/harness/atomic/adapter.ts @@ -195,7 +195,17 @@ export function atomicTurnExtension(policy: TurnPolicy): ExtensionFactory { }; }, }); + let stage = false; + atomic.on("session_start", (_event, ctx) => { + stage = ctx.subagentPolicy !== undefined; + }); atomic.on("before_agent_start", event => { + if (stage) { + atomic.setActiveTools( + atomic.getActiveTools().filter(name => name !== ATOMIC_RESULT_TOOL_NAME), + ); + return; + } if (!policy.full) atomic.setActiveTools(activeNames(policy)); return { systemPrompt: policy.full @@ -204,6 +214,10 @@ export function atomicTurnExtension(policy: TurnPolicy): ExtensionFactory { }; }); atomic.on("tool_call", event => { + if (stage) { + if (event.toolName !== ATOMIC_RESULT_TOOL_NAME) return; + return { block: true, reason: `${event.toolName} is not available in a workflow stage.` }; + } if (policy.full && event.toolName !== ATOMIC_RESULT_TOOL_NAME) return; if (activeNames(policy).includes(event.toolName)) return; return { block: true, reason: `${event.toolName} is not available in this turn.` }; diff --git a/apps/server/src/harness/atomic/full.test.ts b/apps/server/src/harness/atomic/full.test.ts index 1e15f9c23..9907bd1c2 100644 --- a/apps/server/src/harness/atomic/full.test.ts +++ b/apps/server/src/harness/atomic/full.test.ts @@ -517,6 +517,8 @@ test( )!; expect(stage.toolNames).toContain("bash"); expect(stage.toolNames).toContain("write"); + expect(stage.toolNames).not.toContain(ATOMIC_RESULT_TOOL_NAME); + expect(stage.system).not.toContain("CHOPIN-INSTRUCTIONS-MARKER"); } finally { if (environment !== undefined) process.env.NODE_ENV = environment; await room.close(); diff --git a/apps/server/src/harness/atomic/full.ts b/apps/server/src/harness/atomic/full.ts index 123710029..4cf23e980 100644 --- a/apps/server/src/harness/atomic/full.ts +++ b/apps/server/src/harness/atomic/full.ts @@ -251,10 +251,10 @@ export function workflowRuns(planner: FullPlanner): ExtensionFactory { let names = new Map(); let parents = new Map(); let seen = new Set(); - planner.rootOf = runId => parents.get(runId) ?? runId; + let stage = true; let ready = false; let publish = () => { - if (!ready) return; + if (stage || !ready) return; for (let [id, card] of cards) { if (seen.has(id) && !roots.has(id) && card.ended === undefined) { card.status = "finished"; @@ -270,6 +270,9 @@ export function workflowRuns(planner: FullPlanner): ExtensionFactory { for (let wake of planner.waiters ?? []) wake(); }; atomic.on("session_start", (_event, ctx) => { + stage = ctx.subagentPolicy !== undefined; + if (stage) return; + planner.rootOf = runId => parents.get(runId) ?? runId; lease?.dispose(); lease = ctx.observeWorkflowActivity(frame => { if (frame.kind === "snapshot") { @@ -283,7 +286,7 @@ export function workflowRuns(planner: FullPlanner): ExtensionFactory { }); }); atomic.on("tool_result", event => { - if (event.toolName !== "workflow" || event.input.action !== "run") return; + if (stage || event.toolName !== "workflow" || event.input.action !== "run") return; let runId = launchedRunId(event.content); let name = typeof event.input.workflow === "string" ? event.input.workflow : undefined; if (!runId || !name) return; @@ -295,6 +298,7 @@ export function workflowRuns(planner: FullPlanner): ExtensionFactory { } }); atomic.on("workflow_lifecycle", event => { + if (stage) return; if (event.target.kind !== "prompt") parents.set(event.target.runId, event.rootRunId); foldLifecycle(cards, event, names.get(event.rootRunId)); publish(); diff --git a/bun.lock b/bun.lock index 1a4544a02..0b9a908c6 100644 --- a/bun.lock +++ b/bun.lock @@ -301,7 +301,7 @@ "@ai-sdk/harness-pi": "1.0.148", "@ai-sdk/mcp": "2.0.72", "@ai-sdk/sandbox-just-bash": "1.0.146", - "@bastani/atomic": "0.9.31", + "@bastani/atomic": "0.9.32", "@earendil-works/pi-coding-agent": "0.85.1", "ai": "7.0.135", "typebox": "1.3.7", @@ -455,27 +455,27 @@ "@base-ui/utils": ["@base-ui/utils@0.3.2", "", { "dependencies": { "@babel/runtime": "^7.29.2", "@floating-ui/utils": "^0.2.12", "reselect": "^5.2.0", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-oWy1aq/I2GmYjpl4PhEAhzflF8VPGKgZeq0xAWTbfD5KBWyxcN0ZP2+WHSUm/5Z6lVMBDLReLcoXwSYoRc/zNQ=="], - "@bastani/atomic": ["@bastani/atomic@0.9.31", "", { "dependencies": { "@bastani/atomic-natives": "0.9.31", "@bastani/pi-ai": "0.9.31", "@dbos-inc/dbos-sdk": "4.25.14", "@earendil-works/pi-agent-core": "1.1.0", "@earendil-works/pi-client": "1.1.0", "@earendil-works/pi-codemode": "1.1.0", "@earendil-works/pi-protocol": "1.1.0", "@earendil-works/pi-tui": "1.1.0", "@modelcontextprotocol/ext-apps": "^1.7.5", "@modelcontextprotocol/sdk": "1.32.1", "@mozilla/readability": "^0.6.0", "@silvia-odwyer/photon-node": "0.3.4", "@typesafe-ai/sdk": "0.6.0", "brace-expansion": "5.0.12", "chalk": "6.0.0", "cross-spawn": "7.0.6", "diff": "8.0.4", "embedded-postgres": "18.4.0-beta.17", "glob": "13.0.6", "grok-mermaid": "0.2.3", "highlight.js": "10.7.3", "hosted-git-info": "9.0.3", "ignore": "7.0.8", "jiti": "2.7.0", "linkedom": "^0.18.13", "lru-cache": "11.5.3", "markit-ai": "0.5.3", "minimatch": "10.2.6", "open": "^11.0.1", "p-limit": "^7.3.2", "pg": "8.23.0", "proper-lockfile": "4.1.2", "quickjs-wasi": "3.6.2", "semver": "7.8.5", "turndown": "^7.2.0", "typebox": "1.3.27", "undici": "8.10.2", "unpdf": "1.8.1", "yaml": "2.9.0", "zod": "^3.25.0 || ^4.0.0" }, "optionalDependencies": { "@mariozechner/clipboard": "0.3.9" }, "bin": { "atomic": "dist/cli.js" } }, "sha512-iEHe8KXq0G1Xk6n1b52MO8K2Iud4RNt7iL570QuLV1a4YcK+sJQV4ocDzfaq89KOaf0WNSviq0K+afrrGnNOFQ=="], + "@bastani/atomic": ["@bastani/atomic@0.9.32", "", { "dependencies": { "@bastani/atomic-natives": "0.9.32", "@bastani/pi-ai": "0.9.32", "@dbos-inc/dbos-sdk": "4.25.14", "@earendil-works/pi-agent-core": "1.1.0", "@earendil-works/pi-client": "1.1.0", "@earendil-works/pi-codemode": "1.1.0", "@earendil-works/pi-protocol": "1.1.0", "@earendil-works/pi-tui": "1.1.0", "@modelcontextprotocol/ext-apps": "^1.7.5", "@modelcontextprotocol/sdk": "1.32.1", "@mozilla/readability": "^0.6.0", "@silvia-odwyer/photon-node": "0.3.4", "@typesafe-ai/sdk": "0.6.0", "brace-expansion": "5.0.12", "chalk": "6.0.0", "cross-spawn": "7.0.6", "diff": "8.0.4", "embedded-postgres": "18.4.0-beta.17", "glob": "13.0.6", "grok-mermaid": "0.2.3", "highlight.js": "10.7.3", "hosted-git-info": "9.0.3", "ignore": "7.0.8", "jiti": "2.7.0", "linkedom": "^0.18.13", "lru-cache": "11.5.3", "markit-ai": "0.5.3", "minimatch": "10.2.6", "open": "^11.0.1", "p-limit": "^7.3.2", "pg": "8.23.0", "proper-lockfile": "4.1.2", "quickjs-wasi": "3.6.2", "semver": "7.8.5", "turndown": "^7.2.0", "typebox": "1.3.27", "undici": "8.10.2", "unpdf": "1.8.1", "yaml": "2.9.0", "zod": "^3.25.0 || ^4.0.0" }, "optionalDependencies": { "@mariozechner/clipboard": "0.3.9" }, "bin": { "atomic": "dist/cli.js" } }, "sha512-NVZeJcTRBnIRoARHnFAeKzSSxXenGzbciJop/loBOfRkTWSetWrPoOq0nBcxJt6r6KVmt6AgX+Ub3mYdGruf2w=="], - "@bastani/atomic-natives": ["@bastani/atomic-natives@0.9.31", "", { "optionalDependencies": { "@bastani/atomic-natives-darwin-arm64": "0.9.31", "@bastani/atomic-natives-darwin-x64": "0.9.31", "@bastani/atomic-natives-linux-arm64-gnu": "0.9.31", "@bastani/atomic-natives-linux-arm64-musl": "0.9.31", "@bastani/atomic-natives-linux-x64-gnu": "0.9.31", "@bastani/atomic-natives-linux-x64-musl": "0.9.31", "@bastani/atomic-natives-win32-arm64-msvc": "0.9.31", "@bastani/atomic-natives-win32-x64-msvc": "0.9.31" } }, "sha512-N2BFAm6K0AEriXQ5rtdgpncNhn9qEQ/rwRK1Ck0QHtrooMgZStxnyUiEDlJsvTu/pNwPse1t3LMEHPitxmQsFw=="], + "@bastani/atomic-natives": ["@bastani/atomic-natives@0.9.32", "", { "optionalDependencies": { "@bastani/atomic-natives-darwin-arm64": "0.9.32", "@bastani/atomic-natives-darwin-x64": "0.9.32", "@bastani/atomic-natives-linux-arm64-gnu": "0.9.32", "@bastani/atomic-natives-linux-arm64-musl": "0.9.32", "@bastani/atomic-natives-linux-x64-gnu": "0.9.32", "@bastani/atomic-natives-linux-x64-musl": "0.9.32", "@bastani/atomic-natives-win32-arm64-msvc": "0.9.32", "@bastani/atomic-natives-win32-x64-msvc": "0.9.32" } }, "sha512-mwbLFCDeW8SPwEeJW0H0ceijcugD7ewRHcUu20nAynjOfNXL+IAT5XwK2kvo0zePh+Ycs+TthVad7EHOV6JbZw=="], - "@bastani/atomic-natives-darwin-arm64": ["@bastani/atomic-natives-darwin-arm64@0.9.31", "", { "os": "darwin", "cpu": "arm64" }, "sha512-lNrS+99g580zsZaQY/ewM9ZS+/KWSTd7qI0SToVtNF4ujsSoEyShN0MyiiJmm6dNabTfPrYNEMMFBcRWLZHhlg=="], + "@bastani/atomic-natives-darwin-arm64": ["@bastani/atomic-natives-darwin-arm64@0.9.32", "", { "os": "darwin", "cpu": "arm64" }, "sha512-0+nZSvGYQTiAJO5pGoAoPRB5PjcgB0Afmn+HaQj3jRGAtWgdJkfI8SSYpE2qytHFwMb7eE4XKIYxEsIOtpDJzg=="], - "@bastani/atomic-natives-darwin-x64": ["@bastani/atomic-natives-darwin-x64@0.9.31", "", { "os": "darwin", "cpu": "x64" }, "sha512-MrCWQTyuF6OYFVZZ/fK/xoHe04PmWjzcie/3GxdfejFlqwQZ16TsademRzuV9OVK53C4HUyVKSgjBLl5kdMNgA=="], + "@bastani/atomic-natives-darwin-x64": ["@bastani/atomic-natives-darwin-x64@0.9.32", "", { "os": "darwin", "cpu": "x64" }, "sha512-dUfbuDYZ7ampykupe4a7zzt4wKQYt8+z+/1pkZy2lQRb21voIDxlEMzSPcIHcSIh95y3e9pOCBYljFz6r13DNg=="], - "@bastani/atomic-natives-linux-arm64-gnu": ["@bastani/atomic-natives-linux-arm64-gnu@0.9.31", "", { "os": "linux", "cpu": "arm64" }, "sha512-1si6hq3QcDLMxWZMlg3lkQ+X/Orhc75tlapNHFhhVuxcrZs4xLZiF56IVGqGYntyHXy34RWUfhjqRzzpVImSEg=="], + "@bastani/atomic-natives-linux-arm64-gnu": ["@bastani/atomic-natives-linux-arm64-gnu@0.9.32", "", { "os": "linux", "cpu": "arm64" }, "sha512-FWWKqQkJf01ZoJ+e3+27WjDiveE5/DUl8NWs+D2u9ElhqWyZWWWU5Q/1VCQG8ySE8hyYmnCB3llN8KCrCq7UnA=="], - "@bastani/atomic-natives-linux-arm64-musl": ["@bastani/atomic-natives-linux-arm64-musl@0.9.31", "", { "os": "linux", "cpu": "arm64" }, "sha512-oPl7okgeTUhPXE0TF60/YDJr5iEQnNQv/7cDkXLlOgyExkl1tnXYzN23vl/mAkqmVCoVcZfdJxH9lLNzOHasiA=="], + "@bastani/atomic-natives-linux-arm64-musl": ["@bastani/atomic-natives-linux-arm64-musl@0.9.32", "", { "os": "linux", "cpu": "arm64" }, "sha512-9bgA80Bh7PleHERf+S4G7fseGzoeaG8PN+C2WCs7RHFnGX/CboY7qkbyst4zS09U/t+0+nGJOIC0KU61jJLnmw=="], - "@bastani/atomic-natives-linux-x64-gnu": ["@bastani/atomic-natives-linux-x64-gnu@0.9.31", "", { "os": "linux", "cpu": "x64" }, "sha512-SXHm4OleVePHq8GC7asDXkElfzU4HIiqPmJRWdxlhHVTrO1r8QJjjKKOXKXfUfrQlB8/6rTCRMw3dQz49bm4Rg=="], + "@bastani/atomic-natives-linux-x64-gnu": ["@bastani/atomic-natives-linux-x64-gnu@0.9.32", "", { "os": "linux", "cpu": "x64" }, "sha512-6MbMEjPvuaT/vnwr/XwUBQrOhhXFY9uQakoeSeMmr/JqdxoyOReZYjNuIQBse6OBMMGCFxYUSLk8gU+9GThWYg=="], - "@bastani/atomic-natives-linux-x64-musl": ["@bastani/atomic-natives-linux-x64-musl@0.9.31", "", { "os": "linux", "cpu": "x64" }, "sha512-GYWtFdcCE20mr6mOrc1Kia/8z0KbGKnXrLaoWEiSA5YdkRXMufGVzNj1Cd+1NyuFrDpGlv0mgA8Ry5V4ae06QQ=="], + "@bastani/atomic-natives-linux-x64-musl": ["@bastani/atomic-natives-linux-x64-musl@0.9.32", "", { "os": "linux", "cpu": "x64" }, "sha512-5CJdkFKSvuCSOLTffwTqczlNe0d8axEOGNA7LaENsDBtXzO5fZQ0RFJFq1WdZ5GMaq3HY50IUHTu/GTbNlUV+Q=="], - "@bastani/atomic-natives-win32-arm64-msvc": ["@bastani/atomic-natives-win32-arm64-msvc@0.9.31", "", { "os": "win32", "cpu": "arm64" }, "sha512-2gEeRfcPWba5wK1bmP6kTfLFJzwZXNq4aJypLyz1wd2K8QY6RPSG823cZthkc9Ya6VfZmVkgtWbBV3puHvUIMw=="], + "@bastani/atomic-natives-win32-arm64-msvc": ["@bastani/atomic-natives-win32-arm64-msvc@0.9.32", "", { "os": "win32", "cpu": "arm64" }, "sha512-gN1Qhj3sncRMmo0sNrmM0y4Tgb+5EgEV9VBoaYXMEnigD0opthFkXztE+pYSoXtfpe4g8/ourzDY/tkV/vKQjQ=="], - "@bastani/atomic-natives-win32-x64-msvc": ["@bastani/atomic-natives-win32-x64-msvc@0.9.31", "", { "os": "win32", "cpu": "x64" }, "sha512-9OLy1/Ut7mI5Saz1dRabkH1OYsjjITzKOsPtamVDSJi5Pbs36nzNCEe/IuuuiOxFwGu/vpBaNAPS6UOsukXl2A=="], + "@bastani/atomic-natives-win32-x64-msvc": ["@bastani/atomic-natives-win32-x64-msvc@0.9.32", "", { "os": "win32", "cpu": "x64" }, "sha512-mY9V5v54Wplxk/mkY2hLDBte0NI2nIFpLFXThTvEDEewRyN7rvLDNvanxI6lB49+8PEQrZSkRsz2jUihXCSL8Q=="], - "@bastani/pi-ai": ["@bastani/pi-ai@0.9.31", "", { "dependencies": { "@anthropic-ai/sdk": "0.129.0", "@aws-sdk/client-bedrock-runtime": "3.1127.0", "@earendil-works/pi-telemetry": "1.1.0", "@google/genai": "2.21.0", "@smithy/node-http-handler": "4.12.1", "http-proxy-agent": "9.1.0", "https-proxy-agent": "9.1.0", "openai": "7.19.0", "partial-json": "0.1.7", "typebox": "1.3.27" }, "bin": { "pi-ai": "dist/cli.js" } }, "sha512-RdwJ8b4avhxsxuSR10I3Mm8XFFT5G6FPQQmNxaWvUX12sYKnYKazOo470Roos3gr17VsIC6IXjNRbhpI0dmzjQ=="], + "@bastani/pi-ai": ["@bastani/pi-ai@0.9.32", "", { "dependencies": { "@anthropic-ai/sdk": "0.129.0", "@aws-sdk/client-bedrock-runtime": "3.1127.0", "@earendil-works/pi-telemetry": "1.1.0", "@google/genai": "2.21.0", "@smithy/node-http-handler": "4.12.1", "http-proxy-agent": "9.1.0", "https-proxy-agent": "9.1.0", "openai": "7.19.0", "partial-json": "0.1.7", "typebox": "1.3.27" }, "bin": { "pi-ai": "dist/cli.js" } }, "sha512-Edwujf3lVRoluFSXhc5kIESBxfp1GIyWlVJgsFLi6pYOAQdH1eAEa8+2o9tOSBK9FsvOkv60BwFBfxZcJnCtGA=="], "@borewit/text-codec": ["@borewit/text-codec@0.2.2", "", {}, "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ=="], diff --git a/docs/self-hosting.md b/docs/self-hosting.md index 66c998a10..4677be24c 100644 --- a/docs/self-hosting.md +++ b/docs/self-hosting.md @@ -115,7 +115,7 @@ it. The Pi contract suite (`apps/server/src/harness/pi.contract.test.ts`) covers this against the real Pi agent loop; run it before bumping `@ai-sdk/harness-pi` or `@earendil-works/pi-coding-agent`. -`HARNESS=atomic` runs Atomic 0.9.31 in the Chopin server process through its +`HARNESS=atomic` runs Atomic 0.9.32 in the Chopin server process through its headless SDK (`createAgentSession()`). It does not spawn the `atomic` CLI, use RPC mode, or substitute Atomic for Pi's runtime. diff --git a/package.json b/package.json index 8caa23160..3078a691b 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "@ai-sdk/harness-pi": "1.0.148", "@ai-sdk/mcp": "2.0.72", "@ai-sdk/sandbox-just-bash": "1.0.146", - "@bastani/atomic": "0.9.31", + "@bastani/atomic": "0.9.32", "@earendil-works/pi-coding-agent": "0.85.1", "ai": "7.0.135", "typebox": "1.3.7",