diff --git a/apps/server/src/harness/atomic/full.test.ts b/apps/server/src/harness/atomic/full.test.ts index 5c9f55f91..be6eeb874 100644 --- a/apps/server/src/harness/atomic/full.test.ts +++ b/apps/server/src/harness/atomic/full.test.ts @@ -1,7 +1,7 @@ import { afterAll, expect, test } from "bun:test"; -import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises"; +import { mkdir, mkdtemp, rm, stat, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; -import { join } from "node:path"; +import { dirname, join } from "node:path"; import { HarnessAgent } from "@ai-sdk/harness/agent"; import { createJustBashNetworkSandboxSession } from "@ai-sdk/sandbox-just-bash"; import { jsonSchema, tool } from "ai"; @@ -341,6 +341,10 @@ export default workflow({ let files = { operator: await Bun.file(join(agentDir, "settings.json")).exists(), journal: await Bun.file(journal).exists(), + journalDirectoryMode: await stat(dirname(journal)).then( + info => info.mode & 0o777, + () => undefined, + ), defaultJournal: await Bun.file(join(root, "workflows", "journal.sqlite")).exists(), environment: process.env.ATOMIC_WORKFLOW_JOURNAL_PATH, project: projectPackage @@ -558,6 +562,8 @@ test( // and through the session rather than the process-wide environment variable. expect(result.files).toMatchObject({ journal: true, defaultJournal: false }); expect(result.files?.environment).toBeUndefined(); + // Only the server's user can enter its directory, which also holds the worker-logs/ Atomic keeps. + expect(result.files?.journalDirectoryMode).toBe(0o700); } finally { if (environment !== undefined) process.env.NODE_ENV = environment; await room.close(); diff --git a/bun.lock b/bun.lock index 8d620cdfa..ddab69ea1 100644 --- a/bun.lock +++ b/bun.lock @@ -315,7 +315,7 @@ "@ai-sdk/harness": "1.0.146", "@ai-sdk/mcp": "2.0.72", "@ai-sdk/sandbox-just-bash": "1.0.146", - "@bastani/atomic": "0.9.42", + "@bastani/atomic": "0.9.43", "ai": "7.0.135", "typebox": "1.3.7", "zod": "4.4.3", @@ -456,27 +456,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.42", "", { "dependencies": { "@bastani/atomic-natives": "0.9.42", "@bastani/pi-ai": "0.9.42", "@earendil-works/pi-agent-core": "1.4.0", "@earendil-works/pi-codemode": "1.4.0", "@earendil-works/pi-tui": "1.4.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.7.0", "brace-expansion": "5.0.12", "chalk": "6.0.0", "cross-spawn": "7.0.6", "diff": "8.0.4", "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", "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-oumUw1AdVFvnGRdRFNl2Sv1JBd8feRQE2qLhsZ5ZLSF1NCKtKKlFjvKb71ENCcZ9DKBkSTibNwp99vTQyUCPRA=="], + "@bastani/atomic": ["@bastani/atomic@0.9.43", "", { "dependencies": { "@bastani/atomic-natives": "0.9.43", "@bastani/pi-ai": "0.9.43", "@earendil-works/pi-agent-core": "1.4.0", "@earendil-works/pi-codemode": "1.4.0", "@earendil-works/pi-tui": "1.4.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.7.0", "brace-expansion": "5.0.12", "chalk": "6.0.0", "cross-spawn": "7.0.6", "diff": "8.0.4", "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", "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-3vxPdLY2RtFw52sdjVJK/nOQ8tMBJJezLwXbwuW0Fiba/zO+hlv9OqVmco+UK+lITdr4WUP1pNhbVdOHiDCGcQ=="], - "@bastani/atomic-natives": ["@bastani/atomic-natives@0.9.42", "", { "optionalDependencies": { "@bastani/atomic-natives-darwin-arm64": "0.9.42", "@bastani/atomic-natives-darwin-x64": "0.9.42", "@bastani/atomic-natives-linux-arm64-gnu": "0.9.42", "@bastani/atomic-natives-linux-arm64-musl": "0.9.42", "@bastani/atomic-natives-linux-x64-gnu": "0.9.42", "@bastani/atomic-natives-linux-x64-musl": "0.9.42", "@bastani/atomic-natives-win32-arm64-msvc": "0.9.42", "@bastani/atomic-natives-win32-x64-msvc": "0.9.42" } }, "sha512-WZCjkRF8R3BqqaoSalF6sl0HmCJCW0dJd+XahCFWLeUn51nmd8I3F0ew/IiOuXYMNOjW6xtyu+1RI4seAa8Yzg=="], + "@bastani/atomic-natives": ["@bastani/atomic-natives@0.9.43", "", { "optionalDependencies": { "@bastani/atomic-natives-darwin-arm64": "0.9.43", "@bastani/atomic-natives-darwin-x64": "0.9.43", "@bastani/atomic-natives-linux-arm64-gnu": "0.9.43", "@bastani/atomic-natives-linux-arm64-musl": "0.9.43", "@bastani/atomic-natives-linux-x64-gnu": "0.9.43", "@bastani/atomic-natives-linux-x64-musl": "0.9.43", "@bastani/atomic-natives-win32-arm64-msvc": "0.9.43", "@bastani/atomic-natives-win32-x64-msvc": "0.9.43" } }, "sha512-Z2kaOXqIV6Hzt8TPIiYulqXYjwSXsdD4WVyyD9AlsxOQYh0ZAVxcn2sofI2Lrbjv+ZVAoNcGnXRG+9mYXIvpFA=="], - "@bastani/atomic-natives-darwin-arm64": ["@bastani/atomic-natives-darwin-arm64@0.9.42", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kB8p6Cu4C6Cbk5M8htoo0HeSVg7ASs83nvfUlu8j7mR/OVIojIieWhzQnFM/OvAhTrzzkwmFlY1fg7cd9ytSTw=="], + "@bastani/atomic-natives-darwin-arm64": ["@bastani/atomic-natives-darwin-arm64@0.9.43", "", { "os": "darwin", "cpu": "arm64" }, "sha512-L6IdGXu9byEYt5qDJo95DXhvdd8yreSHC0FcorNWQQHTDcJ0KQJp4vQv4wF2lEjXhyIUuQ6jbk2Akfy60XGjxA=="], - "@bastani/atomic-natives-darwin-x64": ["@bastani/atomic-natives-darwin-x64@0.9.42", "", { "os": "darwin", "cpu": "x64" }, "sha512-q5n6eq9mYTi/UkOC1KyQ9RLT5FwgCrxWkFBGiYOgAAVogCSe93b8kpPiMd1m+RUFzeDDmbXkp3pRC9JewXqK+g=="], + "@bastani/atomic-natives-darwin-x64": ["@bastani/atomic-natives-darwin-x64@0.9.43", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZPaZKQDIqN1mS8+UQWwoujZcHngMW00ZBtnZSmovtI4uHjlt7Uq6bLT4oDpV9w/j3C8m7eyuwqWc+hc2QLPzFQ=="], - "@bastani/atomic-natives-linux-arm64-gnu": ["@bastani/atomic-natives-linux-arm64-gnu@0.9.42", "", { "os": "linux", "cpu": "arm64", "libc": "glibc" }, "sha512-MWFfXLBauY9bCOSJG2yDFz/JqCw6SQnCH7j/HpMwVFlH50I0sqycqchp/WPmkgKj1RIDALmJdsiSgk+HoH3iJg=="], + "@bastani/atomic-natives-linux-arm64-gnu": ["@bastani/atomic-natives-linux-arm64-gnu@0.9.43", "", { "os": "linux", "cpu": "arm64", "libc": "glibc" }, "sha512-NlzeDTd1xfMnaUK4k7r3sVJnk6tUwQFXM+2bn9TMT/y9PmCwf/zdwhELeYmq1Dw3lTmCLDVCEvO+VLC19A6a5g=="], - "@bastani/atomic-natives-linux-arm64-musl": ["@bastani/atomic-natives-linux-arm64-musl@0.9.42", "", { "os": "linux", "cpu": "arm64", "libc": "musl" }, "sha512-6R+7YjhRcnhoR00J7+NYiCmzhT5I0zH3LHxnAWIf0Q1aBJ7BmR9eFPFkyrh4kiqUoDtHypz6BtVyoDGWRL5hTA=="], + "@bastani/atomic-natives-linux-arm64-musl": ["@bastani/atomic-natives-linux-arm64-musl@0.9.43", "", { "os": "linux", "cpu": "arm64", "libc": "musl" }, "sha512-KB5CxYvCTo3xpEk+1jVL4E1BfpqEy8SoUB929KkYw5BW/6a58iuBwSPVh7G8l4rttflQGS38SSBEB5zR9NyYLg=="], - "@bastani/atomic-natives-linux-x64-gnu": ["@bastani/atomic-natives-linux-x64-gnu@0.9.42", "", { "os": "linux", "cpu": "x64", "libc": "glibc" }, "sha512-3PYdlncGACpv0RCAQND4aoQVgmceItH0kO+4NX9gBGioxV2tyl+lXQBXDrxGrtbwCFnoWo4tHK1VmiNVI00JmA=="], + "@bastani/atomic-natives-linux-x64-gnu": ["@bastani/atomic-natives-linux-x64-gnu@0.9.43", "", { "os": "linux", "cpu": "x64", "libc": "glibc" }, "sha512-axRBq+r8nbh/aUHWpxs5vY1Y5CWAmM3Dbvc2irQzvIwJwlh3kJJ2YGtyqRlOJ865Kug/3kyebASoGnPfgA5mtw=="], - "@bastani/atomic-natives-linux-x64-musl": ["@bastani/atomic-natives-linux-x64-musl@0.9.42", "", { "os": "linux", "cpu": "x64", "libc": "musl" }, "sha512-0KNKhSaqpYmiltI/Hn/OyRdCPu8j3yH+OoxKJOvdUjC7Yz8JbmBgXAS8iCzxW2j3ImVRafq/TDnZjkC8E0mSNA=="], + "@bastani/atomic-natives-linux-x64-musl": ["@bastani/atomic-natives-linux-x64-musl@0.9.43", "", { "os": "linux", "cpu": "x64", "libc": "musl" }, "sha512-OhI/WtyJQ7A1LKMhzkpZZDPvnRACJ83pt3t/TrPBxyNNpjJi8nkZssC26WxCUJUQfAHkMfeXJoHrS2+WveIqNw=="], - "@bastani/atomic-natives-win32-arm64-msvc": ["@bastani/atomic-natives-win32-arm64-msvc@0.9.42", "", { "os": "win32", "cpu": "arm64" }, "sha512-GOZ0bpq4nMyiN1Rf1qvTON7SPfXhSNutEX69/V0nXjZyMW+76F7FBltaPGOuTZwNo/IeYDsSdpRDOK/+nZWBAA=="], + "@bastani/atomic-natives-win32-arm64-msvc": ["@bastani/atomic-natives-win32-arm64-msvc@0.9.43", "", { "os": "win32", "cpu": "arm64" }, "sha512-xVp0zj+aGvpS5N3Uvx4ik8woYo3wOotMK3epeW+sr+6LsySglB+ndxxMs5kCcnfBIu5jYcwU134Ja+KDaYwIkA=="], - "@bastani/atomic-natives-win32-x64-msvc": ["@bastani/atomic-natives-win32-x64-msvc@0.9.42", "", { "os": "win32", "cpu": "x64" }, "sha512-fLS42PRe/2TOtIie06cDqYWAP9dWBQN6AzyG8vI0BjJCA3OfYHj2MSl7alW/j8KdK9tXD1t9i5FC3COVi895bQ=="], + "@bastani/atomic-natives-win32-x64-msvc": ["@bastani/atomic-natives-win32-x64-msvc@0.9.43", "", { "os": "win32", "cpu": "x64" }, "sha512-9pld9tA/dB8IfBe4vWoGMfX2tHWTaVpH5uhoMrzhGB71+3vvYWaWYtyqJ+xeMiQg6gueT3N0ihHpSpo8QPl/9A=="], - "@bastani/pi-ai": ["@bastani/pi-ai@0.9.42", "", { "dependencies": { "@anthropic-ai/sdk": "0.129.0", "@aws-sdk/client-bedrock-runtime": "3.1127.0", "@earendil-works/pi-telemetry": "1.4.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-ORPzQhHtEMhcQ4Fc4mMS4vP+Gli2IRAyHoKUnVLg/rKMmDJmdsIZtOOyS55NGyP7qoRD7mPMjEl+4JQjv7a7tA=="], + "@bastani/pi-ai": ["@bastani/pi-ai@0.9.43", "", { "dependencies": { "@anthropic-ai/sdk": "0.129.0", "@aws-sdk/client-bedrock-runtime": "3.1127.0", "@earendil-works/pi-telemetry": "1.4.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-KO+sc350H9Xv9G1LhMr57yuqu/N02s9ch/8KNe0L4VM/iShcuCWOd4bWkP956cVGDJYpd4/INylONAi3RHjLhg=="], "@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 685ee3e31..d5b8a1b0f 100644 --- a/docs/self-hosting.md +++ b/docs/self-hosting.md @@ -75,7 +75,7 @@ each owner's GitHub App user token and does not consume `HARNESS_AUTH`; setting `auto` on loopback passes the startup guard but does not enable host login in that adapter. -`HARNESS=atomic` runs Atomic 0.9.42 in the Chopin server process through its +`HARNESS=atomic` runs Atomic 0.9.43 in the Chopin server process through its headless SDK (`createAgentSession()`). It does not spawn the `atomic` CLI or use RPC mode. @@ -165,6 +165,17 @@ Atomic caveats: [Full Atomic Planner](hosted-agent.md#full-atomic-planner)). The Docker image sets `XDG_STATE_HOME=/var/lib/chopin`; mount a volume there to keep runs and those directories when the container is replaced. +- Local workflow worker pools stay off unless the operator's Atomic settings + set `workflows.localWorkers`. With a pool, Atomic 0.9.43 keeps each worker's + standard error in `worker-logs/` beside the journal, so under + `$XDG_STATE_HOME/chopin/atomic/worker-logs//`, inside the directory + Chopin creates for the journal with access for the server's user only. It + deletes a log when its worker shuts down normally but keeps the logs of + workers that failed; remove them yourself. A child whose worker dies is + replayed on a new worker, up to three attempts; after that the run fails and + its card in Chat says so. The settings `workflows.localWorkers.startupTimeoutMs` + and `leaseMs` set how long a worker may take to start and how long an + unresponsive one keeps its child. - Atomic depends on `typebox` 1.3.27 while Chopin pins 1.3.7. Host tool schemas pass to Atomic as plain JSON Schema, so the two versions never meet. diff --git a/package.json b/package.json index 077145c29..4e19f7aa1 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "@ai-sdk/harness": "1.0.146", "@ai-sdk/mcp": "2.0.72", "@ai-sdk/sandbox-just-bash": "1.0.146", - "@bastani/atomic": "0.9.42", + "@bastani/atomic": "0.9.43", "ai": "7.0.135", "typebox": "1.3.7", "zod": "4.4.3"