qwen-code/docs/users
C0d3N1nja97342 aac9606f78
fix(cli): skip terminal redraw optimizer on WSL/ConPTY (#7897)
* fix(cli): skip terminal redraw optimizer on WSL/ConPTY and enable sync output on Windows Terminal (#7634)

The streaming text repetition bug on WSL + Windows Terminal is caused by
the terminal redraw optimizer batching cursor-up sequences, which ConPTY
processes differently from individual per-line erases. The cursor lands
at the wrong row, causing each new frame to overlap remnants of the
previous one.

Two fixes:
1. Skip the redraw optimizer when WSL (WSL_DISTRO_NAME / WSL_INTEROP)
   or Windows Terminal (WT_SESSION) is detected, falling back to Ink's
   original per-line erase sequences that ConPTY handles correctly.
2. Enable synchronized output (DEC mode 2026) for Windows Terminal,
   which has supported it since v1.6, making frame updates atomic and
   masking any residual cursor positioning issues.

Fixes #7634

* fix: add WSL_INTEROP test and clear env vars in beforeEach to fix test fragility

Address review feedback on #7897:
- P1: clear WSL/Windows Terminal env vars in beforeEach so existing
  optimizer tests don't silently break when run inside WSL
- P2: add dedicated test for WSL_INTEROP detection

* review: address wenshao feedback on #7897

- Accept injectable env in installTerminalRedrawOptimizer (matches sibling
  terminalSupportsSynchronizedOutput), eliminating the need for
  beforeEach env-stubbing in test files
- Add QWEN_CODE_LEGACY_ERASE_LINES=0 as a force-on escape hatch for
  WSL/Windows Terminal users whose terminals handle the batched
  sequences correctly
- Collapse three near-identical WSL/WT skip tests into it.each
- Correct Windows Terminal DEC 2026 support version: v1.18, not v1.6
- Move WT_SESSION check above the TERM declaration in
  terminalSupportsSynchronizedOutput so the term isn't declared before
  its only consumer
- Add a table case asserting TMUX guard still wins over WT_SESSION
- Pass explicit empty env to installTerminalRedrawOptimizer in the
  synchronizedOutput composition test so it doesn't depend on the
  runner's environment

* fix(cli): narrow optimizer skip to WSL only, drop WT_SESSION

Per wenshao's review: WT_SESSION is set on the Windows side and is not
propagated into WSL shells without WSLENV, so it can never be the env
var that fires for #7634. Remove WT_SESSION from the optimizer skip
(WSL_DISTRO_NAME + WSL_INTEROP remain) and from the synchronized-output
allowlist. The synchronized-output change for Windows Terminal belongs
in its own PR once confirmed; bundling it into a WSL bug fix mixed two
independent behavior changes.

Also correct the comment: 'WSL or Windows Terminal' -> 'WSSL only',
and remove the WT_SESSION test cases from both test files.

* fix(cli): clean up WT_SESSION comment residue and pin its exclusion

Per review: the drop of the WT_SESSION skip left stale comments and no
test pinning the deliberate exclusion. Fix the force-enable comment
(WSL only, not Windows Terminal), complete the truncated WT_SESSION
rationale, and add a test asserting WT_SESSION alone does NOT trigger
the skip (it is not propagated into WSL shells). Also stub
QWEN_CODE_LEGACY_ERASE_LINES in beforeEach so the suite is isolated
from a host that has the flag set.

* refactor(cli): extract shared isWsl(env) into terminal-env util

WSL detection was inlined in terminalRedrawOptimizer (this PR) and
duplicated as a private helper in voice-availability. Extract a single
isWsl(env) into ui/utils/terminal-env.ts and use it from both sites so
the marker set cannot drift. Requested by maintainer in #7897 reviews.

* fix(ui): add license header and gate WSL_INTEROP in voice preflight

Round-3 review: terminal-env.ts shipped without the @license header
every sibling carries; and the voice-side isWsl migration was inert under
the test probe because voice-availability.test.ts only exercised the
WSL_DISTRO_NAME marker. Add the header and cover WSL_INTEROP via it.each. #7897

* docs(ui): note the separate core-side WSL check in terminal-env

Round-4 review: the extraction comment claimed the marker set cannot
drift, but ripgrepUtils.wslTimeout() in packages/core keeps its own
narrower WSL_INTEROP-only check because core cannot import from cli.
Document the exception so a future maintainer greps both sites. #7897

* docs(cli): document QWEN_CODE_LEGACY_ERASE_LINES escape hatch

Round-5 review (R5-1): isWsl(env) relies solely on env markers, which
env-scrubbing launchers (sudo, env -i) strip - so the #7634 skip never
fires in those contexts. Document the launch-time =1 fallback and note
it must be passed at launch because sudo drops the flag too. Also closes
the round-2 R2-3 gap (the flag was previously undocumented). #7897

* refactor(cli): move isWsl to core and apply maintainer review polish

wenshao's manual review suggested moving the shared WSL marker check to
packages/core so cli can import it (core cannot import from cli), while
ripgrepUtils.wslTimeout() keeps its deliberately narrower predicate. Also:

- Sharpen the ConPTY divergence comment with the concrete sequences the
  optimizer emits (CSI 1 B cursor-down, CSI n A multi-count) that Ink's
  native erase path never does.
- Replace the beforeEach vi.stubEnv test fixture with explicit empty-env
  arguments (truer 'not on WSL' fixture, no host-env dependency).
- Note the env parameter exists for testability.
- Trim the moved file's doc block to durable facts and tighten the docs
  row wording. #7897

* test(cli): pin the env default-parameter seam in redraw optimizer

Round-7 review: the production call path (installTerminalRedrawOptimizer
with no env arg) was never exercised - every test passed env explicitly,
so a mutation to the = process.env default (e.g. = {}) would pass green
while silently disabling the WSL skip and =1 escape hatch in production.
Add a hermetic test that stubs WSL_DISTRO_NAME and asserts the no-arg call
skips the optimizer. #7897

* test(cli): restore afterEach env cleanup for default-seam test

Round-8 review: placing vi.unstubAllEnvs() as the last statement in the
default-seam test body meant a failing expect (the exact regression the
test pins) would skip the cleanup and leak WSL_DISTRO_NAME=Ubuntu into
process.env for the rest of the file. Move the cleanup back into the
describe-level afterEach so it runs even on assertion failure. #7897

* test(cli): close the two minor coverage gaps from chiga0's review

Maintainer chiga0 approved the PR but noted two minor test gaps:

- The default-seam test only stubbed WSL_DISTRO_NAME, so a host-set
  QWEN_CODE_LEGACY_ERASE_LINES=1 would pass it for the wrong reason; stub
  the flag too so the assertion depends only on the WSL marker.
- The tri-state flag has no case for a non-standard truthy value; add one
  pinning that 'garbage' falls through to the platform default (WSL skip). #7897

* docs(cli): correct 'only path' claim in ConPTY divergence comment

Round-11 review: the comment asserted the optimizer is the ONLY path
emitting CSI 1 B / CSI n A, but the repo's patched ink build also emits
both sequence classes on its cursor-positioning path (buildCursorSuffix /
buildReturnToBottom, reachable via BaseTextInput.setCursorPosition).
Skipping the optimizer on WSL does not remove these from interactive
input. Narrow the claim to the per-frame erase-and-redraw path. #7897
2026-08-24 03:58:48 +00:00
..
configuration fix(cli): skip terminal redraw optimizer on WSL/ConPTY (#7897) 2026-08-24 03:58:48 +00:00
extension fix(core): support public GitHub extensions with older Git (#9690) 2026-08-23 13:03:15 +00:00
features docs(agent): clarify parameter preconditions (#9580) 2026-08-24 02:27:09 +00:00
ide-integration fix(cli): replace all emoji with Unicode text symbols in TUI rendering (#5999) 2026-06-30 15:18:01 +00:00
reference fix(cli): switch completion tabs with bare arrows (#8576) 2026-08-11 02:29:11 +00:00
support fix(cli): add ui.mouseTracking setting to restore right-click and URL clicks (#8198) 2026-08-01 14:15:42 +00:00
_meta.ts feat(daemon): merge daemon-mode feature batch into main (#4490) 2026-06-12 00:34:49 +08:00
common-workflow.md docs: fix stale defaults, CLI syntax, and tool naming drift (#5158) 2026-06-15 20:06:34 +08:00
integration-github-action.md feat(web-shell): show subagent sessions in detail panel (#7380) 2026-07-22 02:31:08 +00:00
integration-jetbrains.md feat(cli): expose reasoning effort through ACP (#8526) 2026-08-11 10:32:33 +00:00
integration-vscode.md fix(core): honor NO_PROXY for model requests (#6640) 2026-07-10 10:41:04 +00:00
integration-zed.md docs(integration): use CDN URLs for images and fix formatting 2026-03-16 14:12:48 +08:00
overview.md feat(auth): add Kimi (Moonshot AI) as a built-in third-party provider (#9814) 2026-08-24 03:18:40 +00:00
quickstart.md feat(auth): add Kimi (Moonshot AI) as a built-in third-party provider (#9814) 2026-08-24 03:18:40 +00:00
qwen-serve-deploy-local.md feat: consolidate Local Control into one daemon-owned implementation (#9106) 2026-08-17 16:44:48 +00:00
qwen-serve.md feat(daemon): add batch extension activation APIs (#8788) 2026-08-19 06:42:48 +00:00