Skip to content

feat(subagents): add resource, capability and model controls - #1086

Open
lyx2145181 wants to merge 6 commits into
agegr:mainfrom
lyx2145181:feat/subagent-resource-whitelists
Open

lyx2145181 wants to merge 6 commits into
agegr:mainfrom
lyx2145181:feat/subagent-resource-whitelists

Conversation

@lyx2145181

@lyx2145181 lyx2145181 commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Give subagent profiles their own resource selections, Code mode/MCP capabilities, and model-override control, while keeping the existing profile editor and session lifecycle.

The goal is to make a role's configuration meaningful for the child it creates: select what it loads, explicitly opt into host capabilities, and keep its chosen model instead of silently inheriting a different parent loadout.

User-facing changes

Select skills and extensions per role

  • Choose individual skills and extensions using compact, searchable pickers in the existing Resources field.
  • Show a concise selection summary; open one picker at the current Choose button rather than adding permanent configuration panels.
  • Use a tri-state bulk control to select the entire enabled catalog as concrete entries, regardless of the current search, or clear the selection. Preserve unknown/ambiguous saved entries instead of silently removing them.
  • Keep the existing draft/Save workflow: opening, searching, retrying, and closing a picker do not save or change a selection. Built-in profiles remain read-only.

Opt into Code mode and selected MCP servers

  • Add independent, default-off Code mode and MCP switches alongside skills/extensions.
  • Choose exact MCP server identities by scope and name; children do not inherit the parent's MCP loadout or an automatic All/wildcard selection.
  • Keep stored selections when MCP is switched off, and show unavailable/blocked entries without discarding them.
  • The picker only reads the masked, files-only MCP overview. It does not edit server settings, enable servers, run Test, or start Sign-in.

Keep configured role and child models

  • Add Allow parent model override beside the specified model, default off.
  • When a role specifies a model and overrides are off, ignore the parent's Agent.model parameter and use the role model—even if the ignored parameter names an unknown or ambiguous model. Do not reject the task merely to make the parent retry without that parameter.
  • With overrides enabled, allow an explicit per-create selection without editing the role. Roles without a specified model keep the existing explicit-selection/inheritance behavior.
  • Resume ignores attached model parameters and retains the child's current model, including manual changes. Later parent/profile edits do not reassign an existing child.
  • Cold reopening restores the saved active-branch model even before conversation messages exist. An unavailable saved model or missing configured authentication is an error, not a reason to silently select a default.

English, Simplified Chinese, and Traditional Chinese strings are included.

Technical adjustments

Resource loading and authorization

  • Discover a static, source-aware resource catalog without evaluating extension code or installing packages. Apply restricted selections before SDK imports, using native resource discovery, scoped settings, and canonical project trust.
  • Preserve foreign profile frontmatter and unedited aliases/selections. Apply narrowly scoped updates when toggling profiles and retain omitted capability/model fields from older clients.
  • Restore children from their resource snapshots rather than rereading a changed role. Refresh non-resource settings while keeping transient child changes local.
  • Account for tools registered during session_start/resource discovery: do not use early enumeration as the SDK's permanent allowlist. Enforce frozen builtin/extension authority using the actual registration winner for both direct calls and nested tool_call execution.

Delegated-run lifecycle

  • Route delegated create/resume through AgentSessionWrapper admission, readiness, prompt preparation, and cancellation, and await actual completion rather than a prompt acknowledgment.
  • Handle readiness failures immediately and recheck cancellation at queued/binding boundaries.
  • Reset extension UI cancellation on resume after Stop without an unnecessary rebind.

Native host capabilities

  • Reuse the existing builtin extension factory, McpHost, project trust, scoped settings, and credential storage rather than introducing a parallel pipeline.
  • Use Code mode with models: false; tool search is a dependency, not a third profile setting. Respect native builtin disable/replacement rules.
  • Authorize the selected scoped server and actual registry owner before transport value resolution, process spawning, or network connection.
  • Separate structural declaration from execution-time readiness checks for MCP aggregates. Retain legitimate declarations during SDK catalog lag without replaying an old active-tool set or undoing explicit disablement.
  • Resource snapshot v3 freezes capability flags, selected server identities, and tool authority—not configuration bytes, credentials, or remote tool catalogs. Existing v1/v2 snapshots gain no new host capabilities.

Model selection and editor reuse

  • Resolve the selected create model before worktree/session/resource side effects. A protected role's ignored parent parameter is not parsed.
  • Restore the saved child model from the active branch, including setup-only sessions, while leaving ordinary unsent-session defaults unchanged.
  • Reuse the current model lookup, profile frontmatter, Toggle/Field components, and draft/Save flow. The override switch is disabled with an accessible explanation when no role model is specified; its dormant intent is retained.
  • No new permission store or model-related resource snapshot version is introduced.

Compatibility and limits

  • Existing boolean resource selections remain supported; CSV/string-array selections and foreign YAML are preserved through the native profile workflow.
  • Intentional behavior change: roles with a specified model no longer accept parent model overrides by default. Enable the new switch to retain that behavior. Manual child model changes remain available.
  • v1 keeps its historical hard allowlist; v2 retains its frozen resource/tool policy; neither is migrated or promoted to Code mode/MCP.
  • Existing profile Save, copy, enabled PATCH, trust, and built-in read-only behavior are retained. No dependency/lockfile changes or user-data migration are included.
  • These controls are not a filesystem/network/extension-JavaScript sandbox. Trusted extension code is not isolated, and guarded execution is not hard registry isolation.
  • MCP aggregate admission relies on the audited SDK 1.0 public catalog-update timing; the corresponding integration coverage should be revisited on SDK upgrades.

Validation

  • Exported and validated the final staged tree independently from the live preview checkout.
  • Typecheck: tsc --noEmit --incremental false.
  • ESLint: zero errors/warnings; git diff --check clean.
  • Isolated temporary-HOME/agent-directory offline suite: 2,426 passed.
  • Separately mocked plugin-update suite with offline unset: 5 passed. This is not a claim that one environment's npm test covers both paths.
  • Independent focused review and integration checks for resources, late tools, host admission, readiness/Stop/resume, model selection, and cold restoration.
  • In-process faux providers verify actual request model identities and single-shot behavior, including real Agent → controller → child resume after a manual model change.
  • Manual preview testing of the final model behavior was reported successful after restarting the development preview to discard pre-change in-memory tool closures.

Related open work and design choices

These are related proposals, not prerequisites. The model behavior above is an explicit reviewable policy choice rather than an accidental silent override.

Review structure

This PR contains six existing logical commits; it does not rewrite or squash their history:

  1. Resource scoping and late-tool policy.
  2. Compact resource pickers.
  3. Wrapper-based delegated lifecycle.
  4. Scoped Code mode/MCP runtime support.
  5. Compact capability controls.
  6. Configured role/child model preservation.

The model editor, resolver, persistence compatibility, and cold-restore fix form one complete final increment, so they are submitted together rather than as partially functioning layers. Unrelated font/sidebar/session-list customizations and personal planning files are excluded.

Why:
Subagents need resource selection before extension import, while approved
late registrations must remain usable under SDK 1.0's hard tool allowlist.

Safety:
Resolve restricted resources before import and apply real project trust.
Enforce a frozen, winner-specific policy for direct and nested execution.
Handle queued readiness failures immediately and recheck cancellation
before delegated prompts, including cancellation before listener setup.
This is not a filesystem or extension-JavaScript sandbox.

Compatibility:
Preserve foreign YAML, unedited selections and legacy boolean clients.
Keep v1 hard allowlists; restore v2 from its creation snapshot, not the
current profile. Refresh non-resource scoped settings without persisting
transient setters or widening resource and builtin permissions.

Validation:
Exported and checked this staged tree independently of the pending UI.
Typecheck and ESLint passed. Isolated offline suite: 2339 passed;
separately mocked plugin-update suite: 5 passed.
No build, real provider request, MCP connection or deployment was run.
Why:
Boolean switches cannot show or edit resource whitelists. Compact summaries
and an on-demand picker keep the profile editor readable without changing
its draft and Save workflow.

Safety:
Search, navigation and retry leave selections unchanged. The single
tri-state bulk control selects the full enabled catalog as explicit paths,
not future-enabled All, and preserves unknown or ambiguous entries.
Share catalog matching, use native DOM contracts, clamp fixed positions
to the visual viewport and avoid refocusing on responsive width changes.
Keep built-in profiles read-only and distinguish explicit from automatic
focus restoration.

Validation:
Exported and checked this staged tree independently.
Typecheck and ESLint passed. Isolated offline suite: 2366 passed;
separately mocked plugin-update suite: 5 passed.
Post-fix browser acceptance stopped after two harness environment failures;
no browser pass or physical keyboard/pinch-zoom verification is claimed.
No real profile save, build or deployment was run.
Why:
Direct SDK prompts bypass the wrapper's prompt and Stop lifecycle.
Delegated runs must await completion and resume extension UI after Stop.

Safety:
Use wrapper admission, readiness and cancellation for create and resume.
Reset extension UI cancellation before prompting without rebinding.
Share MCP preparation with normal prompts.

Compatibility:
Keep v2 snapshots and legacy test-host fallbacks unchanged.
Introduce no capability fields, profile APIs or host authorization changes.

Validation:
Exported and checked this staged tree independently.
Typecheck, ESLint and whitespace checks passed.
Isolated offline suite: 2367 passed; separately mocked plugin suite: 5 passed.
Independent targeted tests: 41 passed. The lifecycle test also passed with
pending v3 code; restoring the old runtime in a temporary copy reproduced
an interrupted-UI Stop timeout.
No browser validation, build, deployment or real provider/MCP request.
Why:
Subagent roles need independent Code mode and MCP capabilities with
explicit server selection, rather than inheriting a parent's loadout.

Safety:
Apply real scoped builtin switches and project trust.
Check selected registration ownership before transport value resolution,
and enforce actual-winner authorization for direct and nested tool calls.
Use the child's frozen builtin selection for read-only MCP policy.
Separate aggregate declaration from execution during SDK catalog lag;
preserve explicit tool disablement without replaying an old active set.
This is not a filesystem, network or extension-JavaScript sandbox.
The roster observer depends on audited SDK 1.0 catalog-update timing.

Compatibility:
Default both capabilities off and preserve omitted fields from old clients.
Freeze scoped server identities in v3 snapshots, not config or credentials.
Keep v1/v2 authority unchanged without migration or capability promotion.
Share existing factories, hosts and credential storage; include no UI changes.

Validation:
Exported and checked this staged tree independently.
Typecheck, ESLint and whitespace checks passed with no warnings.
Isolated offline suite: 2384 passed; separately mocked plugin suite: 5 passed.
Independent capability, lifecycle and profile API tests: 22 passed.
No browser validation, build, deployment or real provider/MCP request.
Why:
Expose independent Code mode and MCP role capabilities without expanding
the profile editor into a separate configuration panel.

Safety:
Reuse the Resources field, responsive cards and shared picker DOM policy.
Read the masked files-only MCP overview; never change server configuration,
enable servers or invoke Test or Sign-in.
Keep built-in profiles read-only and preserve dormant scoped selections.
Search, retry and stale responses do not change the draft.

Compatibility:
Use the existing profile draft and Save flow.
Default legacy drafts off and preserve exact scoped names when copying.
Add matching English, Simplified Chinese and Traditional Chinese strings.
Leave backend authorization and snapshot behavior unchanged.

Validation:
Exported and checked this staged tree independently.
Typecheck, ESLint and whitespace checks passed with no warnings.
Isolated offline suite: 2395 passed; separately mocked plugin suite: 5 passed.
Independent UI and shared resource-picker tests: 57 passed.
Static, SSR and mocked checks are not browser or real keyboard acceptance.
No browser validation, real profile save, build, deployment or real
provider/MCP request.
Why:
Parent-supplied model parameters should not silently replace a role's
specified model, and reopening a setup-only child should not reset its
recorded choice to the default.

Behavior:
Add a default-off profile switch for parent model overrides beside the
model selector. With a specified role model and the switch off, ignore
parent model parameters and continue using the role model without retry.
Keep explicit choice and inheritance unchanged for roles without a model.
Resume ignores attached model parameters and retains the child's current
model, including manual changes. Cold restoration uses the active branch's
recorded choice and fails if that model or configured auth is unavailable.

Compatibility:
Reuse profile frontmatter, the draft/Save flow and existing model lookup.
Preserve omitted fields from old clients, copies and foreign frontmatter.
Keep built-ins read-only and normal unsent-session defaults unchanged.
Introduce no permission store, dependency or resource snapshot version.
Roles relying on parent overrides must explicitly enable the new switch.

Validation:
Exported and checked this staged tree independently.
Typecheck, ESLint and whitespace checks passed with no warnings.
Isolated offline suite: 2426 passed; separately mocked plugin suite: 5 passed.
Independent targeted review: 123 passed, with additional cold-restore checks.
Real in-process provider fixtures verify one-shot role selection and a real
Agent-to-controller resume retaining the manually selected child model.
Manual model behavior was confirmed by the tester after preview restart.
No real provider request or comprehensive browser acceptance was run by
this validation; no production deployment was performed.

This branch has not been deployed

No deployments
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.

1 participant