From 67e0081c6d573b701ed931f96e14dbe5b4258a17 Mon Sep 17 00:00:00 2001 From: Claude Sonnet 5 Date: Fri, 3 Jul 2026 08:49:43 +0000 Subject: refactor(executor): extract provider-neutral tool-use loop (Phase 1) Splits LocalRunner's OpenAI-specific agentic loop into reusable, provider- agnostic pieces so later phases can add native Anthropic/OpenAI/Google/Groq/ OpenRouter adapters without duplicating the control flow: - internal/provider: neutral Provider/ChatRequest/ChatResponse types, plus an openaicompat adapter wrapping the existing internal/llm.Client unchanged - internal/sandbox: Sandbox interface + HostSandbox (git clone/push/cleanup, read_file/write_file/run_bash/glob), lifted verbatim from local.go/localtools.go - internal/agentloop: the extracted tool-use loop (request/response/tool- dispatch/loop, ask_user blocking, stream-json envelope, summary fallback) - internal/agentchannel: AgentChannel/SubtaskSpec/BlockedError/ErrAgentBlocked moved out of internal/executor so agentloop can use them without an import cycle; internal/executor re-exports via type aliases, so no call site changes - internal/executor/nativerunner.go: NativeRunner replaces LocalRunner, wiring agentloop.Loop + openaicompat + HostSandbox together - config.Providers map[string]ProviderConfig added (unused until Phase 2+) Zero intended behavior change: go test -race ./... passes across all packages, and end-to-end stream-json/summary/changestats output was verified byte-compatible against a fake OpenAI-compatible server. Adds test coverage for sandbox tool-dispatch (git clone/push, read/write/bash/glob) that LocalRunner never had. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01V1moSNCJRcP6kykA4tyUSs --- internal/sandbox/sandbox.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 internal/sandbox/sandbox.go (limited to 'internal/sandbox/sandbox.go') diff --git a/internal/sandbox/sandbox.go b/internal/sandbox/sandbox.go new file mode 100644 index 0000000..4275475 --- /dev/null +++ b/internal/sandbox/sandbox.go @@ -0,0 +1,25 @@ +// Package sandbox defines the filesystem/shell/git surface an agent loop +// executes tool calls against. Sandbox is intentionally narrow — just the +// operations internal/agentloop's read_file/write_file/run_bash/glob tools +// and its git clone/push/cleanup lifecycle need. +// +// Phase 1 ships exactly one implementation, HostSandbox, which lifts the +// LocalRunner's existing behavior (host git clone into a temp dir, plain +// os.Exec-backed file/bash tools) verbatim. A DockerSandbox (isolation +// improvements, new safety checks) is explicitly out of scope for this phase. +package sandbox + +import "context" + +// Sandbox is the environment a single task execution runs its tool calls +// against. +type Sandbox interface { + ReadFile(ctx context.Context, path string) (string, error) + WriteFile(ctx context.Context, path, content string) error + RunBash(ctx context.Context, command string) (stdout, stderr string, exitCode int, err error) + Glob(ctx context.Context, pattern string) ([]string, error) + GitClone(ctx context.Context, remote, branch string) error + GitPush(ctx context.Context, branch string) error + WorkDir() string + Cleanup(ctx context.Context) error +} -- cgit v1.2.3