provider

package
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 20, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package provider defines the AI provider abstraction for Forge.

Forge supports multiple AI coding agents (Claude, Gemini, GitHub Copilot CLI, OpenAI Codex CLI) and selects among them in priority order. When the active provider signals a rate limit the pipeline automatically retries with the next provider.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsRateLimitError

func IsRateLimitError(exitCode int, stderr, resultSubtype string) bool

IsRateLimitError inspects exit code, stderr text, and the stream-json subtype to decide whether a Smith failure was caused by the provider's rate limit.

This function is intentionally broad — it is better to fall back to the next provider unnecessarily than to hard-fail on a transient limit.

Types

type Kind

type Kind string

Kind is the canonical name of a provider.

const (
	Claude  Kind = "claude"
	Gemini  Kind = "gemini"
	Copilot Kind = "copilot" // gh copilot
	OpenAI  Kind = "openai"  // OpenAI Codex CLI
)

type OutputFormat

type OutputFormat int

OutputFormat describes how the provider writes its response to stdout.

const (
	// StreamJSON means the provider emits newline-delimited JSON events
	// (Claude and Gemini stream-json mode). smith.go parses these events.
	StreamJSON OutputFormat = iota
	// PlainText means the provider writes the raw assistant response text
	// directly to stdout (GitHub Copilot CLI --silent mode).
	PlainText
)

type Provider

type Provider struct {
	// Kind is the canonical provider name.
	Kind Kind
	// Command is the binary to execute. If empty, the Kind default is used.
	Command string
	// Model is the specific model to request from the provider.
	// Supported for all provider kinds via the --model flag.
	// When empty the provider's own default model is used.
	Model string
	// Backend is a named backend configuration (e.g. "ollama") that sets
	// environment variables to redirect the provider CLI to an alternative
	// API endpoint. Empty means the provider's default backend.
	Backend string
	// Env holds additional environment variables to set on the subprocess.
	// These are merged on top of the inherited environment. Populated
	// automatically for known backends (e.g. ollama) or can be set manually.
	Env map[string]string
}

Provider describes one AI backend along with any per-instance overrides.

func Defaults

func Defaults() []Provider

Defaults returns the default ordered list of providers. Claude is tried first, then Gemini (no specific model — CLI picks its default).

To use specific Gemini models in priority order, list them explicitly in forge.yaml using the "gemini/model-name" syntax:

settings:
  providers:
    - claude
    - gemini/gemini-2.5-pro
    - gemini/gemini-3-flash-preview
    - gemini/gemini-2.5-flash
    - gemini/gemini-2.5-flash-lite

GitHub Copilot CLI is NOT included by default because it consumes premium "Copilot for CLI" quota that requires manual approval. To enable Copilot as a fallback, add it explicitly:

settings:
  providers: [claude, gemini, copilot]

func FromConfig

func FromConfig(specs []string) []Provider

FromConfig builds a Provider slice from configuration strings.

Accepted formats:

"claude"                          – Claude with default command
"gemini"                          – Gemini with default command and model
"gemini/gemini-2.5-pro"           – Gemini, specific model
"gemini:mybin"                     – Gemini, custom binary, default model
"gemini:mybin/gemini-2.5-pro"      – Gemini, custom binary, specific model
"openai"                           – OpenAI Codex CLI with default command and model
"openai/o3"                        – OpenAI Codex CLI, specific model
"openai:codex/o3"                  – OpenAI, custom binary (codex), specific model
"claude:ollama"                    – Claude CLI targeting local Ollama instance
"claude:ollama/qwen2.5-coder:32b"  – Claude CLI targeting Ollama with specific model

The optional "/model" suffix selects a specific model to pass via --model. The optional ":command" infix overrides the binary to execute, unless it matches a known backend name (e.g. "ollama"), in which case environment variables are set instead.

func (Provider) BuildArgs

func (p Provider) BuildArgs(claudeFlags []string) []string

BuildArgs returns the full argument list for a one-shot non-interactive run.

The prompt text is NOT included in the returned args — it must be written to the process's stdin instead. This avoids the Windows CreateProcess command-line length limit (32 767 chars) for large Forge prompts.

claudeFlags are additional flags specified by callers (e.g. --max-turns or --tools ""). For non-Claude providers these are translated where possible and silently dropped where they have no equivalent.

func (Provider) Cmd

func (p Provider) Cmd() string

Cmd returns the effective binary name.

func (Provider) FetchQuota

func (p Provider) FetchQuota(_ context.Context) (*Quota, error)

FetchQuota is a placeholder for future provider quota reporting via CLI.

Neither 'claude --usage' nor 'gemini --quota' are supported non-interactive commands with a stable, machine-readable output format. Until a verified format is confirmed, this method is intentionally a no-op to avoid calling unsupported flags and silently swallowing real execution errors.

Quota data is captured automatically from stream-json events during normal Smith runs (see readStreamJSON). FetchQuota exists as an extension point for any future proactive quota polling.

func (Provider) Format

func (p Provider) Format() OutputFormat

Format returns the output format this provider writes to stdout.

func (Provider) Label

func (p Provider) Label() string

Label returns a human-readable identifier for this provider suitable for log messages. When a backend is set it includes it (e.g. "claude:ollama/qwen2.5-coder:32b"). When a model is set it returns "kind/model" (e.g. "gemini/gemini-2.5-pro"); otherwise it returns just the kind string.

type Quota

type Quota struct {
	RequestsRemaining int        `json:"requests_remaining,omitempty"`
	RequestsLimit     int        `json:"requests_limit,omitempty"`
	RequestsReset     *time.Time `json:"requests_reset,omitempty"`
	TokensRemaining   int        `json:"tokens_remaining,omitempty"`
	TokensLimit       int        `json:"tokens_limit,omitempty"`
	TokensReset       *time.Time `json:"tokens_reset,omitempty"`
}

Quota holds remaining request/token counts and reset times.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL