Skip to content

feat(llm-drivers,api,dashboard): coding-agent class, actual_model reporting, CodeWhale driver, provider grouping#6220

Merged
houko merged 3 commits into
mainfrom
feat/coding-agent-actual-model
Jun 18, 2026
Merged

feat(llm-drivers,api,dashboard): coding-agent class, actual_model reporting, CodeWhale driver, provider grouping#6220
houko merged 3 commits into
mainfrom
feat/coding-agent-actual-model

Conversation

@houko

@houko houko commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Treats coding-agent CLIs as a first-class category distinct from raw provider APIs, generalizes "report the model the CLI actually used" (#6157, codex-cli) across that category, adds a new CodeWhale coding-agent driver, and surfaces the distinction in the dashboard. Delivered as one feature across three commits.

1. is_coding_agent() driver classification

New LlmDriver::is_coding_agent() trait method (default false), overridden true by the coding-agent CLI drivers (claude-code, codex-cli, gemini-cli, qwen-code, codewhale). Orthogonal to the existing LlmFamily (wire format): claude-code and the Anthropic HTTP API are both LlmFamily::Anthropic, yet only the former is a coding agent. Coding agents own model selection, so they are the drivers that can populate CompletionResponse::actual_model. aider.rs is unwired dead code and left untouched.

2. actual_model reporting across coding agents

  • codex-cli — already done in feat(llm-drivers,kernel): report the model codex actually used (#6134) #6157 (stderr banner).
  • claude-code — captures the resolved model from the stream-json init event. The non-stream --output-format json result carries no model field, so that path stays None (field captured for forward-compat).
  • qwen-code — best-effort capture from the JSON / stream events where the CLI reports a model.
  • codewhale — see below.

3. New CodeWhale driver

CodeWhale (Hmbown/CodeWhale) is an open-source Rust terminal coding agent, DeepSeek-V4-first and OpenAI-compatible, whose /model auto re-picks a model per turn. The driver spawns codewhale exec --json (one-shot, so CodeWhale does a single model call rather than running its own agent loop on top of LibreFang's) and parses the summary's model field into actual_model. Registered in the provider factory (ApiFormat::CodeWhale, provider id codewhale), CLI-availability detection, is_cli_provider, and the CLI fallback priority list.

4. Dashboard grouping

GET /api/providers now includes is_coding_agent per provider (via the new registry helper is_coding_agent_provider, ApiFormat-based — no driver instantiation). The endpoint returns untyped JSON, so no openapi/SDK regen is needed. The Providers page splits the configured list into a "Coding Agents" section and a "Providers" section (headers shown only when both groups are present). i18n keys added to en/zh/uk.

Verification

Run in the repo's Dockerfile.rust-dev image (no native toolchain on the dev box; isolated named target volume) and via pnpm:

  • cargo fmt --check — clean
  • cargo clippy -p librefang-llm-driver -p librefang-llm-drivers --all-targets -- -D warnings — zero warnings
  • cargo test -p librefang-llm-drivers --lib — 575 passed (incl. 8 CodeWhale tests, is_coding_agent classification per driver, is_coding_agent_provider, known-providers count)
  • cargo test -p librefang-llm-driver --lib — 62 passed
  • cargo check -p librefang-api --lib — clean
  • dashboard: pnpm typecheck clean, eslint clean on ProvidersPage.tsx, locale-parity vitest passes, ProvidersPage.test.tsx 10 passed

Notes / out of scope

  • No CHANGELOG entry: CHANGELOG.md already has a pre-existing duplicate ## [Unreleased] (line ~841, the historical #2 block) on main, which trips the pre-commit duplicate guard for any new [Unreleased] addition. That stale section should be folded into a release separately; flagging rather than touching historical content here.
  • actual_model for claude-code's non-stream path and qwen-code is best-effort: those CLIs don't always emit the model in machine-readable output. The field is captured wherever they do.

…nt()

Coding-agent CLI drivers (Claude Code, Codex, Gemini CLI, Qwen Code) delegate model selection to an external process that may resolve a model different from the requested id, so they — not raw provider APIs — are the drivers that can meaningfully report CompletionResponse.actual_model (generalizing #6157, which did this for codex-cli).

This axis is orthogonal to LlmFamily (wire format): claude-code and the Anthropic HTTP API are both LlmFamily::Anthropic, yet only the former is a coding agent. The new trait method defaults to false (additive — no existing construction site or HTTP provider changes); the four wired coding-agent drivers override it to true. aider.rs is unwired dead code and is left untouched.
@github-actions github-actions Bot added the size/M 50-249 lines changed label Jun 18, 2026
Evan added 2 commits June 18, 2026 17:42
…rom coding agents

Builds on the is_coding_agent classification:

- New CodeWhale CLI driver (codewhale): spawns `codewhale exec --json` one-shot and parses the summary's `model` field into CompletionResponse.actual_model. CodeWhale's `/model auto` re-picks a model per turn, so the resolved model can differ from the requested id. Registered in the provider factory (ApiFormat::CodeWhale, provider id `codewhale`), wired into CLI-availability / is_cli_provider / the CLI fallback priority list. is_coding_agent() = true.
- claude-code: capture the resolved model from the stream-json `init` event into actual_model. The non-stream `--output-format json` result carries no model field, so that path stays None (the field is captured for forward-compat).
- qwen-code: best-effort actual_model capture from the JSON / stream events where the CLI reports one.
- New drivers::is_coding_agent_provider(name) registry helper (ApiFormat-based) mirroring the per-driver classification without instantiating a driver.
- GET /api/providers (and the dashboard snapshot) now include `is_coding_agent` per provider so the dashboard can group coding agents apart from raw provider APIs. The endpoint returns untyped JSON, so no openapi/SDK regen is needed.

Verified in the dev image: cargo fmt --check clean; clippy -p librefang-llm-drivers --all-targets -D warnings zero; cargo test -p librefang-llm-drivers --lib 575 passed (incl. 8 codewhale tests + is_coding_agent_provider classification + known-providers count); cargo check -p librefang-api --lib clean.
…iders

Consumes the new `is_coding_agent` field from GET /api/providers to split the configured-provider list into a "Coding Agents" section (claude-code, codex-cli, gemini-cli, qwen-code, codewhale) and a "Providers" section, each with its own header. Headers only appear when both groups are present, so a single-group view stays flat. Adds the section_coding_agents / section_providers i18n keys to en/zh/uk and the is_coding_agent field to the ProviderItem type. Also memoizes the `providers` array so the new useMemos don't surface an exhaustive-deps warning.

Verified: pnpm typecheck clean; eslint clean on ProvidersPage; locale-parity vitest passes; ProvidersPage.test.tsx 10 passed.
@github-actions github-actions Bot added size/L 250-999 lines changed and removed size/M 50-249 lines changed labels Jun 18, 2026
@houko houko changed the title feat(llm-driver): classify coding-agent CLI drivers via is_coding_agent() feat(llm-drivers,api,dashboard): coding-agent class, actual_model reporting, CodeWhale driver, provider grouping Jun 18, 2026
@houko
houko merged commit 0250ed8 into main Jun 18, 2026
35 checks passed
@houko
houko deleted the feat/coding-agent-actual-model branch June 18, 2026 15:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L 250-999 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant