@khorsheed/dsh-local-agent 0.1.0-rc.8 → 0.2.0-rc.1
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 +4 -0
- package/README.en.md +1 -1
- package/README.i18n.yaml +2 -2
- package/README.md +1 -1
- package/lib/client.js +78 -78
- package/lib/tool-factory.js +256 -0
- package/lib/typert.host.js +17 -109
- package/lib/typert.remote-client.js +15 -15
- package/lib/types/tool-factory.d.ts +70 -0
- package/lib/types/tool-factory.js +324 -0
- package/package.json +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# 变更记录
|
|
2
2
|
|
|
3
|
+
## 0.2.0-rc.1(2026-09-30)
|
|
4
|
+
|
|
5
|
+
- **家族折叠:委派工具工厂收进本包**。新增 `./tool-factory` 导出(`mountSubagentDelegationTool` / `subagentToolConfigSchema` / `SubagentToolConfig` / `RESUME_HINT_PREFIX`)——原共享包 `@khorsheed/dsh-local-agent-tool-subagent` 的实现整体迁入,该包随之退役。各 provider 的委派工具改为各自包内的 `./tool` 组合入口(`@khorsheed/dsh-local-agent-kimi/tool` 等),由 agent 预设点名按会话授予,不再挂 profile 根;工具来源标签的 owner 由调用入口传自己包名,工厂不再硬编码。随工厂迁入新增 peer 依赖 `@deepseek-ai/dsh-tools`。
|
|
6
|
+
|
|
3
7
|
## 0.1.0-rc.8(2026-09-30)
|
|
4
8
|
|
|
5
9
|
家族同版联动:加宽 `@deepseek-ai/dsh-*` peer 区间以覆盖宿主 0.2.0(0.2.0 的兼容闸会禁用 peer 区间不覆盖宿主版本的已装插件)。无功能变更。
|
package/README.en.md
CHANGED
|
@@ -111,7 +111,7 @@ export function registerCodex(ctx: Context): void {
|
|
|
111
111
|
|
|
112
112
|
### Delegation registry (resume carrier)
|
|
113
113
|
|
|
114
|
-
The registry also owns the family's **delegation registry**: a per-child-session record of which provider and CLI session a delegation used, plus a per-(parent, provider) FIFO of delegation intents. The family tool (`@khorsheed/dsh-local-agent-tool-subagent
|
|
114
|
+
The registry also owns the family's **delegation registry**: a per-child-session record of which provider and CLI session a delegation used, plus a per-(parent, provider) FIFO of delegation intents. The family tool (each provider package's `./tool` composition entry, sharing this package's `./tool-factory` export — the former `@khorsheed/dsh-local-agent-tool-subagent` package retired at the family fold) stages exactly one intent per call before `ctx.subagents.start()`, and the owning provider consumes exactly one per start — so fresh and resume rounds stay paired even under parallel delegation. A resume handle (the dsh child session id) resolves through the registry, which rejects a handle naming an unknown child, another parent's session, or the wrong provider; the subagent request descriptor cannot carry the target, so this service is the family-internal carrier. Mappings persist per harness in an append-only `delegations.jsonl` under the harness's scoped home (last line per child session wins), so a resume handle survives a host restart.
|
|
115
115
|
|
|
116
116
|
### Delegation call options (facade)
|
|
117
117
|
|
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# last confirmed-consistent state. Both languages carry equal authority; after
|
|
3
3
|
# editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/local-agent/README.en.md
|
|
5
|
-
packages/local-agent/README.en.md:
|
|
6
|
-
packages/local-agent/README.md:
|
|
5
|
+
packages/local-agent/README.en.md: 94e1222b1d0da755b9d1bdd1cbf3d3561dafa033
|
|
6
|
+
packages/local-agent/README.md: d63cf0d8cceadf5c2b6d159c3c638341358e2b3a
|
package/README.md
CHANGED
|
@@ -111,7 +111,7 @@ export function registerCodex(ctx: Context): void {
|
|
|
111
111
|
|
|
112
112
|
### 委派 registry(resume 载体)
|
|
113
113
|
|
|
114
|
-
registry 还持有家族的**委派 registry**:每个子会话一条记录,记下该委派用的 provider 与 CLI 会话,以及按 (parent, provider) 分组的委派 intent FIFO
|
|
114
|
+
registry 还持有家族的**委派 registry**:每个子会话一条记录,记下该委派用的 provider 与 CLI 会话,以及按 (parent, provider) 分组的委派 intent FIFO。家族工具(各 provider 包的 `./tool` 组合入口,实现共享自本包的 `./tool-factory` 导出——原 `@khorsheed/dsh-local-agent-tool-subagent` 已于家族折叠退役)在每次调用 `ctx.subagents.start()` 前恰好 stage 一个 intent,归属 provider 每次 start 恰好消费一个——因此即使并行委派,fresh 轮与 resume 轮也能正确配对。resume 轮的句柄(dsh 子会话 id)经 registry 解析,凡是未知子会话、他人 parent 的会话、或错误 provider 的句柄都会被拒绝;subagent 请求 descriptor 无法携带该目标,因此本服务就是家族内部的载体。映射按 harness 持久化在其作用域目录下的 append-only `delegations.jsonl`(同一子会话最后一行生效),resume 句柄因此能跨宿主重启存活。
|
|
115
115
|
|
|
116
116
|
### 委派调用选项(facade)
|
|
117
117
|
|
package/lib/client.js
CHANGED
|
@@ -165,17 +165,17 @@ window.__ModuleLoader__.load({
|
|
|
165
165
|
document.head.appendChild(tag);
|
|
166
166
|
}
|
|
167
167
|
var MemberConfiguration_module_css_default = {
|
|
168
|
-
"
|
|
169
|
-
"triggerLabel": "pkplGa_triggerLabel",
|
|
170
|
-
"optionLabel": "pkplGa_optionLabel",
|
|
168
|
+
"actions": "pkplGa_actions",
|
|
171
169
|
"candidates": "pkplGa_candidates",
|
|
172
|
-
"
|
|
170
|
+
"root": "pkplGa_root",
|
|
171
|
+
"optionLabel": "pkplGa_optionLabel",
|
|
172
|
+
"triggerLabel": "pkplGa_triggerLabel",
|
|
173
|
+
"panel": "pkplGa_panel",
|
|
174
|
+
"settings": "pkplGa_settings",
|
|
173
175
|
"menuRow": "pkplGa_menuRow",
|
|
176
|
+
"back": "pkplGa_back",
|
|
174
177
|
"check": "pkplGa_check",
|
|
175
|
-
"
|
|
176
|
-
"panel": "pkplGa_panel",
|
|
177
|
-
"actions": "pkplGa_actions",
|
|
178
|
-
"root": "pkplGa_root"
|
|
178
|
+
"fields": "pkplGa_fields"
|
|
179
179
|
};
|
|
180
180
|
//#endregion
|
|
181
181
|
//#region src/client/ModelConfigurationFields.tsx
|
|
@@ -6046,12 +6046,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6046
6046
|
"requestId": string(),
|
|
6047
6047
|
"revision": number(),
|
|
6048
6048
|
"status": union([
|
|
6049
|
-
literal("cancelled"),
|
|
6050
6049
|
literal("pending"),
|
|
6051
6050
|
literal("applying"),
|
|
6052
6051
|
literal("failed"),
|
|
6053
6052
|
literal("unsupported"),
|
|
6054
6053
|
literal("applied"),
|
|
6054
|
+
literal("cancelled"),
|
|
6055
6055
|
literal("conflict"),
|
|
6056
6056
|
literal("locked")
|
|
6057
6057
|
]),
|
|
@@ -6071,8 +6071,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6071
6071
|
let _khorsheed_dsh_local_agent_localAgentGateway_controlMemberInbox_parameter_3$schema$value;
|
|
6072
6072
|
const _khorsheed_dsh_local_agent_localAgentGateway_controlMemberInbox_parameter_3$schema = () => _khorsheed_dsh_local_agent_localAgentGateway_controlMemberInbox_parameter_3$schema$value ??= union([
|
|
6073
6073
|
_undefined(),
|
|
6074
|
-
literal("
|
|
6075
|
-
literal("
|
|
6074
|
+
literal("cancelled"),
|
|
6075
|
+
literal("done")
|
|
6076
6076
|
]);
|
|
6077
6077
|
let _khorsheed_dsh_local_agent_localAgentGateway_controlMemberInbox_parameter_4$schema$value;
|
|
6078
6078
|
const _khorsheed_dsh_local_agent_localAgentGateway_controlMemberInbox_parameter_4$schema = () => _khorsheed_dsh_local_agent_localAgentGateway_controlMemberInbox_parameter_4$schema$value ??= union([_undefined(), string()]);
|
|
@@ -6205,10 +6205,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6205
6205
|
let _khorsheed_dsh_local_agent_localAgentGateway_followMemberDirectory_result$schema$value;
|
|
6206
6206
|
const _khorsheed_dsh_local_agent_localAgentGateway_followMemberDirectory_result$schema = () => _khorsheed_dsh_local_agent_localAgentGateway_followMemberDirectory_result$schema$value ??= object({
|
|
6207
6207
|
"status": union([
|
|
6208
|
-
literal("stale"),
|
|
6209
|
-
literal("error"),
|
|
6210
6208
|
literal("loading"),
|
|
6211
6209
|
literal("ready"),
|
|
6210
|
+
literal("stale"),
|
|
6211
|
+
literal("error"),
|
|
6212
6212
|
literal("unsupported")
|
|
6213
6213
|
]),
|
|
6214
6214
|
"refreshing": boolean(),
|
|
@@ -6249,7 +6249,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6249
6249
|
"id": string(),
|
|
6250
6250
|
"turn": number(),
|
|
6251
6251
|
"step": number(),
|
|
6252
|
-
"kind": union([literal("
|
|
6252
|
+
"kind": union([literal("think"), literal("text")]),
|
|
6253
6253
|
"text": string(),
|
|
6254
6254
|
"revision": number(),
|
|
6255
6255
|
"receivedAt": number()
|
|
@@ -6260,8 +6260,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6260
6260
|
const _khorsheed_dsh_local_agent_localAgentGateway_followMembers_parameter_0$schema = () => _khorsheed_dsh_local_agent_localAgentGateway_followMembers_parameter_0$schema$value ??= array(object({
|
|
6261
6261
|
"memberId": string(),
|
|
6262
6262
|
"channel": union([
|
|
6263
|
-
literal("directory"),
|
|
6264
6263
|
literal("configuration"),
|
|
6264
|
+
literal("directory"),
|
|
6265
6265
|
literal("output")
|
|
6266
6266
|
])
|
|
6267
6267
|
}));
|
|
@@ -6389,10 +6389,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6389
6389
|
"channel": literal("directory"),
|
|
6390
6390
|
"value": object({
|
|
6391
6391
|
"status": union([
|
|
6392
|
-
literal("stale"),
|
|
6393
|
-
literal("error"),
|
|
6394
6392
|
literal("loading"),
|
|
6395
6393
|
literal("ready"),
|
|
6394
|
+
literal("stale"),
|
|
6395
|
+
literal("error"),
|
|
6396
6396
|
literal("unsupported")
|
|
6397
6397
|
]),
|
|
6398
6398
|
"refreshing": boolean(),
|
|
@@ -6434,7 +6434,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6434
6434
|
"id": string(),
|
|
6435
6435
|
"turn": number(),
|
|
6436
6436
|
"step": number(),
|
|
6437
|
-
"kind": union([literal("
|
|
6437
|
+
"kind": union([literal("think"), literal("text")]),
|
|
6438
6438
|
"text": string(),
|
|
6439
6439
|
"revision": number(),
|
|
6440
6440
|
"receivedAt": number()
|
|
@@ -6446,8 +6446,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6446
6446
|
"memberId": string(),
|
|
6447
6447
|
"channel": literal("error"),
|
|
6448
6448
|
"source": union([
|
|
6449
|
-
literal("directory"),
|
|
6450
6449
|
literal("configuration"),
|
|
6450
|
+
literal("directory"),
|
|
6451
6451
|
literal("output")
|
|
6452
6452
|
]),
|
|
6453
6453
|
"message": string()
|
|
@@ -6460,10 +6460,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6460
6460
|
let _khorsheed_dsh_local_agent_localAgentGateway_followModelDirectory_result$schema$value;
|
|
6461
6461
|
const _khorsheed_dsh_local_agent_localAgentGateway_followModelDirectory_result$schema = () => _khorsheed_dsh_local_agent_localAgentGateway_followModelDirectory_result$schema$value ??= object({
|
|
6462
6462
|
"status": union([
|
|
6463
|
-
literal("stale"),
|
|
6464
|
-
literal("error"),
|
|
6465
6463
|
literal("loading"),
|
|
6466
6464
|
literal("ready"),
|
|
6465
|
+
literal("stale"),
|
|
6466
|
+
literal("error"),
|
|
6467
6467
|
literal("unsupported")
|
|
6468
6468
|
]),
|
|
6469
6469
|
"refreshing": boolean(),
|
|
@@ -6628,10 +6628,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6628
6628
|
"choices": array(string()),
|
|
6629
6629
|
"directory": object({
|
|
6630
6630
|
"status": union([
|
|
6631
|
-
literal("stale"),
|
|
6632
|
-
literal("error"),
|
|
6633
6631
|
literal("loading"),
|
|
6634
6632
|
literal("ready"),
|
|
6633
|
+
literal("stale"),
|
|
6634
|
+
literal("error"),
|
|
6635
6635
|
literal("unsupported")
|
|
6636
6636
|
]),
|
|
6637
6637
|
"refreshing": boolean(),
|
|
@@ -6790,10 +6790,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6790
6790
|
let _khorsheed_dsh_local_agent_localAgentGateway_memberDirectory_result$schema$value;
|
|
6791
6791
|
const _khorsheed_dsh_local_agent_localAgentGateway_memberDirectory_result$schema = () => _khorsheed_dsh_local_agent_localAgentGateway_memberDirectory_result$schema$value ??= union([literal(null), object({
|
|
6792
6792
|
"status": union([
|
|
6793
|
-
literal("stale"),
|
|
6794
|
-
literal("error"),
|
|
6795
6793
|
literal("loading"),
|
|
6796
6794
|
literal("ready"),
|
|
6795
|
+
literal("stale"),
|
|
6796
|
+
literal("error"),
|
|
6797
6797
|
literal("unsupported")
|
|
6798
6798
|
]),
|
|
6799
6799
|
"refreshing": boolean(),
|
|
@@ -6836,11 +6836,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6836
6836
|
"id": string(),
|
|
6837
6837
|
"text": string(),
|
|
6838
6838
|
"status": union([
|
|
6839
|
-
literal("running"),
|
|
6840
|
-
literal("done"),
|
|
6841
|
-
literal("cancelled"),
|
|
6842
6839
|
literal("failed"),
|
|
6840
|
+
literal("cancelled"),
|
|
6843
6841
|
literal("queued"),
|
|
6842
|
+
literal("running"),
|
|
6843
|
+
literal("done"),
|
|
6844
6844
|
literal("uncertain")
|
|
6845
6845
|
]),
|
|
6846
6846
|
"createdAt": number(),
|
|
@@ -6981,10 +6981,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6981
6981
|
"choices": array(string()),
|
|
6982
6982
|
"directory": object({
|
|
6983
6983
|
"status": union([
|
|
6984
|
-
literal("stale"),
|
|
6985
|
-
literal("error"),
|
|
6986
6984
|
literal("loading"),
|
|
6987
6985
|
literal("ready"),
|
|
6986
|
+
literal("stale"),
|
|
6987
|
+
literal("error"),
|
|
6988
6988
|
literal("unsupported")
|
|
6989
6989
|
]),
|
|
6990
6990
|
"refreshing": boolean(),
|
|
@@ -7038,10 +7038,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7038
7038
|
let _khorsheed_dsh_local_agent_localAgentGateway_modelDirectory_result$schema$value;
|
|
7039
7039
|
const _khorsheed_dsh_local_agent_localAgentGateway_modelDirectory_result$schema = () => _khorsheed_dsh_local_agent_localAgentGateway_modelDirectory_result$schema$value ??= union([literal(null), object({
|
|
7040
7040
|
"status": union([
|
|
7041
|
-
literal("stale"),
|
|
7042
|
-
literal("error"),
|
|
7043
7041
|
literal("loading"),
|
|
7044
7042
|
literal("ready"),
|
|
7043
|
+
literal("stale"),
|
|
7044
|
+
literal("error"),
|
|
7045
7045
|
literal("unsupported")
|
|
7046
7046
|
]),
|
|
7047
7047
|
"refreshing": boolean(),
|
|
@@ -7120,12 +7120,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7120
7120
|
"requestId": string(),
|
|
7121
7121
|
"revision": number(),
|
|
7122
7122
|
"status": union([
|
|
7123
|
-
literal("cancelled"),
|
|
7124
7123
|
literal("pending"),
|
|
7125
7124
|
literal("applying"),
|
|
7126
7125
|
literal("failed"),
|
|
7127
7126
|
literal("unsupported"),
|
|
7128
7127
|
literal("applied"),
|
|
7128
|
+
literal("cancelled"),
|
|
7129
7129
|
literal("conflict"),
|
|
7130
7130
|
literal("locked")
|
|
7131
7131
|
]),
|
|
@@ -8277,29 +8277,29 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8277
8277
|
document.head.appendChild(tag);
|
|
8278
8278
|
}
|
|
8279
8279
|
var MemberComposer_module_css_default = {
|
|
8280
|
-
"modelChipLabel": "_7o4e8W_modelChipLabel",
|
|
8281
|
-
"modelPicker": "_7o4e8W_modelPicker",
|
|
8282
|
-
"modelItem": "_7o4e8W_modelItem",
|
|
8283
|
-
"input": "_7o4e8W_input",
|
|
8284
|
-
"frame": "_7o4e8W_frame",
|
|
8285
8280
|
"root": "_7o4e8W_root",
|
|
8281
|
+
"error": "_7o4e8W_error",
|
|
8282
|
+
"dock": "_7o4e8W_dock",
|
|
8283
|
+
"modelMenu": "_7o4e8W_modelMenu",
|
|
8284
|
+
"modelItemReset": "_7o4e8W_modelItemReset",
|
|
8285
|
+
"modelItemHint": "_7o4e8W_modelItemHint",
|
|
8286
|
+
"card": "_7o4e8W_card",
|
|
8287
|
+
"frame": "_7o4e8W_frame",
|
|
8288
|
+
"modelPicker": "_7o4e8W_modelPicker",
|
|
8289
|
+
"modelChipLabel": "_7o4e8W_modelChipLabel",
|
|
8290
|
+
"chevron": "_7o4e8W_chevron",
|
|
8286
8291
|
"row": "_7o4e8W_row",
|
|
8287
8292
|
"header": "_7o4e8W_header",
|
|
8288
|
-
"chevron": "_7o4e8W_chevron",
|
|
8289
|
-
"primary": "_7o4e8W_primary",
|
|
8290
|
-
"modelItemCheck": "_7o4e8W_modelItemCheck",
|
|
8291
|
-
"modelItemReset": "_7o4e8W_modelItemReset",
|
|
8292
8293
|
"modelChip": "_7o4e8W_modelChip",
|
|
8293
|
-
"modelMenu": "_7o4e8W_modelMenu",
|
|
8294
|
-
"dockRow": "_7o4e8W_dockRow",
|
|
8295
|
-
"error": "_7o4e8W_error",
|
|
8296
|
-
"modelItemHint": "_7o4e8W_modelItemHint",
|
|
8297
|
-
"dock": "_7o4e8W_dock",
|
|
8298
|
-
"running": "_7o4e8W_running",
|
|
8299
|
-
"chevronOpen": "_7o4e8W_chevronOpen",
|
|
8300
8294
|
"modelItemCurrent": "_7o4e8W_modelItemCurrent",
|
|
8301
8295
|
"modelItemLabel": "_7o4e8W_modelItemLabel",
|
|
8302
|
-
"
|
|
8296
|
+
"running": "_7o4e8W_running",
|
|
8297
|
+
"modelItem": "_7o4e8W_modelItem",
|
|
8298
|
+
"modelItemCheck": "_7o4e8W_modelItemCheck",
|
|
8299
|
+
"chevronOpen": "_7o4e8W_chevronOpen",
|
|
8300
|
+
"dockRow": "_7o4e8W_dockRow",
|
|
8301
|
+
"input": "_7o4e8W_input",
|
|
8302
|
+
"primary": "_7o4e8W_primary"
|
|
8303
8303
|
};
|
|
8304
8304
|
//#endregion
|
|
8305
8305
|
//#region src/client/MemberComposer.tsx
|
|
@@ -9360,30 +9360,30 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9360
9360
|
document.head.appendChild(tag);
|
|
9361
9361
|
}
|
|
9362
9362
|
var ProviderAuthBlock_module_css_default = {
|
|
9363
|
-
"
|
|
9364
|
-
"rowName": "On5p7W_rowName",
|
|
9363
|
+
"status": "On5p7W_status",
|
|
9365
9364
|
"retryButton": "On5p7W_retryButton",
|
|
9366
|
-
"
|
|
9367
|
-
"
|
|
9368
|
-
"codeInput": "On5p7W_codeInput",
|
|
9369
|
-
"dotOn": "On5p7W_dotOn",
|
|
9370
|
-
"intro": "On5p7W_intro",
|
|
9365
|
+
"credentialDot": "On5p7W_credentialDot",
|
|
9366
|
+
"promptText": "On5p7W_promptText",
|
|
9371
9367
|
"rowTag": "On5p7W_rowTag",
|
|
9372
|
-
"
|
|
9373
|
-
"
|
|
9374
|
-
"status": "On5p7W_status",
|
|
9375
|
-
"rows": "On5p7W_rows",
|
|
9376
|
-
"logoutButton": "On5p7W_logoutButton",
|
|
9368
|
+
"rowCard": "On5p7W_rowCard",
|
|
9369
|
+
"rowName": "On5p7W_rowName",
|
|
9377
9370
|
"openPage": "On5p7W_openPage",
|
|
9371
|
+
"logoutButton": "On5p7W_logoutButton",
|
|
9372
|
+
"rowPending": "On5p7W_rowPending",
|
|
9373
|
+
"dotOn": "On5p7W_dotOn",
|
|
9378
9374
|
"section": "On5p7W_section",
|
|
9379
|
-
"loginPrompt": "On5p7W_loginPrompt",
|
|
9380
|
-
"promptText": "On5p7W_promptText",
|
|
9381
9375
|
"dotOff": "On5p7W_dotOff",
|
|
9382
|
-
"loginButton": "On5p7W_loginButton",
|
|
9383
|
-
"rowIdentity": "On5p7W_rowIdentity",
|
|
9384
9376
|
"rowHead": "On5p7W_rowHead",
|
|
9377
|
+
"rowActions": "On5p7W_rowActions",
|
|
9378
|
+
"title": "On5p7W_title",
|
|
9379
|
+
"loginButton": "On5p7W_loginButton",
|
|
9380
|
+
"loginPrompt": "On5p7W_loginPrompt",
|
|
9381
|
+
"codeInput": "On5p7W_codeInput",
|
|
9382
|
+
"rows": "On5p7W_rows",
|
|
9383
|
+
"intro": "On5p7W_intro",
|
|
9384
|
+
"dotPending": "On5p7W_dotPending",
|
|
9385
9385
|
"rosterError": "On5p7W_rosterError",
|
|
9386
|
-
"
|
|
9386
|
+
"rowIdentity": "On5p7W_rowIdentity"
|
|
9387
9387
|
};
|
|
9388
9388
|
//#endregion
|
|
9389
9389
|
//#region src/client/ProviderAuthBlock.tsx
|
|
@@ -9656,10 +9656,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9656
9656
|
document.head.appendChild(tag);
|
|
9657
9657
|
}
|
|
9658
9658
|
var AuthStatusDot_module_css_default = {
|
|
9659
|
-
"credentialDot": "OFjNUG_credentialDot",
|
|
9660
9659
|
"dotOn": "OFjNUG_dotOn",
|
|
9661
|
-
"
|
|
9662
|
-
"
|
|
9660
|
+
"dotOff": "OFjNUG_dotOff",
|
|
9661
|
+
"credentialDot": "OFjNUG_credentialDot",
|
|
9662
|
+
"dotPending": "OFjNUG_dotPending"
|
|
9663
9663
|
};
|
|
9664
9664
|
//#endregion
|
|
9665
9665
|
//#region src/client/AuthStatusDot.tsx
|
|
@@ -9685,18 +9685,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9685
9685
|
document.head.appendChild(tag);
|
|
9686
9686
|
}
|
|
9687
9687
|
var MemberInboxView_module_css_default = {
|
|
9688
|
-
"
|
|
9689
|
-
"
|
|
9690
|
-
"notice": "Qhm0ea_notice",
|
|
9691
|
-
"recovery": "Qhm0ea_recovery",
|
|
9688
|
+
"lead": "Qhm0ea_lead",
|
|
9689
|
+
"row": "Qhm0ea_row",
|
|
9692
9690
|
"action": "Qhm0ea_action",
|
|
9693
|
-
"root": "Qhm0ea_root",
|
|
9694
|
-
"panel": "Qhm0ea_panel",
|
|
9695
9691
|
"reconcile": "Qhm0ea_reconcile",
|
|
9696
9692
|
"header": "Qhm0ea_header",
|
|
9697
|
-
"
|
|
9698
|
-
"
|
|
9693
|
+
"notice": "Qhm0ea_notice",
|
|
9694
|
+
"list": "Qhm0ea_list",
|
|
9695
|
+
"iconAction": "Qhm0ea_iconAction",
|
|
9696
|
+
"root": "Qhm0ea_root",
|
|
9697
|
+
"recovery": "Qhm0ea_recovery",
|
|
9699
9698
|
"preview": "Qhm0ea_preview",
|
|
9699
|
+
"panel": "Qhm0ea_panel",
|
|
9700
9700
|
"toggle": "Qhm0ea_toggle"
|
|
9701
9701
|
};
|
|
9702
9702
|
//#endregion
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import z from "@deepseek-ai/schemastery";
|
|
2
|
+
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
3
|
+
//#region lib/types/tool-factory.js
|
|
4
|
+
/**
|
|
5
|
+
* The family-owned delegation-tool factory: the model-facing subagent tool
|
|
6
|
+
* over one configured `ctx.subagents` provider, replacing the official
|
|
7
|
+
* tool-subagent rows in the harness bundles. The schema is the official subset
|
|
8
|
+
* (`description`/`prompt`) plus an optional `resume` handle: the dsh child
|
|
9
|
+
* session id returned by the first delegation's result text. A resumed call
|
|
10
|
+
* continues the SAME CLI conversation instead of starting a fresh one — the
|
|
11
|
+
* family providers spawn their CLI's resume command (kimi `-S`, claude
|
|
12
|
+
* `--resume`, codex `exec resume`) under the harness scoped home, appending
|
|
13
|
+
* the new round into the same dsh child session.
|
|
14
|
+
*
|
|
15
|
+
* The resume target never travels inside the prompt: task text is untrusted,
|
|
16
|
+
* and a forged handle embedded there would hijack another session's context.
|
|
17
|
+
* The tool instead carries the handle as a first-class `resume` parameter and
|
|
18
|
+
* resolves it through the localAgent service, which rejects any handle that
|
|
19
|
+
* does not name a delegation recorded for THIS parent session and provider.
|
|
20
|
+
* Continuation rounds still go through `ctx.subagents.start()`, so lifecycle
|
|
21
|
+
* events (`subagent/start`/`subagent/end`) and the standard 子代理 surface are
|
|
22
|
+
* unchanged.
|
|
23
|
+
*
|
|
24
|
+
* This module used to ship as the standalone companion package
|
|
25
|
+
* `@khorsheed/dsh-local-agent-tool-subagent` (0.1.x); the family fold moved it
|
|
26
|
+
* into the core package as the `./tool-factory` export (the worktrees 0.3.0 /
|
|
27
|
+
* room 0.2.0 pattern, one level down: the mountable row is each PROVIDER's own
|
|
28
|
+
* `./tool` composition entry, which binds its provider/toolName defaults and
|
|
29
|
+
* passes its package name as the tool-origin owner). `local-agent-dsh`
|
|
30
|
+
* consumes the same factory for its settings-driven dynamic `subagent_dsh`
|
|
31
|
+
* mount. The factory itself is never a loader row.
|
|
32
|
+
*
|
|
33
|
+
* @module @khorsheed/dsh-local-agent/tool-factory
|
|
34
|
+
*/
|
|
35
|
+
/**
|
|
36
|
+
* Tag the model-visible tool with its origin (AGENTS.md § Tool origin tagging;
|
|
37
|
+
* seam S12): the capability catalog reads this `Symbol.for`-keyed tag back
|
|
38
|
+
* through `ctx.tools.get()`. This factory registers on behalf of every family
|
|
39
|
+
* provider, so the owner arrives as a PARAMETER — the calling entry's own
|
|
40
|
+
* package identity — never a hardcoded package name. The tag is host-side
|
|
41
|
+
* only and never travels on the model wire.
|
|
42
|
+
*/
|
|
43
|
+
const definePluginTool = (def, owner) => Object.assign(def, { [Symbol.for("dsh.tool.origin")]: {
|
|
44
|
+
channel: "plugin",
|
|
45
|
+
owner
|
|
46
|
+
} });
|
|
47
|
+
/**
|
|
48
|
+
* Model-visible self-description appended to a FRESH delegation's result, so
|
|
49
|
+
* the model can continue the same conversation in a later round. Pinned
|
|
50
|
+
* verbatim; the resume tool's `resume` parameter carries the handle.
|
|
51
|
+
*/
|
|
52
|
+
const RESUME_HINT_PREFIX = "追问请带 resume=\"";
|
|
53
|
+
/**
|
|
54
|
+
* The Config schema of a provider's `./tool` composition entry: every field
|
|
55
|
+
* optional, defaulting to the CALLING provider's own values, so a preset row
|
|
56
|
+
* needs no config (`- id: tool-subagent-kimi / name:
|
|
57
|
+
* '@khorsheed/dsh-local-agent-kimi/tool'` mounts the kimi delegation tool).
|
|
58
|
+
*
|
|
59
|
+
* Bare `z` return annotation: `z<Config>` fails schemastery 3.18.4's variance
|
|
60
|
+
* under exactOptionalPropertyTypes (TS2375) and dropping the annotation trips
|
|
61
|
+
* TS2742; the interface stays the apply signature's contract.
|
|
62
|
+
*/
|
|
63
|
+
function subagentToolConfigSchema(provider, toolName) {
|
|
64
|
+
return z.object({
|
|
65
|
+
provider: z.string().default(provider),
|
|
66
|
+
toolName: z.string().default(toolName)
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/** Render text blocks from the canonical JSON block array without trusting arbitrary values. */
|
|
70
|
+
function outputValueText(values) {
|
|
71
|
+
return values.filter((value) => typeof value === "object" && value !== null && !Array.isArray(value) && value.type === "text" && typeof value.text === "string").map((value) => value.text).join("");
|
|
72
|
+
}
|
|
73
|
+
/** A non-`completed` stop reason means the child did not finish cleanly. */
|
|
74
|
+
function stopReasonError(result) {
|
|
75
|
+
switch (result.stopReason) {
|
|
76
|
+
case "completed": return;
|
|
77
|
+
case "aborted": return "subagent run was cancelled";
|
|
78
|
+
case "error": return result.diagnostic === void 0 ? "subagent run failed" : `subagent run failed: ${result.diagnostic}`;
|
|
79
|
+
case "max-tokens": return "subagent run hit its token limit before finishing";
|
|
80
|
+
case "refusal": return "subagent declined the task";
|
|
81
|
+
default: return `subagent run ended abnormally (${String(result.stopReason)})`;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Fuse a caller-owned controller with the tool execution's signal so EITHER
|
|
86
|
+
* abort cancels the run — the same shape the facade's tracked controller
|
|
87
|
+
* uses. The active-delegation registry's stop lever aborts the controller;
|
|
88
|
+
* the tool's own execution abort flows through the execution signal.
|
|
89
|
+
*/
|
|
90
|
+
function fusedSignal(controller, caller) {
|
|
91
|
+
return caller === void 0 ? controller.signal : AbortSignal.any([controller.signal, caller]);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Append the child's preserved partial answer to a stop-reason error so a
|
|
95
|
+
* truncated or cancelled child's real text still reaches the parent model.
|
|
96
|
+
* @param error - the stop-reason headline.
|
|
97
|
+
* @param output - the child's selected output (`SubagentResult.output`).
|
|
98
|
+
* @returns the headline, extended with the partial text when any exists.
|
|
99
|
+
*/
|
|
100
|
+
function withPartialText(error, output) {
|
|
101
|
+
const text = output.filter((block) => block.type === "text").map((block) => block.text).join("");
|
|
102
|
+
return text.length === 0 ? error : `${error}\nPartial output before the run ended:\n${text}`;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Collect and release one foreground run without letting disposal replace an
|
|
106
|
+
* independent result failure.
|
|
107
|
+
*/
|
|
108
|
+
async function settleForegroundRun(run) {
|
|
109
|
+
const [execution] = await Promise.allSettled([run.result.then((result) => {
|
|
110
|
+
const error = stopReasonError(result);
|
|
111
|
+
if (error !== void 0) throw new Error(withPartialText(error, result.output));
|
|
112
|
+
return {
|
|
113
|
+
kind: "foreground",
|
|
114
|
+
runId: run.id,
|
|
115
|
+
output: result.output
|
|
116
|
+
};
|
|
117
|
+
})]);
|
|
118
|
+
const [disposal] = await Promise.allSettled([Promise.resolve().then(() => run.dispose())]);
|
|
119
|
+
if (execution.status === "rejected") {
|
|
120
|
+
if (disposal.status === "rejected") throw new AggregateError([execution.reason, disposal.reason], `subagent run failed: ${String(execution.reason)}; dispose failed: ${String(disposal.reason)}`);
|
|
121
|
+
throw execution.reason;
|
|
122
|
+
}
|
|
123
|
+
if (disposal.status === "rejected") throw disposal.reason;
|
|
124
|
+
return execution.value;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Model-facing wording for the family CLI providers, which never inherit the
|
|
128
|
+
* parent's conversation (they are fresh CLI processes under a scoped home).
|
|
129
|
+
*/
|
|
130
|
+
function familyWording() {
|
|
131
|
+
return {
|
|
132
|
+
description: "Delegate a self-contained task to a local coding-agent CLI (separate process, its own scoped home) so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. To continue the same CLI conversation in a later round, pass the child session id returned by the first result as `resume`. This is the one-shot path — it fits a task you will not revisit. When you expect to work with the SAME agent over several rounds (review → fix → re-review style iteration) and the `room_invite` tool is available, prefer inviting it as a named room member instead: name it by its function (e.g. \"design-review\", \"restart-test\") so later rounds can address it by role and reuse the context it has accumulated.",
|
|
133
|
+
promptDescription: "The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. Never embed a resume handle inside this text.",
|
|
134
|
+
resumeDescription: "Optional dsh child session id returned by the first delegation's result text, to continue that same CLI conversation in a later round. Omit for a fresh delegation. Never embed the handle inside `prompt` — pass it here."
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Mount the family delegation tool on one provider: register the
|
|
139
|
+
* model-visible tool while the provider is registered, mirroring provider
|
|
140
|
+
* lifecycle (sibling load order and HMR replacement can change provider
|
|
141
|
+
* availability while the calling fiber stays active).
|
|
142
|
+
* @param ctx - the calling entry's plugin context (a preset-scope mount, or
|
|
143
|
+
* local-agent-dsh's toggle-owned dynamic plugin).
|
|
144
|
+
* @param config - resolved provider/toolName pair.
|
|
145
|
+
* @param owner - the calling package's own name, stamped as the tool-origin
|
|
146
|
+
* owner (never hardcoded here — this factory serves every family provider).
|
|
147
|
+
*/
|
|
148
|
+
function mountSubagentDelegationTool(ctx, config, owner) {
|
|
149
|
+
const toolName = config.toolName ?? "subagent";
|
|
150
|
+
const wording = familyWording();
|
|
151
|
+
let disposeTool;
|
|
152
|
+
const mount = () => {
|
|
153
|
+
disposeTool = ctx.tools.register(definePluginTool(defineTool({
|
|
154
|
+
name: toolName,
|
|
155
|
+
description: wording.description,
|
|
156
|
+
parameters: {
|
|
157
|
+
description: {
|
|
158
|
+
type: "string",
|
|
159
|
+
required: true,
|
|
160
|
+
description: "A short (3-5 word) description of the delegated task, for display."
|
|
161
|
+
},
|
|
162
|
+
prompt: {
|
|
163
|
+
type: "string",
|
|
164
|
+
required: true,
|
|
165
|
+
description: wording.promptDescription
|
|
166
|
+
},
|
|
167
|
+
resume: {
|
|
168
|
+
type: "string",
|
|
169
|
+
description: wording.resumeDescription
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
output: {
|
|
173
|
+
schema: {
|
|
174
|
+
type: "object",
|
|
175
|
+
additionalProperties: false,
|
|
176
|
+
properties: {
|
|
177
|
+
kind: {
|
|
178
|
+
type: "string",
|
|
179
|
+
required: true,
|
|
180
|
+
const: "foreground"
|
|
181
|
+
},
|
|
182
|
+
runId: {
|
|
183
|
+
type: "string",
|
|
184
|
+
required: true
|
|
185
|
+
},
|
|
186
|
+
output: {
|
|
187
|
+
type: "array",
|
|
188
|
+
required: true,
|
|
189
|
+
items: { type: "json" }
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
render: (_args, value) => [{
|
|
194
|
+
type: "text",
|
|
195
|
+
text: outputValueText(value.output)
|
|
196
|
+
}]
|
|
197
|
+
},
|
|
198
|
+
isConcurrencySafe: () => true,
|
|
199
|
+
async execute(args, exec) {
|
|
200
|
+
const parent = exec.agent;
|
|
201
|
+
if (!parent) throw new Error("subagent tool requires a calling agent (exec.agent was undefined)");
|
|
202
|
+
const parentSessionId = parent.session.id;
|
|
203
|
+
const resumeHandle = args.resume;
|
|
204
|
+
const resume = resumeHandle === void 0 ? void 0 : ctx.localAgent.resolveDelegation(resumeHandle, {
|
|
205
|
+
provider: config.provider,
|
|
206
|
+
parentSessionId
|
|
207
|
+
});
|
|
208
|
+
if (resumeHandle === void 0) ctx.localAgent.stageDelegationIntent(parentSessionId, config.provider, { kind: "fresh" });
|
|
209
|
+
else if (resume !== void 0) {
|
|
210
|
+
await ctx.localAgent.ensureChildLive?.(resumeHandle);
|
|
211
|
+
ctx.localAgent.stageDelegationIntent(parentSessionId, config.provider, {
|
|
212
|
+
kind: "resume",
|
|
213
|
+
childSessionId: resumeHandle,
|
|
214
|
+
cliSessionId: resume.cliSessionId
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
const request = {
|
|
218
|
+
label: args.description,
|
|
219
|
+
prompt: [{
|
|
220
|
+
type: "text",
|
|
221
|
+
text: args.prompt
|
|
222
|
+
}],
|
|
223
|
+
parent
|
|
224
|
+
};
|
|
225
|
+
const controller = new AbortController();
|
|
226
|
+
const run = await ctx.subagents.start(config.provider, {
|
|
227
|
+
...request,
|
|
228
|
+
signal: fusedSignal(controller, exec.signal)
|
|
229
|
+
});
|
|
230
|
+
const registry = ctx.localAgent;
|
|
231
|
+
if (typeof registry.trackDelegationRun === "function") registry.trackDelegationRun(String(run.id), run, () => controller.abort());
|
|
232
|
+
const settled = await settleForegroundRun(run);
|
|
233
|
+
if (resume === void 0) return {
|
|
234
|
+
...settled,
|
|
235
|
+
output: [...settled.output, {
|
|
236
|
+
type: "text",
|
|
237
|
+
text: `${RESUME_HINT_PREFIX}${run.id}"`
|
|
238
|
+
}]
|
|
239
|
+
};
|
|
240
|
+
return settled;
|
|
241
|
+
}
|
|
242
|
+
}), owner));
|
|
243
|
+
};
|
|
244
|
+
ctx.on("subagent/provider-added", (provider) => {
|
|
245
|
+
if (provider.name === config.provider && disposeTool === void 0) mount();
|
|
246
|
+
});
|
|
247
|
+
ctx.on("subagent/provider-removed", (name) => {
|
|
248
|
+
if (name !== config.provider || disposeTool === void 0) return;
|
|
249
|
+
disposeTool();
|
|
250
|
+
disposeTool = void 0;
|
|
251
|
+
});
|
|
252
|
+
if (ctx.subagents.getProvider(config.provider) !== void 0) mount();
|
|
253
|
+
else ctx.logger.info(`subagent provider "${config.provider}" not registered yet; the "${toolName}" tool will register when it appears`);
|
|
254
|
+
}
|
|
255
|
+
//#endregion
|
|
256
|
+
export { RESUME_HINT_PREFIX, mountSubagentDelegationTool, subagentToolConfigSchema };
|