@yangdcm/dsh-expert-team 1.2.1 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/README.en.md +4 -0
- package/README.md +4 -0
- package/lib/command.js +56 -5
- package/lib/lead-toolface.js +46 -0
- package/lib/settings.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,32 @@
|
|
|
3
3
|
本包遵循[语义化版本](https://semver.org/lang/zh-CN/)。dsh 宿主版本线的对应关系写在
|
|
4
4
|
`package.json` 的 `engines.dsh` 与 `dsh.compatibility` 里,插件市场按它判断"这个插件跟你的宿主兼不兼容"。
|
|
5
5
|
|
|
6
|
+
## 1.2.3
|
|
7
|
+
|
|
8
|
+
**给 lead 工具面收窄加开关**(因为 1.2.2 让一个从未生效的行为突然生效了)
|
|
9
|
+
|
|
10
|
+
- 背景:A 线"把执行类工具从 lead 手上拿走"此前因取错作用域**从未真正生效**,1.2.2 修好后它会
|
|
11
|
+
立刻改变日常形态 —— expert-team 会话的 lead 不再持有 `bash/write/edit/grep/glob`。
|
|
12
|
+
这是设计意图,但**没有开关的行为变更不该只留一个"忍着或回退版本"的选项**。
|
|
13
|
+
- 新增开关 `gates.leadToolFace`(`on`/`off`,默认 `on`):优先级与档位门一致
|
|
14
|
+
**`config.leadToolFace` > `DSH_EXPERT_TEAM_LEAD_TOOLFACE` > 设置(官方面板/浮层) > 默认 on**;
|
|
15
|
+
非法值一律回默认 on(不猜、不报错 —— 与档位门同一条纪律)。
|
|
16
|
+
- 关掉时**出声一次**(`[expert-team] lead 工具面收窄已关闭…`):否则"我明明关了"与
|
|
17
|
+
"开关没生效"看起来一模一样。
|
|
18
|
+
## 1.2.2
|
|
19
|
+
|
|
20
|
+
**修掉"lead 工具面收窄静默失效"**(拿真机启动日志换来的)
|
|
21
|
+
|
|
22
|
+
- 症状:每次创建 agent 都刷一行 `lead 工具面**未**收窄(nothing-to-deny)… 宿主里这些名字一个都不存在`,
|
|
23
|
+
而实际上模型可见的 `bash/write/edit/grep/glob` **存在** —— 结论不成立,收窄也没发生。
|
|
24
|
+
- 根因:宿主 `tools.view(scope)` **不传 scope = 全局视图**;0.1.5 起模型可见工具由 preset 注册在
|
|
25
|
+
**agent 平面**,于是全局视图"非空但缺这几个名字",纯函数据实报 `nothing-to-deny`。
|
|
26
|
+
宿主自己的 `restrict()` 用的就是 `scopeOf(this.ctx)`,我们却用了不传 scope 的 `view()`。
|
|
27
|
+
- 修法:新增 `agentScopedToolNames()`(动态 import `@deepseek-ai/dsh-scope` 取 `scopeOf(agent.ctx)`,
|
|
28
|
+
再 `view(scope)`);取不到 scope 时返回 `knownNames: undefined` ⇒ 如实报 **no-known-names**
|
|
29
|
+
("我不知道有什么"),绝不再退化成"宿主里没有这些工具"这种不成立的结论。
|
|
30
|
+
- 告警去重:同一 status 每进程只喊一次(十行同样的 warn 会把"响亮"变成噪声,
|
|
31
|
+
而噪声的代价是所有告警一起被降权)。两种零仍然分得清。
|
|
6
32
|
## 1.2.1
|
|
7
33
|
|
|
8
34
|
**卸载回收覆盖历史副本**(1.2.0 的补丁)
|
package/README.en.md
CHANGED
|
@@ -91,6 +91,10 @@ pnpm install && dsh web
|
|
|
91
91
|
> on the official page — its value type cannot be expressed reliably in the host schema, so it stays with
|
|
92
92
|
> the overlay's settings tab and `$DSH_HOME/expert-team/settings.json`. On a host with no settings service
|
|
93
93
|
> every setting falls back to that file.
|
|
94
|
+
>
|
|
95
|
+
> **The A-line switch**: the "narrow the lead's tool face" gate (`gates.leadToolFace`, default `on`)
|
|
96
|
+
> decides whether execution tools (`bash/write/edit/grep/glob`) are taken away from the lead and given
|
|
97
|
+
> to the role subagents. Turn it off with `config.leadToolFace` or `DSH_EXPERT_TEAM_LEAD_TOOLFACE=off`.
|
|
94
98
|
|
|
95
99
|
## Quick start
|
|
96
100
|
|
package/README.md
CHANGED
|
@@ -84,6 +84,10 @@ pnpm install && dsh web
|
|
|
84
84
|
> 并且随插件市场的**备份与恢复**一起走。**诚实边界**:`默认班底`(角色 id 数组)不在官方页面里
|
|
85
85
|
> —— 它的取值类型在宿主 schema 里表达不可靠,继续由浮层设置页签与
|
|
86
86
|
> `$DSH_HOME/expert-team/settings.json` 负责;宿主没有 settings 服务时,全部设置退回该文件。
|
|
87
|
+
>
|
|
88
|
+
> **A 线开关**:设置里的「门禁 → 收窄 lead 工具面」(`gates.leadToolFace`,默认 `on`)决定
|
|
89
|
+
> 是否把执行类工具(`bash/write/edit/grep/glob`)从 lead 手上拿走、交给角色子代理。
|
|
90
|
+
> 也可用 `config.leadToolFace` 或环境变量 `DSH_EXPERT_TEAM_LEAD_TOOLFACE=off` 关闭。
|
|
87
91
|
|
|
88
92
|
## 快速上手
|
|
89
93
|
|
package/lib/command.js
CHANGED
|
@@ -41,7 +41,7 @@ import { collectTokenUsage } from './metrics/token-usage.js';
|
|
|
41
41
|
import { renderTokenSection } from './metrics/tokens.js';
|
|
42
42
|
// A 线(token 成本治理 · 第 2 步):**收窄 lead 自己的工具面**。判定全在
|
|
43
43
|
// `lib/lead-toolface.js`(纯函数、零宿主依赖、可单测);这里只负责在 agent **创建时刻**接线。
|
|
44
|
-
import { planLeadToolFace, shouldNarrowLeadToolFace } from './lead-toolface.js';
|
|
44
|
+
import { planLeadToolFace, shouldNarrowLeadToolFace, agentScopedToolNames } from './lead-toolface.js';
|
|
45
45
|
// G 线(档位):档位词表/裁剪表/suggestTier 的**唯一真源**。SKILL 的裁剪表、`/team status`
|
|
46
46
|
// 的输出、浮层候选项全部从这里来 —— 两处各写一份就是又一次「一个事实多份拷贝」。
|
|
47
47
|
import { normalizeTier, suggestTier, tierSummaryLine, tierDetailLines, tierChoices, TIER_SPEC, TIER_LABELS_ZH, DEFAULT_TIER, narrowedRoles } from './tier.js';
|
|
@@ -565,6 +565,7 @@ function reapplySettingsDerived() {
|
|
|
565
565
|
resolveLimits(PLUGIN_CONFIG, limitsBaseFromSettings(s));
|
|
566
566
|
resolveRoundLimits(PLUGIN_CONFIG, roundLimitsBaseFromSettings(s));
|
|
567
567
|
resolveTierGate(PLUGIN_CONFIG, s.gates);
|
|
568
|
+
resolveLeadToolFace(PLUGIN_CONFIG, s.gates);
|
|
568
569
|
return true;
|
|
569
570
|
} catch (e) {
|
|
570
571
|
console.warn('[expert-team] 重算设置派生值失败(保持上一次生效值):' + String(e && e.message ? e.message : e));
|
|
@@ -1611,6 +1612,28 @@ const TIER_GATE_VALUES = ['soft', 'hard'];
|
|
|
1611
1612
|
const TIER_GATE_ENV = 'DSH_EXPERT_TEAM_TIER_GATE';
|
|
1612
1613
|
let TIER_GATE = DEFAULT_TIER_GATE;
|
|
1613
1614
|
|
|
1615
|
+
// ── lead 工具面收窄的开关(2026-09-14 加)──────────────────────────────────────
|
|
1616
|
+
// 为什么需要它:A 线的"把执行类工具从 lead 手上拿走"此前因一个 bug **从未真正生效**
|
|
1617
|
+
// (清单取错作用域,见 lib/lead-toolface.js)。修好之后它会立刻改变日常使用形态 ——
|
|
1618
|
+
// lead(含正在跟你对话的那个)不再持有 bash/write/edit/grep/glob,执行全部落到角色子代理。
|
|
1619
|
+
// 这是设计意图,但**没有开关的行为变更不该只留给用户一个"忍着或回退版本"**。
|
|
1620
|
+
// 优先级与档位门完全一致:**config > env > 设置控制台 > 内置默认(on)**。
|
|
1621
|
+
const DEFAULT_LEAD_TOOLFACE = 'on';
|
|
1622
|
+
const LEAD_TOOLFACE_VALUES = ['on', 'off'];
|
|
1623
|
+
const LEAD_TOOLFACE_ENV = 'DSH_EXPERT_TEAM_LEAD_TOOLFACE';
|
|
1624
|
+
let LEAD_TOOLFACE = DEFAULT_LEAD_TOOLFACE;
|
|
1625
|
+
|
|
1626
|
+
/** 解析 lead 工具面收窄开关(非法值一律回默认 on —— 与档位门同理,不猜不报错)。 */
|
|
1627
|
+
function resolveLeadToolFace(config, base) {
|
|
1628
|
+
const cfgRaw = String((config && typeof config === 'object' && config.leadToolFace) || '').trim().toLowerCase();
|
|
1629
|
+
const envRaw = String(((typeof process !== 'undefined' && process.env) || {})[LEAD_TOOLFACE_ENV] || '').trim().toLowerCase();
|
|
1630
|
+
const baseRaw = String((base && typeof base === 'object' ? base.leadToolFace : base) || '').trim().toLowerCase();
|
|
1631
|
+
LEAD_TOOLFACE = LEAD_TOOLFACE_VALUES.includes(cfgRaw) ? cfgRaw
|
|
1632
|
+
: (LEAD_TOOLFACE_VALUES.includes(envRaw) ? envRaw
|
|
1633
|
+
: (LEAD_TOOLFACE_VALUES.includes(baseRaw) ? baseRaw : DEFAULT_LEAD_TOOLFACE));
|
|
1634
|
+
return LEAD_TOOLFACE;
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1614
1637
|
/**
|
|
1615
1638
|
* 解析档位门是软还是硬。**非法值一律回默认(soft)**,不猜也不报错 ——
|
|
1616
1639
|
* 一个拼错的开关值把流程卡死(hard)比静默放行更糟,而"卡死"正是最贵的失败模式。
|
|
@@ -4409,7 +4432,20 @@ async function executeTeamCommand(ctx, invocation) {
|
|
|
4409
4432
|
/** 并发写追踪器:**进程级单例**(跨工具调用累积;`_live` 暴露以便单测重置与断言)。 */
|
|
4410
4433
|
const WRITE_TRACER = createWriteTracer();
|
|
4411
4434
|
|
|
4412
|
-
|
|
4435
|
+
/**
|
|
4436
|
+
* lead 工具面告警去重:同一 status 每个进程只喊一次。
|
|
4437
|
+
* 为什么:该告警按 **agent 创建**触发,一个会话里每建一个 agent 都会喊 —— 十行同样的 warn
|
|
4438
|
+
* 会把"响亮"变成"噪声",而噪声的代价是所有告警一起被降权(本仓反复记录过的失败模式)。
|
|
4439
|
+
* 去重只影响**重复次数**,不影响"第一次一定喊",也不合并不同 status(两种零仍然分得清)。
|
|
4440
|
+
*/
|
|
4441
|
+
const LEAD_TOOLFACE_WARNED = new Set();
|
|
4442
|
+
let LEAD_TOOLFACE_OFF_LOGGED = false;
|
|
4443
|
+
function warnLeadToolFaceOnce(status, detail) {
|
|
4444
|
+
if (LEAD_TOOLFACE_WARNED.has(status)) return;
|
|
4445
|
+
LEAD_TOOLFACE_WARNED.add(status);
|
|
4446
|
+
console.warn(`[expert-team] lead 工具面**未**收窄(${status}):${detail}`);
|
|
4447
|
+
}
|
|
4448
|
+
export const _live = { pushActivity, phaseAccountingViolations, loggedPhases, authorityViolations, WRITE_TRACER, createWriteTracer, formatConflict, summarizeTool, parseLogLine, roleOfSub, mapRoleToSub, membersFromState, buildRoleSubMap, resolveSubRoles, childSessionTiming, SUB_HEADER_CACHE, workflowEventIndex, workflowChildLabels, workflowChildMeta, workflowRuns, WF_EVENT_CACHE, rememberSessionRun, sessionRunFor, runOwnerSession, SESSION_RUNS, parseTeamCommand, deriveMemberEntries, schemaViolations, runHealth, RUN_STALL_MS, scaffoldFingerprint, SCAFFOLD_REQUIRED, strandedTasks, settleStranded, IN_FLIGHT_STATUSES, normalizeCoverage, SCHEMA_WARN_SEEN, pushActivityEvent, DEFAULT_LIMITS, LIMITS, resolveLimits, capacityViolations, DEFAULT_ROUND_LIMITS, ROUND_LIMITS, ROUND_LIMIT_ENV, resolveRoundLimits, ROUND_LIMIT_OF_KIND, roundOf, isQualityTask, normTitle, roundLimitViolations, reworkLoopWriteGuard, mutateTasks, readStandingRules, appendStandingRule, rulesRun, scopeOverlapWarnings, applyTaskStatus, waitRun, eventFamily, verdictFromToken, normalizeRoleName, truncateCodepoints, filterRunScopedSubs, runCreatedAtMs, runLogTail, liveFiles, LIVE_FILES_CACHE, DEFAULT_ROLES, resolveTierGate, TIER_GATE_ENV, snapshotRun, settingsPath, loadSettingsSync, currentSettings, limitsBaseFromSettings, roundLimitsBaseFromSettings, effectiveTierGate: () => TIER_GATE, ensureSkillInstalled, ensurePresetInstalled, uninstallInstalled, buildSkillRegistration, parseSkillMarkdown, PLUGIN_VERSION, INSTALL_STAMP, runtimeSkillRegistered: () => RUNTIME_SKILL_REGISTERED, agentScopedToolNames, warnLeadToolFaceOnce, resolveLeadToolFace, LEAD_TOOLFACE_ENV, effectiveLeadToolFace: () => LEAD_TOOLFACE, installHostSettings, hostValues, hostScope, hostSettingsNote, updateHostSettings, pickFileOnly, pickHostExpressible, buildHostSchema, hostBase, hostSchemaPaths, reapplySettingsDerived, currentSettings, mergeSettings };
|
|
4413
4449
|
|
|
4414
4450
|
export function apply(ctx, config) {
|
|
4415
4451
|
// 留一份 config:设置在运行时改变(官方面板 / 浮层)时要**用同一份 config** 重算上限与档位门,
|
|
@@ -4427,6 +4463,8 @@ export function apply(ctx, config) {
|
|
|
4427
4463
|
resolveRoundLimits(config, roundLimitsBaseFromSettings());
|
|
4428
4464
|
// G 线:档位门软/硬(config.tierGate > DSH_EXPERT_TEAM_TIER_GATE > 设置 > soft)。
|
|
4429
4465
|
resolveTierGate(config, currentSettings().gates);
|
|
4466
|
+
// A 线开关:config > env > 设置 > 默认(on)。关掉即 lead 保留全部工具。
|
|
4467
|
+
resolveLeadToolFace(config, currentSettings().gates);
|
|
4430
4468
|
// 批 2-1:宿主若提供 ctx.fs,就让它接管工件写入(真实版本栅栏);否则保持同语义的回退实现。
|
|
4431
4469
|
// 机会式探测而非 inject —— 见 ARTIFACT 声明处的说明(inject 缺失服务会让整条命令挂不上)。
|
|
4432
4470
|
const hostFsAdopted = adoptHostFs(ctx);
|
|
@@ -4589,7 +4627,7 @@ export function apply(ctx, config) {
|
|
|
4589
4627
|
// 为什么是这个时刻:`agent/created` 由宿主 `announce()` 在**创建时刻**发出;宿主自己对
|
|
4590
4628
|
// 子代理也是在组合(setup)阶段调 `childCtx.tools.restrict(...)`(`dsh-subagent:554`)。
|
|
4591
4629
|
// 即:**照抄宿主自己的时序**,不另造。
|
|
4592
|
-
ctx.on('agent/created', ({ agent }) => {
|
|
4630
|
+
ctx.on('agent/created', async ({ agent }) => {
|
|
4593
4631
|
try {
|
|
4594
4632
|
const agents = ctx.get('agents');
|
|
4595
4633
|
// ① preset 必须是专家团(`composedPreset` 读活动作用域链,未写会话头也答得出)
|
|
@@ -4599,12 +4637,25 @@ export function apply(ctx, config) {
|
|
|
4599
4637
|
const isRoot = agents?.roots?.().includes(agent) === true;
|
|
4600
4638
|
if (!shouldNarrowLeadToolFace({ presetId, isRoot }).apply) return; // 无关 agent:静默返回,不是失败
|
|
4601
4639
|
|
|
4602
|
-
|
|
4640
|
+
if (LEAD_TOOLFACE === 'off') {
|
|
4641
|
+
// 关掉时**出声一次**:否则"我明明关了"与"开关没生效"看起来一模一样(两种零纪律)。
|
|
4642
|
+
if (!LEAD_TOOLFACE_OFF_LOGGED) {
|
|
4643
|
+
LEAD_TOOLFACE_OFF_LOGGED = true;
|
|
4644
|
+
console.log(`[expert-team] lead 工具面收窄已关闭(${LEAD_TOOLFACE_ENV}=off 或设置 gates.leadToolFace=off)⇒ lead 保留全部工具`);
|
|
4645
|
+
}
|
|
4646
|
+
return;
|
|
4647
|
+
}
|
|
4648
|
+
|
|
4649
|
+
// ③ **必须取 agent 作用域**的名字清单:`view()` 不传 scope = 全局视图,而模型可见工具
|
|
4650
|
+
// 在 0.1.5 起由 preset 注册在 agent 平面 ⇒ 全局视图非空但缺那几个名字,收窄会静默失效
|
|
4651
|
+
// 且给出"宿主里没有这些工具"的错误结论(拿真机日志换来的教训,详见 lead-toolface.js)。
|
|
4652
|
+
const { knownNames, reason } = await agentScopedToolNames({ agentCtx: agent.ctx });
|
|
4603
4653
|
const plan = planLeadToolFace({ platform: process.platform, knownNames });
|
|
4604
4654
|
if (!plan.effective) {
|
|
4605
4655
|
// **两种零都要出声**:`no-known-names`(我不知道宿主有什么)与
|
|
4606
4656
|
// `nothing-to-deny`(宿主确实没有这些)不是同一件事,不能长成同一个样子。
|
|
4607
|
-
|
|
4657
|
+
// 但同一状态**只喊一次**:每个会话都刷会把 warn 变成噪声,而噪声会让所有告警一起被降权。
|
|
4658
|
+
warnLeadToolFaceOnce(plan.status, `${plan.notes.join(' ')}(清单来源:${reason})`);
|
|
4608
4659
|
return;
|
|
4609
4660
|
}
|
|
4610
4661
|
// 成功不打印:每个会话都刷一行会把 warn 变成噪声(本仓纪律:warn 必须保持可见)。
|
package/lib/lead-toolface.js
CHANGED
|
@@ -177,3 +177,49 @@ export function shouldNarrowLeadToolFace({ presetId, isRoot } = {}) {
|
|
|
177
177
|
if (isRoot !== true) return { apply: false, reason: 'is-subagent' };
|
|
178
178
|
return { apply: true, reason: 'lead' };
|
|
179
179
|
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* 取**agent 作用域**下的"可限制工具名清单"。
|
|
183
|
+
*
|
|
184
|
+
* ── 为什么必须带 scope(这一条是拿真机日志换来的)────────────────────────────
|
|
185
|
+
* 宿主 `tools.view(scope)` 的文档写得很直白:**不传 scope = 全局视图**。而 0.1.5 起模型可见的
|
|
186
|
+
* `bash/write/edit/grep/glob` 由 **preset 注册在 agent 平面**,不再是全局工具 ——
|
|
187
|
+
* 于是 `view()`(全局)会返回一个**非空但缺这几个名字**的集合,`planLeadToolFace` 据此报
|
|
188
|
+
* `nothing-to-deny`,收窄**静默失效**,而日志还在说"宿主里这些名字一个都不存在"(不属实)。
|
|
189
|
+
* 宿主自己的 `restrict()` 用的就是 `scopeOf(this.ctx)` —— 本函数照抄同一条取 scope 的路。
|
|
190
|
+
*
|
|
191
|
+
* scope 是 `@deepseek-ai/dsh-scope` 里的**模块私有 Symbol**(`Symbol("dsh.scope")`,不是
|
|
192
|
+
* `Symbol.for`),因此只能经该包的 `scopeOf()` 取得 ⇒ **动态 import**:仓库里解析不到该包时
|
|
193
|
+
* 返回 `knownNames: undefined`,由调用方如实报 `no-known-names`("我不知道有什么"),
|
|
194
|
+
* 绝不退化成"宿主里没有这些工具"那种**不成立**的结论。
|
|
195
|
+
*
|
|
196
|
+
* @param {object} input
|
|
197
|
+
* @param {object} [input.agentCtx] - `agent.ctx`(scope 就挂在它上面)
|
|
198
|
+
* @param {object} [input.tools] - 工具服务(默认取 `agentCtx.tools`)
|
|
199
|
+
* @param {Function} [input.loadScope] - **仅供测试**注入 `@deepseek-ai/dsh-scope` 的加载器
|
|
200
|
+
* @returns {Promise<{knownNames: Set<string>|undefined, reason: string}>}
|
|
201
|
+
*/
|
|
202
|
+
export async function agentScopedToolNames({ agentCtx, tools, loadScope } = {}) {
|
|
203
|
+
const loader = typeof loadScope === 'function' ? loadScope : () => import('@deepseek-ai/dsh-scope');
|
|
204
|
+
let scopeOf;
|
|
205
|
+
try {
|
|
206
|
+
const mod = await loader();
|
|
207
|
+
scopeOf = mod && mod.scopeOf;
|
|
208
|
+
} catch (e) {
|
|
209
|
+
return { knownNames: undefined, reason: 'scope-module-unavailable:' + String((e && e.message) || e) };
|
|
210
|
+
}
|
|
211
|
+
if (typeof scopeOf !== 'function') return { knownNames: undefined, reason: 'scope-of-missing' };
|
|
212
|
+
const service = tools || (agentCtx && agentCtx.tools);
|
|
213
|
+
if (!service || typeof service.view !== 'function') return { knownNames: undefined, reason: 'tools-service-unavailable' };
|
|
214
|
+
let scope;
|
|
215
|
+
try { scope = scopeOf(agentCtx); } catch { return { knownNames: undefined, reason: 'scope-undetectable' }; }
|
|
216
|
+
if (scope === undefined) return { knownNames: undefined, reason: 'not-a-scoped-ctx' };
|
|
217
|
+
try {
|
|
218
|
+
const view = service.view(scope);
|
|
219
|
+
const names = view && view.restrictableNames;
|
|
220
|
+
const size = names && typeof names.size === 'number' ? names.size : 0;
|
|
221
|
+
return { knownNames: names, reason: size > 0 ? 'ok' : 'empty-scoped-view' };
|
|
222
|
+
} catch (e) {
|
|
223
|
+
return { knownNames: undefined, reason: 'view-failed:' + String((e && e.message) || e) };
|
|
224
|
+
}
|
|
225
|
+
}
|
package/lib/settings.js
CHANGED
|
@@ -57,6 +57,7 @@ export const SETTINGS_SPEC = {
|
|
|
57
57
|
boundarySpec: { type: 'bool', default: true, label: '规格边界章节(SPEC.md)', hint: '边界没填就不让进 implement' },
|
|
58
58
|
loopGuard: { type: 'bool', default: true, label: '振荡检测(A→B→A→B)', hint: '宿主那份只管同工具重复,这份管来回振荡' },
|
|
59
59
|
tierGate: { type: 'enum', values: ['soft', 'hard'], default: 'soft', label: '档位选择门', hint: 'soft = 建议先生效;hard = 不选不开工' },
|
|
60
|
+
leadToolFace: { type: 'enum', values: ['on', 'off'], default: 'on', label: '收窄 lead 工具面', hint: 'on = 执行类工具(bash/write/edit/grep/glob)从 lead 手上拿走,交给角色子代理(省 token);off = lead 保留全部工具' },
|
|
60
61
|
maxReviewRounds: { type: 'int', min: 1, max: 20, default: 3, label: '评审轮次上限', hint: '到顶的正确动作是升级用户,不是再来一轮' },
|
|
61
62
|
maxTestRounds: { type: 'int', min: 1, max: 20, default: 3, label: '测试轮次上限', hint: '同上' },
|
|
62
63
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yangdcm/dsh-expert-team",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "dsh「专家团」bundle:一句自然语言自动组建/持久化一支 12 角色多智能体团队,共享工作区协议 + 阶段门控编排 + 结构化交接 + 质量门禁/自动调度,实现者直接改代码并产出持久工件;带 live 团队浮层(质量门禁/覆盖率/工件预览)。 · Role-based multi-agent expert team for DeepSeek Harness: one sentence in, a staged and gated team delivery out.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|