Repository navigation
feat: Phase 3 provider abstraction and cache (Gemini-first) - #5
Conversation
- LLMProvider protocol, LLMResponse, ProviderUnavailable in providers/base - GeminiProvider over google-genai with tenacity retry on 5xx/429/transport - CachedProvider on diskcache, keyed sha256(template_version+model+prompt), template_version=1 - cache_dir config override; DEFAULT_MODEL now gemini-3.5-flash-lite (literal SDK ID) - TokenBudgetManager.from_config resolves real context windows (named risk fixed) - plan.md Phase 3 corrected to Gemini-first (local-only, gitignored) - Anthropic intentionally deferred to stretch ideas - 113 tests green; fake-client only, no real API calls
…ds, and speed up tenacity tests
Review Fixes Applied (commit 9e6721f)All review feedback items have been addressed and verified:
Verification
|
|
Note: Aligned |
|
Added |
…d orchestrator consolidation - #1 (Blocker): Fail loud with exit code 1 on git errors, budget cap breaches, and gh CLI errors across pr-summary and changelog CLI commands. - #2: Prevent duplicate printing when no changes/commits exist by early returning None. - #3: Route diagnostic warnings, budget alerts, and error messages to stderr console (err_console) to keep stdout clean for Unix piping. - #4: Correctly parse and surface breaking changes (exclamation mark and BREAKING CHANGE: footers) in conventional commits and templates. - #5: Bump changelog template to version 2, including from_ref..to_ref range and explicit release headers. - #6: Support --title (-t) flag in pr-summary and propagate gh pr create failures. - #7: Remove dead head argument from fallback PR summary. - #8: Consolidate duplicate budget checking, safe telemetry recording, and heuristic token counters into orchestrator.py. - #9: Enforce strict type hints with CommitLogEntry in fallback.py.
Overview
Phase 3:
LLMProviderabstraction with a caching wrapper and a Gemini backend, resolving the plan.md vs AGENTS.md conflict in favor of Gemini-first (the locked-in default). Anthropic stays deferred to the stretch-ideas list.What changed
providers/base.py(new)LLMProviderProtocol (generate(prompt, model) -> LLMResponse)LLMResponsedataclass:text,model, optionalinput_tokens/output_tokensProviderUnavailable(Phase 4 catches) +RetryableProviderErrormarkerproviders/gemini.py(new)GeminiProviderovergoogle-genai, lazygenai.Client(api_key=...)likeGeminiTokenCountertenacityretry on transient failures (5xxServerError, 429,httpx.TransportError), 3 attempts, exponential backoff; final failure →ProviderUnavailableproviders/cache.py(new)CachedProviderondiskcache, keysha256(template_version + model + prompt)template_versionhardcoded"1"until Phase 4 ships real templates (avoids a key migration)~/.cache/gitmate/(XDG), overridableconfig.pyDEFAULT_MODEL→gemini-3.5-flash-lite(literal SDK ID, confirmed real), with a comment on Gemini's retirement cadencecache_diroverride field + validationtoken_budget.pyTokenBudgetManager.from_config(cfg, counter)resolvesget_context_window(cfg)— closes the Phase 2 named risk (no 1M default against a 200k model)plan.md— Phase 3 text corrected to Gemini-first (local-only file, gitignored)Tests (113 green, no real API calls)
generate()— two identical calls hit the underlying provider oncecache_diroverride honoredProviderUnavailable(3 calls), non-transient 400 raised oncefrom_config:gemini-3.5-flash-lite→ 1,048,576;claude-3-5-sonnet→ 200,000; override; unknown-model raisesDeferred (intentional)
AnthropicProvider(secondary) — stretch idea, after the abstraction is proven