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:
33
tests/unit/llm/test_factory.py
Normal file
33
tests/unit/llm/test_factory.py
Normal file
@@ -0,0 +1,33 @@
|
||||
"""Tests for markitect.llm.factory."""
|
||||
|
||||
import pytest
|
||||
|
||||
from markitect.llm.factory import create_adapter
|
||||
from markitect.llm.openrouter import OpenRouterAdapter
|
||||
from markitect.llm.claude_code import ClaudeCodeAdapter
|
||||
from markitect.llm.exceptions import LLMConfigurationError
|
||||
|
||||
|
||||
class TestCreateAdapter:
|
||||
def test_openrouter(self):
|
||||
adapter = create_adapter("openrouter", api_key="sk-test")
|
||||
assert isinstance(adapter, OpenRouterAdapter)
|
||||
|
||||
def test_claude_code(self):
|
||||
adapter = create_adapter("claude-code")
|
||||
assert isinstance(adapter, ClaudeCodeAdapter)
|
||||
|
||||
def test_unknown_provider(self):
|
||||
with pytest.raises(LLMConfigurationError) as exc_info:
|
||||
create_adapter("unknown-provider")
|
||||
assert "unknown-provider" in str(exc_info.value)
|
||||
|
||||
def test_model_passed_through(self):
|
||||
adapter = create_adapter("claude-code", model="opus")
|
||||
assert adapter._model == "opus"
|
||||
|
||||
def test_openrouter_system_prompt(self):
|
||||
adapter = create_adapter(
|
||||
"openrouter", api_key="sk-test", system_prompt="Be helpful"
|
||||
)
|
||||
assert adapter._system_prompt == "Be helpful"
|
||||
Reference in New Issue
Block a user