Repository navigation
Conversation
Keep dedicated user subagents out of unrelated session catalogs while preserving global defaults and portable Markdown definitions. Persist project visibility locally and filter before runtime catalog assembly. Expose project selection in the editor independently of enablement, using the project archive sources so recent folders remain selectable. Cover persistence, catalog isolation, and the settings save flow. Refs vastsa#1431
muzimu217
left a comment
There was a problem hiding this comment.
Checked out the branch and reproduced the CI failure locally — full review below.
The JS failure is a stale source assertion, one line to fix
apps/desktop/test/agent-capability-settings.test.mjs:42 ("skills and MCP filter one list by level...") asserts the SubagentEditorSheet source still contains settings\.globalOnly. This PR intentionally replaces that "global-only" label with the real scope control, so the assertion no longer matches. Reproduced locally on head 758764a09:
✖ skills and MCP filter one list by level instead of stacking two sections
AssertionError: The input did not match the regular expression /settings\.globalOnly/
Updating that assertion to the new shape is the only thing between this PR and a green JS job — the new subagent-project-scope.test.mjs suite itself passes its non-Electron tests, and the Electron E2E check is green on CI.
Host-side implementation verified against #1431's facts
This is exactly the "wiring" the issue's verification pointed at, done right:
user_subagents.rs:302active_for(project_path)now consumes the project path (was an unused_project_pathstub that only filteredenabled), andset_scope(:518) persists instead of discarding — both matching the MCP-side reference implementation.project_scope.rsis the right shape: app-localagent-capabilities/subagent-scopes.json(atomic tmp+rename write), missing file defaults to all-global, corrupt file fails closed (returns an error instead of degrading to "everything visible") — that fail-closed choice matches the body's promise and is the safer default for a visibility control.- Keeping definitions in
~/.agents/subagentsand not adding a project-level directory preserves ADR 0112's frozen decision; the scope living app-local (not in the shareable Markdown) is a reasonable split since scope lists carry machine-local absolute paths. - The A/B/no-project isolation tests (
user_subagents.rs:844-851) cover the delegation-catalog filter, and the author's cross-projectUnknown subagentruntime rejection check closes the "model forces the name" hole the issue's soft-isolation workaround couldn't.
Two non-blocking notes
- Policy: this is a
featduring the fix/perf contribution window — the body already flags this honestly, so that call belongs to the maintainer; the implementation itself is ready for that decision to go either way. - The scope file is keyed by subagent id; the rename-preserves-scope behavior is tested, which is the right place to have pinned it.
Once the stale assertion is updated this should be mergeable from a correctness standpoint.
The settings list now labels each subagent with its activation scope.\nReplace the obsolete global-only expectation with both supported labels.
Resolve the ADR from the shared documentation directory so the Chinese marketplace page no longer blocks documentation and workspace builds.
|
Confirmed on our side: the new |
Keep the upstream canonical ADR link when combining both dead-link fixes. Preserve the project scope implementation while incorporating current main.
Keep the project-scope acceptance scenario alongside the new main scenarios when resolving the E2E documentation conflict. Preserve the existing feature implementation and shared branch history.
|
感谢这个 PR——也抱歉让你等了一段时间。 这个改动看起来做得不错,唯一缺的是视觉证据:由于这次改动涉及界面,仅凭 diff 我们没法判断实际效果。 方便的话,请在描述中补充两张截图:
补充之后,我们就能看到真实效果,并放心判断是否合并。 |
The list grouped user documents under a global level label, which read as activation scope once a definition could be limited to selected projects. Name the group after its source so it sits beside Built-in, and let each row badge state where the definition applies. Keys stay next to the other subagent source labels, and the dead global-only key goes away now that the scope control replaced it. The settings IA spec, the E2E plan and its Chinese mirror, and ADR 0270 describe the group by its new name. Refs vastsa#1431
A session path under a folder with multibyte characters could not answer `agents.active`: the prefix comparison sliced the target at a byte offset that landed inside a character, so the task panicked and the caller waited for its timeout. Compare whole lowercased strings instead. Project scope also traveled through config sync. The payload carried the scope, so a definition scoped to another device's folders either matched nothing there or overwrote that device's own scope with the global one. Scope names folders on one machine, so capture drops it and apply ignores whatever arrives; an existing definition keeps this device's scope and a new one starts global. The editor warns while Projects is selected with no folder, reusing the copy the floating picker already had. Covered by a character-level path test, a two-device sync test against the local S3 fixture, an apply-side unit test, and a sibling folder with a multibyte name in the real host E2E. Refs vastsa#1431
The first pass showed throwaway fixture projects; these use PI-Desktop and apps/desktop so the scope picker and the delegation results read as a real configuration.
The project paths are the author's local directories, so they are covered in the screenshot only; no product code changes.
|
Since this PR is now the canonical implementation for #1431 (I'm withdrawing my duplicate #1561), flagging its one red check so it doesn't sit:
Everything else is green and the PR is |
|
Correction to my earlier note — the red check is stale, and the fix has not been tried yet. I said "rebase should clear it". Checking properly: the failing job is run 39007392721 / job 117322549692, dated 2026-10-17 05:51 UTC, and the PR head What the stale failure actually is: Concretely for this branch:
So the action is just: rebase and let CI run once. My earlier phrasing implied a rebase had already been tried — it has not. |
|
Reviewed the host side in an isolated worktree (head Scope is enforced at execution, not just in the list. That was my main concern, so I traced it: The multibyte fix is a real bug fix, not incidental. Storage handling is careful. Two non-blocking notes:
The only blocker to landing is the stale red check: the failing job is from 2026-10-17 05:51, before this head, and the assertion it fails on ( |
Scanning user documents pruned enablement state for ids that no longer exist but left their project scope behind. A document recreated later under the same id silently inherited that scope, so a subagent came back limited to projects the user never chose for it. Prune the scope file against the same id set, next to the enablement prune. Refs vastsa#1431
|
感谢这么细致的 review,特别是确认了范围是在执行时校验、而不只是在列表里隐藏。 关于你提的两点:
另外已合入最新 main( |
|
Re-reviewed the current head (
So a project-scoped definition cannot reach an unrelated session through any path I can find, and the One operational thing, not a code finding: the head is now 39 commits behind Nothing else from me on the code. This is the implementation the #1431 proposal describes, and the two gaps you closed (unlink failure, out-of-app deletion leaving scope entries) were the ones I would have flagged next. |
Refresh the PR head with upstream main (8a8d564) so the base gate stays satisfied. Upstream main changed only outside the subagent scope surface; no conflicts.




Closes #1431。
目前用户创建的子智能体会出现在所有会话的
Task工具中,项目专用的子智能体也会被其他项目看到。本 PR 增加“全局 / 指定项目”设置,让模型只看到并调用当前项目适用的子智能体。改动
Task中的可用子智能体。例如 A 专用的子智能体只在 A 及其子目录的会话中可用,在 B 或无项目会话中不可见;即使模型指定它的名字,也会被拒绝执行。scope字段和子智能体加载流程,由 Host 在agents.active(projectPath)中筛选。范围设置单独保存在应用本地,不改动子智能体 Markdown;重命名保留设置,删除时清理。截图
完整界面 —— 设置 → 子智能体。「自定义」分组(
~/.agents/subagents)下,每一行带有自己的作用范围标签(全局或N 个项目),启用开关保持独立:改动位置特写 —— 编辑子智能体时的「作用范围」控件。选「指定项目」后,项目多选列表直接展开在编辑器内,带搜索框;当前打开的项目标有「当前打开」,但不会自动勾选。
(截图用的是本仓库:
desktop-ui-reviewer限定到apps/desktop,所以在仓库根目录项目里不可见。)更新(2026-10-17)
e219a3e4c)。scope,导致 A 设备专用的子智能体到 B 设备不可用,旧版本的全局设置还会冲掉项目限定。现在范围只留在本机,并补充双设备同步测试。?传播fs::remove_file的失败(原先是.ok()静默吞掉)。销毁旧文件失败时,下一轮扫描会让旧 id 复活,所以现在显式报错而不是假装成功。~/.agents/subagents,但生效范围改由每行标签说明,避免和项目限定的行矛盾。Unknown subagent 'frontend-reviewer',未启动子任务;中文命名的项目正常响应、无卡顿。验证
data_relocation的路径用例在 macOS 本地失败,CI 的 Rust 检查为绿,属环境差异。范围修改在下一次加载工具目录时生效,不中断正在运行的子智能体。旧版本不识别新增的范围设置,降级后会恢复原来的全局可用行为。范围设置只保存在本机,不随云同步传递。