From c110bf8168e9782e340372a6ccf8d40e5e701901 Mon Sep 17 00:00:00 2001 From: Nick Sweeting Date: Thu, 3 Sep 2026 14:17:51 -0700 Subject: [PATCH] Stop initializing Git repositories for OpenCode sessions --- archivebox/opencode/views.py | 46 ++----------------------- archivebox/tests/test_opencode_agent.py | 37 ++++++++++++++++---- 2 files changed, 33 insertions(+), 50 deletions(-) diff --git a/archivebox/opencode/views.py b/archivebox/opencode/views.py index 6a728753..9a160ae9 100644 --- a/archivebox/opencode/views.py +++ b/archivebox/opencode/views.py @@ -6,7 +6,6 @@ import logging import os import re import signal -import shutil import subprocess import threading import time @@ -247,7 +246,7 @@ def _settings(config: dict) -> dict: } -def _resolve_binary(binary: str, config: dict) -> tuple[Any, Any, dict[str, str]]: +def _resolve_binary(binary: str, config: dict) -> tuple[Any, dict[str, str]]: try: from abxpkg import BinProvider from abx_plugins.plugins.base.utils import load_required_binary_from_config @@ -285,11 +284,7 @@ def _resolve_binary(binary: str, config: dict) -> tuple[Any, Any, dict[str, str] providers=providers, base_env=binary_environ, ) - return ( - loaded_dependencies[-1], - loaded_dependencies[1], - binary_env, - ) + return loaded_dependencies[-1], binary_env def _project_route(workdir: Path, session_id: str = "") -> str: @@ -302,12 +297,6 @@ def _project_route(workdir: Path, session_id: str = "") -> str: def _ensure_project_files(settings: dict) -> None: workdir = settings["workdir"].resolve() workdir.mkdir(parents=True, exist_ok=True) - git_marker = workdir / ".git" / "not-a-git" - if git_marker.exists(): - # Current OpenCode hangs on the legacy fake marker, so remove only - # that invalid shape before initializing the real worktree. - shutil.rmtree(git_marker.parent) - editable_skill_path = settings["opencode_dir"] / "SKILL.md" editable_skill_path.parent.mkdir(parents=True, exist_ok=True) if not editable_skill_path.exists(): @@ -336,18 +325,6 @@ def _ensure_default_session(settings: dict) -> str: workdir = settings["workdir"].resolve() params = {"directory": str(workdir)} timeout = settings["timeout"] - project = requests.post( - f"{settings['origin']}/project/git/init", - params=params, - timeout=timeout, - ) - project.raise_for_status() - project_data = project.json() - if Path(str(project_data.get("worktree") or "/")).resolve() != workdir: - raise RuntimeError( - f"OpenCode initialized the wrong project worktree: {project_data.get('worktree')!r}", - ) - sessions = requests.get( f"{settings['origin']}/session", params={**params, "roots": "true", "limit": 55}, @@ -419,7 +396,7 @@ def _ensure_opencode(settings: dict) -> tuple[bool, str]: _stop_owned_process(_PROCESS) try: - binary, git_binary, binary_env = _resolve_binary( + binary, binary_env = _resolve_binary( settings["binary"], settings["config"], ) @@ -450,23 +427,6 @@ def _ensure_opencode(settings: dict) -> tuple[bool, str]: settings["home"].mkdir(parents=True, exist_ok=True) _ensure_project_files(settings) - if not (workdir / ".git").exists(): - try: - git_init = git_binary.exec( - cmd=("init", "--quiet"), - cwd=workdir, - env=env, - timeout=settings["timeout"], - ) - except (AssertionError, OSError, subprocess.SubprocessError) as err: - return False, f"OpenCode project initialization failed: {err}" - if git_init.returncode != 0: - output = (git_init.stderr or git_init.stdout or "").strip() - return ( - False, - f"OpenCode project initialization failed: {output or f'git exited with {git_init.returncode}'}", - ) - if _health(settings): return True, "" diff --git a/archivebox/tests/test_opencode_agent.py b/archivebox/tests/test_opencode_agent.py index af0ef60c..e35b8df4 100644 --- a/archivebox/tests/test_opencode_agent.py +++ b/archivebox/tests/test_opencode_agent.py @@ -95,7 +95,7 @@ def live_opencode(opencode_archive_config): settings["archivebox_base_url"] = "http://admin.archivebox.localhost:8000" settings["archivebox_admin_url"] = "http://admin.archivebox.localhost:8000/admin" settings["archivebox_api_url"] = "http://admin.archivebox.localhost:8000/api/" - binary, _, binary_env = views._resolve_binary(settings["binary"], settings["config"]) + binary, binary_env = views._resolve_binary(settings["binary"], settings["config"]) version = binary.exec( cmd=("--version",), env={**os.environ, **binary_env}, @@ -218,7 +218,8 @@ def test_opencode_proxy_serves_real_project_and_session(admin_client, live_openc HTTP_SEC_FETCH_SITE="same-origin", ) assert project.status_code == 200 - assert workdir.encode() in project.content + assert project.json()["id"] == "global" + assert not project.json().get("vcs") path = admin_client.get( f"/admin/agent/opencode/path?directory={encoded_workdir}", @@ -226,7 +227,7 @@ def test_opencode_proxy_serves_real_project_and_session(admin_client, live_openc HTTP_SEC_FETCH_SITE="same-origin", ) assert path.status_code == 200 - assert workdir.encode() in path.content + assert path.json()["directory"] == workdir sessions = admin_client.get( f"/admin/agent/opencode/session?directory={encoded_workdir}&roots=true&limit=55", @@ -234,7 +235,8 @@ def test_opencode_proxy_serves_real_project_and_session(admin_client, live_openc HTTP_SEC_FETCH_SITE="same-origin", ) assert sessions.status_code == 200 - assert b"id" in sessions.content + assert any(session["id"] == agent.context["recent_session_id"] and session["directory"] == workdir for session in sessions.json()) + assert not (Path(workdir) / ".git").exists() def test_opencode_proxy_restarts_server_for_an_existing_agent_page(admin_client, live_opencode): @@ -391,10 +393,16 @@ def test_opencode_proxy_sse_returns_headers_before_restart_finishes(admin_client assert owned_process.poll() is None -def test_opencode_starts_with_isolated_state(live_opencode): +def test_opencode_starts_with_isolated_state(admin_client, live_opencode): workdir = str(live_opencode.config.data_dir.resolve()) state_dir = live_opencode.config.state_dir + assert not (Path(workdir) / ".git").exists() + agent = admin_client.get("/admin/agent", HTTP_HOST=ADMIN_TEST_HOST) + assert agent.status_code == 200 + assert agent.context["recent_session_id"] + assert not (Path(workdir) / ".git").exists() + project = requests.get( f"{live_opencode.settings['origin']}/project/current", params={"directory": workdir}, @@ -409,11 +417,26 @@ def test_opencode_starts_with_isolated_state(live_opencode): config.raise_for_status() assert Path(live_opencode.settings["workdir"]).resolve() == Path(workdir) - assert Path(str(project.json()["worktree"])).resolve() == Path(workdir) + assert project.json()["id"] == "global" + assert not project.json().get("vcs") assert config.json()["model"] == "opencode/big-pickle" assert config.json()["snapshot"] is False assert live_opencode.process.poll() is None - assert (live_opencode.config.data_dir / ".git").is_dir() + path = requests.get( + f"{live_opencode.settings['origin']}/path", + params={"directory": workdir}, + timeout=live_opencode.settings["timeout"], + ) + path.raise_for_status() + assert Path(path.json()["directory"]).resolve() == Path(workdir) + + diff = requests.get( + f"{live_opencode.settings['origin']}/vcs/diff", + params={"directory": workdir, "mode": "git"}, + timeout=5, + ) + diff.raise_for_status() + assert diff.json() == [] assert (state_dir / "data" / "opencode" / "opencode.db").is_file() assert (state_dir / "SKILL.md").is_file() assert (state_dir / "config" / "opencode" / "skills" / "archivebox" / "SKILL.md").resolve() == state_dir / "SKILL.md"