qwen-code/packages/cli
Shaojin Wen 19761af072
fix(cli): stamp QWEN_CODE_CLI at the workspace entry and publish QWEN_CODE_MODEL (#7993)
* fix(cli): stamp QWEN_CODE_CLI at the workspace entry and publish the active model as QWEN_CODE_MODEL

Skill subprocesses shell out through `"${QWEN_CODE_CLI:-qwen}"`. The npm entry
(scripts/cli-entry.js) stamps QWEN_CODE_CLI, but the workspace entry
(packages/cli/dist/index.js) never did — so a dev run, or any direct
`node dist/index.js` launch, leaves the variable unset and every review
subcommand the /review skill issues silently lands in whatever global `qwen`
PATH resolves to. Measured on a live run: a freshly built CLI's review pipeline
executed entirely on a global v0.21.0 — `script-lint` did not exist there, so
the deterministic gate the skill expected was silently absent, and any
behavioral fix to the review CLI is inert in such runs.

Stamp the entry in runCliEntryPoint, first-writer-wins: an outer launcher
(cli-entry.js, the desktop shim) has already stamped in-process and must keep
winning; an empty value counts as unset, matching the consumer's `:-`
semantics. The entry is derived as `../index.js` from the compiled
dist/src/cli.js — the shebang-bearing bin — and skipped entirely for non-file
schemes (vitest) and unbuilt layouts (tsx dev runs keep today's fallback).
tsc emits dist/index.js as 0644 and the spawn-time filter blanks a
non-execable entry, so the stamp grants 0o755 best-effort; a failed chmod
degrades to today's `qwen` fallback.

Separately, subprocesses had no authoritative way to learn the ACTIVE model:
the /review skill's compose step wants a modelId, and the orchestrator resorts
to reading settings files — wrong under QWEN_HOME isolation and after /model
switches (measured: a report stamped with a model that never ran the review).
Publish QWEN_CODE_MODEL exactly the way QWEN_CODE_SESSION_ID is published: the
first Config claims the process-global slot, only the claiming instance
republishes (on refreshAuth and every model-change notification), and
getShellContextEnvVars passes it through, omitted when absent. The daemon
limitation is the session ID's own — later sessions read the first session's
model — and is documented at both the producer and the consumer.

* fix(core): clarify QWEN_CODE_MODEL daemon comment and cover refreshAuth republish (#7993)

* test(cli): cover stampCliEntryEnv wiring in runCliEntryPoint (#7993)

* fix(core): publish QWEN_CODE_MODEL per session and preserve entry mode on stamp (#7993)

Address review feedback:

- Key QWEN_CODE_MODEL on the session (registerSessionModel/getSessionModel),
  mirroring the project dir, so daemon-mode subprocesses read their own
  session's active model instead of the first session's. The process-global
  slot remains as the single-session CLI fallback. This also neutralizes the
  order-dependent claim: a throwaway Config's registration is keyed under a
  session id no real spawn resolves.
- stampCliEntryEnv now adds exec bits to the existing mode (mode | 0o111)
  rather than setting 0o755, so a private 0o600 checkout becomes execable
  without becoming world-readable.
- Cross-reference scripts/dev.js and scripts/start.js in the stamp doc comment
  and note the bundled `node dist/cli.js` launch is intentionally not stamped.
- Widen the AuthType test mock to include QWEN_OAUTH, pin the stamp-before-run
  ordering in the wiring test, and cover the per-session model lookup.

* fix(cli): correct comment on Vite rewrite mechanism in protocol guard (#7993)

* fix(core): re-key per-session model registry on startNewSession (#7993)

startNewSession minted a new session id and re-stamped QWEN_CODE_SESSION_ID
but left the per-session model registry keyed on the outgoing id. After
/clear (or /reset, /new, /resume) a non-owner Config's subprocesses then
resolved the model by the new id, missed, and fell back to another
session's value. Unregister the old entry and republish under the new id.

Also correct the stampCliEntryEnv comments: npm start / npm run dev route
through scripts/start.js and scripts/dev.js, which stamp QWEN_CODE_CLI
themselves, so the only uncovered launcher is a direct node dist/index.js.

---------

Co-authored-by: verify <verify@local>
Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com>
Co-authored-by: Qwen Code Bot <qwen-code-bot@alibaba-inc.com>
2026-07-30 02:40:18 +00:00
..
src fix(cli): stamp QWEN_CODE_CLI at the workspace entry and publish QWEN_CODE_MODEL (#7993) 2026-07-30 02:40:18 +00:00
.gitignore feat(core): add opt-in built-in web_search backed by the DashScope Responses API (#7215) 2026-07-21 10:59:36 +00:00
index.ts fix(cli): add bootstrap fast paths (#6188) 2026-07-02 22:28:11 +00:00
package.json feat(channels): add GitLab polling channel adapter (#7862) 2026-07-29 14:28:31 +00:00
test-setup.ts feat(serve): persist dynamic workspace registrations (#6716) 2026-07-11 16:49:40 +00:00
tsconfig.json feat(channels): add GitLab polling channel adapter (#7862) 2026-07-29 14:28:31 +00:00
vitest.config.ts fix(serve): Release managed session writer locks on shutdown (#7812) 2026-07-28 10:18:35 +00:00