dsh-agent-toolkit 0.2.1 → 0.2.2

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/lib/client.js CHANGED
@@ -67,15 +67,15 @@ window.__ModuleLoader__.load({
67
67
  document.head.appendChild(tag);
68
68
  }
69
69
  var delegate_card_module_css_default = {
70
- "row": "_8wQUq_row",
70
+ "chip": "_8wQUq_chip",
71
71
  "summary": "_8wQUq_summary",
72
- "childLink": "_8wQUq_childLink",
73
72
  "result": "_8wQUq_result",
74
- "prompt": "_8wQUq_prompt",
75
73
  "body": "_8wQUq_body",
76
- "chip": "_8wQUq_chip",
74
+ "root": "_8wQUq_root",
77
75
  "visuallyHidden": "_8wQUq_visuallyHidden",
78
- "root": "_8wQUq_root"
76
+ "row": "_8wQUq_row",
77
+ "prompt": "_8wQUq_prompt",
78
+ "childLink": "_8wQUq_childLink"
79
79
  };
80
80
  //#endregion
81
81
  //#region src/client/delegate/delegate-card.tsx
@@ -311,8 +311,8 @@ window.__ModuleLoader__.load({
311
311
  document.head.appendChild(tag);
312
312
  }
313
313
  var entry_module_css_default$1 = {
314
- "rail": "VJWWsa_rail",
315
- "trigger": "VJWWsa_trigger"
314
+ "trigger": "VJWWsa_trigger",
315
+ "rail": "VJWWsa_rail"
316
316
  };
317
317
  //#endregion
318
318
  //#region src/client/shared/entry.tsx
@@ -411,33 +411,33 @@ window.__ModuleLoader__.load({
411
411
  document.head.appendChild(tag);
412
412
  }
413
413
  var agents_module_css_default = {
414
- "editor": "KsfSLW_editor",
415
- "textarea": "KsfSLW_textarea",
416
- "toolGroupSet": "KsfSLW_toolGroupSet",
417
- "builtinBadge": "KsfSLW_builtinBadge",
418
- "actions": "KsfSLW_actions",
419
- "hint": "KsfSLW_hint",
414
+ "select": "KsfSLW_select",
415
+ "agentDesc": "KsfSLW_agentDesc",
416
+ "error": "KsfSLW_error",
420
417
  "toolCheck": "KsfSLW_toolCheck",
421
- "dialog": "KsfSLW_dialog",
422
- "agentRowActive": "KsfSLW_agentRowActive",
423
418
  "agentName": "KsfSLW_agentName",
424
- "agentDesc": "KsfSLW_agentDesc",
425
- "field": "KsfSLW_field",
426
- "listPane": "KsfSLW_listPane",
427
- "agentRow": "KsfSLW_agentRow",
419
+ "toolGroupSet": "KsfSLW_toolGroupSet",
420
+ "dialog": "KsfSLW_dialog",
428
421
  "block": "KsfSLW_block",
429
- "blockTitle": "KsfSLW_blockTitle",
430
- "select": "KsfSLW_select",
422
+ "field": "KsfSLW_field",
431
423
  "readonlyId": "KsfSLW_readonlyId",
424
+ "input": "KsfSLW_input",
425
+ "toolMode": "KsfSLW_toolMode",
426
+ "blockTitle": "KsfSLW_blockTitle",
427
+ "hint": "KsfSLW_hint",
428
+ "actions": "KsfSLW_actions",
432
429
  "toolGrid": "KsfSLW_toolGrid",
433
- "dangerButton": "KsfSLW_dangerButton",
434
430
  "createButton": "KsfSLW_createButton",
435
- "input": "KsfSLW_input",
431
+ "listPane": "KsfSLW_listPane",
432
+ "agentRowActive": "KsfSLW_agentRowActive",
433
+ "editor": "KsfSLW_editor",
434
+ "split": "KsfSLW_split",
435
+ "agentRow": "KsfSLW_agentRow",
436
+ "builtinBadge": "KsfSLW_builtinBadge",
436
437
  "toolGroupTitle": "KsfSLW_toolGroupTitle",
437
- "error": "KsfSLW_error",
438
- "editorPane": "KsfSLW_editorPane",
439
- "toolMode": "KsfSLW_toolMode",
440
- "split": "KsfSLW_split"
438
+ "dangerButton": "KsfSLW_dangerButton",
439
+ "textarea": "KsfSLW_textarea",
440
+ "editorPane": "KsfSLW_editorPane"
441
441
  };
442
442
  //#endregion
443
443
  //#region src/client/agents/AgentEditor.tsx
@@ -951,24 +951,24 @@ window.__ModuleLoader__.load({
951
951
  document.head.appendChild(tag);
952
952
  }
953
953
  var prompt_module_css_default = {
954
- "dialog": "VZk1fa_dialog",
955
- "error": "VZk1fa_error",
956
- "tabActive": "VZk1fa_tabActive",
954
+ "layerRow": "VZk1fa_layerRow",
955
+ "layerName": "VZk1fa_layerName",
957
956
  "hint": "VZk1fa_hint",
958
- "editorPane": "VZk1fa_editorPane",
957
+ "tabActive": "VZk1fa_tabActive",
958
+ "error": "VZk1fa_error",
959
959
  "layerRowActive": "VZk1fa_layerRowActive",
960
- "textarea": "VZk1fa_textarea",
961
960
  "actions": "VZk1fa_actions",
962
- "layerRow": "VZk1fa_layerRow",
963
- "layerName": "VZk1fa_layerName",
961
+ "tab": "VZk1fa_tab",
962
+ "split": "VZk1fa_split",
963
+ "textarea": "VZk1fa_textarea",
964
964
  "tabs": "VZk1fa_tabs",
965
+ "editor": "VZk1fa_editor",
966
+ "listPane": "VZk1fa_listPane",
965
967
  "readonlyTag": "VZk1fa_readonlyTag",
966
968
  "layerOrder": "VZk1fa_layerOrder",
967
- "tab": "VZk1fa_tab",
968
- "listPane": "VZk1fa_listPane",
969
+ "dialog": "VZk1fa_dialog",
969
970
  "field": "VZk1fa_field",
970
- "split": "VZk1fa_split",
971
- "editor": "VZk1fa_editor"
971
+ "editorPane": "VZk1fa_editorPane"
972
972
  };
973
973
  //#endregion
974
974
  //#region src/client/prompt/PromptLayersModal.tsx
@@ -1452,12 +1452,12 @@ window.__ModuleLoader__.load({
1452
1452
  document.head.appendChild(tag);
1453
1453
  }
1454
1454
  var chart_module_css_default = {
1455
- "tooltip": "_8LXSJW_tooltip",
1456
- "tooltipTotal": "_8LXSJW_tooltipTotal",
1457
1455
  "swatchCached": "_8LXSJW_swatchCached",
1458
- "tooltipTitle": "_8LXSJW_tooltipTitle",
1459
- "chartTheme": "_8LXSJW_chartTheme",
1456
+ "tooltipTotal": "_8LXSJW_tooltipTotal",
1457
+ "tooltip": "_8LXSJW_tooltip",
1460
1458
  "legend": "_8LXSJW_legend",
1459
+ "chartTheme": "_8LXSJW_chartTheme",
1460
+ "tooltipTitle": "_8LXSJW_tooltipTitle",
1461
1461
  "swatchFresh": "_8LXSJW_swatchFresh"
1462
1462
  };
1463
1463
  //#endregion
@@ -1473,13 +1473,13 @@ window.__ModuleLoader__.load({
1473
1473
  }
1474
1474
  var ActivityHeatmap_module_css_default = {
1475
1475
  "level2": "hjrYrq_level2",
1476
+ "level4": "hjrYrq_level4",
1476
1477
  "level1": "hjrYrq_level1",
1477
1478
  "level0": "hjrYrq_level0",
1478
- "months": "hjrYrq_months",
1479
1479
  "grid": "hjrYrq_grid",
1480
- "level4": "hjrYrq_level4",
1481
1480
  "level3": "hjrYrq_level3",
1482
- "week": "hjrYrq_week"
1481
+ "week": "hjrYrq_week",
1482
+ "months": "hjrYrq_months"
1483
1483
  };
1484
1484
  //#endregion
1485
1485
  //#region ../usage/src/client/usage/ActivityHeatmap.tsx
@@ -52516,19 +52516,19 @@ ${te.current.stack}
52516
52516
  document.head.appendChild(tag);
52517
52517
  }
52518
52518
  var UsageModal_module_css_default = {
52519
+ "pagerButton": "MODeXa_pagerButton",
52520
+ "row": "MODeXa_row",
52519
52521
  "pager": "MODeXa_pager",
52520
- "total": "MODeXa_total",
52521
52522
  "tab": "MODeXa_tab",
52522
- "dateLabel": "MODeXa_dateLabel",
52523
- "row": "MODeXa_row",
52524
52523
  "tabs": "MODeXa_tabs",
52525
- "dialog": "MODeXa_dialog",
52524
+ "dateLabel": "MODeXa_dateLabel",
52525
+ "sectionTitle": "MODeXa_sectionTitle",
52526
52526
  "rowName": "MODeXa_rowName",
52527
52527
  "rowCalls": "MODeXa_rowCalls",
52528
+ "dialog": "MODeXa_dialog",
52529
+ "total": "MODeXa_total",
52528
52530
  "compaction": "MODeXa_compaction",
52529
- "pagerButton": "MODeXa_pagerButton",
52530
- "tabActive": "MODeXa_tabActive",
52531
- "sectionTitle": "MODeXa_sectionTitle"
52531
+ "tabActive": "MODeXa_tabActive"
52532
52532
  };
52533
52533
  //#endregion
52534
52534
  //#region ../usage/src/client/usage/UsageModal.tsx
@@ -55153,28 +55153,28 @@ ${te.current.stack}
55153
55153
  document.head.appendChild(tag);
55154
55154
  }
55155
55155
  var bots_module_css_default = {
55156
- "dialog": "vTbXga_dialog",
55157
- "textarea": "vTbXga_textarea",
55156
+ "stepSeparator": "vTbXga_stepSeparator",
55157
+ "formActions": "vTbXga_formActions",
55158
+ "field": "vTbXga_field",
55158
55159
  "botRow": "vTbXga_botRow",
55159
- "botName": "vTbXga_botName",
55160
- "channelBadge": "vTbXga_channelBadge",
55161
- "stepActive": "vTbXga_stepActive",
55162
- "tabActive": "vTbXga_tabActive",
55163
55160
  "tabs": "vTbXga_tabs",
55164
55161
  "step": "vTbXga_step",
55165
- "tab": "vTbXga_tab",
55166
- "error": "vTbXga_error",
55167
- "formActions": "vTbXga_formActions",
55168
- "scanSection": "vTbXga_scanSection",
55169
- "field": "vTbXga_field",
55170
- "steps": "vTbXga_steps",
55171
- "stepSeparator": "vTbXga_stepSeparator",
55172
- "input": "vTbXga_input",
55162
+ "createButton": "vTbXga_createButton",
55163
+ "tabActive": "vTbXga_tabActive",
55164
+ "textarea": "vTbXga_textarea",
55173
55165
  "select": "vTbXga_select",
55166
+ "channelBadge": "vTbXga_channelBadge",
55167
+ "status": "vTbXga_status",
55168
+ "stepActive": "vTbXga_stepActive",
55169
+ "input": "vTbXga_input",
55170
+ "scanSection": "vTbXga_scanSection",
55171
+ "dialog": "vTbXga_dialog",
55174
55172
  "groupTitle": "vTbXga_groupTitle",
55173
+ "error": "vTbXga_error",
55174
+ "steps": "vTbXga_steps",
55175
55175
  "group": "vTbXga_group",
55176
- "createButton": "vTbXga_createButton",
55177
- "status": "vTbXga_status"
55176
+ "botName": "vTbXga_botName",
55177
+ "tab": "vTbXga_tab"
55178
55178
  };
55179
55179
  //#endregion
55180
55180
  //#region src/client/bots/BotForm.tsx
package/lib/index.d.ts CHANGED
@@ -47,6 +47,21 @@ interface BotsModuleConfig {
47
47
  errorDetailMaxChars: number;
48
48
  }
49
49
  //#endregion
50
+ //#region src/agents/team-preset.d.ts
51
+ /** 本功能的可调配置(Config schema 在 ../index.ts)。 */
52
+ interface AgentTeamPresetConfig {
53
+ /** 总开关:false 时启动不生成/刷新 preset。 */
54
+ enabled: boolean;
55
+ /** 生成的 preset id(即目录名)。 */
56
+ id: string;
57
+ /** 源 preset id,读其 composition 做派生。 */
58
+ source: string;
59
+ /** preset.yml 的显示名。 */
60
+ name: string;
61
+ /** preset.yml 的描述。 */
62
+ description: string;
63
+ }
64
+ //#endregion
50
65
  //#region src/index.d.ts
51
66
  declare const name = "dsh-agent-toolkit";
52
67
  declare const inject: string[];
@@ -62,6 +77,7 @@ interface Config {
62
77
  provider: string;
63
78
  toolName: string;
64
79
  feishu: BotsModuleConfig;
80
+ agentTeamPreset: AgentTeamPresetConfig;
65
81
  }
66
82
  /** layers/rules 的 schemastery schema 照归档 prompt-stack/src/index.ts:21-41 逐字段平移(含 overrides transform hack)。 */
67
83
  declare const Config: z<unknown, Config>;
package/lib/index.js CHANGED
@@ -1,16 +1,16 @@
1
1
  import z from "@deepseek-ai/schemastery";
2
2
  import { z as z$1 } from "zod";
3
3
  import { defineDomain, domainTable } from "@deepseek-ai/dsh-storage-domain";
4
- import { readFile, readdir } from "node:fs/promises";
5
- import { join } from "node:path";
4
+ import { access, mkdir, readFile, readdir, writeFile } from "node:fs/promises";
5
+ import { join, resolve } from "node:path";
6
6
  import yaml from "js-yaml";
7
- import { resolveDshHome } from "@deepseek-ai/dsh-home-paths";
7
+ import { expandHomePath, resolveDshHome } from "@deepseek-ai/dsh-home-paths";
8
8
  import { defineTool } from "@deepseek-ai/dsh-tools";
9
+ import { createUserMessage } from "@deepseek-ai/dsh-llm";
9
10
  import { existsSync } from "node:fs";
10
11
  import { SessionId } from "@deepseek-ai/dsh-session";
11
12
  import { credentialRef } from "@deepseek-ai/dsh-credentials";
12
13
  import * as lark from "@larksuiteoapi/node-sdk";
13
- import { createUserMessage } from "@deepseek-ai/dsh-llm";
14
14
  import { randomBytes, randomUUID } from "node:crypto";
15
15
  import { setupUsage } from "@dsh-agent-toolkit/token-usage";
16
16
  //#region src/agents/store.ts
@@ -1612,6 +1612,59 @@ function setupAgentsApi(ctx, deps) {
1612
1612
  });
1613
1613
  }
1614
1614
  //#endregion
1615
+ //#region src/agents/create-command.ts
1616
+ /** 拼装 /create-agent 的引导文本(模型面契约,文案为规格锁定内容)。 */
1617
+ function buildCreateAgentGuidance(input) {
1618
+ const lines = [
1619
+ "# 交互式创建 Agent 团队成员",
1620
+ "",
1621
+ "## 工作流(三步)",
1622
+ "1. 澄清需求:需求不明确时用 ask_user_question 向用户提问,整个流程提问总次数不超过 5 次,不重复问已确认的信息;",
1623
+ "2. 生成推荐并请用户确认:推荐 id / name / description / persona / tools 五个字段(id 是团队内唯一标识,name 是显示名,description 是职责一句话描述,persona 是系统提示词个性段,tools 是工具白名单);",
1624
+ "3. 迭代:用户有修改意见时按意见修订名称、描述、个性和工具后再次确认,直到用户明确确认。"
1625
+ ];
1626
+ if (input.requirement !== "") lines.push("", "## 用户初始需求", `用户已在命令中提供初始需求:「${input.requirement}」。请据此减少提问轮次,仅就不明确的点提问。`);
1627
+ lines.push("", "## 现有 Agent id(不可复用)", input.agentIds.join(", "), "id 规则:小写字母开头,仅含小写字母/数字/连字符([a-z0-9-]),最长 32 字符。", "", "## 可用工具清单", `原生工具:${NATIVE_TOOL_NAMES.join(", ")}`, `全局工具:${input.globalTools.join(", ")}`, "省略 tools 字段表示不限制(Agent 可使用全部工具)。一旦给出白名单,该 Agent 只有列出的工具可用:通常应保留原生工具,否则失去读文件/搜索/执行命令等基本能力(最终取舍按需求判断,如只读角色可去掉 write/edit)。");
1628
+ if (input.origin === void 0) lines.push("", "## 落库", "当前宿主无 web 服务,无法自动落库。用户确认推荐后,请把最终配置完整输出给用户,并提示其打开 Agents 面板按推荐内容手动创建。");
1629
+ else lines.push("", "## 落库(用户明确确认后执行)", "用你的 shell 工具调用 Agents 面板同一 HTTP 端点完成创建:", `1. 先 GET ${input.origin}/dsh-agent-toolkit/api/agents 复核所选 id 仍未被占用;`, `2. 再 PUT ${input.origin}/dsh-agent-toolkit/api/agents/<id>,请求体为 JSON(不要在 body 中携带 id 或 builtin 字段):`, " {\"name\":\"...\",\"description\":\"...\",\"persona\":\"...\",\"tools\":{\"allow\":[\"...\"]}}", " (description/persona/tools 均可省略;省略 tools 表示不限制)", "3. curl 示例(Windows 的 pwsh 里用 curl.exe):", ` curl.exe -s -X PUT "${input.origin}/dsh-agent-toolkit/api/agents/<id>" -H "Content-Type: application/json" -d "{\\"name\\":\\"...\\"}"`, `4. 返回 200 后必须再 GET ${input.origin}/dsh-agent-toolkit/api/agents,在返回列表中找到该 id 的记录,把它的 name/description/persona/tools 关键字段展示给用户,作为落库证据;`, "5. 落库成功后告知用户可在 Agents 面板查看、并可被 team_delegate 委派;任一步返回 4xx 则把错误信息展示给用户,修正后重试。");
1630
+ return lines.join("\n");
1631
+ }
1632
+ /**
1633
+ * 注册 /create-agent。webServer 为可选服务按仓库规则经 ctx.get 读取(不进 inject),
1634
+ * 缺席(headless/CLI)时 origin 为 undefined,引导文本落库节降级为手动创建指引。
1635
+ *
1636
+ * 命令结果(command/done)是 log-only、不进模型:引导文本必须经 agent.followup
1637
+ * 投递为 user 消息驱动主 Agent(与 channels/inbound.ts 同一机制),命令卡只回执短文案。
1638
+ */
1639
+ function setupCreateAgentCommand(ctx, deps) {
1640
+ ctx.commands.register({
1641
+ name: "create-agent",
1642
+ description: "交互式创建 Agent 团队成员:访谈澄清需求 → 推荐配置 → 确认后经面板 API 落库",
1643
+ input: { hint: "初始需求描述,可空" },
1644
+ handler: ({ rawInput, agent }) => {
1645
+ const webServer = ctx.get("webServer");
1646
+ const origin = webServer === void 0 ? void 0 : `http://127.0.0.1:${webServer.port}`;
1647
+ const text = buildCreateAgentGuidance({
1648
+ requirement: rawInput.trim(),
1649
+ agentIds: deps.registry.list().map((agent) => agent.id),
1650
+ globalTools: deps.listTools(),
1651
+ origin
1652
+ });
1653
+ agent.followup(createUserMessage({
1654
+ content: [{
1655
+ type: "text",
1656
+ text
1657
+ }],
1658
+ source: { kind: "user" }
1659
+ }));
1660
+ return {
1661
+ kind: "success",
1662
+ text: "已向主 Agent 发出创建 Agent 引导,请继续对话完成访谈与确认。"
1663
+ };
1664
+ }
1665
+ });
1666
+ }
1667
+ //#endregion
1615
1668
  //#region src/channels/agent-setup.ts
1616
1669
  /** bot 会话角色 persona 的 scoped 段名:与全局 persona 层同名,scoped 注册即 shadow 覆盖主 Agent persona。 */
1617
1670
  const TOOLKIT_PERSONA_SECTION = "prompt-stack:persona";
@@ -3141,6 +3194,125 @@ function setupBots(ctx, config, deps) {
3141
3194
  });
3142
3195
  }
3143
3196
  //#endregion
3197
+ //#region src/agents/team-preset.ts
3198
+ /**
3199
+ * Agent 团队 preset 自动生成:派生宿主当前 shipped standard composition,
3200
+ * 文本级禁用 subagent 工具族 4 个行,写入首个 trust=user 的 preset root。
3201
+ * 设计:docs/superpowers/specs/2026-09-02-agent-team-preset-design.md
3202
+ */
3203
+ /** 禁用目标行:覆盖与 team_delegate 竞争/配套的 5 个模型可见工具所属的 4 个行。 */
3204
+ const TEAM_PRESET_DISABLED_ROWS = [
3205
+ "tool-subagent",
3206
+ "tool-subagent-fork",
3207
+ "tool-subagent-control",
3208
+ "tool-subagent-list-agents"
3209
+ ];
3210
+ /**
3211
+ * 文本级锚点改写:对 4 个目标行各插入一行 `disabled: true`(缩进 = 锚点缩进 + 2 空格)。
3212
+ * 锚点是整行精确匹配 `- id: <行id>`(忽略首尾空白),防 tool-subagent 误中
3213
+ * tool-subagent-fork / tool-subagent-control 前缀;锚点所属块内(锚点行之后、
3214
+ * 首个缩进 <= 锚点缩进的非空行之前)已有 `disabled:` 键则跳过——既幂等,也避免
3215
+ * 与宿主已有的 `disabled: !!js ...` 撞出 YAML 重复键。锚点缺失 warn 并跳过该锚点,
3216
+ * 其余照常。除插入行外文本逐字节不变。
3217
+ */
3218
+ function disableSubagentRows(source, warn) {
3219
+ const lines = source.split("\n");
3220
+ for (const row of TEAM_PRESET_DISABLED_ROWS) {
3221
+ const anchor = `- id: ${row}`;
3222
+ const index = lines.findIndex((line) => line.trim() === anchor);
3223
+ if (index === -1) {
3224
+ warn(`dsh-agent-toolkit: agent-team preset 锚点行 "${anchor}" 在源 composition 中缺失,已跳过`);
3225
+ continue;
3226
+ }
3227
+ const indent = lines[index].length - lines[index].trimStart().length;
3228
+ let hasDisabled = false;
3229
+ for (let i = index + 1; i < lines.length; i += 1) {
3230
+ const line = lines[i];
3231
+ if (line.trim() === "") continue;
3232
+ if (line.length - line.trimStart().length <= indent) break;
3233
+ if (/^\s*disabled\s*:/.test(line)) {
3234
+ hasDisabled = true;
3235
+ break;
3236
+ }
3237
+ }
3238
+ if (hasDisabled) continue;
3239
+ lines.splice(index + 1, 0, `${" ".repeat(indent + 2)}disabled: true`);
3240
+ }
3241
+ return lines.join("\n");
3242
+ }
3243
+ const COMPOSITION_FILE = "agent.cordis.yml";
3244
+ const METADATA_FILE = "preset.yml";
3245
+ /**
3246
+ * 生成目录的归属标记:无此标记的同名目录视为用户手工 preset,不覆盖。
3247
+ * 标记必须在 mkdir 后最先写入(marker-first):这样写 composition/metadata 失败留下的是
3248
+ * 带标记的半成品目录,下次启动会被正常重写自愈;若最后才写标记,则半成品目录无标记、
3249
+ * 会被误判为用户手工 preset 而永久卡死不覆盖。
3250
+ */
3251
+ const MARKER_FILE = ".generated-by";
3252
+ const MARKER_CONTENT = "dsh-agent-toolkit";
3253
+ /** 镜像宿主 PRESET_ID:preset id 即目录名,正则白名单是路径逃逸的 containment 边界。 */
3254
+ const PRESET_ID = /^[a-z0-9][a-z0-9-]*$/;
3255
+ const GENERATED_HEADER = "# 本文件由 dsh-agent-toolkit 自动生成,勿手改(每次启动重写)。\n";
3256
+ /**
3257
+ * 启动时生成/刷新 agent-team preset。所有失败路径 warn 降级,不影响插件其余功能。
3258
+ * 不设为默认 preset、卸载不删目录(可能有会话在用;composition 不引用 toolkit 行,
3259
+ * 残留 preset 自身仍可用)。每次启动重写:standing mount 按文件代际,重写只影响新会话。
3260
+ */
3261
+ async function setupAgentTeamPreset(ctx, config) {
3262
+ if (!config.enabled) return;
3263
+ const warn = (msg) => {
3264
+ ctx.logger.warn(msg);
3265
+ };
3266
+ const agentPresets = ctx.get("agentPresets", false);
3267
+ if (agentPresets === void 0) return;
3268
+ if (!PRESET_ID.test(config.id)) {
3269
+ warn(`dsh-agent-toolkit: agentTeamPreset.id "${config.id}" 不是合法 preset id,跳过 agent-team 生成`);
3270
+ return;
3271
+ }
3272
+ let source;
3273
+ try {
3274
+ source = await agentPresets.read(config.source);
3275
+ } catch (error) {
3276
+ warn(`dsh-agent-toolkit: 读取源 preset "${config.source}" 失败,跳过 agent-team 生成:${error instanceof Error ? error.message : String(error)}`);
3277
+ return;
3278
+ }
3279
+ const root = agentPresets.roots.find((r) => r.trust === "user");
3280
+ if (root === void 0) {
3281
+ warn("dsh-agent-toolkit: preset roots 中无 trust=user 的目录,跳过 agent-team 生成");
3282
+ return;
3283
+ }
3284
+ const composition = GENERATED_HEADER + disableSubagentRows(source, warn);
3285
+ const dir = join(resolve(expandHomePath(root.path)), config.id);
3286
+ try {
3287
+ const markerPath = join(dir, MARKER_FILE);
3288
+ let dirExists = true;
3289
+ try {
3290
+ await access(dir);
3291
+ } catch {
3292
+ dirExists = false;
3293
+ }
3294
+ if (dirExists) {
3295
+ let marked = false;
3296
+ try {
3297
+ marked = (await readFile(markerPath, "utf8")).trim() === MARKER_CONTENT;
3298
+ } catch {}
3299
+ if (!marked) {
3300
+ warn(`dsh-agent-toolkit: ${dir} 已存在且非本插件生成,不覆盖,跳过 agent-team 生成`);
3301
+ return;
3302
+ }
3303
+ }
3304
+ await mkdir(dir, { recursive: true });
3305
+ await writeFile(markerPath, `${MARKER_CONTENT}\n`, "utf8");
3306
+ await writeFile(join(dir, COMPOSITION_FILE), composition, "utf8");
3307
+ await writeFile(join(dir, METADATA_FILE), yaml.dump({
3308
+ name: config.name,
3309
+ description: config.description
3310
+ }, { lineWidth: -1 }), "utf8");
3311
+ } catch (error) {
3312
+ warn(`dsh-agent-toolkit: 写入 agent-team preset 失败(${dir}):${error instanceof Error ? error.message : String(error)}`);
3313
+ }
3314
+ }
3315
+ //#endregion
3144
3316
  //#region src/index.ts
3145
3317
  const name = "dsh-agent-toolkit";
3146
3318
  const inject = [
@@ -3195,6 +3367,19 @@ const Config = z.object({
3195
3367
  registerAppTimeoutMs: 6e5,
3196
3368
  processingReactionEmoji: "OneSecond",
3197
3369
  errorDetailMaxChars: 500
3370
+ }),
3371
+ agentTeamPreset: z.object({
3372
+ enabled: z.boolean().default(true),
3373
+ id: z.string().default("agent-team"),
3374
+ source: z.string().default("standard"),
3375
+ name: z.string().default("Agent 团队"),
3376
+ description: z.string().default("Agent 团队模式:禁用原生 subagent 工具族,委派统一走 team_delegate 团队角色")
3377
+ }).default({
3378
+ enabled: true,
3379
+ id: "agent-team",
3380
+ source: "standard",
3381
+ name: "Agent 团队",
3382
+ description: "Agent 团队模式:禁用原生 subagent 工具族,委派统一走 team_delegate 团队角色"
3198
3383
  })
3199
3384
  });
3200
3385
  async function apply(ctx, config) {
@@ -3241,9 +3426,10 @@ async function apply(ctx, config) {
3241
3426
  active: activeRoutes,
3242
3427
  routes: routesTable
3243
3428
  });
3429
+ const listTools = () => ctx.tools.schemas().map((s) => s.name);
3244
3430
  setupAgentsApi(ctx, {
3245
3431
  registry,
3246
- listTools: () => ctx.tools.schemas().map((s) => s.name),
3432
+ listTools,
3247
3433
  listProviders: () => ctx.llm.listProviders().map(({ id, name }) => ({
3248
3434
  id,
3249
3435
  name
@@ -3253,6 +3439,10 @@ async function apply(ctx, config) {
3253
3439
  name
3254
3440
  })))
3255
3441
  });
3442
+ setupCreateAgentCommand(ctx, {
3443
+ registry,
3444
+ listTools
3445
+ });
3256
3446
  setupPromptLayersApi(ctx, {
3257
3447
  source: layerSource,
3258
3448
  rules: config.rules,
@@ -3271,6 +3461,7 @@ async function apply(ctx, config) {
3271
3461
  };
3272
3462
  }
3273
3463
  });
3464
+ await setupAgentTeamPreset(ctx, config.agentTeamPreset);
3274
3465
  if (config.modules.feishu) setupBots(ctx, config.feishu, { registry });
3275
3466
  if (config.modules.usage) setupUsage(ctx, { timezone: config.timezone }, name);
3276
3467
  }