Skip to content

fix(web-shell): keep skill slash commands after starting a new session - #6319

Merged
wenshao merged 3 commits into
QwenLM:mainfrom
wenshao:fix/web-shell-new-session-slash-commands
Jul 5, 2026
Merged

fix(web-shell): keep skill slash commands after starting a new session#6319
wenshao merged 3 commits into
QwenLM:mainfrom
wenshao:fix/web-shell-new-session-slash-commands

Conversation

@wenshao

@wenshao wenshao commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Preserves the workspace-scoped slash-command list when the user starts a new chat, so skill-backed commands keep autocompleting in the new session before its first prompt. Starting a new session now only discards the session-scoped snapshots (the supported-commands and context payloads that carry the cleared session id), while keeping the derived commands/skills that the composer's slash menu reads.

Why it's needed

Every "new session" entry point in the web shell — the sidebar button, the composer quick action, and the /new, /reset and /clear commands — routes through clearSession(), which calls getConnectionAfterSessionClear. That helper deleted connection.commands and connection.skills. Nothing repopulated them: after the old session's SSE stream closes the connection loop returns early on manualSessionClear, and the deferred skill-fetch path never re-runs. So in the newly created (second) session, before the first prompt, the composer fell back to the hardcoded local command list, which omits skills. Typing /rev and pressing Tab therefore would not complete /review.

This is the same class of gap that #6153 fixed for the initial deferred connect (before the very first prompt), except it was triggered on the clear path and left unfixed. Skills, custom commands, MCP-prompt commands and workflow commands are all workspace/config level, not session level, so they stay valid across a clear within the same workspace and should not be dropped.

Reviewer Test Plan

How to verify

  1. qwen serve --web, open the web shell, and let the workspace expose a bundled skill such as /review.
  2. In the first session, type /rev and press Tab — it completes /review.
  3. Start a new chat (sidebar "New Session", or run /new).
  4. In the new session, before sending any prompt, type /rev and press Tab.
    • Before: nothing happens — the slash menu has no /review, so Tab can't complete it.
    • After: it completes to /review, same as the first session.

Automated coverage:

  • packages/webuinpx vitest run src/daemon/session/ — 177 tests pass, including:
    • actions.test.tsgetConnectionAfterSessionClearclears session fields … (asserts commands/skills survive, session-scoped fields are dropped).
    • DaemonSessionProvider.test.tsxkeeps workspace skill slash commands after clearing so /review still autocompletes — drives the real clearSession through the provider and asserts connection.commands still contains review.
  • Mutation check: restoring the old delete next.commands / delete next.skills makes both new tests fail, confirming they lock the behavior.
  • npx tsc --noEmit, eslint and prettier --check on the changed files all pass.

Evidence (Before & After)

The user-visible effect is the slash-menu / Tab completion described above. It is captured behaviorally by the provider-level integration test (real clearSession): before the change the assertion connection.commands contains review fails after a clear; after the change it passes.

Tested on

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

Environment (optional)

Local unit/integration tests via vitest in packages/webui.

Risk & Scope

  • Main risk or tradeoff: after a clear, the preserved command list could briefly be stale if the workspace's available commands changed mid-session (e.g. an MCP server disconnected). It is refreshed by the next session's available_commands_update, and the session-scoped supportedCommands/context are still dropped so metadata is refetched (no stale reuse).
  • Not validated / out of scope: no change to how commands are fetched or to the daemon; only the clear-time state reduction changed.
  • Breaking changes / migration notes: none.

Linked Issues

N/A

中文说明

这个 PR 做了什么

在用户新建会话时,保留工作区级的斜杠命令列表,使得技能类命令在新会话首条 prompt 之前仍能自动补全。新建会话现在只丢弃 session 级的快照(带着被清理 sessionId 的 supported-commands 和 context),而保留输入框斜杠面板读取的 commands/skills

为什么需要

Web Shell 里所有"新建会话"入口——侧边栏按钮、输入框快捷动作,以及 /new/reset/clear 命令——都汇入 clearSession(),它会调用 getConnectionAfterSessionClear。该函数删除了 connection.commandsconnection.skills,而且没人回填:旧会话 SSE 流关闭后,连接循环在 manualSessionClear 处提前返回,抓取技能的 deferred 分支也不会再跑。于是在新建的(第 2 个)会话里、首条 prompt 之前,输入框退化成写死的本地命令列表(不含技能)。此时输入 /rev 按 Tab 补不出 /review

这与 #6153 修复的"初始 deferred 连接(首条 prompt 之前)丢技能命令"是同一类问题,只是触发点在 clear 路径上,之前没修到。技能、自定义命令、MCP prompt、工作流命令都是工作区/配置级、而非会话级,在同一工作区里跨会话依然有效,因此不应被删除。

审阅者测试计划

如何验证

  1. qwen serve --web 打开 web shell,工作区暴露一个内置技能如 /review
  2. 在第 1 个会话输入 /rev 按 Tab —— 补全为 /review
  3. 新建会话(侧边栏 "New Session" 或执行 /new)。
  4. 在新会话里,不发任何 prompt,输入 /rev 按 Tab。
    • 修复前:无反应——斜杠面板里没有 /review,Tab 补不出。
    • 修复后:补全为 /review,与第 1 个会话一致。

自动化覆盖:

  • packages/webuinpx vitest run src/daemon/session/ —— 177 测试通过,含:
    • actions.test.tsgetConnectionAfterSessionClearclears session fields …(断言 commands/skills 保留、session 级字段被删)。
    • DaemonSessionProvider.test.tsxkeeps workspace skill slash commands after clearing so /review still autocompletes —— 通过 provider 驱动真实 clearSession,断言清理后 connection.commands 仍含 review
  • 变异验证:把旧的 delete next.commands / delete next.skills 加回去,两个新测试都变红,确认测试锁住了行为。
  • 对改动文件的 npx tsc --noEmiteslintprettier --check 全部通过。

证据(前 / 后)

用户可见效果即上文的斜杠面板 / Tab 补全,由 provider 级集成测试(真实 clearSession)行为化地捕获:修复前"清理后 connection.commandsreview"断言失败,修复后通过。

测试平台

OS 状态
🍏 macOS
🪟 Windows ⚠️
🐧 Linux ⚠️

环境(可选)

packages/webuivitest 跑本地单测/集成测试。

风险与范围

  • 主要风险/取舍:清理后保留的命令列表,若工作区可用命令在会话中途变化(如某 MCP server 断开)可能短暂陈旧。它会被下个会话的 available_commands_update 刷新,且 session 级的 supportedCommands/context 仍被丢弃以强制重取(不会复用陈旧数据)。
  • 未验证 / 范围外:不改命令抓取方式、不改 daemon;仅改动清理时的状态裁剪。
  • 破坏性变更 / 迁移说明:无。

关联 Issue

N/A

Starting a new session (the sidebar button, quick action, and the /new,
/reset and /clear commands all route through clearSession) ran
getConnectionAfterSessionClear, which deleted connection.commands and
connection.skills. Nothing repopulated them: the SSE loop returns early on
manualSessionClear and the deferred skill-fetch path never re-runs, so before
the new session's first prompt the composer fell back to the hardcoded local
command list. That list omits skills, so typing "/rev" and pressing Tab would
not complete "/review".

Preserve the workspace-scoped commands and skills across a clear (skills,
custom, MCP-prompt and workflow slash commands all live at the workspace/config
level, not the session), and only drop the session-scoped supportedCommands and
context snapshots. This keeps skill-backed slash commands autocompleting in the
new deferred session before its first prompt — the same guarantee QwenLM#6153 added
for the initial deferred connect — while still forcing the next session to
refetch fresh metadata. The next session's available_commands_update refreshes
the list once it lands.
@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

Re-run — incorporating the author's follow-up commit (6fa5c7f) and response.

Template looks good ✓

Problem: observed bug, same class as #6153. clearSession()getConnectionAfterSessionClear deleted commands/skills, and the deferred skill-fetch never re-ran on manualSessionClear. Result: skill-backed slash commands vanish from autocomplete in the new session. Reproduction steps are concrete (start new session, type /rev, Tab).

Direction: aligned — direct continuation of the deferred-connect fix (#6153), closing the gap on the clear path. Web shell slash-command autocomplete is core UX.

Approach: minimal and focused. Three targeted code changes (clear path, event handler, session attach). The length > 0!== undefined swap in the event handler and session attach is a meaningful secondary fix: an authoritative empty daemon snapshot now correctly clears stale commands. The new rejection-path test (commit 6fa5c7f) fills the error-handling gap from the prior review.

On the deferred-connect length > 0 question from the prior round: the author's pushback is correct. workspaceSkills() is session-less and per #6169 returns { initialized: false, skills: [] } when the ACP child isn't ready — an empty result there means "couldn't determine", not "no skills". The length > 0 guard is a deliberate defense against that transient. This PR actually improves that path by preserving commands across the clear, so the deferred state shows the previous session's still-valid commands while the child warms up.

Moving on to code review. 🔍

中文说明

重新运行——结合作者的后续提交 (6fa5c7f) 和回复。

模板完整 ✓

问题:已观测到的 bug,与 #6153 同类。clearSession()getConnectionAfterSessionClear 删除了 commands/skills,deferred 技能抓取在 manualSessionClear 上不再执行。结果:新会话中技能类斜杠命令从自动补全中消失。复现步骤具体可验证。

方向:对齐——#6153 deferred-connect 修复的延续,补上 clear 路径的缺口。Web shell 斜杠命令自动补全是核心 UX。

方案:极简且聚焦。三处定向代码改动。事件处理器和 session attach 中 length > 0!== undefined 的替换是有意义的二级修复。新增的拒绝路径测试(提交 6fa5c7f)填补了前次审查的错误处理缺口。

关于 deferred-connect 路径保留 length > 0 的问题:作者的反驳是正确的。workspaceSkills() 是无会话的,据 #6169,ACP child 未就绪时返回空——这里的空意味着"无法确定"而非"没有技能"。length > 0 是对该瞬态的刻意防御。本 PR 实际通过跨 clear 保留命令改善了该路径。

进入代码审查 🔍

Qwen Code · qwen3.7-max

@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

Re-run — incorporating commit 6fa5c7f (rejection-path test).

Code Review

The diff is surgical and consistent across all three code paths.

getConnectionAfterSessionClear (actions.ts): Two delete lines removed. commands/skills are workspace-scoped derivatives from mapSupportedCommands(), not session-scoped snapshots. The raw supportedCommands (carrying the cleared sessionId) is still correctly deleted. The replacement comments clearly document the workspace-vs-session scoping rationale.

updateConnectionFromDaemonEvent (mappers.ts): commands.length > 0 ? commands : current.commands replaced with a direct commands assignment. The available_commands_update is the daemon's authoritative snapshot — assigning directly (matching skills) means an empty list correctly clears stale entries rather than preserving them.

Session attach (DaemonSessionProvider.tsx): Same pattern — supportedCommands !== undefined ? commands : current.commands distinguishes a fulfilled-but-empty result (authoritative) from a skipped/failed fetch (not authoritative, preserve the list).

Rejection-path test (6fa5c7f): The new keeps preserved commands when the next supported-commands fetch fails test in DaemonSessionProvider.test.tsx covers the error path — when supportedCommands() throws, the rejection leaves supportedCommands === undefined, so the !== undefined guard correctly preserves the command list. One nuance worth recording from the author's response: reverting to length > 0 would not change the rejection path (both conditions fall back to current.commands when supportedCommands is undefined), but the test still adds real error-path coverage.

Deferred-connect path (~line 470): Left intentionally at length > 0. Per the author's response, this is correct — workspaceSkills() is session-less and can return empty when ACP isn't ready (#6169). The length > 0 guard is deliberate defense against that transient. The right key for hardening that path would be skillsResult.value.initialized === true, which is #6169-adjacent and belongs in a separate PR.

No correctness bugs, no security concerns, no convention violations.

Testing

Unit tests run in worktree (3 commits, including 6fa5c7f):

 ✓ src/daemon/session/mappers.test.ts (12 tests) 5ms
 ✓ src/daemon/session/actions.test.ts (13 tests) 24ms
 ✓ src/daemon/session/DaemonSessionProvider.test.tsx (135 tests) 2979ms

 Test Files  3 passed (3)
      Tests  160 passed (160)
   Duration  4.06s

npx tsc --noEmit -p packages/webui/tsconfig.json — clean (exit 0).

New/updated tests locking the fix:

  • actions.test.tsgetConnectionAfterSessionClear — asserts commands/skills survive clear, session-scoped fields dropped; new test for undefined-before-clear (immediate clear before first available_commands_update)
  • mappers.test.tsupdateConnectionFromDaemonEvent — asserts empty update clears stale commands (the direct assignment fix)
  • DaemonSessionProvider.test.tsxkeeps workspace skill slash commands after clearing — drives real clearSession through the provider, asserts connection.commands still contains review
  • DaemonSessionProvider.test.tsxdrops preserved commands when the next session reports an empty list — end-to-end: clear → create session → attach → authoritative empty list replaces stale commands
  • DaemonSessionProvider.test.tsxkeeps preserved commands when the next supported-commands fetch fails — error path: supportedCommands() rejecting leaves commands intact (6fa5c7f)

CI on GitHub: all 7 active checks green (ubuntu-latest Test ✓, Classify PR ✓, 4 review-pr checks ✓).

Web Shell E2E

This bug requires browser-based web shell interaction (slash menu + Tab autocomplete) to reproduce visually. The provider-level integration test covers the same behavioral guarantee programmatically — it drives the real clearSession flow through the React component tree and asserts the slash-command list survives. With five tests across three layers (pure function, mapper, provider) and the mutation check confirming they lock the behavior, this is sufficient.

中文说明

重新运行——结合提交 6fa5c7f(拒绝路径测试)。

代码审查

Diff 精准且在三个代码路径间保持一致。

getConnectionAfterSessionClear (actions.ts): 删除两行 deletecommands/skills 是由 mapSupportedCommands() 派生的工作区级数据。原始 supportedCommands 仍被正确删除。

updateConnectionFromDaemonEvent (mappers.ts): commands.length > 0 ? commands : current.commands 替换为直接赋值 commandsavailable_commands_update 是 daemon 的权威快照——直接赋值意味着空列表能正确清除陈旧条目。

Session attach (DaemonSessionProvider.tsx): supportedCommands !== undefined 区分成功返回空(权威)和跳过/失败(不权威,保留列表)。

拒绝路径测试 (6fa5c7f): 新测试覆盖 supportedCommands() 抛异常时的错误路径——拒绝使 supportedCommands === undefined!== undefined 守卫正确保留命令列表。作者指出的细节:回退到 length > 0 不会改变拒绝路径的行为,但测试仍增加了真实的错误路径覆盖。

Deferred-connect 路径: 刻意保留 length > 0workspaceSkills() 是无会话的,ACP 未就绪时可能返回空(#6169),length > 0 是对该瞬态的刻意防御。

未发现正确性 bug、安全问题或规范违反。

测试

worktree 中单元测试(3 个提交,含 6fa5c7f):

  • actions.test.ts:13 测试全部通过
  • mappers.test.ts:12 测试全部通过
  • DaemonSessionProvider.test.tsx:135 测试全部通过
  • 合计:160 测试通过,0 失败

npx tsc --noEmit — 通过。

CI:全部 7 个活跃检查绿色。

Web Shell E2E

该 bug 需要浏览器内 web shell 交互才能视觉复现。Provider 级集成测试以编程方式覆盖了相同行为保障,跨三层五个测试锁住行为,足够。

Qwen Code · qwen3.7-max

@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

Re-run — after the author's follow-up commit and response to review feedback.

This is a clean, well-targeted fix. Two deleted delete lines, a meaningful length > 0!== undefined swap on two additional paths, and comprehensive test coverage at three layers.

The author's follow-up commit (6fa5c7f) adds the rejection-path test I flagged as missing in the prior round — keeps preserved commands when the next supported-commands fetch fails. The author's pushback on the deferred-connect length > 0 suggestion is correct and well-reasoned: workspaceSkills() is session-less and can return empty when ACP isn't ready (#6169), so the length > 0 guard is deliberate defense, not an inconsistency. If hardening is ever needed there, the right key is skillsResult.value.initialized === true, which is a separate concern.

160 tests pass (up from 159), typecheck clean, CI all green. The test suite covers: commands survive a clear, session-scoped fields are dropped, undefined-before-clear is handled gracefully, an authoritative empty update clears stale commands, a failed fetch preserves the list, and the full provider flow drives real clearSession through the React tree.

No concerns remain. Approving.

中文说明

重新运行——在作者后续提交和回复审查反馈之后。

这是一个干净、目标明确的修复。删除两行 delete,两条路径上有意义的 length > 0!== undefined 替换,跨三层的全面测试覆盖。

作者的后续提交 (6fa5c7f) 补充了前次审查指出的拒绝路径测试。作者对 deferred-connect length > 0 建议的反驳正确且充分:workspaceSkills() 是无会话的,ACP 未就绪时可能返回空(#6169),length > 0 是刻意防御而非不一致。

160 测试通过(较上次增加 1 个),typecheck 通过,CI 全绿。测试覆盖:命令在 clear 后存活、session 级字段被丢弃、undefined-before-clear 被优雅处理、权威空更新清除陈旧命令、失败抓取保留列表、完整 provider 流程驱动真实 clearSession

无剩余顾虑。批准合并。

Qwen Code · qwen3.7-max

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, looks ready to ship. ✅

Comment thread packages/webui/src/daemon/session/actions.ts

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Downgraded from Approve to Comment: CI still running.

— qwen3.7-max via Qwen Code /review

Comment thread packages/webui/src/daemon/session/actions.test.ts
…tive

Address review feedback on the new-session command fix. Preserving commands
across a clear means a later refresh must be able to clear them again when the
workspace command list genuinely shrinks to empty, otherwise the preserved
entries would keep autocompleting forever.

Both refresh paths previously kept the previous list on an empty result
(`commands.length > 0 ? commands : current.commands`):

- The streamed available_commands_update handler now assigns the mapped
  commands directly, matching how skills were already handled — the daemon
  snapshot is authoritative.
- The post-attach supported-commands assignment now falls back to the
  preserved list only when the fetch was skipped or failed
  (supportedCommands === undefined), not when it returned an empty list.

Add tests: an available_commands_update that empties the list clears stale
commands; a fulfilled-empty supported-commands fetch after a clear drops the
preserved commands; and getConnectionAfterSessionClear is exercised with the
commands/skills fields already absent.

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Two additional suggestions that don't map to a specific diff line:

Missing test for supportedCommands() rejection path — The supportedCommands !== undefined ternary (line 851) was introduced specifically to handle the case where the supportedCommands() fetch rejects, but no test exercises that rejection path. Both new provider tests use mocks that resolve successfully. A regression reverting to length > 0 would pass all existing tests while silently dropping preserved commands when the fetch fails in production.

Deferred-connect bootstrap uses same length > 0 pattern (~line 470-475, unchanged) — The deferred-connect path still uses deferredSkillCommands.length > 0 / deferredSkills.length > 0 guards to decide whether to overwrite commands/skills. Now that commands survive clear, a fulfilled-but-empty workspaceSkills() result would leave stale commands from the previous session in the deferred state — the same bug class this PR fixes in the other two code paths. Consider keying on the fetch outcome: skillsResult.status === 'fulfilled' rather than deferredSkills.length > 0.

Comment thread packages/webui/src/daemon/session/DaemonSessionProvider.tsx
@wenshao

wenshao commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, looks ready to ship. ✅

Add error-path coverage for the post-attach command assignment: when the
new session's supportedCommands() rejects, supportedCommands stays undefined
and the commands preserved across the clear must survive rather than being
wiped. Complements the fulfilled-empty test, which locks that a successful
empty snapshot is instead treated as authoritative.
@wenshao

wenshao commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks for the two follow-ups. One implemented, one I'd push back on:

1. Missing test for the supportedCommands() rejection path — added (keeps preserved commands when the next supported-commands fetch fails, 6fa5c7f). One nuance worth recording: reverting to length > 0 would not change the rejection path — on reject, supportedCommands is undefined and the mapped commands is [], so both length > 0 and !== undefined fall back to current.commands. The only behavioral difference is the fulfilled-empty case, which is locked by drops preserved commands when the next session reports an empty list. The new reject test still adds real error-path coverage (a daemon hiccup during attach must not wipe the list), so it's worth having.

2. Deferred-connect workspaceSkills() guard — intentionally left as length > 0. That path is not equivalent to the other two. available_commands_update and session-scoped supportedCommands() come from a live ACP session, so a fulfilled-empty result is authoritative. workspaceSkills() is session-less and, per #6169, returns { initialized: false, skills: [] } when the ACP child isn't ready yet — an empty result there usually means "couldn't determine", not "no skills". The length > 0 guard is a deliberate defense against that transient; keying on fulfilled would trust the not-ready empty and wipe the list, re-introducing exactly the #6169 disappearing-/review bug. Note this PR actually improves that path: preserving commands across the clear means the deferred state now shows the previous session's still-valid workspace commands instead of nothing while the child warms up. If we ever want to harden the genuinely-empty-but-initialized case, the right key is skillsResult.value.initialized === true — but that's #6169-adjacent and I'd keep it separate.

中文

两条后续建议,一条已实现,一条我想反驳:

1. 缺 supportedCommands() 拒绝路径的测试——已加keeps preserved commands when the next supported-commands fetch fails,6fa5c7f)。一个值得记录的细节:回退到 length > 0 其实不会改变拒绝路径——拒绝时 supportedCommandsundefined 映射出的 commands[],故 length > 0!== undefined 都回退到 current.commands。唯一的行为差异在成功返回空的情况,已由 drops preserved commands when the next session reports an empty list 锁定。新增的拒绝测试仍是真实的错误路径覆盖(attach 时 daemon 抖动不得清空列表),值得保留。

2. 延迟连接的 workspaceSkills() 守卫——有意保留 length > 0 这条路径与另外两条不等价。available_commands_update 和会话级 supportedCommands() 来自活跃 ACP 会话,成功返回空即权威。workspaceSkills()无会话的,据 #6169,ACP child 未就绪时返回 { initialized: false, skills: [] }——这里的空通常意味着"无法确定",而非"没有技能"。length > 0 是对该瞬态的刻意防御;改成按 fulfilled 判断会信任"未就绪的空"并清空列表,正是 #6169/review 消失的 bug。注意本 PR 实际改善了该路径:跨 clear 保留命令后,延迟态现在显示上个会话仍有效的工作区命令,而非在 child 预热期间空白。若日后要加固"真为空且已 initialized"的情况,正确的判据是 skillsResult.value.initialized === true——但那与 #6169 相邻,我会单独处理。

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No review findings. Downgraded from Approve to Comment: CI still running.

— qwen3.7-max via Qwen Code /review

@wenshao

wenshao commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, looks ready to ship. ✅

@doudouOUC doudouOUC left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM. All review comments have been properly addressed:

  1. Staleness gap (actions.ts) — Fixed by making available_commands_update unconditionally authoritative and using supportedCommands !== undefined as the fallback guard.
  2. Missing undefined-before-clear test (actions.test.ts) — Added, confirms delete calls are harmless no-ops.
  3. models length pattern (DaemonSessionProvider.tsx) — Correctly scoped out; different lifecycle semantics, no staleness risk.

The workspace-vs-session scoping is well-defined, the three code paths are consistent, and the test coverage locks the behavior against regressions.

@wenshao
wenshao added this pull request to the merge queue Jul 5, 2026
Merged via the queue into QwenLM:main with commit 54ba259 Jul 5, 2026
91 checks passed

@ytahdn ytahdn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No issues found. LGTM! ✅

— qwen3.7-max via Qwen Code /review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants