feat: add qwen update and /update commands with auto-update support#5780
Conversation
…ion to update output ## Changes ### Compatibility fixes (standalone-update.ts) - ensurePathInShellRc: use install script's begin/end block markers (# Qwen Code PATH block begin/end) instead of single-line marker, preventing duplicate PATH entries - ensurePathInShellRc: fish shell uses set -gx PATH (matching install script) - ensurePathInShellRc: use single-quoted paths with shell_quote-style escaping - ensureBinWrapper: use #!/usr/bin/env sh shebang (matching install script) ### Version output - qwen update: show current version in 'up to date' message (Qwen Code X.Y.Z is up to date!) - /update slash command: same version display ### Build fix - esbuild.config.js: add ink/dom and ink/components/CursorContext aliases for ink 7.x compatibility ### i18n - en.js: add 9 update-related translation keys Co-Authored-By: Claude <[email protected]>
- zh: Simplified Chinese - zh-TW: Traditional Chinese - ja: Japanese - ru: Russian - de: German - pt: Portuguese (Brazil) - fr: French - ca: Catalan Co-Authored-By: Claude <[email protected]>
wenshao
left a comment
There was a problem hiding this comment.
[Critical] [test] standalone-update.test.ts:146 asserts expect(content).toContain('#!/bin/sh') but the source at standalone-update.ts:563 was changed to emit #!/usr/bin/env sh. This test will fail on CI. Fix: expect(content).toContain('#!/usr/bin/env sh'). (This line is not in the diff hunk so it's reported here.)
|
@qwen-code /review |
| _Qwen Code review request accepted. Review is queued in [workflow run](https://github.com/QwenLM/qwen-code/actions/runs/28066293110)._ |
wenshao
left a comment
There was a problem hiding this comment.
R2 review — 3 additional suggestions beyond the 7 existing comments. Reverse audit converged in round 1 (no new gaps).
Deterministic analysis: tsc: 1 finding (TS2367, already reported R1). eslint: 1 finding (filename-naming on updateCommand.ts — not in eslint.legacy-filenames.mjs; existing camelCase command files are allowlisted but this new file is not).
Needs human review (low confidence):
- Hardlink entries (
entry.type === 'Link') in tar extraction are not validated for path traversal —standalone-update.ts:~258. The post-extractionvalidateExtractedPathsprovides defense-in-depth butrealpathSyncdoes not follow hardlinks. ensureBinWrapperTOCTOU betweenexistsSyncandwriteFileSync—standalone-update.ts:~559. Low practical risk (user's own bin dir).- Bash rc file selection on macOS prefers
.bash_profilewhile the install script prefers.bashrc—standalone-update.ts:~589. Comment claims to match install script but priority is reversed.
— qwen3.7-max via Qwen Code /review
|
Summary: Please continue reviewing when you have a chance. |
|
Addressed the latest review follow-ups in 10d3f36. Summary:
Verification:
Note: Please continue reviewing when you have a chance. |
yiliang114
left a comment
There was a problem hiding this comment.
The qwen update / /update surface reads cleanly, and the hardening in standalone-update.ts is solid — POSIX single-quote escaping, wx exclusive-create to close the wrapper TOCTOU, hardlink filtering, and the begin/end block-marker idempotency all look right. One blocker and two non-blocking notes.
Blocking — CI is red on all three platforms, but it's a single compile error, not a test failure:
src/commands/update.test.ts(37,7): error TS2322:
Type '{ _: never[]; $0: string; }' is not assignable to type 'ArgumentsCamelCase<Record<string, never>>'.
Record<string, never> gives ArgumentsCamelCase<…> a [key: string]: never index signature that _/$0 can't satisfy, so tsc --build fails and everything downstream goes red. The update handler ignores its args entirely, so the simplest fix is to drop the generic (ArgumentsCamelCase) or cast: { _: [], $0: 'qwen' } as unknown as ArgumentsCamelCase<Record<string, never>>. (The earlier #!/usr/bin/env sh and TS2367 findings look addressed — this is the only remaining build error.)
Non-blocking — explicit update vs. enableAutoUpdate. Both qwen update and /update gate the standalone self-update on enableAutoUpdate !== false. A standalone user who set enableAutoUpdate: false and then explicitly runs qwen update gets "Unable to auto-update this standalone installation. Please reinstall from: …" instead of an update. An explicit command arguably should honor explicit intent regardless of the background-auto-update preference — worth deciding before merge.
Non-blocking — PR description drift. The description lists installationInfo.ts, handleAutoUpdate.ts, updateEventEmitter.ts, and standalone-update-verify.ts as new files, but they aren't in this diff (already present / untouched). The actual change adds commands/update.ts + ui/commands/update-command.ts, registers them, adds resolveUpdateCommand, and hardens standalone-update.ts. Tightening the description would make the history easier to follow.
|
Following up on the Today the startup path already auto-updates everyone who hasn't disabled it: That leaves two cases where an explicit command is genuinely non-redundant:
Both are exactly what the current gating turns off — both commands early-out on The direction — a first-class Related, smaller: there are now three paths that check-and-update — startup Not blocking on its own — the build error above is the real merge blocker — but this is the design question I'd want answered. |
|
Addressed the latest follow-ups in af5d733. Summary:
Verification:
I also attempted local builds:
|
wenshao
left a comment
There was a problem hiding this comment.
Additional findings:
handleAutoUpdate.ts:78-82 still contains a character-for-character duplicate of the @latest → version replacement logic that this PR extracted into resolveUpdateCommand in installationInfo.ts. The two copies will silently drift if the nightly-detection heuristic or replacement pattern changes in one place without the other. Consider consolidating by having handleAutoUpdate.ts import and call resolveUpdateCommand.
— qwen3.7-max via Qwen Code /review
|
Addressed the latest unresolved review follow-ups in 25903a1. Summary:
Verification:
Note: Resolved the addressed review threads. Please continue reviewing when you have a chance. |
|
@qwen-code /triage |
1 similar comment
|
@qwen-code /triage |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
|
@qwen-code /resolve |
Merge origin/main into PR QwenLM#5780 branch, resolving conflicts in: - startInteractiveUI.tsx: kept both update check logic (PR) and startPostRenderPrefetches call (main) - gemini.test.tsx: combined update-related tests (PR) with postRenderPrefetches/IDE connection tests (main) - i18n locale files (9 files): kept both update command translations (PR) and history-gap/reload-plugins translations (main)
|
Qwen Code resolved the merge conflicts and pushed the branch update. Merge Conflict Resolution Summary — PR #5780Conflicts Found11 files had merge conflicts between the PR branch and 1.
|
|
@qwen-code /triage |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
c6816ec
Head branch was pushed to by a user without write access
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed — no blockers. Suggestion-level recommendations are in the Suggestion summary comment below.
Suggestions — commit
|
|
@qwen-code /triage |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
Summary
Adds
qwen updateCLI command and/updateslash command that check fornew releases and install them automatically (standalone) or guide the user
through manual update steps (npm / yarn / pnpm).
How it works
qwen update
├── Query npm registry for latest version
├── Detect installation type
│ ├── standalone → download archive → SHA256 verify → signature check → smoke test → atomic replace
│ └── npm / yarn / pnpm → show update command (or auto-run npm install)
└── Report result
npm install -g @qwen-code/[email protected]sudo npm install -g ...git pullSafety
QWEN_REQUIRE_SIGNATURE=1)--versionbefore replacing current install.new→.oldswap with automatic rollback on failureOutput examples
$ qwen update
Qwen Code 0.19.1 is up to date!
$ qwen update
Qwen Code update available! 0.19.1 → 0.20.0
Standalone install detected. Attempting to automatically update now...
████████████████████████████████████████ 100%
Update successful! The new version will be used on your next run.
$ qwen update
Qwen Code update available! 0.19.1 → 0.20.0
Installed with npm. Attempting to automatically update now...
Run the following to update:
npm install -g @qwen-code/[email protected]
Files
packages/cli/src/commands/update.tsqwen updateCLI commandpackages/cli/src/ui/commands/updateCommand.ts/updateslash commandpackages/cli/src/utils/standalone-update.tspackages/cli/src/utils/standalone-update-verify.tspackages/cli/src/utils/standalone-update.test.tspackages/cli/src/utils/installationInfo.tspackages/cli/src/utils/handleAutoUpdate.tspackages/cli/src/utils/updateEventEmitter.tspackages/cli/src/config/config.tsqwen updatecommandpackages/cli/src/services/BuiltinCommandLoader.ts/updateslash commandpackages/cli/src/i18n/locales/*.jsTesting
qwen --versionworksqwen updateshows version when up to dateset -gx PATHmatching install script