feat(daemon): add workspace skill toggle API - #6816
Conversation
E2E test reportTested on macOS with a locally built bundle, loopback bearer authentication, and a temporary workspace. The live model invocation check reused the existing local login state; all settings writes remained inside the temporary workspace. BaselineThe installed Results
Automated verificationTargeted route, persistence, ACP refresh, status mapping, and SDK Vitest cases passed. Full |
|
Thanks for the PR! Template looks good ✓ Problem: Real gap — daemon clients can inspect workspace skills via GET but had no API to toggle them, forcing out-of-band settings edits. The before/after evidence in the PR body is concrete (HTTP 404 → working toggle). Direction: Aligned. Mirrors the existing Size: 1008 production lines, 752 test lines, 162 doc lines. This is a Approach: Mirrors Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ 问题: 真实缺口 — daemon 客户端可以通过 GET 查看工作区 skill,但没有 API 来切换它们,只能在接口外编辑配置。PR 描述中的 before/after 证据具体(HTTP 404 → 可用 toggle)。 方向: 对齐。镜像现有 规模: 1008 行生产代码、752 行测试、162 行文档。 方案: 镜像 进入代码审查 🔍 — Qwen Code · qwen3.7-max |
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
…ggle # Conflicts: # docs/developers/qwen-serve-protocol.md # packages/acp-bridge/src/status.ts # packages/cli/src/serve/workspace-skills-mapping.ts # packages/sdk-typescript/src/daemon/types.ts
ytahdn
left a comment
There was a problem hiding this comment.
Reviewed — no blockers. 2 Warnings, 4 Suggestions, 4 Nits posted inline.
Overall: High-quality implementation with thorough error handling, correct lock semantics, and comprehensive test coverage. Two Warnings flag a multi-workspace performance gap and a benign TOCTOU window — neither is a blocker but both merit attention.
— qwen-code via Qwen Code /review
|
Follow-up to the review summary: Thanks for the thorough review. I addressed every inline thread:
All 10 inline threads have been replied to and resolved. Verification after the fix: |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed — no blockers. Suggestions are inline.
— qwen3.7-max via Qwen Code /review
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed — no blockers. Suggestions are inline.
wenshao
left a comment
There was a problem hiding this comment.
Reviewed — no blockers. Suggestions are inline.
— qwen3.7-max via Qwen Code /review
Independent local verification report (maintainer, macOS)Built and live-tested this PR locally at head 0955627 in a clean worktree (fresh Builds & test suites
Live daemon E2E (bundled daemon, isolated HOME, bearer token, 2 workspaces)Before/after + persistence semantics. The installed Live ACP session refresh — the core value of the PR, confirmed end-to-end: with one live session, disable returns Workspace-qualified route, deferred activation & SDK. On the secondary workspace (which has no ACP child until its first session), Error contract & gates — all nine documented rejections reproduced live with the exact status/code/fields (404 Notes for merging
中文版本(Chinese version)独立本地验证报告(维护者,macOS)在干净 worktree 中于 PR head 0955627 完成本地构建与真实测试(全新 构建与测试套件
Live daemon E2E(bundle daemon、隔离 HOME、bearer token、双工作区)前后对比与持久化语义:未含本 PR 的已安装 Live ACP 会话刷新(本 PR 的核心价值,端到端确认):存在一个 live 会话时,禁用返回 工作区限定路由、deferred 激活与 SDK:次级工作区在首个会话前没有 ACP child, 错误契约与闸门:文档中的全部 9 种拒绝路径均以准确的 status/code/字段实测复现(404 合并注意事项
|
|
@qwen-code /resolve |
Resolve conflict in run-qwen-serve.ts where origin/main added fileSystem and persistApprovalMode to the bridge creation object while the PR branch added persistDisabledSkills to the workspace service creation. Both changes are complementary and independent.
|
Qwen Code resolved the merge conflicts and pushed the branch update. Merge Conflict Resolution Summary — PR #6816ConflictFile: The conflict occurred in the dynamic workspace bridge creation section ( HEAD (PR branch —
|




What this PR does
Adds daemon REST and TypeScript SDK support for enabling or disabling a loaded workspace skill through
skills.disabled, with both primary-workspace and workspace-qualified routes and theworkspace_skill_togglecapability.The mutation resolves skill names case-insensitively, persists the canonical name under a workspace settings lock, preserves orphaned entries, rejects skills the CLI panel cannot toggle, and reports whether activation was applied, deferred, or partial. A dedicated ACP refresh reloads workspace settings for the child and every active session, updates available commands, and refreshes skill consumers while reusing the existing
settings_changedevent.The workspace skill status now exposes a false-only
userInvocablefield so clients can distinguish model-only skills without changing the default response shape. Protocol, SDK, and design documentation describe the contract and distinguishskills.disabledfromdisable-model-invocationmetadata.Why it's needed
Daemon clients can inspect workspace skills but could not perform the same enable/disable action as the CLI
/skillspanel. Remote clients therefore had to edit settings out of band and could not reliably refresh already-running sessions. This API gives daemon consumers one guarded, capability-discoverable mutation with the same toggleability and scope-lock semantics as the CLI.Reviewer Test Plan
How to verify
workspace_skill_toggle.skills.disabledis updated without deleting unrelated entries, and the workspace skill snapshot reports it disabled.activation: deferred; repeat with a higher-scope disable entry or a non-user-invocable/inactive-extension skill and confirm the request returns 409 without changing workspace settings.Evidence (Before & After)
Before: the installed
qwen 0.18.5-preview.0daemon returned HTTP 404 forPOST /workspace/skills/review/enable.After: the locally bundled daemon persisted a case-insensitive disable as canonical
review, returneddeferredwith no child, omitted the skill from a subsequently created session, rejected its Skill tool call, then returnedappliedwith one refreshed session after re-enabling and allowed that same session to invoke it successfully.Tested on
Environment (optional)
Locally built and bundled daemon on macOS, loopback HTTP with bearer authentication, a temporary workspace, and the existing local login state for the live model invocation check. Targeted daemon route, persistence, ACP refresh, status mapping, and SDK tests passed, along with full build, typecheck, lint, and bundle verification.
Risk & Scope
Linked Issues
No linked issue.
中文说明
本 PR 做了什么
新增通过
skills.disabled开启或关闭已加载工作区 skill 的 daemon REST 与 TypeScript SDK 支持,同时覆盖主工作区和工作区限定路由,并新增workspace_skill_togglecapability。该变更对 skill 名称执行大小写不敏感解析,在工作区 settings 锁内持久化规范名称,保留 orphan 配置,拒绝 CLI 面板不可切换的 skill,并返回
applied、deferred或partial激活状态。专用 ACP 刷新会重新加载 child 和每个活动会话的工作区设置、更新可用命令并刷新 skill 消费者,同时复用现有settings_changed事件。工作区 skill 状态新增 false-only 的可选
userInvocable字段,让客户端在不改变默认响应形状的前提下识别仅模型可用的 skill。协议、SDK 和设计文档补充了完整契约,并说明skills.disabled与disable-model-invocation元数据的区别。为什么需要
Daemon 客户端可以查看工作区 skill,但此前无法执行与 CLI
/skills面板相同的开启/关闭操作。远程客户端只能在接口之外编辑配置,也无法可靠刷新已经运行的会话。该 API 为 daemon 消费者提供了一个受保护、可通过 capability 探测的变更入口,并与 CLI 保持相同的可切换性和 scope 锁定语义。Reviewer 测试计划
如何验证
workspace_skill_toggle。skills.disabled更新且不删除无关项,并确认工作区 skill 状态显示为 disabled。activation: deferred;使用高层 scope 禁用项、非 user-invocable skill 或 inactive-extension skill 时,确认返回 409 且不修改工作区配置。前后证据
之前:已安装的
qwen 0.18.5-preview.0daemon 对POST /workspace/skills/review/enable返回 HTTP 404。之后:本地 bundle daemon 将大小写不敏感的禁用操作规范化持久化为
review,无 child 时返回deferred,后续创建的会话不再提供该 skill 并拒绝其 Skill tool 调用;重新启用时返回applied和一个已刷新会话,同一会话随后成功调用该 skill。测试平台
环境(可选)
在 macOS 上使用本地构建和 bundle 的 daemon、loopback HTTP、bearer 鉴权和临时工作区进行验证;实时模型调用检查仅复用现有本地登录态。Daemon 路由、持久化、ACP 刷新、状态映射和 SDK 的定向测试全部通过,全量 build、typecheck、lint 和 bundle 也通过。
风险与范围
关联 Issue
无关联 issue。