feat(llm): add LLM integration module with OpenRouter and Claude Code adapters
Implements markitect/llm/ package with concrete LLMAdapter implementations:
- OpenRouterAdapter: HTTP via urllib with retry/backoff on 429/5xx
- ClaudeCodeAdapter: subprocess-based Claude CLI with stdin piping
- Factory pattern: create_adapter("openrouter") or create_adapter("claude-code")
- API key resolution chain: constructor > env var > project-root key file
- 42 unit tests, 2 integration tests (gated on API key / CLI availability)
Also adds the infospace-with-history example with Wealth of Nations VSM
analysis pipeline, templates, schemas, source chapters, and processed
output for chapters 1-2. process_chapters.py now supports --provider
and --model flags for automatic LLM-driven processing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
59
roadmap/260210-llm-integration/WORKPLAN.md
Normal file
59
roadmap/260210-llm-integration/WORKPLAN.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# LLM Integration Module — Work Plan
|
||||
|
||||
**Date**: 2026-02-10
|
||||
**Status**: Implemented
|
||||
|
||||
## Overview
|
||||
|
||||
Added `markitect/llm/` package providing concrete `LLMAdapter` implementations
|
||||
so any MarkiTect component can call an LLM through OpenRouter (HTTP) or
|
||||
Claude Code CLI (subprocess).
|
||||
|
||||
## Module Layout
|
||||
|
||||
```
|
||||
markitect/llm/
|
||||
├── __init__.py # Public API
|
||||
├── exceptions.py # LLMError hierarchy (extends MarkitectError)
|
||||
├── config.py # LLMConfig dataclass, API key resolution
|
||||
├── _http.py # Sync HTTP helper (urllib.request)
|
||||
├── _token_estimator.py # Rough token counting for CLI backend
|
||||
├── openrouter.py # OpenRouterAdapter(LLMAdapter)
|
||||
├── claude_code.py # ClaudeCodeAdapter(LLMAdapter)
|
||||
└── factory.py # create_adapter() factory function
|
||||
```
|
||||
|
||||
## Design Decisions
|
||||
|
||||
- Implements existing `LLMAdapter` ABC — no interface changes
|
||||
- No new pip dependencies (stdlib only: urllib.request, subprocess)
|
||||
- API key resolution: constructor arg > env var > project-root key file
|
||||
- Factory pattern: `create_adapter("openrouter")` or `create_adapter("claude-code")`
|
||||
|
||||
## Testing
|
||||
|
||||
- 42 unit tests in `tests/unit/llm/` (all mocked, no network)
|
||||
- Integration tests in `tests/integration/llm/` (skip if no API key / CLI)
|
||||
|
||||
## Example Integration
|
||||
|
||||
`examples/infospace-with-history/process_chapters.py` accepts `--provider`
|
||||
and `--model` CLI args. When a provider is specified, each pipeline stage
|
||||
auto-generates output via the LLM adapter instead of waiting for manual input.
|
||||
|
||||
## Verification
|
||||
|
||||
```bash
|
||||
# Unit tests
|
||||
pytest tests/unit/llm/ -v
|
||||
|
||||
# Integration (OpenRouter)
|
||||
OPENROUTER_API_KEY=$(cat apikey-openrouter.txt) pytest tests/integration/llm/test_openrouter_live.py -v
|
||||
|
||||
# Integration (Claude Code CLI)
|
||||
pytest tests/integration/llm/test_claude_code_live.py -v
|
||||
|
||||
# End-to-end
|
||||
python examples/infospace-with-history/process_chapters.py \
|
||||
--chapter book-1-chapter-03 --provider claude-code --no-commit
|
||||
```
|
||||
Reference in New Issue
Block a user