From 843c1628cbaa0a28de09041512ed134f21d2b78c Mon Sep 17 00:00:00 2001 From: Terence Tan Date: Thu, 16 Jul 2026 13:46:33 +0800 Subject: [PATCH 1/2] feat: install Claude Agent SDK in sandbox bootstrap --- docs/onecomputer/claude-agent-sdk-runtime.md | 36 +++++++++++++++++++ .../sandbox-providers/kasm-local-provider.ts | 9 ++++- 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 docs/onecomputer/claude-agent-sdk-runtime.md diff --git a/docs/onecomputer/claude-agent-sdk-runtime.md b/docs/onecomputer/claude-agent-sdk-runtime.md new file mode 100644 index 0000000..c2e1083 --- /dev/null +++ b/docs/onecomputer/claude-agent-sdk-runtime.md @@ -0,0 +1,36 @@ +# Claude Agent SDK runtime requirement + +ONEComputer sandboxes are used by ONEVibe as the execution boundary for +Claude agents. Claude Code CLI availability is not sufficient for this +contract: the sandbox must also contain the Claude Agent SDK so a Node worker +can call `query()` directly and stream native SDK messages into ONEVibe's +durable journal/SSE projection. + +The Kasm bootstrap installs the pinned runtime dependency: + +```text +@anthropic-ai/claude-agent-sdk@0.3.210 +``` + +Bootstrap must fail closed unless both checks pass: + +```sh +claude --version +NODE_PATH=/home/kasm-user/.npm-global/lib/node_modules node -e "const {createRequire}=require('node:module'); createRequire(process.cwd() + '/.onevibe-agent-sdk.mjs').resolve('@anthropic-ai/claude-agent-sdk')" +``` + +The package is installed as an image/bootstrap dependency alongside +`@anthropic-ai/claude-code`, `pptxgenjs`, and `pdf-lib`; it must not be +installed by an agent during a user task. A sandbox is not `bootstrapped` until +the SDK module check succeeds. This keeps model execution deterministic and +prevents a task from silently switching to a CLI-only runtime. + +ONEVibe transfers the worker source into the conversation workspace and +executes it with Node 22. The worker owns the SDK query, session persistence, +LiteLLM environment, bounded tool list, and raw journal. ONEComputer remains +the provider/control boundary; the web browser receives only server-projected +events and never receives the sandbox process, credential, X11, or VNC handle. + +The corresponding ONEVibe proof is documented in +`onevibe/docs/ONECOMPUTER-CLAUDE-AGENT-SDK.md`. A fresh Azure deployment must +be run before claiming the combined SDK + visual + SSE gate. diff --git a/packages/api/src/services/sandbox-providers/kasm-local-provider.ts b/packages/api/src/services/sandbox-providers/kasm-local-provider.ts index f109a66..9a37f46 100644 --- a/packages/api/src/services/sandbox-providers/kasm-local-provider.ts +++ b/packages/api/src/services/sandbox-providers/kasm-local-provider.ts @@ -221,7 +221,14 @@ async function installClaudeDesktopAndCode(id: string): Promise { return execInSandbox( id, - "set -e; export PATH=/opt/node22/bin:/home/kasm-user/.npm-global/bin:$PATH; npm install -g @anthropic-ai/claude-code --prefix /home/kasm-user/.npm-global; grep -q npm-global /home/kasm-user/.bashrc || echo 'export PATH=/opt/node22/bin:/home/kasm-user/.npm-global/bin:$PATH' >> /home/kasm-user/.bashrc; claude --version", + "set -e; export PATH=/opt/node22/bin:/home/kasm-user/.npm-global/bin:$PATH; npm install -g @anthropic-ai/claude-code @anthropic-ai/claude-agent-sdk@0.3.210 pptxgenjs pdf-lib --prefix /home/kasm-user/.npm-global; grep -q npm-global /home/kasm-user/.bashrc || echo 'export PATH=/opt/node22/bin:/home/kasm-user/.npm-global/bin:$PATH' >> /home/kasm-user/.bashrc; claude --version; NODE_PATH=/home/kasm-user/.npm-global/lib/node_modules node -e \"require('pptxgenjs'); require('pdf-lib'); const {createRequire}=require('node:module'); createRequire(process.cwd() + '/.onevibe-agent-sdk.mjs').resolve('@anthropic-ai/claude-agent-sdk')\"", + ); +} + +async function installClaudeDesktop(id: string): Promise { + return execInSandboxAsRoot( + id, + "set -e; . /etc/os-release; case ${VERSION_ID%%.*} in 22|23|24) ;; *) exit 20 ;; esac; apt-get update; apt-get install -y curl ca-certificates gpg; curl -fsSLo /usr/share/keyrings/claude-desktop-archive-keyring.asc https://downloads.claude.ai/claude-desktop/key.asc; echo 'deb [arch=amd64,arm64 signed-by=/usr/share/keyrings/claude-desktop-archive-keyring.asc] https://downloads.claude.ai/claude-desktop/apt/stable stable main' > /etc/apt/sources.list.d/claude-desktop.list; apt-get update; apt-get install -y claude-desktop", ); } From 39c76a6735d94134a7b425d0cdc30972395f820e Mon Sep 17 00:00:00 2001 From: Terence Tan Date: Thu, 16 Jul 2026 13:50:39 +0800 Subject: [PATCH 2/2] fix: remove unused desktop installer --- .../src/services/sandbox-providers/kasm-local-provider.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/api/src/services/sandbox-providers/kasm-local-provider.ts b/packages/api/src/services/sandbox-providers/kasm-local-provider.ts index 9a37f46..85d4daf 100644 --- a/packages/api/src/services/sandbox-providers/kasm-local-provider.ts +++ b/packages/api/src/services/sandbox-providers/kasm-local-provider.ts @@ -225,13 +225,6 @@ async function installClaudeDesktopAndCode(id: string): Promise { ); } -async function installClaudeDesktop(id: string): Promise { - return execInSandboxAsRoot( - id, - "set -e; . /etc/os-release; case ${VERSION_ID%%.*} in 22|23|24) ;; *) exit 20 ;; esac; apt-get update; apt-get install -y curl ca-certificates gpg; curl -fsSLo /usr/share/keyrings/claude-desktop-archive-keyring.asc https://downloads.claude.ai/claude-desktop/key.asc; echo 'deb [arch=amd64,arm64 signed-by=/usr/share/keyrings/claude-desktop-archive-keyring.asc] https://downloads.claude.ai/claude-desktop/apt/stable stable main' > /etc/apt/sources.list.d/claude-desktop.list; apt-get update; apt-get install -y claude-desktop", - ); -} - async function configureClaudeDesktop3p(id: string): Promise { const managedSettings = JSON.stringify({ inferenceProvider: "gateway",