Skip to content

fix(ui): display model name instead of id in statusline and startup banner - #4741

Merged
wenshao merged 5 commits into
QwenLM:mainfrom
zzhenyao:fix/statusline-model-name
Jun 4, 2026
Merged

fix(ui): display model name instead of id in statusline and startup banner#4741
wenshao merged 5 commits into
QwenLM:mainfrom
zzhenyao:fix/statusline-model-name

Conversation

@zzhenyao

@zzhenyao zzhenyao commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Adds getModelDisplayName() to ModelsConfig and Config that resolves the current model id to its human-readable display name from the model registry, falling back to the raw id when not found. Replaces ui.currentModel || cfg.getModel() with cfg.getModelDisplayName() in the statusline (preset and command mode), the statusline preview dialog, and the startup banner. The model selection dialog now shows the model id in italic parentheses after the model name.

Why it's needed

The statusline and startup banner displayed the raw model id (e.g. qwen3-coder-plus) instead of the model's display name. The data flow was a pure-string pipeline — getModel() returns only a bare string id, and the name/label field was never threaded to the UI layer. This PR adds name resolution at the display layer without changing any existing API or business logic.

Fixes: #4722

Reviewer Test Plan

Evidence (Before & After)

Before:
QQ20260603-191307
QQ20260603-191330

After:
QQ20260603-192207
QQ20260603-192236

How to verify

  1. Build and run

    npm run build
    npm start
  2. Statusline shows model display name instead of id

    • Start the CLI with a model that has a display name different from its id
    • The statusline footer should show the display name (e.g. Qwen3 Coder Plus instead of qwen3-coder-plus)
    • Both preset mode and command mode should display the same name
  3. Startup banner shows model display name

    • The startup banner line (e.g. API Key | Qwen3 Coder Plus) should show the display name, not the raw id
  4. Model selection dialog shows name with id suffix

    • Run /model to open the model selection dialog
    • Each model should display as name (id) with the id in italic
  5. Regression

    • Model switching, /model command, settings persistence: all work as before (these use model id internally, unchanged)

Tested on

OS Status
🍏 macOS ⚠️
🪟 Windows ⚠️
🐧 Linux

Risk & Scope

  • Main risk or tradeoff: None — getModelDisplayName() is a new method; existing getModel() and all business logic remain unchanged. Falls back to raw id if model not found in registry.
  • Not validated / out of scope: Multi-key model identity separation (tracked separately)
  • Breaking changes / migration notes: None

Linked Issues

中文说明

新增 getModelDisplayName() 方法,将 model id 解析为 model name 显示。statusline 和启动 banner 两处改为显示 model name(原为 model id)。模型选择界面在 name 后追加斜体显示 model id。

本次改动仅在显示层增加 name 解析,不修改任何现有 API 或业务逻辑。getModel() 返回值不变,ui.currentModel 类型和值不变,模型切换、设置持久化、provider lookup 等所有业务逻辑不受影响。

@zzhenyao
zzhenyao marked this pull request as ready for review June 3, 2026 12:01
@zzhenyao

zzhenyao commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

@pomelo-nwu Hi, I've implemented the fix for #4722 Issue 1 (display bug). The PR adds getModelDisplayName() to ModelsConfig and Config that resolves the current model id to its display name from the model registry, and updates the statusline, startup banner, and model selection dialog to use it. No existing API or business logic is changed.

Issue 2 (multi-key architecture) is out of scope for this PR, it requires extending settings persistence to include baseUrl, which is a larger change that needs your decision on whether to pursue.

If you have time, I'd appreciate a review!

Comment thread packages/cli/src/ui/components/ModelDialog.tsx Outdated
Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
@wenshao

wenshao commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Local Verification Report — PR #4741

Tested on: macOS Darwin 25.4.0 (Apple Silicon)
Branch: fix/statusline-model-name @ fcfc092
Base: main
Tester: wenshao


Test Results Summary

Test Suite Result Details
packages/cli AppHeader.test.tsx PASS 6 tests passed
packages/cli StatusLineDialog.test.tsx PASS 5 tests passed
packages/cli useStatusLine.test.ts PASS 67 tests passed
npm run typecheck PASS 0 errors
npm run lint --workspace=packages/cli FAIL 1 parse error in ModelDialog.tsx:302
npm run lint --workspace=packages/core PASS 0 errors
npm run build (packages/cli) FAIL 8 TS errors in ModelDialog.tsx (syntax)

Unit tests: 78 passed, 0 failures. But build and lint fail.


Build-Breaking Issue

Commit fcfc092 ("Update packages/cli/src/ui/components/ModelDialog.tsx") introduces a syntax error — it wraps the model id display in a conditional {model.id !== model.label && (...)} but does not remove the original 3 lines that the conditional was meant to replace.

Current (broken):

{model.id !== model.label && (
  <Text color={theme.text.secondary} italic>
    {' '}
    ({model.id})
  </Text>
)}
  {' '}           // ← orphaned lines, should be deleted
  ({model.id})    // ← orphaned lines, should be deleted
</Text>           //  orphaned lines, should be deleted

Fix — remove lines 299-301 in packages/cli/src/ui/components/ModelDialog.tsx:

{model.id !== model.label && (
  <Text color={theme.text.secondary} italic>
    {' '}
    ({model.id})
  </Text>
)}
{isRuntime && (

This is the only issue found. The core logic (getModelDisplayName() in modelsConfig.ts, config.ts, useStatusLine.ts, AppHeader.tsx, StatusLineDialog.tsx) is correct and all unit tests pass.


Conclusion

Not merge-ready — please remove the 3 orphaned lines in ModelDialog.tsx (lines 299-301 at current HEAD). After that fix, the PR should be good to go.


Verified locally by wenshao

Comment thread packages/cli/src/ui/components/ModelDialog.tsx Outdated
* its resolved name. Falls back to the raw model id when the model is not
* found in the registry (e.g. runtime models or unknown models).
*/
getModelDisplayName(modelId: string): string {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] ModelsConfig.getModelDisplayName() and Config.getModelDisplayName() have zero unit tests. The consumer tests (AppHeader, StatusLineDialog, useStatusLine) mock the method entirely with vi.fn(() => '...'), so the actual resolution logic is untested.

Three branches in this method are uncovered: (1) model found in registry → returns resolved.name, (2) currentAuthType falsy → returns raw modelId, (3) model not found → returns raw modelId. Same applies to the Config wrapper's 'unknown' fallback.

Consider adding describe('getModelDisplayName') blocks in both modelsConfig.test.ts and config.test.ts.

— qwen3.7-max via Qwen Code /review

Comment thread packages/core/src/config/config.ts Outdated
*/
getModelDisplayName(): string {
const modelId = this.getModel();
return modelId ? this.modelsConfig.getModelDisplayName(modelId) : 'unknown';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The modelId ? ... : 'unknown' guard is unreachable dead code — this.getModel() always returns a truthy string because ModelsConfig.getModel() falls back to DEFAULT_QWEN_MODEL ('coder-model'). The 'unknown' branch can never execute.

This creates a misleading impression that a "no model" scenario is handled when it cannot actually occur. Consider either simplifying to return this.modelsConfig.getModelDisplayName(this.getModel()); or adding a unit test that documents the intended contract.

— qwen3.7-max via Qwen Code /review

@wenshao

wenshao commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Verification Report

Reviewer: wenshao
Environment: macOS Darwin 25.4.0, Node.js v22.17.0
Branch: fix/statusline-model-name @ 6e2166f

Build

Check Result
TypeScript (CLI package tsc --noEmit) ✅ Clean
TypeScript (Core package tsc --noEmit) ✅ Clean
ESLint (all 6 PR-changed source files) ✅ Clean

Note: Root-level tsc reports errors in sdk.ts (missing @opentelemetry/instrumentation-undici) and converter.ts (IMAGE_RECITATION/IMAGE_OTHER) — both pre-existing on main, not introduced by this PR.

Tests

Test File Tests Result
AppHeader.test.tsx 6 ✅ All passed
StatusLineDialog.test.tsx 5 ✅ All passed
useStatusLine.test.ts 67 ✅ All passed
ModelDialog.test.tsx 15 ✅ All passed
modelsConfig.test.ts (core) 62 ✅ All passed
config.test.ts (core) 186 ✅ All passed
Total (PR-affected) 341 All passed

Broader UI suite: 3615/3632 passed, 17 failures in AuthDialog.test.tsx / App.test.tsx / AppContainer.test.tsx / BaseTextInput.test.tsx / InputPrompt.test.tsx — confirmed pre-existing on main (AuthDialog alone has 13 failures on main). None of the 3 PR commits touch these files.

Code Review

  • ModelsConfig.getModelDisplayName(modelId) — resolves via modelRegistry.getModel(), falls back to raw id when not found or when currentAuthType is unset
  • Config.getModelDisplayName() — delegates to modelsConfig.getModelDisplayName(this.getModel()), falls back to 'unknown' for empty model id
  • AppHeader.tsx — startup banner uses config.getModelDisplayName() instead of raw getModel()
  • useStatusLine.ts — both preset and command mode statusline use cfg.getModelDisplayName()
  • StatusLineDialog.tsx — preview dialog uses display name
  • ModelDialog.tsx — shows model.label with (model.id) in italic when they differ; no duplicate display
  • No business logic changes — getModel() return value unchanged, model switching/persistence uses raw id as before

Verdict

✅ LGTM — ready to merge. Pure display-layer change with safe fallback semantics. All 341 PR-affected tests pass, TypeScript and ESLint clean, no regressions introduced.

@wenshao

wenshao commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Local Verification Report (Round 2) — PR #4741

Tested on: macOS Darwin 25.4.0 (Apple Silicon)
Branch: fix/statusline-model-name @ 5aa35e6
Base: main
Tester: wenshao


Previous Issue — Resolved

The syntax error in ModelDialog.tsx (orphaned lines 299-301) reported in Round 1 has been fixed in commit 6e2166f2.


Test Results Summary

Test Suite Result Details
packages/cli AppHeader.test.tsx PASS 6 tests
packages/cli StatusLineDialog.test.tsx PASS 5 tests
packages/cli useStatusLine.test.ts PASS 67 tests
packages/cli ModelDialog.test.tsx PASS 15 tests (new)
packages/core modelsConfig.test.ts PASS 66 tests (includes new getModelDisplayName tests)
packages/core config.test.ts PASS 189 tests (includes new getModelDisplayName tests)
npm run typecheck PASS 0 errors
npm run lint --workspace=packages/cli PASS 0 errors
npm run lint --workspace=packages/core PASS 0 errors
npm run build (core → acp-bridge → cli) PASS All 3 packages compile successfully

Total: 348 tests passed, 0 failures. All checks green.


Changes Since Round 1

The author addressed feedback with 3 new commits:

  • 6e2166f2 — fix: removed the duplicate model.id display lines (the build-breaking syntax error)
  • 97043fdb — test: added unit tests for ModelsConfig.getModelDisplayName() and Config.getModelDisplayName()
  • 5aa35e63 — refactor: simplified Config.getModelDisplayName() by removing dead 'unknown' fallback branch

Conclusion

PR is now merge-ready. The syntax error from Round 1 is fixed, new unit tests cover the getModelDisplayName() logic, and all build/lint/typecheck/test gates pass on macOS.


Verified locally by wenshao

@zzhenyao

zzhenyao commented Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

@wenshao Thanks for the review! All R2 comments addressed:

  • Removed orphaned duplicate JSX fragment from ModelDialog (merge artifact from prior commit)
  • Added unit tests for ModelsConfig.getModelDisplayName() and Config.getModelDisplayName() covering all resolution branches
  • Simplified Config.getModelDisplayName() by removing unreachable unknown fallback (getModel() always returns a truthy value via DEFAULT_QWEN_MODEL)

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No high-confidence issues found. LGTM! ✅ All R2 feedback addressed. 333 tests pass, tsc/eslint clean. — qwen3.7-max via Qwen Code /review

@zzhenyao

zzhenyao commented Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

@wenshao Appreciate the approval!🙏

@yiliang114 yiliang114 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Clean display-layer fix — getModelDisplayName() resolves the model id to its registry name at the UI boundary without touching any business logic. The fallback-to-raw-id design covers runtime and unregistered models gracefully. Test coverage looks solid across all three branches.

One minor nit (non-blocking): the modelId ? ... : 'unknown' ternary in Config.getModelDisplayName() is dead code since getModel() always returns a truthy string via DEFAULT_QWEN_MODEL. Could simplify to a direct call.

@yiliang114 yiliang114 added category/ui User interface and display scope/model-switching Model selection and switching status/ready-for-merge Ready to be merged type/bug Something isn't working as expected labels Jun 4, 2026
@wenshao
wenshao merged commit 6d083fa into QwenLM:main Jun 4, 2026
11 checks passed
xaelistic pushed a commit to xaelistic/qwen-code that referenced this pull request Jun 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category/ui User interface and display scope/model-switching Model selection and switching status/ready-for-merge Ready to be merged type/bug Something isn't working as expected

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Statusline shows model id instead of name; model id used as unique key blocks multi-key setups

3 participants