generated from coulomb/repo-seed
feat: WP-0001 foundation + WP-0002 core extensions
WP-0001 — Foundation & GAAF Baseline - SCOPE.md, ARCHITECTURE-LAYERS.md, contracts/ tree - .claude/rules/ stubs filled (architecture, stack, boundary) - 57 tests (pytest), pyproject.toml with ruff+mypy, CI workflow WP-0002 — Core Extensions (FR-4 + FR-3) - FR-4: BudgetTracker (thread-safe) + LLMBudgetExceededError + optional RunConfig.budget_tracker + enforcement in all adapters - FR-3: async_execute_prompt on LLMAdapter ABC (asyncio.to_thread fallback) + native asyncio.create_subprocess_exec in ClaudeCodeAdapter 81 tests passing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
94
contracts/functional/adapters.md
Normal file
94
contracts/functional/adapters.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Contract: Functional — Provider Adapters
|
||||
|
||||
**Layer:** Functional
|
||||
**Version:** 0.1.0
|
||||
**Maturity:** Beta (all adapters)
|
||||
**Last updated:** 2026-04-01
|
||||
|
||||
---
|
||||
|
||||
## Common adapter contract
|
||||
|
||||
All provider adapters implement `LLMAdapter` (see `contracts/core/llm-adapter.md`).
|
||||
|
||||
Additional shared guarantees:
|
||||
|
||||
- Constructors resolve API keys at instantiation and raise `LLMConfigurationError`
|
||||
immediately if no key is found (fail-fast).
|
||||
- HTTP-based adapters (`OpenAIAdapter`, `GeminiAdapter`, `OpenRouterAdapter`)
|
||||
use `_http.post_json` and do not add runtime dependencies beyond stdlib.
|
||||
- `metadata` in the returned `LLMResponse` always contains `"provider"` and
|
||||
`"latency_seconds"` keys.
|
||||
- HTTP adapters that retry (`OpenAIAdapter`, `OpenRouterAdapter`) use
|
||||
exponential backoff: `sleep(2 ** attempt)` on 429 and 5xx.
|
||||
|
||||
---
|
||||
|
||||
## OpenAIAdapter
|
||||
|
||||
**Provider key:** `"openai"`
|
||||
**Default model:** `gpt-4.1-mini`
|
||||
**API:** `https://api.openai.com/v1/chat/completions`
|
||||
**Auth:** `OPENAI_API_KEY` env var or `apikey-chatgpt.txt` in project root
|
||||
**Retries:** 3 (exponential backoff on 429 and 5xx)
|
||||
|
||||
---
|
||||
|
||||
## GeminiAdapter
|
||||
|
||||
**Provider key:** `"gemini"`
|
||||
**Default model:** `gemini-2.5-flash`
|
||||
**API:** `https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent`
|
||||
**Auth:** `GEMINI_API_KEY` env var or `apikey-geminifree.txt` in project root
|
||||
**Retries:** 0 (no retry logic; rate-limit handling deferred)
|
||||
**Note:** System prompt is simulated via a user/model turn pair (Gemini has no native system role).
|
||||
|
||||
---
|
||||
|
||||
## OpenRouterAdapter
|
||||
|
||||
**Provider key:** `"openrouter"`
|
||||
**Default model:** `anthropic/claude-sonnet-4`
|
||||
**API:** `https://openrouter.ai/api/v1/chat/completions` (configurable via `LLMConfig.api_base`)
|
||||
**Auth:** `OPENROUTER_API_KEY` env var or `apikey-openrouter.txt` in project root
|
||||
**Retries:** 3 (exponential backoff on 429 and 5xx)
|
||||
**Note:** OpenRouter is an OpenAI-compatible endpoint; `RunConfig.model_params` are merged into the payload.
|
||||
|
||||
---
|
||||
|
||||
## ClaudeCodeAdapter
|
||||
|
||||
**Provider key:** `"claude-code"`
|
||||
**Default model:** n/a (uses the CLI's configured default)
|
||||
**Auth:** none (delegates to locally installed `claude` CLI)
|
||||
**Subprocess:** `claude --print [--model M]` with prompt on stdin
|
||||
**Token counts:** estimated via `_token_estimator` (not provider-reported)
|
||||
**validate_config:** runs `claude --version`; returns `False` if CLI not found
|
||||
|
||||
---
|
||||
|
||||
## EmbeddingAdapter ABC
|
||||
|
||||
`llm_connect.embedding_adapter.EmbeddingAdapter`
|
||||
|
||||
```python
|
||||
class EmbeddingAdapter(ABC):
|
||||
@abstractmethod
|
||||
def embed(self, texts: list[str]) -> list[list[float]]: ...
|
||||
```
|
||||
|
||||
Invariant: returns a list of the same length as `texts`.
|
||||
|
||||
### OpenAICompatibleEmbeddingAdapter
|
||||
|
||||
Compatible with any OpenAI-format embedding endpoint (`/v1/embeddings`).
|
||||
Default model: `text-embedding-3-small`.
|
||||
|
||||
---
|
||||
|
||||
## EmbeddingCache
|
||||
|
||||
`llm_connect.embedding_cache.EmbeddingCache`
|
||||
|
||||
Disk-backed cache keyed by text content (SHA-256 hash).
|
||||
`get_or_compute(text, compute_fn)` returns cached vector or calls `compute_fn`.
|
||||
Reference in New Issue
Block a user