Documentation
¶
Index ¶
- Variables
- func IsToolReadOnly(name string) bool
- func ParseReviewOutput(raw string) *state.ReviewOutput
- type Agent
- func (a *Agent) ChatStream(ctx context.Context, systemPrompt string, messages []Message, ...) (string, error)
- func (a *Agent) ModelName() string
- func (a *Agent) ProviderName() string
- func (a *Agent) SetBaseRef(ref string)
- func (a *Agent) SetHeadRef(ref string)
- func (a *Agent) SetRawDiffs(diffs map[string]string)
- func (a *Agent) SetReviewGetter(fn func() string)
- func (a *Agent) SwitchModel(modelID string, maxOutputTokens int, temperature float64, thinkingBudget int) error
- type AgentOption
- type Capabilities
- type ChatEvent
- type ChatEventType
- type ChatRequest
- type ChatResponse
- type Client
- type ContentBlock
- type GeminiProvider
- func (g *GeminiProvider) Capabilities() Capabilities
- func (g *GeminiProvider) Chat(ctx context.Context, req ChatRequest) (*ChatResponse, error)
- func (g *GeminiProvider) ModelID() string
- func (g *GeminiProvider) Name() string
- func (g *GeminiProvider) StreamChat(ctx context.Context, req ChatRequest) (<-chan ChatEvent, error)
- type JSONSchema
- type Message
- type ModelInfo
- type ModelSwitcher
- type Provider
- type ProviderMessage
- type Role
- type StopReason
- type TextBlock
- type ThinkingBlock
- type TokenUsage
- type ToolChoice
- type ToolConfigurer
- type ToolDef
- type ToolExecutor
- type ToolParam
- type ToolParams
- type ToolResultBlock
- type ToolUseBlock
- type UsageTracker
Constants ¶
This section is empty.
Variables ¶
var ChatPrompt string
ChatPrompt is the system prompt for general follow-up questions.
var ReviewBatchPrompt string
ReviewBatchPrompt is the system prompt for reviewing a batch of files during multi-pass PR review. Phase 1: RECALL mode — report everything.
var ReviewFilePrompt string
ReviewFilePrompt is the system prompt used when reviewing a single file's diff.
var ReviewPRPrompt = ReviewPRSystemPrompt + `
You have access to tools — use them proactively to understand the code:
- git_diff: Get the unified diffs for changed files.
- read_file: Read any file from the PR branch (after changes). Supports pagination.
- read_base_file: Read a file from the base branch (before changes).
- grep: Search for patterns across the codebase (regex). Find callers, usages, related code.
- list_dir: List directory contents to understand the project structure.
- gh_pr_checks: Check CI status for the PR.
- gh_pr_comments: Read existing review comments.
## Workflow
1. Use git_diff to read the diffs for all changed files
2. Use read_file and read_base_file to examine files when you need more context
3. Use grep to find callers, usages, and related code
4. Use gh_pr_checks to check CI status
5. Use gh_pr_comments to read existing review comments
## Output Format
You MUST return ONLY a JSON object matching this exact schema — no prose before or after:
` + "```json" + `
{
"summary": "one paragraph capturing what the PR does and overall quality",
"verdict": "approve | request_changes | comment",
"findings": [
{
"severity": "critical | high | medium | low | nit",
"category": "bug | security | performance | testing | style | architecture | docs",
"file": "path/to/file.go",
"line": 42,
"title": "short title",
"detail": "what's wrong and why it matters",
"suggestion": "concrete fix, code snippet preferred",
"cwe": "CWE-XXX (for security findings only, omit for non-security)"
}
],
"missing_tests": ["behaviors that should be tested but aren't"],
"questions_for_author": ["genuine ambiguities, not rhetorical"]
}
` + "```" + `
Guidelines:
- "findings" array MUST be sorted by severity: critical first, nit last
- Every finding MUST include file and line
- "suggestion" may be empty string if no concrete fix is obvious
- "missing_tests" and "questions_for_author" may be empty arrays
- If the PR is clean, return verdict "approve" with an empty findings array
- Return ONLY the JSON — no markdown, no prose, no explanation`
ReviewPRPrompt is the system prompt for single-pass PR review. Combines the embedded review instructions with structured JSON output requirements and tool workflow guidance.
var ReviewPRSystemPrompt string
ReviewPRSystemPrompt is the high-quality, agent-driven review prompt used as the base for single-pass PR review.
var ReviewSynthesisPrompt string
ReviewSynthesisPrompt is the system prompt for the final synthesis pass. Phase 2: FILTER mode — verify, deduplicate, prioritize. Output is structured JSON matching ReviewOutput schema.
Functions ¶
func IsToolReadOnly ¶
IsToolReadOnly returns true if the named tool is safe for concurrent execution.
func ParseReviewOutput ¶
func ParseReviewOutput(raw string) *state.ReviewOutput
ParseReviewOutput parses a raw AI response into a structured ReviewOutput. It handles common LLM quirks: markdown code fences, leading/trailing prose, and minor JSON formatting issues. Returns nil if parsing fails.
Types ¶
type Agent ¶
type Agent struct {
// contains filtered or unexported fields
}
Agent wraps a Provider with a tool-calling loop. It implements Client and ToolConfigurer for backward compatibility with the existing UI and review code.
func NewAgent ¶
func NewAgent(provider Provider, toolExec *ToolExecutor, opts ...AgentOption) *Agent
NewAgent creates an Agent that uses the given Provider for API calls and the ToolExecutor for handling tool calls within the iterative loop.
func (*Agent) ChatStream ¶
func (a *Agent) ChatStream(ctx context.Context, systemPrompt string, messages []Message, onToken func(string)) (string, error)
ChatStream implements Client. It runs the iterative tool-calling loop:
- Build ChatRequest with system prompt, history, tools (and cache hint).
- Call provider.StreamChat, emit text/thinking/tool tokens to the TUI.
- Inspect Response.Content for ToolUseBlocks.
- If tool calls found: execute (parallel if all read-only), build ToolResultBlock per tool_use (matched by ID, in order), append to history, loop.
- If no tool calls: surface final text.
- Cap iterations at maxRounds. On hit, surface partial result + "max iterations reached" message.
Quirk tolerance: if the model emits text without any tool_use blocks but the text looks like a preamble ("I'll now use …" pattern without substance), we tolerate this once and continue. On the second occurrence, we terminate.
func (*Agent) ProviderName ¶
ProviderName returns the name of the underlying LLM provider.
func (*Agent) SetBaseRef ¶
SetBaseRef configures the git ref for reading base-branch files.
func (*Agent) SetHeadRef ¶
SetHeadRef configures the git ref used for file reading tools.
func (*Agent) SetRawDiffs ¶
SetRawDiffs provides the raw unified diffs for the git_diff tool.
func (*Agent) SetReviewGetter ¶
SetReviewGetter provides a function that returns the latest PR review summary.
type AgentOption ¶
type AgentOption func(*Agent)
AgentOption configures an Agent.
func WithDebugLogger ¶
func WithDebugLogger(w io.Writer) AgentOption
WithDebugLogger enables debug logging to the given writer. All requests, responses, and tool calls are logged (with secrets redacted).
func WithMaxRounds ¶
func WithMaxRounds(n int) AgentOption
WithMaxRounds sets the maximum number of tool-calling loop iterations.
func WithUsageTracker ¶ added in v1.3.0
func WithUsageTracker(tracker *UsageTracker) AgentOption
WithUsageTracker attaches a UsageTracker that accumulates token counts across all ChatStream calls. Useful for cost estimation and benchmarking.
type Capabilities ¶
type Capabilities struct {
PromptCaching bool // explicit caching API (Anthropic, Gemini)
StructuredOutput bool // JSON-schema-constrained output
ParallelToolCalls bool
MaxContextTokens int
}
Capabilities describes what a provider supports.
type ChatEvent ¶
type ChatEvent struct {
Type ChatEventType
Text string // EventText, EventThinking
ToolUse *ToolUseBlock // EventToolUse
Response *ChatResponse // EventDone
Err error // EventError
}
ChatEvent is a single streaming event from a provider.
type ChatEventType ¶
type ChatEventType int
ChatEventType categorizes streaming events.
const ( EventText ChatEventType = iota // regular text chunk EventThinking // thinking/reasoning text EventToolUse // tool call EventDone // final event with complete response EventError // error during streaming )
type ChatRequest ¶
type ChatRequest struct {
Model string
System string
Messages []ProviderMessage
Tools []ToolDef
ToolChoice ToolChoice
MaxOutputTokens int
Temperature float64
JSONSchema *JSONSchema // structured output, optional
CachePrefix bool // hint: cache system + leading messages if supported
}
ChatRequest is the canonical request to a provider.
type ChatResponse ¶
type ChatResponse struct {
Content []ContentBlock // mix of TextBlock, ThinkingBlock, ToolUseBlock
StopReason StopReason
Usage TokenUsage
}
ChatResponse is the canonical response from a provider.
type Client ¶
type Client interface {
// ChatStream sends a conversation to the LLM and streams the response.
// systemPrompt is prepended as a system instruction.
// onToken is called for each streamed chunk. Chunks may be:
// - plain text (regular model output)
// - "\x00THOUGHT:<text>" — model thinking/reasoning
// - "\x00TOOL_START:<name>(<args>)" — tool execution starting
// - "\x00TOOL_DONE:<name>|<status>|<duration>" — tool execution finished
// Returns the full assembled response text, or an error.
ChatStream(ctx context.Context, systemPrompt string, messages []Message, onToken func(string)) (string, error)
}
Client is the interface for LLM providers.
type ContentBlock ¶
type ContentBlock interface {
// contains filtered or unexported methods
}
ContentBlock is a piece of message content. Implementations: TextBlock, ThinkingBlock, ToolUseBlock, ToolResultBlock.
type GeminiProvider ¶
type GeminiProvider struct {
APIKey string
Model string
BaseURL string // override for testing; empty uses the real Gemini API
HTTPClient *http.Client // optional; defaults to a client with no timeout (context-based cancellation)
// ModelConfig holds per-model tuning (maxOutputTokens, temperature,
// thinkingBudget). Set by the caller from config.GetModelConfig().
ModelConfig struct {
MaxOutputTokens int
Temperature float64
ThinkingBudget int
}
}
GeminiProvider implements Provider for the Google Gemini API. It handles single request/response translation; the iterative tool-calling loop lives in Agent.
func (*GeminiProvider) Capabilities ¶
func (g *GeminiProvider) Capabilities() Capabilities
func (*GeminiProvider) Chat ¶
func (g *GeminiProvider) Chat(ctx context.Context, req ChatRequest) (*ChatResponse, error)
Chat performs a non-streaming request by collecting StreamChat events.
func (*GeminiProvider) ModelID ¶
func (g *GeminiProvider) ModelID() string
func (*GeminiProvider) Name ¶
func (g *GeminiProvider) Name() string
func (*GeminiProvider) StreamChat ¶
func (g *GeminiProvider) StreamChat(ctx context.Context, req ChatRequest) (<-chan ChatEvent, error)
StreamChat makes a single streaming API call and returns a channel of events. It translates ChatRequest to Gemini's native format, streams the SSE response, and emits canonical ChatEvents. The channel is closed when the response ends.
type JSONSchema ¶
type JSONSchema struct {
Name string
Schema json.RawMessage
}
JSONSchema is a simplified JSON Schema for structured output.
type ModelInfo ¶
type ModelInfo interface {
// ProviderName returns the provider name (e.g. "gemini", "anthropic").
ProviderName() string
// ModelName returns the model identifier (e.g. "gemini-2.5-pro").
ModelName() string
}
ModelInfo is optionally implemented by clients that can report their model identity.
type ModelSwitcher ¶
type ModelSwitcher interface {
// SwitchModel changes the active model to the given ID and applies the
// provided tuning parameters. Returns an error if the model is invalid.
SwitchModel(modelID string, maxOutputTokens int, temperature float64, thinkingBudget int) error
}
ModelSwitcher is optionally implemented by clients that support switching the underlying model at runtime (e.g. via a TUI model picker).
type Provider ¶
type Provider interface {
Name() string
ModelID() string
Capabilities() Capabilities
Chat(ctx context.Context, req ChatRequest) (*ChatResponse, error)
StreamChat(ctx context.Context, req ChatRequest) (<-chan ChatEvent, error)
}
Provider is the canonical interface for LLM providers. Each supported model (Gemini, Anthropic, OpenAI) plugs in behind this interface.
Chat performs a single non-streaming request. StreamChat performs a single streaming request; the returned channel delivers events until closed. The final event is always EventDone (on success) or EventError (on failure).
type ProviderMessage ¶
type ProviderMessage struct {
Role Role
Content []ContentBlock
}
ProviderMessage is a rich message for the Provider interface. Unlike the simple Message type (used by the Agent's external API), this carries structured content blocks.
type StopReason ¶
type StopReason string
StopReason indicates why the model stopped generating.
const ( StopEndTurn StopReason = "end_turn" StopToolUse StopReason = "tool_use" StopMaxTokens StopReason = "max_tokens" StopError StopReason = "error" )
type ThinkingBlock ¶
ThinkingBlock carries model reasoning/thinking text. Signature is an opaque continuity token (Gemini thoughtSignature).
type TokenUsage ¶
type TokenUsage struct {
InputTokens int
OutputTokens int
CacheHits int // tokens served from cache (if supported)
}
TokenUsage reports token consumption for a single request.
type ToolChoice ¶
type ToolChoice string
ToolChoice controls how the model selects tools.
const ( ToolChoiceAuto ToolChoice = "auto" ToolChoiceRequired ToolChoice = "required" ToolChoiceNone ToolChoice = "none" )
type ToolConfigurer ¶
type ToolConfigurer interface {
// SetHeadRef configures the git ref used for file reading tools.
SetHeadRef(ref string)
// SetBaseRef configures the git ref for reading base-branch files (before changes).
SetBaseRef(ref string)
// SetRawDiffs provides the raw unified diffs for the git_diff tool.
SetRawDiffs(diffs map[string]string)
// SetReviewGetter provides a function that returns the latest PR review summary.
SetReviewGetter(fn func() string)
}
ToolConfigurer is optionally implemented by clients that support tools.
type ToolDef ¶
type ToolDef struct {
Name string
Description string
Parameters ToolParams
ReadOnly bool // true if this tool only reads state (safe for parallel execution)
}
ToolDef defines a tool the model can call. Provider-agnostic; each adapter translates to its native format.
func CanonicalToolDefs ¶
func CanonicalToolDefs() []ToolDef
CanonicalToolDefs returns provider-agnostic tool definitions. Each provider adapter translates these to its native format. Tools are grouped: file/code inspection, git, GitHub (gh CLI), other.
type ToolExecutor ¶
type ToolExecutor struct {
HeadRef string // e.g. "origin/feature-branch" — the PR head ref for git show
BaseRef string // e.g. "origin/main" — the PR base ref for reading pre-change files
RawDiffs map[string]string // filePath -> raw unified diff (set by UI after PR load, used by review flow)
ReviewGetter func() string // returns the latest PR review summary, or "" if none
// contains filtered or unexported fields
}
ToolExecutor handles executing tool calls from the LLM.
func (*ToolExecutor) ExecuteTool ¶
func (t *ToolExecutor) ExecuteTool(name string, args map[string]interface{}) (result string, isError bool)
ExecuteTool runs a tool call and returns the result. Results starting with "Error:" are flagged as isError=true so the model can recover gracefully.
type ToolParam ¶
type ToolParam struct {
Type string
Description string
Enum []string // optional enum values
Items *ToolParam // for array types
}
ToolParam describes a single parameter.
type ToolParams ¶
type ToolParams struct {
Type string // always "object" for function parameters
Properties map[string]ToolParam
Required []string
}
ToolParams describes the parameters object for a tool.
type ToolResultBlock ¶
type ToolResultBlock struct {
ToolUseID string
Name string // tool name (needed by Gemini's functionResponse)
Content string
IsError bool
}
ToolResultBlock carries the result of executing a tool.
type ToolUseBlock ¶
type ToolUseBlock struct {
ID string
Name string
Args json.RawMessage
Signature string // opaque thought signature (Gemini); must be echoed back
}
ToolUseBlock represents a tool/function call from the model.
type UsageTracker ¶ added in v1.3.0
type UsageTracker struct {
InputTokens int
OutputTokens int
CacheHits int
Calls int // number of API calls
// contains filtered or unexported fields
}
UsageTracker accumulates token usage across multiple API calls. It is safe for concurrent use.
func (*UsageTracker) Add ¶ added in v1.3.0
func (t *UsageTracker) Add(u TokenUsage)
Add records usage from a single API call.
func (*UsageTracker) Reset ¶ added in v1.3.0
func (t *UsageTracker) Reset()
Reset zeroes all counters.
func (*UsageTracker) Snapshot ¶ added in v1.3.0
func (t *UsageTracker) Snapshot() UsageTracker
Snapshot returns a copy of the current accumulated usage.