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>
2.0 KiB
2.0 KiB
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
LLMAdapterABC — 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")orcreate_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
# 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