Documentation
¶
Index ¶
- Constants
- func DefaultGeminiModelDiscovery() harnesses.ModelDiscoverySnapshot
- func FindGeminiQuotaWindow(windows []harnesses.QuotaWindow, limitID string) *harnesses.QuotaWindow
- func GeminiQuotaCachePath() (string, error)
- func GeminiQuotaSnapshotAge(snapshot *GeminiQuotaSnapshot, now time.Time) time.Duration
- func IsGeminiQuotaFresh(snapshot *GeminiQuotaSnapshot, now time.Time, staleAfter time.Duration) bool
- func ModelDiscoveryFromText(text, source string) harnesses.ModelDiscoverySnapshot
- func ParseGeminiModelManage(text string) []harnesses.QuotaWindow
- func ReadGeminiQuotaFromCassette(dir string) ([]harnesses.QuotaWindow, error)
- func ReadGeminiQuotaViaPTY(timeout time.Duration, opts ...QuotaPTYOption) ([]harnesses.QuotaWindow, error)
- func ResolveGeminiModelAlias(model string, snapshot harnesses.ModelDiscoverySnapshot) string
- func TierLimitIDForModel(model string) (string, bool)
- func WriteGeminiQuota(path string, snapshot GeminiQuotaSnapshot) error
- type AuthSnapshot
- type GeminiQuotaRoutingDecision
- type GeminiQuotaSnapshot
- type QuotaPTYOption
- type Runner
Constants ¶
const DefaultGeminiQuotaStaleAfter = 15 * time.Minute
const GeminiAuthFreshnessWindow = 7 * 24 * time.Hour
const GeminiModelDiscoveryFreshnessWindow = 24 * time.Hour
Variables ¶
This section is empty.
Functions ¶
func DefaultGeminiModelDiscovery ¶
func DefaultGeminiModelDiscovery() harnesses.ModelDiscoverySnapshot
func FindGeminiQuotaWindow ¶
func FindGeminiQuotaWindow(windows []harnesses.QuotaWindow, limitID string) *harnesses.QuotaWindow
FindGeminiQuotaWindow returns the QuotaWindow matching limitID, or nil.
func GeminiQuotaCachePath ¶
GeminiQuotaCachePath returns the durable Gemini quota cache path.
func GeminiQuotaSnapshotAge ¶
func GeminiQuotaSnapshotAge(snapshot *GeminiQuotaSnapshot, now time.Time) time.Duration
GeminiQuotaSnapshotAge reports snapshot age relative to now.
func IsGeminiQuotaFresh ¶
func IsGeminiQuotaFresh(snapshot *GeminiQuotaSnapshot, now time.Time, staleAfter time.Duration) bool
IsGeminiQuotaFresh reports whether a snapshot is present and not stale.
func ModelDiscoveryFromText ¶
func ModelDiscoveryFromText(text, source string) harnesses.ModelDiscoverySnapshot
ModelDiscoveryFromText extracts Gemini model IDs from caller-provided CLI output without assuming a current default model list.
func ParseGeminiModelManage ¶
func ParseGeminiModelManage(text string) []harnesses.QuotaWindow
ParseGeminiModelManage parses the raw text captured from `gemini` in /model manage. It returns one QuotaWindow per recognised tier, with the tier label, used percent, reset text, and a derived quota state. Tiers missing in the captured text are simply absent from the returned slice.
func ReadGeminiQuotaFromCassette ¶
func ReadGeminiQuotaFromCassette(dir string) ([]harnesses.QuotaWindow, error)
ReadGeminiQuotaFromCassette replays a previously recorded cassette and re-parses its final frame as Gemini /model manage output.
func ReadGeminiQuotaViaPTY ¶
func ReadGeminiQuotaViaPTY(timeout time.Duration, opts ...QuotaPTYOption) ([]harnesses.QuotaWindow, error)
ReadGeminiQuotaViaPTY launches Gemini, sends /model manage, and returns the parsed tier quota windows. Callers must only treat non-empty, non-error results as authoritative — Gemini CLI renders /model manage as a version- sensitive TUI, so a timeout or empty parse means "quota unknown".
func ResolveGeminiModelAlias ¶
func ResolveGeminiModelAlias(model string, snapshot harnesses.ModelDiscoverySnapshot) string
func TierLimitIDForModel ¶
TierLimitIDForModel returns the tier limit_id that covers the given concrete Gemini model ID (e.g. "gemini-2.5-pro" -> "gemini-pro"). Unknown models return ("", false).
func WriteGeminiQuota ¶
func WriteGeminiQuota(path string, snapshot GeminiQuotaSnapshot) error
WriteGeminiQuota atomically persists a GeminiQuotaSnapshot to path.
Types ¶
type AuthSnapshot ¶
type AuthSnapshot struct {
Authenticated bool
AuthType string
Account *harnesses.AccountInfo
CapturedAt time.Time
Fresh bool
Source string
Detail string
}
AuthSnapshot captures non-secret Gemini CLI auth/account evidence. It never stores API keys, OAuth tokens, refresh tokens, or raw credential payloads.
func ReadAuthEvidence ¶
func ReadAuthEvidence(now time.Time) AuthSnapshot
ReadAuthEvidence reads Gemini CLI auth evidence from the user's configured environment and ~/.gemini directory. It is best-effort because Gemini CLI has no stable non-interactive quota command; routing uses this as auth/account freshness evidence and exposes quota as unknown.
func ReadAuthEvidenceFromDir ¶
func ReadAuthEvidenceFromDir(dir string, now time.Time) AuthSnapshot
ReadAuthEvidenceFromDir reads non-secret Gemini CLI auth evidence from a caller-provided .gemini directory. Tests use this for credential-free replay.
type GeminiQuotaRoutingDecision ¶
type GeminiQuotaRoutingDecision struct {
// PreferGemini is true when the snapshot is fresh and at least one
// non-exhausted tier is present.
PreferGemini bool
// SnapshotPresent is true when a snapshot was found (even if stale).
SnapshotPresent bool
// Fresh is true when the snapshot is present and newer than staleAfter.
Fresh bool
// Age is the snapshot age (zero when absent).
Age time.Duration
// Snapshot is the cached snapshot when present.
Snapshot *GeminiQuotaSnapshot
// AvailableTiers lists tier limit_ids (e.g. "gemini-flash") that are
// fresh and below the exhaustion threshold.
AvailableTiers []string
// ExhaustedTiers lists tier limit_ids currently blocked (e.g. "gemini-pro"
// at 100% used).
ExhaustedTiers []string
// Reason describes the diagnostic outcome.
Reason string
}
GeminiQuotaRoutingDecision summarises whether foreground routing may select Gemini without probing the CLI inline. The decision is made per tier: a tier is "available" only when it has a fresh, non-exhausted quota window.
func DecideGeminiQuotaRouting ¶
func DecideGeminiQuotaRouting(snapshot *GeminiQuotaSnapshot, now time.Time, staleAfter time.Duration) GeminiQuotaRoutingDecision
DecideGeminiQuotaRouting turns a durable quota snapshot into a foreground routing decision. Missing, stale, or empty quota evidence keeps Gemini out of automatic routing.
func ReadGeminiQuotaRoutingDecision ¶
func ReadGeminiQuotaRoutingDecision(now time.Time, staleAfter time.Duration) GeminiQuotaRoutingDecision
ReadGeminiQuotaRoutingDecision reads the default cache and produces a routing decision in one call.
func (GeminiQuotaRoutingDecision) IsGeminiTierAvailable ¶
func (d GeminiQuotaRoutingDecision) IsGeminiTierAvailable(model string) bool
IsGeminiTierAvailable reports whether the tier for a concrete Gemini model is currently selectable according to the decision. An unknown model returns false so routing never silently picks a model outside the parsed tier set.
type GeminiQuotaSnapshot ¶
type GeminiQuotaSnapshot struct {
CapturedAt time.Time `json:"captured_at"`
Windows []harnesses.QuotaWindow `json:"windows"`
Source string `json:"source"` // e.g. "pty", "cassette"
Account *harnesses.AccountInfo `json:"account,omitempty"`
Detail string `json:"detail,omitempty"`
}
GeminiQuotaSnapshot captures parsed Gemini CLI /model manage quota evidence in a durable cache so foreground routing consumers do not invoke PTY capture inline.
Auth/account freshness on its own is NOT quota evidence. Only a parsed GeminiQuotaSnapshot with one or more tier windows promotes Gemini beyond the "quota unknown" state.
func ReadGeminiQuota ¶
func ReadGeminiQuota() (*GeminiQuotaSnapshot, bool)
ReadGeminiQuota reads the default Gemini quota cache.
func ReadGeminiQuotaFrom ¶
func ReadGeminiQuotaFrom(path string) (*GeminiQuotaSnapshot, bool)
ReadGeminiQuotaFrom reads a Gemini quota snapshot from a specific path.
func RefreshGeminiQuotaViaPTY ¶
func RefreshGeminiQuotaViaPTY(timeout time.Duration, opts ...QuotaPTYOption) (GeminiQuotaSnapshot, error)
RefreshGeminiQuotaViaPTY launches the probe and returns a ready-to-write durable snapshot. The Account field is filled from ReadAuthEvidence so the snapshot records auth/account context alongside quota evidence (but the quota decision is still gated on parsed windows, not on Account alone).
func (*GeminiQuotaSnapshot) MaxUsedPercent ¶
func (s *GeminiQuotaSnapshot) MaxUsedPercent() float64
MaxUsedPercent returns the largest used-percent across all tier windows in the snapshot. Returns 0 for nil/empty snapshots.
type QuotaPTYOption ¶
type QuotaPTYOption func(*quotaPTYOptions)
QuotaPTYOption configures a Gemini quota PTY probe.
func WithQuotaPTYCassetteDir ¶
func WithQuotaPTYCassetteDir(dir string) QuotaPTYOption
func WithQuotaPTYCommand ¶
func WithQuotaPTYCommand(binary string, args ...string) QuotaPTYOption
func WithQuotaPTYEnv ¶
func WithQuotaPTYEnv(env ...string) QuotaPTYOption
func WithQuotaPTYWorkdir ¶
func WithQuotaPTYWorkdir(workdir string) QuotaPTYOption
type Runner ¶
type Runner struct {
// Binary is the absolute path to the gemini executable. When empty the
// runner resolves "gemini" via PATH at Execute time.
Binary string
// BaseArgs is prepended to the per-request argument list.
// Gemini default: ["--output-format", "stream-json"].
BaseArgs []string
// PromptMode controls how the prompt is delivered.
// "arg" (default) sends "-p <prompt>"; "stdin" sends "-p ”" and writes
// the prompt to stdin. Gemini requires -p/--prompt for headless mode.
PromptMode string
// EventBuffer overrides the per-Execute channel buffer size.
EventBuffer int
}
Runner is the subprocess-backed gemini harness. It launches gemini in headless mode (-p/--prompt), buffers stream-json stdout, and emits text_delta + final events after the process exits.
When the output is valid JSON with a stats.models token block, usage is extracted per the DDx ExtractUsage("gemini", ...) shape.
func (*Runner) Execute ¶
func (r *Runner) Execute(ctx context.Context, req harnesses.ExecuteRequest) (<-chan harnesses.Event, error)
Execute runs one resolved request through the gemini CLI and emits events on the returned channel. Since gemini has no stream-json mode, events are emitted after the process exits (emit-on-EOF pattern).
func (*Runner) HealthCheck ¶
HealthCheck verifies the gemini binary is present.
func (*Runner) Info ¶
func (r *Runner) Info() harnesses.HarnessInfo
Info returns identity + capability metadata for this harness.