Skip to content

Commit 88b3c6e

Browse files
rohoswaggerclaude
andcommitted
feat(craft): persist opencode session data across sandbox sleep/wake
Move opencode's session storage from container-local ~/.local/share/ to the shared workspace volume via XDG_DATA_HOME. This ensures session data is captured in snapshots and restored on wake, allowing ephemeral ACP clients to resume conversation context after sleep/wake cycles. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent de31483 commit 88b3c6e

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

backend/onyx/server/features/build/sandbox/kubernetes/internal/acp_exec_client.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"""
2222

2323
import json
24+
import shlex
2425
import threading
2526
import time
2627
from collections.abc import Generator
@@ -175,8 +176,17 @@ def start(self, cwd: str = "/workspace", timeout: float = 30.0) -> None:
175176

176177
k8s = self._get_k8s_client()
177178

178-
# Start opencode acp via exec
179-
exec_command = ["opencode", "acp", "--cwd", cwd]
179+
# Start opencode acp via exec.
180+
# Set XDG_DATA_HOME so opencode stores session data on the shared
181+
# workspace volume (accessible from file-sync container for snapshots)
182+
# instead of the container-local ~/.local/share/ filesystem.
183+
data_dir = shlex.quote(f"{cwd}/.opencode-data")
184+
safe_cwd = shlex.quote(cwd)
185+
exec_command = [
186+
"/bin/sh",
187+
"-c",
188+
f"XDG_DATA_HOME={data_dir} exec opencode acp --cwd {safe_cwd}",
189+
]
180190

181191
logger.info(f"[ACP] Starting client: pod={self._pod_name} cwd={cwd}")
182192

backend/onyx/server/features/build/sandbox/kubernetes/kubernetes_sandbox_manager.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,6 +1472,7 @@ def create_snapshot(
14721472
the snapshot and upload to S3. Captures:
14731473
- sessions/$session_id/outputs/ (generated artifacts, web apps)
14741474
- sessions/$session_id/attachments/ (user uploaded files)
1475+
- sessions/$session_id/.opencode-data/ (opencode session data for resumption)
14751476
14761477
Args:
14771478
sandbox_id: The sandbox ID
@@ -1496,9 +1497,10 @@ def create_snapshot(
14961497
f"{session_id_str}/{snapshot_id}.tar.gz"
14971498
)
14981499

1499-
# Exec into pod to create and upload snapshot (outputs + attachments)
1500-
# Uses s5cmd pipe to stream tar.gz directly to S3
1501-
# Only snapshot if outputs/ exists. Include attachments/ only if non-empty.
1500+
# Create tar and upload to S3 via file-sync container.
1501+
# .opencode-data/ is already on the shared workspace volume because we set
1502+
# XDG_DATA_HOME to the session directory when starting opencode (see
1503+
# ACPExecClient.start()). No cross-container copy needed.
15021504
exec_command = [
15031505
"/bin/sh",
15041506
"-c",
@@ -1511,6 +1513,7 @@ def create_snapshot(
15111513
fi
15121514
dirs="outputs"
15131515
[ -d attachments ] && [ "$(ls -A attachments 2>/dev/null)" ] && dirs="$dirs attachments"
1516+
[ -d .opencode-data ] && [ "$(ls -A .opencode-data 2>/dev/null)" ] && dirs="$dirs .opencode-data"
15141517
tar -czf - $dirs | /s5cmd pipe {s3_path}
15151518
echo "SNAPSHOT_CREATED"
15161519
""",
@@ -1632,6 +1635,7 @@ def restore_snapshot(
16321635
Steps:
16331636
1. Exec s5cmd cat in file-sync container to stream snapshot from S3
16341637
2. Pipe directly to tar for extraction in the shared workspace volume
1638+
(.opencode-data/ is restored automatically since XDG_DATA_HOME points here)
16351639
3. Regenerate configuration files (AGENTS.md, opencode.json, files symlink)
16361640
4. Start the NextJS dev server
16371641

0 commit comments

Comments
 (0)