Skip to content

feat!: GAPT 컨테이너 샌드박스 제거 → XGeny 실행 세션 (3.0.0) - #2

Merged
CocoRoF merged 1 commit into
mainfrom
feat/xgeny-sandbox-runtime
Aug 11, 2026
Merged

feat!: GAPT 컨테이너 샌드박스 제거 → XGeny 실행 세션 (3.0.0)#2
CocoRoF merged 1 commit into
mainfrom
feat/xgeny-sandbox-runtime

Conversation

@CocoRoF

@CocoRoF CocoRoF commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

XGEN 은 GAPT 와 무관하다. 그런데 샌드박스 표면 전체가 GAPT 의 docker exec 전제 위에 얹혀 있었고, XGEN 의 어떤 호스트도 그것을 쓰지 않았다. xgen-workflow 가 런타임에서 import 하는 것을 전수 확인한 결과 tools._sandbox, sandbox_exec_tool, build_container_cli_client, ContainerCLIRunner 사용처 0건.

남겨 두면 새 실행 기반(xgen-workflow-sandbox)을 그 위에 또 얹게 된다.

제거 (BREAKING)

대상
tools/_sandbox.py — docker exec + 경로 변환 3종 199
ContainerCLIRunner / SandboxHandle 250
build_container_cli_client 47
attach_runtime(containerize_cli=)
GAPT 전용 테스트 2개 247

attach_runtime(containerize_cli=) 은 샌드박스가 LLM 클라이언트의 스폰 방식을 바꾸던 결합이었다. 이제 어떤 프로바이더든 클라이언트는 호스트에서 돌고 샌드박스에는 도구를 통해서만 닿는다 — 백엔드마다 격리 방식이 갈리면 "이 백엔드에서만 되는 도구"가 생긴다.

추가 — tools/_xgeny_sandbox.py

class XgenySandbox(Protocol):
    workdir: str
    async def ensure(self) -> None
    async def exec(self, argv, *, cwd, stdin, env, timeout_s) -> ExecResult
    async def read_bytes(self, path) -> bytes
    async def write_bytes(self, path, data) -> int
  • 파일 읽기·쓰기가 1급 연산이다. GAPT 는 cat / sh -c 'cat > …' 서브프로세스로 흉내냈는데, 그러면 파일 하나 읽는 데 프로세스가 뜨고 "없는 파일"과 "권한 없음"이 똑같이 "명령 실패"로 뭉개진다.
  • 경로 가드가 한 곳(sandbox_path)에 있다. 세션 밖으로 나가는 경로는 전부 여기를 지난다 — 도구마다 각자 막으면 새 도구가 매번 빠뜨린다.
  • 경로 변환 계층이 없다. 호스트가 양쪽 루트를 같은 문자열로 맞춘다. GAPT 의 변환 함수 3개가 통째로 사라졌다.

변경

내장 도구 7종(Bash/Read/Write/Edit/Glob/Grep/workspace_*)이 새 프리미티브를 쓴다. 분기 조건(if context.sandbox is not None)은 그대로 — 앞으로 추가될 도구도 같은 자리에서 갈라진다.

Migration

호스트는 container_name 대신 workdir 을 갖고 exec/read_bytes/write_bytes 를 구현하는 객체를 ToolContext.sandbox 에 넘긴다. 경로 변환은 필요 없다.

검증

4,732 passed, 15 skipped, ruff clean. 활성 코드의 docker exec / container_name 0건.

🤖 Generated with Claude Code

XGEN 은 GAPT 와 무관하다. 그런데 샌드박스 표면 전체가 GAPT 의 `docker exec`
전제 위에 얹혀 있었고, **XGEN 의 어떤 호스트도 그것을 쓰지 않았다** —
xgen-workflow 가 런타임에서 가져오는 것을 전수 확인한 결과 `tools._sandbox`,
`sandbox_exec_tool`, `build_container_cli_client`, `ContainerCLIRunner`
사용처 0건. 남겨 두면 새 실행 기반을 그 위에 또 얹게 된다.

제거
  - tools/_sandbox.py — docker exec 전송 + 호스트↔컨테이너 경로 변환 3종
  - ContainerCLIRunner / SandboxHandle / build_container_cli_client
  - Pipeline.attach_runtime(containerize_cli=) — 샌드박스가 LLM 클라이언트의
    스폰 방식을 바꾸던 결합. 이제 어떤 프로바이더든 클라이언트는 호스트에서
    돌고, 샌드박스에는 도구를 통해서만 닿는다. 백엔드마다 격리 방식이 갈리면
    "이 백엔드에서만 되는 도구"가 생긴다.

추가 — tools/_xgeny_sandbox.py
  - XgenySandbox 프로토콜(workdir + async ensure/exec/read_bytes/write_bytes)
  - 파일 읽기·쓰기가 1급 연산이다. GAPT 는 cat / sh -c 'cat > …' 서브프로세스로
    흉내냈는데, 그러면 파일 하나 읽는 데 프로세스가 뜨고 "없는 파일"과
    "권한 없음"이 똑같이 "명령 실패"로 뭉개진다.
  - 경로 가드가 sandbox_path 한 곳에 있다 — 세션 밖으로 나가는 경로는 전부
    여기를 지난다. 도구마다 각자 막으면 새 도구가 매번 빠뜨린다.
  - 경로 변환 계층이 없다: 호스트가 양쪽 루트를 같은 문자열로 맞춘다.

변경
  - 내장 도구 7종(Bash/Read/Write/Edit/Glob/Grep/workspace_*)이 새 프리미티브를
    쓴다. 분기 조건(if context.sandbox is not None)은 그대로 — 앞으로 추가될
    도구도 같은 자리에서 갈라진다.
  - SandboxExecTool 이 XgenySandbox 로 실행한다 (계약·직렬화 형식 불변).

4,732 passed, 15 skipped, ruff clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@CocoRoF
CocoRoF merged commit 1a83bec into main Aug 11, 2026
4 of 5 checks passed
@CocoRoF
CocoRoF deleted the feat/xgeny-sandbox-runtime branch August 11, 2026 09:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant