dsh-subagent-pro
v1.3.2
Published
Subagent Pro: per-session delegation toggle, EXTENDED delegation tools (permission tiers -> tool filters, persona/custom_context, thinking_effort/max_tokens, invocation budgets with automatic hard-destroy, model whitelist, parallel ceiling), a browser set
Readme
Subagent Pro
子代理增强插件。构建在官方子代理栈之上。1.3.0 起,本插件接管规范名 subagent / subagent_fork(扩展参数版),官方同名工具经安装补丁改名为 subagent_basic / subagent_fork_basic 保留(gate 恒拒,仅作兼容痕迹);其余官方能力(状态面板、状态工具等)不替换:
| 增强 | 说明 |
|---|---|
| 扩展委派工具(1.3.0) | subagent / subagent_fork = 官方参数全集 + 扩展:permission_tier(权限档位)、persona / custom_context、thinking_effort / max_tokens、invocations(1–5 次可插话预算)、provider / model / run_in_background(仅 subagent)。扩展参数先剥离,其余按官方语义经 ctx.subagents 执行 |
| 权限档位 → 工具过滤(1.3.0) | inherited(默认,无过滤)/ restricted(deny 写入类)/ minimal(allow 只读)。档位只能收紧;官方继承机制兜底(审批钉死 never + 沙箱继承)。名单为保守默认(restrictedDenyTools / minimalAllowTools 可覆盖)——工具注册表无读写元数据,无法自动判定 |
| 可调用次数预算(1.3.0) | invocations(默认 1):持久会话事件记账(subagent-pro/invocations[-consumed]);subagent_send 每次消耗 1 次(按子代理串行化防并发超用),用尽自动硬销毁(drain + 归档)并拒绝再发 |
| 模型白名单(1.3.0) | 设置页维护 provider/model 路由白名单(留空=不限);宿主翻译为官方 subagent/model-selection-policy 会话事件,扩展工具在显式选路时强校验;list_subagent_models 随之提供发现能力 |
| 全局天花板(1.3.0) | globalMaxOutputTokens(子代理 max_tokens 只压不抬)、maxParallelChildren(默认 5;运行中直接子代理达到上限时拒绝委派并提示等待) |
| 会话级委派开关 | 输入框左侧「子代理」胶囊,按会话启用/停用委派;状态是持久会话事件(经兼容层注册),重启后仍在 |
| 设置页(人可见可操作) | 插件行配置页:委派倾向、策略注入开关、Prompt 预算、白名单、全局上限/并行数、受门禁工具、禁止委派的权限预设,逐项「说明 → 确认 → 写入」,取消即回滚(受控草稿) |
| 子代理控制面板 | 同一行页下半部:列出直接子代理(状态/最近活动),逐行提供 插话 / 打断 / 读输出(区间)/ 销毁 |
| 模板管理 UI | 列表 + 新建/编辑/删除,宿主写 $DSH_HOME/storages/subagent-pro/templates.json,带确认 |
| 委派策略提示 | 按设置注入 minimal/normal/maximal 委派倾向 + 模板提示 + 权限继承说明 + 扩展参数/并行上限说明 + 停用告示 |
| 委派模板工具 | template_save / template_list / template_use / template_delete(模型侧工具,与控制面板共用同一存储) |
| Prompt 预算 | maxPromptChars:委派任务提示超长直接拒绝(全局输入天花板) |
| 模型选择批量操作 | 官方「子智能体」设置页的模型列表旁注入 全选/清空/反选 工具条;只模拟点击官方勾选框,草稿与保存完全归官方 |
与官方委派工具的共存关系(1.3.0)
- 工具注册表同一层内同名注册会抛错(
dsh-scopeNamedEntries;插件上下文无作用域 → 全局层),因此本插件不能直接「覆盖」官方工具。安装补丁(cordis.patch.yml)用 dsh-app-boot 的 patch 语义把官方两行toolName改为subagent_basic/subagent_fork_basic(fork 行保持 one-shot、spawn 行保持 continuable,其余 config 原样保留),腾出规范名。 - 改名后的官方工具始终被 gate 拒绝(提示改用扩展工具),防止绕过预算/档位/白名单。
- 降级:若补丁未生效(配置漂移),插件在注册时探测到名称被占即跳过自身扩展工具并告警——插件照常加载,官方工具继续可用(仅扩展能力缺失),不会启动失败。
- fork 的结论:官方
subagent_fork= 同一工具包 +provider: fork(dsh-subagent-fork-in-process,inheritsParentContext = true,支持 persona/toolFilter/agentOptions)。因此subagent上不提供inherit_context参数——fork 语义已由subagent_fork承载;fork 保持 one-shot(官方 KV 复用决策),路由保持父级,故不暴露 provider/model,invocations亦不适用。
设置页与 UI 落点(1.2.0)
plugins.row.config(keyed 槽,key =dsh-subagent-pro#subagent-pro):插件详情页的「配置」行进入的页面,含设置表单 + 控制面板 + 模板管理。settings.general.item(list 槽,id =subagent-pro-summary):通用设置里的一行摘要,只做展示与提示(ownerProps 为空,不承载表单)。- 所有可编辑字段都改成
.volatile():这样命名空间才会被dsh-settingsserve(只暴露含 volatile 字段的条目),且编辑无需重载插件即时生效。原有默认值语义保持不变。
控制工具(0.3.0)
在官方 ctx.subagents 原语之上提供模型可直接使用的管理面(官方团队插件留空的能力):
| 工具 | 作用 | 官方原语 |
|---|---|---|
| subagent_list | 列出自己的直接子代理 | listChildren(parentSessionId, signal) |
| subagent_send | 插话/转向运行中的子代理(steer 语义) | sendMessage(sender, childId, content, {signal}) |
| subagent_interrupt | 打断子代理当前轮次(保留信箱与后代) | interrupt(childId, {kind:'user', parentSessionId}) |
| subagent_output | 按字符区间读子代理的助手输出 | 子会话 snapshotEvents() |
| subagent_destroy | 软销毁(释放常驻激活;日志仍可读) | drainContinuableChildren(parent, ids) |
| subagent_memory | 读某子代理的记忆摘要(装了 dsh-agent-memory 才出现) | 能力发现 + agentMemory.summary |
全部工具按调用者会话鉴权:只能操作自己的直接子代理,越权一律拒绝。
权限耦合(0.3.0)
- 策略提示注入当前权限预设与继承规则(读官方
permissionPresets服务,绝不私存副本) - 官方机制保证子代理权限不可能超过父级:子代理继承父会话的沙箱、审批策略固定为
never(越界自动拒绝)、子代理内部无法扩权 - 可选配置
delegationDeniedPresets(如['read-only']):列出的预设下直接拒绝委派
UI 请求通道 —— 信任边界(重要)
浏览器半(客户端 bundle)不能直接调用宿主服务,因此控制面板与模板管理采用「请求队列」:
- 宿主 → 客户端(快照,只读):宿主周期性(2s)与事件驱动地把「所有活跃会话的直接子代理 + 状态/最近活动」写入 volatile 字段
childrenJson、把模板列表写入templatesJson。客户端只读渲染。 - 客户端 → 宿主(请求):客户端把请求写入 volatile 字段
controlRequestJson({ id, op: send|interrupt|output|destroy, parent, child, text?, start?, end? })或templateRequestJson({ id, op: save|delete, name, template? });宿主订阅loader/volatile-update(并以 2s 轮询兜底)读取、按id去重、重新鉴权后执行,把结果写入controlResultJson/templateResultJson。
鉴权(宿主侧,不可绕过):
- 每个控制请求的目标必须是该请求声明的父会话的直接子代理,用官方
subagents.listChildren(parent)重新枚举校验(与工具侧assertOwnChild同一判定逻辑)。外来 childId 一律拒绝。 - 插话/销毁以该父会话的实时 Agent 身份执行(
ctx.agents.get(parent));父会话不是活跃 Agent 时拒绝。 - 模板写入由宿主执行,落
$DSH_HOME/storages/subagent-pro/templates.json。
信任边界(诚实说明):该通道承载的是用户本人对其会话的权限——用户本来就能在输入框里 /subagents-pro off、也能直接操作自己的子代理,所以这里不是针对用户的特权边界。它能挡住的是模型与其他插件:页面本身拿不到任何服务句柄,只能读写该命名空间;而伪造的请求仍会因邻接校验失败而被拒。若页面上下文已被任意脚本攻陷,则与「任意脚本已在 harness 页面内运行」同级的风险——页面内没有任何东西能防住这种情况。
安装(官方方式)
桌面端:插件 → 添加插件,输入包名 dsh-subagent-pro(或本地路径选 tarball)。
前置依赖:dsh-compat-layer(会话事件词表注册)需先安装。
卸载
官方插件页卸载即可。历史日志中的 subagent-pro/toggle 事件仍可读(兼容层注册了该类型);若同时卸载兼容层,请先用其 tools/normalize-session-log.mjs 给历史日志补 ignorable 标记。
设置
static Config(rc.2 标准投影,全部 volatile):proactiveness、promptInjectionEnabled、maxPromptChars、gatedTools(默认含官方委派工具与团队 spawn_teammate)、delegationDeniedPresets;1.3.0 新增 allowedModelsJson(白名单路由 JSON)、globalMaxOutputTokens、maxParallelChildren、restrictedDenyTools、minimalAllowTools;以及 UI 桥接字段 childrenJson / controlRequestJson / controlResultJson / templatesJson / templateRequestJson / templateResultJson。
English
Subagent enhancements layered on the OFFICIAL subagent stack. Since 1.3.0 this plugin OWNS the canonical subagent / subagent_fork names with EXTENDED parameters (permission tiers mapped to official toolFilter — tighten-only; persona/custom_context; thinking_effort / max_tokens with a global output cap; invocation budgets of 1-5 sends with automatic hard-destroy; a user-configured model whitelist enforced on explicit route selection; a parallel-children ceiling with wait semantics). Official semantics are preserved: extension fields are stripped and the rest is dispatched through ctx.subagents.start() / startContinuable() with the official request shape. The official delegation tools are RENAMED by the install patch to subagent_basic / subagent_fork_basic (same-name global registration throws) and always denied by the gate; if the patch did not apply, the plugin skips its own tools with a warning instead of failing. Also included: a per-session delegation toggle, a browser settings page with confirm-and-rollback forms, a live subagent control panel (list / steer / interrupt / ranged output / destroy), a template manager, a delegation-policy prompt (incl. permission inheritance), reusable templates, a prompt budget, a bulk model-selection toolbar, and control tools over the official runtime. Every control tool is caller-scoped. Requires dsh-compat-layer; the child-memory tool appears only when dsh-agent-memory is installed (capability discovery).
The UI bridge is a request queue: the browser may only read its own settings namespace and write two request fields; the host re-authorizes every request against the official direct-child catalog before executing it. This keeps the model and other plugins out — it is not a privilege boundary against the user, who already holds full authority over their own sessions.
License: MIT. Author: jd962.
