Skip to content

feat(llm): LLM integration framework Phase 1 — multi-provider abstraction (closes #63)#152

Merged
Wolfvin merged 1 commit into
mainfrom
feat/issue-63-llm-framework-phase1
Jul 3, 2026
Merged

feat(llm): LLM integration framework Phase 1 — multi-provider abstraction (closes #63)#152
Wolfvin merged 1 commit into
mainfrom
feat/issue-63-llm-framework-phase1

Conversation

@Wolfvin

@Wolfvin Wolfvin commented Jul 2, 2026

Copy link
Copy Markdown
Owner

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

File Purpose
scripts/llm/__init__.py Re-exports public API
scripts/llm/base_tool.py LLMTool ABC + LLMToolInput/LLMToolOutput ABCs + error hierarchy (LLMErrorLLMTimeoutError, 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
tests/test_llm.py 73 network-free tests (SDK calls di-mock)
docs/llm-framework.md Arsitektur + design decisions

Sync'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

from llm import (
    LLMTool, LLMToolInput, LLMToolOutput,
    invoke_llm, resolve_provider,
    LLMError, LLMTimeoutError,
    ProviderNotConfiguredError, ProviderNotInstalledError,
)

Provider dispatch

Dispatch by model name prefix (case-insensitive, first match wins):

Prefix Provider SDK
gpt-, o1-, o3-, o4-, chatgpt- openai openai
claude- anthropic anthropic
bedrock-, amazon. bedrock boto3
gemini- google google-generativeai
deepseek- deepseek openai (OpenAI-compatible)
glm-, glm4-, zai- zai_glm openai (OpenAI-compatible, base URL open.bigmodel.cn)

Force a provider: CODELENS_LLM_PROVIDER=openai env var atau provider= kwarg.

Config (env vars)

Variable Purpose
CODELENS_LLM_MODEL Default model name
CODELENS_LLM_API_KEY Fallback API key for any provider
CODELENS_LLM_PROVIDER Force a provider (skip prefix dispatch)
OPENAI_API_KEY / ANTHROPIC_API_KEY / dll Provider-specific keys (preferred over fallback)

API key resolution: explicit kwarg > provider-specific env var > CODELENS_LLM_API_KEY.

CLI command

codelens llm providers                          # list 6 providers + env vars + SDK pip names
codelens llm config                             # show resolved config (no API key values printed)
codelens llm ping [--model M] [--provider P]    # 1-token smoke test end-to-end

Error model

LLMError (base)
├── LLMTimeoutError              — retryable
├── ProviderNotConfiguredError   — NOT retryable (missing API key / model)
└── ProviderNotInstalledError    — NOT retryable (SDK not importable)

LLMError.retryable flag drives retry loop. Non-retryable errors propagate on first attempt.

Definition of Done (Phase 1, dari issue)

  • LLMTool ABC + LLMToolInput/LLMToolOutput ABCs dengan __hash__/__eq__
  • 6 providers: OpenAI, Anthropic, Bedrock, Google, DeepSeek, Z.ai GLM
  • Dispatch by model_name prefix
  • Lazy import per provider
  • 60s timeout, 3-retry exponential backoff
  • API keys dari env vars per provider
  • Config via CODELENS_LLM_PROVIDER, CODELENS_LLM_MODEL, CODELENS_LLM_API_KEY env vars

Phases 2-5 deferred ke follow-up issues per issue spec.

Verifikasi

  • python3 -m pytest tests/test_llm.py -v73 passed
  • python3 -m pytest tests/test_llm.py tests/test_command_count.py tests/test_doctor.py tests/test_cli.py tests/test_codelens.py214 passed, 0 failed
  • python3 scripts/sync_command_count.py --check → clean
  • codelens llm providers|config|ping smoke-tested end-to-end
  • codelens llm ping correctly reports not_configured when API key missing, sdk_missing when SDK not installed

Design decisions

  1. File name commands/llm_framework.py bukan commands/llm.py — supaya tidak shadow package scripts/llm/ saat commands/__init__.py auto-import semua submodule. User-facing command name (codelens llm ...) unaffected.
  2. Thread-based timeout bukan signal.SIGALRM — CodeLens jalan di Windows; SIGALRM POSIX-only. ThreadPoolExecutor portable.
  3. Dispatch by prefix — most users know model name (gpt-4o), bukan provider. Prefix dispatch makes CODELENS_LLM_MODEL=gpt-4o work out of the box.
  4. Cache deferred to Phase 2 — Phase 1 establishes the abstraction contract (LLMToolInput requires __hash__/__eq__) sehingga cache key "just works" saat Phase 2 land. Lengkap di docs/llm-framework.md.

Findings (di luar scope)

  • tests/test_codelensignore.py::TestBackwardCompat::test_actual_target_dir_is_ignored fails di origin/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.py butuh 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.

…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.
@sonarqubecloud

sonarqubecloud Bot commented Jul 2, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
C Reliability Rating on New Code (required ≥ A)
E Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@Wolfvin Wolfvin merged commit c4a5e53 into main Jul 3, 2026
4 of 11 checks passed
@Wolfvin Wolfvin deleted the feat/issue-63-llm-framework-phase1 branch July 3, 2026 02:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] LLM integration framework — multi-provider abstraction, cache, cost tracking, explanation generator

1 participant