diff --git a/CHANGELOG.md b/CHANGELOG.md index 191c2172d..99805351f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,6 +80,7 @@ Status: stable. - Telegram: scope native skill commands to bound agent per bot. (#4360) Thanks @robhparker. - Mentions: honor mentionPatterns even when explicit mentions are present. (#3303) Thanks @HirokiKobayashi-R. - Discord: restore username directory lookup in target resolution. (#3131) Thanks @bonald. +- Sandbox: include containerWorkdir in sandboxInfo for rw access so agents see correct Docker mount paths. Fixes #4171. - Agents: align MiniMax base URL test expectation with default provider config. (#3131) Thanks @bonald. - Agents: prevent retries on oversized image errors and surface size limits. (#2871) Thanks @Suksham-sharma. - Agents: inherit provider baseUrl/api for inline models. (#2740) Thanks @lploc94. diff --git a/docs/start/onboarding.md b/docs/start/onboarding.md index 2d523a218..ea9c37c8b 100644 --- a/docs/start/onboarding.md +++ b/docs/start/onboarding.md @@ -21,7 +21,10 @@ wizard, and let the agent bootstrap itself. 7) **Onboarding chat** (dedicated session) 8) Ready -## 1) Local vs Remote +## 1) Welcome + security notice +Read the security notice displayed and decide accordingly. + +## 2) Local vs Remote Where does the **Gateway** run? @@ -36,7 +39,7 @@ Gateway auth tip: - If you disable auth, any local process can connect; use that only on fully trusted machines. - Use a **token** for multi‑machine access or non‑loopback binds. -## 2) Local-only auth (Anthropic OAuth) +## 3) Local-only auth (Anthropic OAuth) The macOS app supports Anthropic OAuth (Claude Pro/Max). The flow: @@ -47,12 +50,12 @@ The macOS app supports Anthropic OAuth (Claude Pro/Max). The flow: Other providers (OpenAI, custom APIs) are configured via environment variables or config files for now. -## 3) Setup Wizard (Gateway‑driven) +## 4) Setup Wizard (Gateway‑driven) The app can run the same setup wizard as the CLI. This keeps onboarding in sync with Gateway‑side behavior and avoids duplicating logic in SwiftUI. -## 4) Permissions +## 5) Permissions Onboarding requests TCC permissions needed for: @@ -62,12 +65,12 @@ Onboarding requests TCC permissions needed for: - Microphone / Speech Recognition - Automation (AppleScript) -## 5) CLI (optional) +## 6) CLI (optional) The app can install the global `openclaw` CLI via npm/pnpm so terminal workflows and launchd tasks work out of the box. -## 6) Onboarding chat (dedicated session) +## 7) Onboarding chat (dedicated session) After setup, the app opens a dedicated onboarding chat session so the agent can introduce itself and guide next steps. This keeps first‑run guidance separate diff --git a/src/agents/pi-embedded-runner.buildembeddedsandboxinfo.test.ts b/src/agents/pi-embedded-runner.buildembeddedsandboxinfo.test.ts index 77bdd735b..c6cbc97d7 100644 --- a/src/agents/pi-embedded-runner.buildembeddedsandboxinfo.test.ts +++ b/src/agents/pi-embedded-runner.buildembeddedsandboxinfo.test.ts @@ -143,6 +143,76 @@ describe("buildEmbeddedSandboxInfo", () => { hostBrowserAllowed: true, }); }); + it("includes containerWorkdir as agentWorkspaceMount for rw access", () => { + const sandbox = { + enabled: true, + sessionKey: "session:test", + workspaceDir: "/tmp/moltbot-sandbox", + agentWorkspaceDir: "/tmp/moltbot-workspace", + workspaceAccess: "rw", + containerName: "moltbot-sbx-test", + containerWorkdir: "/workspace", + docker: { + image: "moltbot-sandbox:bookworm-slim", + containerPrefix: "moltbot-sbx-", + workdir: "/workspace", + readOnlyRoot: true, + tmpfs: ["/tmp"], + network: "none", + user: "1000:1000", + capDrop: ["ALL"], + env: { LANG: "C.UTF-8" }, + }, + tools: { + allow: ["exec"], + deny: ["browser"], + }, + browserAllowHostControl: false, + } satisfies SandboxContext; + + expect(buildEmbeddedSandboxInfo(sandbox)).toEqual({ + enabled: true, + workspaceDir: "/tmp/moltbot-sandbox", + workspaceAccess: "rw", + agentWorkspaceMount: "/workspace", + hostBrowserAllowed: false, + }); + }); + it("includes /agent as agentWorkspaceMount for ro access", () => { + const sandbox = { + enabled: true, + sessionKey: "session:test", + workspaceDir: "/tmp/moltbot-sandbox", + agentWorkspaceDir: "/tmp/moltbot-workspace", + workspaceAccess: "ro", + containerName: "moltbot-sbx-test", + containerWorkdir: "/workspace", + docker: { + image: "moltbot-sandbox:bookworm-slim", + containerPrefix: "moltbot-sbx-", + workdir: "/workspace", + readOnlyRoot: true, + tmpfs: ["/tmp"], + network: "none", + user: "1000:1000", + capDrop: ["ALL"], + env: { LANG: "C.UTF-8" }, + }, + tools: { + allow: ["exec"], + deny: ["browser"], + }, + browserAllowHostControl: false, + } satisfies SandboxContext; + + expect(buildEmbeddedSandboxInfo(sandbox)).toEqual({ + enabled: true, + workspaceDir: "/tmp/moltbot-sandbox", + workspaceAccess: "ro", + agentWorkspaceMount: "/agent", + hostBrowserAllowed: false, + }); + }); it("includes elevated info when allowed", () => { const sandbox = { enabled: true, diff --git a/src/agents/pi-embedded-runner/sandbox-info.ts b/src/agents/pi-embedded-runner/sandbox-info.ts index a72797c9c..8032aba4b 100644 --- a/src/agents/pi-embedded-runner/sandbox-info.ts +++ b/src/agents/pi-embedded-runner/sandbox-info.ts @@ -8,11 +8,20 @@ export function buildEmbeddedSandboxInfo( ): EmbeddedSandboxInfo | undefined { if (!sandbox?.enabled) return undefined; const elevatedAllowed = Boolean(execElevated?.enabled && execElevated.allowed); + // For rw access, the agent workspace is mounted at containerWorkdir (typically /workspace). + // For ro access, the agent workspace is mounted read-only at /agent. + // For none access, there is no agent workspace mount. + const agentWorkspaceMount = + sandbox.workspaceAccess === "rw" + ? sandbox.containerWorkdir + : sandbox.workspaceAccess === "ro" + ? "/agent" + : undefined; return { enabled: true, workspaceDir: sandbox.workspaceDir, workspaceAccess: sandbox.workspaceAccess, - agentWorkspaceMount: sandbox.workspaceAccess === "ro" ? "/agent" : undefined, + agentWorkspaceMount, browserBridgeUrl: sandbox.browser?.bridgeUrl, browserNoVncUrl: sandbox.browser?.noVncUrl, hostBrowserAllowed: sandbox.browserAllowHostControl,