mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-11-07 06:19:43 -10:00
* fix(cli): resolve ACP core settings against the active target dir The `qwen/settings/getCore` and `qwen/settings/setCoreValue` handlers in `extMethodInternal` fell back to `process.cwd()` when no explicit `cwd` was passed. In a worktree-backed ACP session the daemon runs from the project root, so workspace-scoped settings were written to `<projectRoot>/.qwen/settings.json` instead of the worktree's own `.qwen/settings.json`. Fall back to `config.getTargetDir()` instead, which `relocateWorkingDirectory()` keeps pinned to the active session workspace (including worktrees). An explicit `cwd` still wins. Fixes #8138 Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-issue-patrol/jmtwqd66dxl * fix(cli): resolve ACP settings from the requesting session's target dir The `qwen/settings/*` + `qwen/permissions/*` handlers resolved their workspace root from `process.cwd()` or the daemon's bootstrap `this.config.getTargetDir()`, both of which stay pinned to the boot workspace. A worktree session relocates *its own* Config, so workspace-scoped writes landed in `<projectRoot>/.qwen/settings.json` instead of the worktree's own `.qwen/settings.json` (#8138). Resolve the workspace root from `session.getConfig().getTargetDir()` (falling back to the bootstrap Config when the client sends no `sessionId`) and apply it uniformly across the settings/permissions surface. An explicit `cwd` still wins. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-closeout/jmtwvd7nnxt * fix(cli): consolidate duplicate @qwen-code/qwen-code-core imports Merge ExtensionManager and the type-only Config/GoalSnapshotV2 into the single existing value import so import/no-duplicates passes under --max-warnings 0. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-conflict/jmtwy83e5xx * fix(cli): resolve getMemoryPaths against the active session target dir Align qwen/settings/getMemoryPaths with its getMemory/setMemory siblings by resolving through settingsCwdFor, so the project memory file points at the requesting session's worktree rather than the daemon boot dir. Correct the settingsCwdFor doc comment, which overstated the no-sessionId fallback as preserving process.cwd() behaviour. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-closeout/jmtxadc55yg * fix(acp): fail loud on unresolvable sessionId, drop per-request env injection settingsCwdFor previously treated an unresolvable sessionId as absent, silently retargeting every qwen/settings/* and qwen/permissions/* read and write to the daemon's bootstrap workspace (a workspace the caller never selected, with its own trust decision). Reject an unresolvable id with errorKind session_not_found instead, keeping the no-sessionId fallback that the workspace-service setRules path depends on. The twelve rewired handlers also called loadSettings without options, so a session-scoped read injected the foreign workspace's .env into the daemon's process-wide process.env. Route them through a shared loadRequestSettings that sets skipLoadEnvironment (and states consumeCorruptionEnvVars explicitly, since an options object replaces loadSettings' = true default). Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-closeout/jmtxixz7myu * fix(cli): scope ACP settings adoption and permission sync to the session workspace Resolve the requesting session's stable workspace root (its bound storage) instead of the live cwd, so session/cd no longer repoints the twelve settings handlers at a subdirectory holding no .qwen/settings.json (R2-2). Only publish a freshly loaded LoadedSettings into the process-wide this.settings cache when it was loaded for the daemon's own workspace, so a bare sessionId read cannot repoint the daemon-global consumers (R2-3). Scope syncLivePermissionManagers fan-out to the workspace a workspace-scoped setRules write landed in, instead of broadcasting the delta to every live session (R2-5). Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-closeout/jmtxn8asoz1 * fix(cli): honor explicit cwd and reject malformed sessionId in ACP settings resolver Reorder `settingsCwdFor` so an explicit request `cwd` wins before the `sessionId` lookup, fixing the R2-1 regression where a request that names its workspace is rejected over a field the resolver never uses. Distinguish a present-but-malformed `sessionId` (number/object/empty string) from an absent one so it fails with `invalidParams` instead of silently retargeting the bootstrap workspace (R3-3). Restore the lost fallback-branch pin and add the both-fields and malformed-sessionId cases the review asked for (R3-4). Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-closeout/jmtxrimarz8 * fix(cli): name and pin the session workspace root, and cover the permission fan-out filter Extract sessionWorkspaceRoot(config) to give the admission-bound storage root (storage.getProjectRoot()) a name distinct from the live getTargetDir() and Config.getProjectRoot(), and route settingsCwdFor and the workspace-scoped permission fan-out through it. This is a pure refactor of the two inline reads. Add two regression cases that pin the fan-out filter against the two mutants that previously survived green: a user-scoped setRules delta must still reach every live session across workspaces (the Workspace guard must stay conditional on scope), and the requesting session must survive its own filter after a session/cd moved its live cwd into a subdirectory (the filter must key on the stable root, not getTargetDir()). Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-closeout/jmty039h3zl * fix(cli): keep MCP/hook/extension writes on the workspace-global coordinate The MCP status/apply routes (buildManagedWorkspaceMcpStatus, reloadWorkspaceMcpDiscovery) and the hooks/extensions status routes resolve only the bootstrap workspace. Resolving sessionId on the write side made a handler answer "saved" for a server no route would ever list or apply, so setMcpServer, removeMcpServer, setHook, removeHook and setExtensionSetting now resolve only an explicit cwd (R3-2, option b). Session-aware resolution stays where write and read-back share the coordinate (core settings, memory, permissions). Co-authored-by: Qwen-Coder <[email protected]> * fix(cli): canonicalize workspace path spellings in permission fan-out syncLivePermissionManagers and adoptRequestSettings compared workspace coordinates with path.resolve only, so a grant revoked under a different spelling of the same directory (symlinked /tmp vs /private/tmp, or a different case) never reached the live session's permission manager while the caller was told it saved — fail-open. Canonicalize both sides with realpathSync.native (path.resolve fallback) plus a darwin/win32 case-fold. Also treat a present-but-empty cwd as absent in the five workspace-global settings handlers (|| instead of ??), matching the session-aware handlers. Co-authored-by: Qwen-Coder <[email protected]> * style(cli): apply prettier formatting to the ACP agent files The Prettier lane flags both files touched by this PR (a JSDoc continuation line and an over-width path.join call), which fails Lint & Static before any later step runs. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-conflict/jmu0kyvtn3f * fix(cli): rely on realpath casing instead of folding case in workspace comparison realpathSync.native() already returns the on-disk casing on macOS and Windows, so the toLowerCase() on top was redundant on case-insensitive volumes and actively wrong on case-sensitive ones: proj and PROJ are genuinely different workspaces there, and folding authorised one under a rule written for the other. Also pin the removal direction of the cross-spelling fan-out and clean up the test symlink. Co-authored-by: Qwen-Coder <[email protected]> --------- Co-authored-by: Qwen-Coder <[email protected]>