diff options
| author | Claude Sonnet 5 <noreply@anthropic.com> | 2026-07-03 08:49:43 +0000 |
|---|---|---|
| committer | Claude Sonnet 5 <noreply@anthropic.com> | 2026-07-03 08:49:43 +0000 |
| commit | 67e0081c6d573b701ed931f96e14dbe5b4258a17 (patch) | |
| tree | bc7f8ce0d57876dd85720924d0275dc39c05e5b4 /internal/provider/provider.go | |
| parent | 3d286974cdc28c68c5ee536ce9303899dae9540e (diff) | |
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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V1moSNCJRcP6kykA4tyUSs
Diffstat (limited to 'internal/provider/provider.go')
| -rw-r--r-- | internal/provider/provider.go | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/internal/provider/provider.go b/internal/provider/provider.go new file mode 100644 index 0000000..fd1022d --- /dev/null +++ b/internal/provider/provider.go @@ -0,0 +1,72 @@ +// Package provider defines a provider-neutral chat/tool-use interface. It is +// independent of any one wire format (OpenAI-compatible, Anthropic Messages, +// Gemini, etc.) so that internal/agentloop's tool-use control flow can drive +// any backend that implements Provider. +// +// Phase 1 ships exactly one implementation, internal/provider/openaicompat, +// which adapts the existing internal/llm.Client. Later phases add native +// Anthropic/OpenAI/Google/Groq/OpenRouter adapters without touching agentloop. +package provider + +import "context" + +// Message is one turn in a chat conversation, in provider-neutral shape. +type Message struct { + Role string // "system" | "user" | "assistant" | "tool" + Text string + ToolCalls []ToolCall // set on assistant turns that invoke tools + ToolResults []ToolResult // set on tool-result turns +} + +// ToolCall is a single tool invocation requested by the model. +type ToolCall struct { + ID string + Name string + ArgsJSON string +} + +// ToolResult is the outcome of executing a ToolCall, fed back to the model. +type ToolResult struct { + ToolCallID string + Name string + Content string + IsError bool +} + +// ToolSpec declares a tool the model may call. +type ToolSpec struct { + Name string + Description string + ParametersJSONSchema map[string]any +} + +// ChatRequest captures the parameters of a single chat completion call. +type ChatRequest struct { + Model string + System string + Messages []Message + Tools []ToolSpec + Temperature *float64 + MaxTokens int +} + +// Usage reports token accounting and (when known) cost for a single call. +type Usage struct { + InputTokens int + OutputTokens int + CostUSD float64 +} + +// ChatResponse is the aggregated result of a chat completion. +type ChatResponse struct { + Text string + ToolCalls []ToolCall + StopReason string + Usage Usage +} + +// Provider is a chat/tool-use backend: one per LLM vendor/wire-format. +type Provider interface { + Name() string + Chat(ctx context.Context, req ChatRequest) (*ChatResponse, error) +} |
