feat: Windows에서 ConPTY 기반 interactive trigger 지원 - #14
Closed
kjh0718 wants to merge 7 commits into
Closed
Conversation
Claude/Codex interactive trigger의 PTY 및 process lifecycle을 internal/terminal.Session으로 추상화한다. - Unix/macOS는 기존 creack/pty 동작 유지 - Windows는 현재 unsupported stub 유지 - provider의 직접 PTY 의존 제거 - terminal abstraction 최소 테스트 추가 ConPTY backend와 Windows continue proxy는 후속 작업으로 분리한다. Refs #1
Windows에서도 interactive provider trigger를 실행할 수 있도록 golang.org/x/sys/windows 기반 ConPTY backend를 구현한다. - CreatePseudoConsole과 PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE로 interactive child를 pseudoconsole에 연결 - CREATE_SUSPENDED → Job Object 할당 → ResumeThread 순서로 descendant process의 job escape race 차단 - background 실행 환경에서도 child stdio가 ConPTY로 연결되도록 STARTF_USESTDHANDLES와 NULL standard handles 적용 - raw ReadFile/WriteFile로 ConPTY I/O 처리 - child 종료 시 HPCON을 비동기로 닫아 blocked Read의 EOF 보장 - Job Object와 conhost bounded reap으로 process tree와 console host 정리 - Wait/Kill/Close/context cancellation lifecycle 동기화 - Windows lifecycle, stdin round-trip, process tree, conhost, Ctrl-C, 반복/동시 session 테스트 추가 Refs #1
Windows에서 .cmd/.bat shim을 CreateProcess의 lpApplicationName으로 직접 실행하던 경로를 문서화된 COMSPEC 경유 방식으로 변경한다. 기존 방식은 일부 Windows 환경에서 동작하지만 cmd.exe의 추가 parsing을 고려하지 않아 공백이 있는 shim 경로가 실패하고, 특정 argument가 별도 명령으로 해석되는 command injection을 실제로 허용했다. - .cmd/.bat을 case-insensitive하게 판별하고 COMSPEC /d /v:off /s /c로 실행 - COMSPEC이 없으면 System32의 cmd.exe 절대 경로 사용 - native executable은 기존 ComposeCommandLine 경로 유지 - batch argument를 cmd 규칙에 맞게 quote하고 metacharacter injection 차단 - literal %, NUL, 개행은 batch를 통해 안전하게 보존할 수 없어 명시적으로 거부 - /v:off로 delayed expansion을 강제 비활성화해 !VAR!을 literal로 유지 - 오류 메시지에 사용자 argument 값을 직접 노출하지 않고 위치만 표시 - .BAT casing, 공백 경로, 공백 argument, metacharacter, injection, COMSPEC fallback, percent 거부 및 delayed expansion 테스트 추가 ConPTY, Job Object, Wait/Kill/Close 및 pipe lifecycle은 변경하지 않는다. Refs #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Windows에서도 Claude Code / Codex의 interactive trigger를 사용할 수 있도록
공통 terminal session abstraction과 native ConPTY backend를 추가합니다.
주요 변경:
Claude/Codex의 직접 PTY 의존을
internal/terminal.Session으로 통합Unix/macOS는 기존
github.com/creack/ptybackend 유지Windows는
golang.org/x/sys/windows기반 native ConPTY 사용Job Object로 child/descendant process lifecycle 관리
.cmd/.batCLI shim을COMSPEC경유로 안전하게 실행Windows lifecycle / I/O / cancellation / cleanup 테스트 추가
Unix
Session.Kill에서 이미 종료된 process를 성공으로 처리하도록 lifecycle contract 통일README / README.zh-CN에 Windows 지원 범위와 설치 방법 반영
Windows에서 실제로 검증한 범위:
Claude Code interactive trigger — PASS
Codex interactive trigger — PASS
native ConPTY terminal — PASS
.cmd/.batshim 실행 — PASSchild / descendant process cleanup — PASS
limitping continue는 Windows에서 아직 지원하지 않으며 이번 PR 범위에 포함하지 않습니다.Checks
gofmt -l .prints nothinggo build ./...go vet ./...go test ./...추가 검증:
WSL2 Ubuntu 20.04 / Go 1.27.0 clean clone에서 위 전체 Checks — PASS
go test -race ./internal/terminal/... -count=1 -timeout 180son WSL2 — PASSWindows
go test ./internal/terminal/... -count=1— PASSWindows
go test ./internal/provider/... -count=1— PASSWindows terminal race test — PASS (MSYS2 UCRT64 GCC)
Windows Claude Code interactive trigger manual E2E — PASS
Windows Codex interactive trigger manual E2E — PASS
기존 Windows
interactive failed to start: unsupported문제 재현되지 않음현재 upstream CI는 Ubuntu에서 실행되므로 Windows-specific path는 위 Windows 환경에서 별도로 검증했습니다.
Safety
I did not include credentials, raw usage responses, or private account metadata
I updated README/config examples for user-facing behavior changes
I considered whether this change can unexpectedly consume provider quota
자동 테스트에서는 실제 Claude/Codex 계정이나 provider quota를 사용하지 않습니다.
최종 Windows manual E2E에서만 Claude Code와 Codex interactive trigger를 각각 1회 실행했습니다.
Out of scope
이번 PR에는 다음 작업을 포함하지 않습니다.
Windows
continueinteractive proxyWindows terminal resize
Windows self-upgrade 지원
Windows notification 지원
Spark의 Windows 실제 E2E 검증
Windows CI workflow 추가
실제 provider 계정을 사용하는 automated E2E