feat(llm): LLM integration framework Phase 1 — multi-provider abstraction (closes #63)#152
Merged
Merged
Conversation
…tion (closes #63) Issue #63 Phase 1: add LLM integration framework with 6-provider abstraction (OpenAI / Anthropic / Bedrock / Google / DeepSeek / Z.ai GLM), lazy import per provider, 60s timeout, 3-retry exponential backoff, config via env vars + explicit kwargs. New files: - scripts/llm/__init__.py — re-exports public API - scripts/llm/base_tool.py — LLMTool ABC + LLMToolInput/Output ABCs + error hierarchy (LLMError → LLMTimeoutError, ProviderNotConfiguredError, ProviderNotInstalledError) - scripts/llm/provider.py — invoke_llm() entry point + resolve_provider() prefix dispatch + 6 _call_<provider> wrappers (lazy SDK import) - scripts/commands/llm_framework.py — 'codelens llm providers|config|ping' command (file named llm_framework.py — not llm.py — to avoid shadowing the scripts/llm/ package when commands/__init__.py auto-imports submodules) - tests/test_llm.py — 73 network-free tests (SDK calls mocked) - docs/llm-framework.md — architecture doc + design decisions Sync'd via 'python3 scripts/sync_command_count.py --apply': - command count 70 → 71 (new 'llm' command registered) - README, SKILL, SKILL-QUICK, pyproject.toml, skill.json, graph_model.py updated to reflect new count Verified: - tests/test_llm.py: 73 passed - tests/test_command_count.py + test_doctor.py + test_cli.py + test_codelens.py: 141 passed (no regressions) - sync_command_count.py --check: clean - 'codelens llm providers|config|ping' smoke-tested end-to-end Phase 2-5 (cache, explanation generator, reasoning offload, MCP prompts) deferred to follow-up issues per issue spec. LLMToolInput ABC already requires __hash__/__eq__ so the Phase 2 disk cache can key off input objects directly without API change.
5 tasks
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




Closes #63
Ringkasan
Phase 1 dari issue #63 — LLM integration framework dengan 6-provider abstraction (OpenAI / Anthropic / Bedrock / Google / DeepSeek / Z.ai GLM). Lazy import per provider, 60s timeout, 3-retry exponential backoff (1s → 2s → 4s), config via env vars + explicit kwargs. Phase 2-5 (cache, explanation generator, reasoning offload, MCP prompts) deferred ke follow-up issues.
Perubahan
New files
scripts/llm/__init__.pyscripts/llm/base_tool.pyLLMToolABC +LLMToolInput/LLMToolOutputABCs + error hierarchy (LLMError→LLMTimeoutError,ProviderNotConfiguredError,ProviderNotInstalledError)scripts/llm/provider.pyinvoke_llm()entry point +resolve_provider()prefix dispatch + 6_call_<provider>wrappers (lazy SDK import)scripts/commands/llm_framework.pytests/test_llm.pydocs/llm-framework.mdSync'd files (auto via
sync_command_count.py --apply)Command count 70 → 71. README, SKILL, SKILL-QUICK, pyproject.toml, skill.json, scripts/graph_model.py updated.
Public API
Provider dispatch
Dispatch by model name prefix (case-insensitive, first match wins):
gpt-,o1-,o3-,o4-,chatgpt-openaiopenaiclaude-anthropicanthropicbedrock-,amazon.bedrockboto3gemini-googlegoogle-generativeaideepseek-deepseekopenai(OpenAI-compatible)glm-,glm4-,zai-zai_glmopenai(OpenAI-compatible, base URLopen.bigmodel.cn)Force a provider:
CODELENS_LLM_PROVIDER=openaienv var atauprovider=kwarg.Config (env vars)
CODELENS_LLM_MODELCODELENS_LLM_API_KEYCODELENS_LLM_PROVIDEROPENAI_API_KEY/ANTHROPIC_API_KEY/ dllAPI key resolution: explicit kwarg > provider-specific env var >
CODELENS_LLM_API_KEY.CLI command
Error model
LLMError.retryableflag drives retry loop. Non-retryable errors propagate on first attempt.Definition of Done (Phase 1, dari issue)
LLMToolABC +LLMToolInput/LLMToolOutputABCs dengan__hash__/__eq__model_nameprefixCODELENS_LLM_PROVIDER,CODELENS_LLM_MODEL,CODELENS_LLM_API_KEYenv varsPhases 2-5 deferred ke follow-up issues per issue spec.
Verifikasi
python3 -m pytest tests/test_llm.py -v→ 73 passedpython3 -m pytest tests/test_llm.py tests/test_command_count.py tests/test_doctor.py tests/test_cli.py tests/test_codelens.py→ 214 passed, 0 failedpython3 scripts/sync_command_count.py --check→ cleancodelens llm providers|config|pingsmoke-tested end-to-endcodelens llm pingcorrectly reportsnot_configuredwhen API key missing,sdk_missingwhen SDK not installedDesign decisions
commands/llm_framework.pybukancommands/llm.py— supaya tidak shadow packagescripts/llm/saatcommands/__init__.pyauto-import semua submodule. User-facing command name (codelens llm ...) unaffected.signal.SIGALRM— CodeLens jalan di Windows; SIGALRM POSIX-only. ThreadPoolExecutor portable.gpt-4o), bukan provider. Prefix dispatch makesCODELENS_LLM_MODEL=gpt-4owork out of the box.LLMToolInputrequires__hash__/__eq__) sehingga cache key "just works" saat Phase 2 land. Lengkap didocs/llm-framework.md.Findings (di luar scope)
tests/test_codelensignore.py::TestBackwardCompat::test_actual_target_dir_is_ignoredfails diorigin/main(pre-existing, bukan regresi dari PR ini). Di-verify dengan checkout main dan run test yang sama — gagal juga.tests/test_lsp_server.py,tests/test_rule_engine.py,tests/test_rule_matcher.pybutuh optional deps (lsprotocol,tree_sitter) yang tidak terinstall di sandbox minimal ini. Di-verify dari CONTEXT.md: "In CI/sandbox minimal (tanpa tree-sitter, tanpa LSP): ~788 passed / ~87 skipped". Bukan regresi.