dsh-expert-group 0.1.11 → 0.1.12
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/client-bundle.js +1 -1
- package/client-settings-main-b.js +4 -1
- package/client.js +1 -1
- package/host/index-assembly-bootstrap.js +3 -1
- package/host/index-assembly-guards.js +13 -3
- package/host/index-auto-recovery.js +3 -0
- package/host/index-expert-tools-admission.js +4 -0
- package/host/index-expert-tools-core.js +53 -15
- package/host/index-expert-tools-fanout.js +5 -2
- package/host/index-root-wait.js +32 -0
- package/package.json +1 -1
package/client-bundle.js
CHANGED
|
@@ -17334,7 +17334,7 @@ renderMainPeriodHint(view,mainPeriod),
|
|
|
17334
17334
|
view.peakValleyBroken
|
|
17335
17335
|
?react.createElement("p",{className:"deg_settings_error"},view.tExtra("settings.pv.broken"))
|
|
17336
17336
|
:null,
|
|
17337
|
-
|
|
17337
|
+
modelConfigSection,
|
|
17338
17338
|
renderSettingsTaskRow(view),
|
|
17339
17339
|
renderSettingsNotificationRow(view),
|
|
17340
17340
|
renderSettingsUnifiedRow(modelView),
|
|
@@ -1386,7 +1386,10 @@
|
|
|
1386
1386
|
view.peakValleyBroken
|
|
1387
1387
|
? react.createElement("p", { className: "deg_settings_error" }, view.tExtra("settings.pv.broken"))
|
|
1388
1388
|
: null,
|
|
1389
|
-
|
|
1389
|
+
// provider 目录是宿主级共享数据(DSH 的 llm 命名空间),不属于 peak / valley 任何一层:
|
|
1390
|
+
// 峰谷启用、本页锁定为「当前时段」编辑视图时仍然渲染,位置与普通模式逐字相同
|
|
1391
|
+
// (副标题之后、任务行之前),切换峰谷前后区域不跳位。
|
|
1392
|
+
modelConfigSection,
|
|
1390
1393
|
renderSettingsTaskRow(view),
|
|
1391
1394
|
renderSettingsNotificationRow(view),
|
|
1392
1395
|
renderSettingsUnifiedRow(modelView),
|
package/client.js
CHANGED
|
@@ -17334,7 +17334,7 @@ renderMainPeriodHint(view,mainPeriod),
|
|
|
17334
17334
|
view.peakValleyBroken
|
|
17335
17335
|
?react.createElement("p",{className:"deg_settings_error"},view.tExtra("settings.pv.broken"))
|
|
17336
17336
|
:null,
|
|
17337
|
-
|
|
17337
|
+
modelConfigSection,
|
|
17338
17338
|
renderSettingsTaskRow(view),
|
|
17339
17339
|
renderSettingsNotificationRow(view),
|
|
17340
17340
|
renderSettingsUnifiedRow(modelView),
|
|
@@ -218,7 +218,9 @@ export function assembleRootWait(state, caps) {
|
|
|
218
218
|
state.rootWaitDomain = rootWaitDomain;
|
|
219
219
|
const { isRootAgentIdentity } = rootWaitDomain;
|
|
220
220
|
|
|
221
|
-
|
|
221
|
+
// rc.2 删除 agents.roots():统一走 root wait 域的双契约枚举(rc.1 roots() /
|
|
222
|
+
// rc.2 list()+root 身份过滤),保证预存 root 仍能登记 lineage 与代次。
|
|
223
|
+
const roots = rootWaitDomain.listRootAgents();
|
|
222
224
|
for (const root of roots) {
|
|
223
225
|
if (isRootAgentIdentity(root) && typeof root.id === "string") {
|
|
224
226
|
host.lineage.activateRoot(root);
|
|
@@ -51,7 +51,6 @@ import {
|
|
|
51
51
|
*/
|
|
52
52
|
export function assembleGuards(state, caps) {
|
|
53
53
|
const { logger } = state;
|
|
54
|
-
const { agents } = state.services;
|
|
55
54
|
const { delegationTracker, forgetRootDisposed, rootUserWaitGuard } = state;
|
|
56
55
|
|
|
57
56
|
/**
|
|
@@ -64,8 +63,18 @@ export function assembleGuards(state, caps) {
|
|
|
64
63
|
state.expertReportGuardDisposers = new Map();
|
|
65
64
|
state.rootStructuredGuardStopping = false;
|
|
66
65
|
|
|
66
|
+
/**
|
|
67
|
+
* root 身份判定(不依赖宿主 roots() 枚举)。
|
|
68
|
+
*
|
|
69
|
+
* 旧实现用 `agents.roots().includes(agent)`;0.2.2-rc.2 删除 roots() 后会恒为 false,
|
|
70
|
+
* 导致 root 结构化文件 guard 在 rc.2 上完全失效。这里改用 root wait 域持有的同一份
|
|
71
|
+
* 结构身份判据(无 parentSession / 无 DEG PARENT marker),两代宿主语义一致。
|
|
72
|
+
*/
|
|
67
73
|
function isRootAgentForStructuredGuard(agent) {
|
|
68
|
-
|
|
74
|
+
// 复用双契约枚举(rc.1 roots() / rc.2 list()+身份过滤)而不是直接判定结构身份:
|
|
75
|
+
// 既保留旧实现"只把真正登记在宿主 root 集合里的 Agent 视为 root"的语义,
|
|
76
|
+
// 也避免 rc.2 上恒为 false 让 root guard 静默失效。
|
|
77
|
+
return state.listRootAgents().includes(agent);
|
|
69
78
|
}
|
|
70
79
|
/**
|
|
71
80
|
* 返回 root 结构化工具 guard 可用的 workspace root。
|
|
@@ -190,7 +199,8 @@ export function assembleGuards(state, caps) {
|
|
|
190
199
|
installRootStructuredPathGuard(agent);
|
|
191
200
|
installExpertReportGuardForAgent(agent);
|
|
192
201
|
});
|
|
193
|
-
|
|
202
|
+
// rc.2 删除 agents.roots():用双契约枚举补齐插件挂载时已存在的 root。
|
|
203
|
+
const roots = state.listRootAgents();
|
|
194
204
|
for (const agent of roots) {
|
|
195
205
|
installRootStructuredPathGuard(agent);
|
|
196
206
|
}
|
|
@@ -563,6 +563,9 @@ export function createRecoveryChildRebuild(deps) {
|
|
|
563
563
|
request,
|
|
564
564
|
label: source.label,
|
|
565
565
|
signal: op.controller?.signal,
|
|
566
|
+
// 恢复重建同样是新 activation:父 Agent 已在 dispatch 边界验证为当前存活对象,
|
|
567
|
+
// rc.2 的 exact-parent 校验依赖它。
|
|
568
|
+
parent,
|
|
566
569
|
}));
|
|
567
570
|
if (!lineage.isLiveGeneration(parent, rootToken)) throw new Error("root generation is no longer live");
|
|
568
571
|
} catch (error) {
|
|
@@ -280,6 +280,8 @@ export function createRoleToolRebuild({ records, core, identity, delegation, rec
|
|
|
280
280
|
request,
|
|
281
281
|
label,
|
|
282
282
|
signal,
|
|
283
|
+
// rc.2 要求 spec.parent 是精确存活父 Agent;同 id 的 replacement 不能被冒充。
|
|
284
|
+
parent,
|
|
283
285
|
}));
|
|
284
286
|
} catch (error) {
|
|
285
287
|
const capacityError = createSubagentCapacityError(error);
|
|
@@ -585,6 +587,8 @@ export function createRoleToolNewChild({ delegation, records, handoff, recovery,
|
|
|
585
587
|
request,
|
|
586
588
|
label,
|
|
587
589
|
signal,
|
|
590
|
+
// 只传本次工具调用已通过 isLiveGeneration 校验的 exact parent。
|
|
591
|
+
parent,
|
|
588
592
|
}));
|
|
589
593
|
} catch (error) {
|
|
590
594
|
// 容量耗尽在 admission 边界就翻译成 DEG 自有可读错误:后续清理/回滚错误
|
|
@@ -426,9 +426,9 @@ export function createExpertChannelResolver({ subagents, storage }) {
|
|
|
426
426
|
/**
|
|
427
427
|
* 宿主当前注册的 provider 名列表。
|
|
428
428
|
*
|
|
429
|
-
* rc.2
|
|
430
|
-
*
|
|
431
|
-
* provider 名。
|
|
429
|
+
* 0.2.2-rc.2 删除了该枚举 seam(只有 rc.1 及更早的 SubagentService 有 `list()`);
|
|
430
|
+
* 因此必须按「seam 不存在 → undefined」降级,调用方只按默认名 + 能力位探测。
|
|
431
|
+
* 绝不用私有 map 或猜测 provider 名。
|
|
432
432
|
*
|
|
433
433
|
* @returns {string[]|undefined} 注册名数组;seam 缺失/抛错/形状非法时 undefined。
|
|
434
434
|
*/
|
|
@@ -655,7 +655,7 @@ export function createExpertChannelResolver({ subagents, storage }) {
|
|
|
655
655
|
}
|
|
656
656
|
|
|
657
657
|
/**
|
|
658
|
-
* DEG-only
|
|
658
|
+
* DEG-only 的三代启动适配器(rc.2 扁平 startActivation / rc.1 嵌套 startActivation / legacy startContinuable)。
|
|
659
659
|
*
|
|
660
660
|
* @param {object} deps - 窄能力面。
|
|
661
661
|
* @param {object} deps.subagents - subagent 服务。
|
|
@@ -667,19 +667,45 @@ export function createExpertActivationStarter({ subagents, channel, structured }
|
|
|
667
667
|
const { contextInheritanceError, validSubagentProviderName } = channel;
|
|
668
668
|
const { armStructuredResultCapture } = structured;
|
|
669
669
|
/**
|
|
670
|
-
*
|
|
670
|
+
* 宿主 startActivation 的 spec 形状探测(只读、无副作用)。
|
|
671
671
|
*
|
|
672
|
-
*
|
|
673
|
-
*
|
|
674
|
-
*
|
|
675
|
-
*
|
|
672
|
+
* 0.2.2-rc.2 把 SubagentActivationSpec 从「request 嵌套」扁平化为直接继承
|
|
673
|
+
* SubagentStartRequest,并把 parent 提升为顶层必填字段;同一次改动新增了
|
|
674
|
+
* namesOf / rootOf / resolveName / waitForTreeWork 这些具名多层级协作 seam,并移除了
|
|
675
|
+
* list() 与 waitForChildren()。这里只做能力探测:任一 rc.2 新增的公开方法存在就按
|
|
676
|
+
* 扁平契约调用;都不存在则保持 0.2.1 / 0.2.2-rc.1 的嵌套 request 契约。
|
|
677
|
+
* 探测必须在调用 startActivation 之前完成——两代契约的 spec 形状互不兼容,猜错会让
|
|
678
|
+
* 宿主解引用 undefined.parent/.request 直接抛错。
|
|
679
|
+
*
|
|
680
|
+
* @returns {boolean} 宿主是否使用 rc.2+ 的扁平 activation spec。
|
|
681
|
+
*/
|
|
682
|
+
function activationSpecIsFlat() {
|
|
683
|
+
return typeof subagents.namesOf === "function"
|
|
684
|
+
|| typeof subagents.rootOf === "function"
|
|
685
|
+
|| typeof subagents.resolveName === "function"
|
|
686
|
+
|| typeof subagents.waitForTreeWork === "function";
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* DEG-only 的三代启动适配器。
|
|
691
|
+
*
|
|
692
|
+
* startActivation 存在时按宿主契约组装 spec:request 仅剥离 DEG 私有字段
|
|
693
|
+
* (顶层 label 与 signal 走 spec 字段,subagentProvider 只用于选择宿主 provider),
|
|
694
|
+
* 其余字段原样透传。parent 必须是**精确的存活父 Agent**——rc.2 在 service 边界用
|
|
695
|
+
* `agents.get(parent.id) === parent` 强校验,缺失会让整个派发以 TypeError 崩溃;
|
|
696
|
+
* rc.1 则从 spec.request.parent 读取同一对象。因此调用方显式传入 parent,
|
|
697
|
+
* request.parent 只作为旧调用点兜底,两代契约都写入同一个精确值。
|
|
698
|
+
*
|
|
699
|
+
* persona 与 toolFilter 是 rc.1 的 child composition 注入字段——宿主在 child scope
|
|
700
|
+
* 上应用它们(persona → child 系统提示词 section,toolFilter → childCtx.tools.restrict),
|
|
676
701
|
* 因此既不能剥离,也不能把 persona 拼进首条任务消息:任务消息只保留
|
|
677
|
-
* buildExpertTaskPrompt 生成的「身份行 + 任务内容」两段。
|
|
678
|
-
*
|
|
702
|
+
* buildExpertTaskPrompt 生成的「身份行 + 任务内容」两段。rc.2 不再从 activation spec
|
|
703
|
+
* 读取这两个字段,DEG 由 agent/created 的 composition 兜底安装同一份边界。
|
|
704
|
+
* delivery 固定为 parent,让 DSH manager 负责 parent notification 和 activation 生命周期。
|
|
679
705
|
* startActivation 本身抛错时原样上抛,只有方法不存在才回退旧 startContinuable,
|
|
680
706
|
* 避免把 admission 错误伪装成兼容路径。
|
|
681
707
|
*/
|
|
682
|
-
async function startExpertActivation({ request, label, signal }) {
|
|
708
|
+
async function startExpertActivation({ request, label, signal, parent }) {
|
|
683
709
|
// 目标 subagent provider(票据 29):唯一来源是请求上的内部字段,所有调用点
|
|
684
710
|
// (角色工具、fan-out 分片、恢复重建)在组装请求时写入同一份值。它只用于选择
|
|
685
711
|
// 宿主 provider,必须在调用宿主前剥离,绝不作为 SubagentStartRequest 字段透传。
|
|
@@ -699,13 +725,25 @@ export function createExpertActivationStarter({ subagents, channel, structured }
|
|
|
699
725
|
subagentProvider: _requestProvider,
|
|
700
726
|
...activationRequest
|
|
701
727
|
} = request ?? {};
|
|
702
|
-
|
|
728
|
+
// 精确的存活父 Agent:rc.2 的 manager 会先解引用 spec.parent.id,再做对象身份校验;
|
|
729
|
+
// 这里在插件边界 fail-closed,避免把 undefined.parent 变成宿主内部 TypeError。
|
|
730
|
+
const activationParent = parent ?? activationRequest.parent;
|
|
731
|
+
if (activationParent === null || typeof activationParent !== "object"
|
|
732
|
+
|| typeof activationParent.id !== "string" || activationParent.id.length === 0) {
|
|
733
|
+
throw new TypeError("RC startActivation requires an exact live parent agent");
|
|
734
|
+
}
|
|
735
|
+
const specBase = {
|
|
703
736
|
provider: targetProvider,
|
|
704
737
|
label: typeof label === "string" ? label : request?.label,
|
|
705
|
-
request: activationRequest,
|
|
706
738
|
signal,
|
|
707
739
|
delivery: "parent",
|
|
708
|
-
}
|
|
740
|
+
};
|
|
741
|
+
// 两代契约都携带同一份精确 parent:rc.1 读 spec.request.parent,rc.2 读 spec.parent。
|
|
742
|
+
// 未知字段(persona/toolFilter 等)在 rc.2 走本地 provider 时被忽略,行为由 DEG 的
|
|
743
|
+
// agent/created composition 兜底保证;绝不为了适配 rc.2 把 rc.1 的合同时序改掉。
|
|
744
|
+
const activation = activationSpecIsFlat()
|
|
745
|
+
? await subagents.startActivation({ ...specBase, ...activationRequest, parent: activationParent })
|
|
746
|
+
: await subagents.startActivation({ ...specBase, request: { ...activationRequest, parent: activationParent } });
|
|
709
747
|
// 结构化交付(票据 30):启动成功即挂接 result,绝不在这里 await 完整结果。
|
|
710
748
|
// request 上的 outputSchema 原样透传给宿主;child_models 只写 structured/标记。
|
|
711
749
|
armStructuredResultCapture(activation, request);
|
|
@@ -1238,8 +1238,11 @@ export function createFanoutToolHooks({ identity, childIo, core, waits, requestB
|
|
|
1238
1238
|
});
|
|
1239
1239
|
}
|
|
1240
1240
|
|
|
1241
|
-
function startContinuable({ request, signal }) {
|
|
1242
|
-
|
|
1241
|
+
function startContinuable({ request, parentAgent, signal }) {
|
|
1242
|
+
// 0.2.2-rc.2 起宿主强制 spec.parent 为精确存活父 Agent:fan-out lifecycle 已在
|
|
1243
|
+
// admission 时从 lineage 解析出 exact parentAgent(冷恢复时按 parentId 重新解析),
|
|
1244
|
+
// 这里原样透传;缺失时由 startExpertActivation 在插件边界 fail-closed。
|
|
1245
|
+
return startExpertActivation({ request, label: request.label, signal, parent: parentAgent });
|
|
1243
1246
|
}
|
|
1244
1247
|
|
|
1245
1248
|
/**
|
package/host/index-root-wait.js
CHANGED
|
@@ -199,6 +199,37 @@ function installRootWaitCore(deps) {
|
|
|
199
199
|
&& agent.options?.[PARENT_MARKER] === void 0;
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
/**
|
|
203
|
+
* 当前存活 root Agent 快照(rc.1 roots() / rc.2 list() 双契约)。
|
|
204
|
+
*
|
|
205
|
+
* 0.2.2-rc.2 删除了 `AgentRegistry.roots()`,只保留 `list()`(全部 live agent);
|
|
206
|
+
* 插件必须在两代宿主上给出同一份「可枚举 root」事实:优先用 rc.1 的精确 roots(),
|
|
207
|
+
* 缺失时用 rc.2 的 list() 再按 DEG 自己的 root 身份判定过滤(无 parentSession、
|
|
208
|
+
* 无 DEG PARENT marker)。两个 seam 都缺失或抛错时返回空数组——与旧实现
|
|
209
|
+
* `typeof agents.roots !== "function" → []` 的降级语义一致,绝不猜测或伪造 root。
|
|
210
|
+
*
|
|
211
|
+
* @returns {Array<object>} root Agent 只读快照。
|
|
212
|
+
*/
|
|
213
|
+
function listRootAgents() {
|
|
214
|
+
try {
|
|
215
|
+
if (typeof agents?.roots === "function") {
|
|
216
|
+
const roots = agents.roots();
|
|
217
|
+
return Array.isArray(roots) ? roots : [];
|
|
218
|
+
}
|
|
219
|
+
if (typeof agents?.list === "function") {
|
|
220
|
+
const all = agents.list();
|
|
221
|
+
// list() 的契约是 Agent 数组;仍先挡 null/非对象,避免身份判定在坏快照上抛错
|
|
222
|
+
// 被外层 catch 静默吞成"没有 root"(丢失可诊断性)。
|
|
223
|
+
return Array.isArray(all)
|
|
224
|
+
? all.filter((agent) => agent !== null && typeof agent === "object" && isRootAgentIdentity(agent))
|
|
225
|
+
: [];
|
|
226
|
+
}
|
|
227
|
+
} catch (error) {
|
|
228
|
+
logTurnWaitError("list roots", error);
|
|
229
|
+
}
|
|
230
|
+
return [];
|
|
231
|
+
}
|
|
232
|
+
|
|
202
233
|
function isLiveRootAgent(agent) {
|
|
203
234
|
return host.lineage.isLiveRoot(agent);
|
|
204
235
|
}
|
|
@@ -361,6 +392,7 @@ function installRootWaitCore(deps) {
|
|
|
361
392
|
safeErrorLabel,
|
|
362
393
|
logTurnWaitError,
|
|
363
394
|
isRootAgentIdentity,
|
|
395
|
+
listRootAgents,
|
|
364
396
|
isLiveRootAgent,
|
|
365
397
|
invalidateRootWaitId,
|
|
366
398
|
invalidateWaitersForAgentActivity,
|