feat(cli): enable /directory command in ACP mode#4826
Conversation
Refactor /directory (show/add) from addItem-based output to returning MessageActionReturn so it works in ACP mode (web-shell). Changes: - Add supportedModes: ['interactive', 'acp'] to parent + both subcommands - Add argumentHint to add subcommand for command palette - Add parent action returning usage hint for bare /directory invocation - Refactor show: return message instead of addItem - Refactor add: collect all outputs into messages array, return single message (messageType: 'error' if any errors, 'info' otherwise) - Add try-catch outer wrapper for unexpected errors - Simplify pathsToAdd parsing (remove no-op split-join) - Update existing .tsx tests to assert on return values instead of addItem - Add new .ts test file with 11 tests covering ACP paths Known limitations: - Mixed success+error returns use messageType: 'error' for the whole message (single MessageActionReturn can't express mixed severity) - Cross-session: directory add is session-scoped, other sessions see the change after restart (pre-existing architectural property) Refs #4514
📋 Review SummaryThis PR refactors the 🔍 General Feedback
🎯 Specific Feedback🟡 High
🟢 Medium
🔵 Low
✅ Highlights
|
|
Thanks for the PR! Template: the PR body covers all the key areas (what/why/validation/risk/linked issues) but uses custom headings instead of the template's structure. Not blocking, but matching the template headings makes it easier for maintainers to scan. Minor. On direction: clearly aligned. Enabling On approach: scope is tight and focused. Three files — implementation, new unit test, and migrated existing test. The addition of a top-level One observation on path parsing: the old code did Moving on to code review. 🔍 中文说明感谢贡献! 模板:PR 正文覆盖了所有关键信息(变更内容/原因/验证/风险/关联 issue),但使用了自定义标题而非模板结构。不阻塞,但匹配模板标题更方便维护者快速浏览。小问题。 方向:明确对齐。在 ACP/web-shell 模式下启用 方案:范围紧凑聚焦。三个文件——实现、新单元测试、迁移后的已有测试。顶层 路径解析的观察:旧代码做了 进入代码审查 🔍 — Qwen Code · qwen3.7-max |
There was a problem hiding this comment.
Pull request overview
Refactors the /directory slash command to return MessageActionReturn results (instead of using TUI-only addItem output), and enables the command in ACP mode so web-shell clients can add/show workspace directories.
Changes:
- Enable ACP execution for
/directory(parent +add/show) viasupportedModes: ['interactive', 'acp']. - Refactor
addandshowactions to returntype: 'message'results and aggregate multi-step output into a single message. - Update and add unit tests to validate ACP support and the new message-returning behavior.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| packages/cli/src/ui/commands/directoryCommand.tsx | Enable ACP mode and refactor /directory actions to return MessageActionReturn instead of addItem UI output. |
| packages/cli/src/ui/commands/directoryCommand.test.tsx | Update existing tests to assert returned message objects rather than addItem calls. |
| packages/cli/src/ui/commands/directoryCommand.test.ts | Add focused tests for ACP supportedModes, argumentHint, and basic message-returning behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…md message 1. Usage hint now shows comma-separated format: `<path>[,<path>,...]` 2. QWEN.md files success message only emitted when memory refresh actually runs
Review fix summary — 0dea510
CI: Reran |
…ch, test consolidation 1. Use messageType 'warning' for partial success (some paths added, some failed) instead of 'error' which throws in ACP mode via Session.ts 2. Wrap gemini.addDirectoryContext() in its own try-catch to prevent losing accumulated success messages on failure 3. Consolidate duplicate .test.ts into .test.tsx, add space-in-path test, add settings.setValue assertion for mixed-result scenario 4. Delete redundant directoryCommand.test.ts
Review fix summary — 4b3721f
All 22 tests pass. |
…uards 1. Add test for addDirectoryContext() rejection → messageType 'warning' + error message 2. Restore null-config tests for both show and add subcommands (lost during consolidation)
Review fix summary — e87b1c0 (round 3)
All 25 tests pass. |
| it('should return error when config is null', async () => { | ||
| if (!showCommand?.action) throw new Error('No action'); | ||
| showCommand.action(mockContext, ''); | ||
| const nullConfigContext = { |
There was a problem hiding this comment.
[Suggestion] Both null-config test stubs (show at line 103, add at line 131) create { services: { config: null } } without a settings property, relying on as unknown as CommandContext to bypass type checking. The add action destructures const { config, settings } = context.services, setting settings to undefined. This works because the if (!config) guard returns early — but if someone inserts settings-accessing code between the destructuring and the null guard, the test will crash with a confusing TypeError.
| const nullConfigContext = { | |
| const nullConfigContext = { | |
| services: { config: null, settings: { merged: {}, workspace: {}, setValue: vi.fn() } }, | |
| } as unknown as CommandContext; |
— DeepSeek/deepseek-v4-pro via Qwen Code /review
| if (gemini) { | ||
| await gemini.addDirectoryContext(); | ||
| if (added.length > 0) { | ||
| try { |
There was a problem hiding this comment.
[Suggestion] The entire shouldLoadMemoryFromIncludeDirectories() branch (lines 222–258, ~36 statements) has zero test coverage — all tests mock it as false. This covers loadServerHierarchicalMemory, setUserMemory, setGeminiMdFileCount, setConditionalRulesRegistry, and the associated error catch. A regression here could silently leave stale memory/rules after adding directories.
Consider adding a test that mocks shouldLoadMemoryFromIncludeDirectories as true and verifies the config setters are called, plus a test where loadServerHierarchicalMemory throws to exercise the error catch.
— qwen3.7-max via Qwen Code /review
| includeDirectories, | ||
| ); | ||
| } catch (error) { | ||
| errors.push( |
There was a problem hiding this comment.
[Suggestion] The settings.setValue error catch has no test — setValue never throws in any test. This means the degradation behavior when settings persistence fails (e.g., read-only workspace) is unverified. The error is pushed to the errors array and the return becomes warning or error, but this is unconfirmed.
Consider adding a test that mocks settings.setValue to throw and asserts the error message and messageType.
— qwen3.7-max via Qwen Code /review
| }, | ||
| kind: CommandKind.BUILT_IN, | ||
| supportedModes: ['interactive'] as const, | ||
| supportedModes: ['interactive', 'acp'] as const, |
There was a problem hiding this comment.
[Suggestion] With ACP mode enabled, remote clients can add arbitrary readable filesystem paths (e.g., /etc, /root/.ssh) to workspace context. The only guard is isRestrictiveSandbox(), which defaults to false. Since workspace context feeds the file crawler, this creates a potential path for directory enumeration via the LLM.
Consider adding ACP-specific path confinement (e.g., restrict to project root or an allowlist) when context.executionMode === 'acp', or document this as an accepted risk for authenticated ACP sessions.
— qwen3.7-max via Qwen Code /review
Local Verification ReportBranch: Unit Tests
Test breakdown:
ESLintTypeScript Type Check
No typecheck errors in Whitespace CheckSummary
All verification checks pass. The PR is ready for merge. Verified locally by wenshao |
Summary
/directory(show/add) fromaddItem-based output to returningMessageActionReturn, enabling ACP mode (web-shell) support./directorywassupportedModes: ['interactive']only and used TUI-onlyaddItemfor output.addsubcommand refactoring — multipleaddItemcalls collapsed into a singleMessageActionReturnwith collected messages.Validation
supportedModesincludes'acp'in the command fileScope / Risk
messageType: 'error'for the whole message — singleMessageActionReturncan't express mixed severity. In interactive mode, successful text renders with error styling when errors coexist (minor visual regression, same tradeoff as other message-returning commands).messagereturn type is handled identically byslashCommandProcessorin interactive modeTesting Matrix
Testing matrix notes:
Linked Issues / Bugs
Refs #4514 (T3.10)
🤖 Generated with Qwen Code