deepfish-ai 2.0.11 → 2.0.13

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/README.md CHANGED
@@ -45,6 +45,7 @@
45
45
  - [工具管理](#工具管理)
46
46
  - [会话管理](#会话管理)
47
47
  - [任务管理](#任务管理)
48
+ - [长任务规划](#长任务规划)
48
49
  - [MCP 管理](#mcp-管理)
49
50
  - [服务管理](#服务管理)
50
51
  - [缓存管理(AI自我学习的缓存)](#缓存管理ai自我学习的缓存)
@@ -183,11 +184,21 @@ ai "我刚问了一个什么问题"
183
184
  | `ai tasks del <index>` | 删除指定任务 |
184
185
  | `ai tasks clear` | 清除所有任务 |
185
186
 
187
+ ### 长任务规划
188
+
189
+ | 命令 | 说明 |
190
+ | ------------------------- | ------------------------------------------ |
191
+ | `ai plan-do <任务描述>` | 将复杂任务拆解为子任务并逐步执行完成 |
192
+ | `ai plan-continue` | 继续执行被中断的 plan-do 任务 |
193
+
186
194
  ### MCP 管理
187
195
 
188
- | 命令 | 说明 |
189
- | ------------- | ------------- |
190
- | `ai mcp edit` | 编辑 MCP 配置 |
196
+ | 命令 | 说明 |
197
+ | --------------------------------- | ---------------- |
198
+ | `ai mcp ls` | 列出所有 MCP 服务器 |
199
+ | `ai mcp edit` | 编辑 MCP 配置 |
200
+ | `ai mcp enable <name\|index>` | 启用 MCP 服务器 |
201
+ | `ai mcp disable <name\|index>` | 禁用 MCP 服务器 |
191
202
 
192
203
  ### 服务管理
193
204
 
package/dist/index.js CHANGED
@@ -8403,10 +8403,10 @@ var require_lib = __commonJS({
8403
8403
  exports2.analyse = analyse;
8404
8404
  var detectFile = (filepath, opts = {}) => new Promise((resolve, reject) => {
8405
8405
  let fd;
8406
- const fs25 = (0, node_1.default)();
8406
+ const fs26 = (0, node_1.default)();
8407
8407
  const handler = (err, buffer) => {
8408
8408
  if (fd) {
8409
- fs25.closeSync(fd);
8409
+ fs26.closeSync(fd);
8410
8410
  }
8411
8411
  if (err) {
8412
8412
  reject(err);
@@ -8418,9 +8418,9 @@ var require_lib = __commonJS({
8418
8418
  };
8419
8419
  const sampleSize = (opts === null || opts === void 0 ? void 0 : opts.sampleSize) || 0;
8420
8420
  if (sampleSize > 0) {
8421
- fd = fs25.openSync(filepath, "r");
8421
+ fd = fs26.openSync(filepath, "r");
8422
8422
  let sample = Buffer.allocUnsafe(sampleSize);
8423
- fs25.read(fd, sample, 0, sampleSize, opts.offset, (err, bytesRead) => {
8423
+ fs26.read(fd, sample, 0, sampleSize, opts.offset, (err, bytesRead) => {
8424
8424
  if (err) {
8425
8425
  handler(err, null);
8426
8426
  } else {
@@ -8432,22 +8432,22 @@ var require_lib = __commonJS({
8432
8432
  });
8433
8433
  return;
8434
8434
  }
8435
- fs25.readFile(filepath, handler);
8435
+ fs26.readFile(filepath, handler);
8436
8436
  });
8437
8437
  exports2.detectFile = detectFile;
8438
8438
  var detectFileSync = (filepath, opts = {}) => {
8439
- const fs25 = (0, node_1.default)();
8439
+ const fs26 = (0, node_1.default)();
8440
8440
  if (opts && opts.sampleSize) {
8441
- const fd = fs25.openSync(filepath, "r");
8441
+ const fd = fs26.openSync(filepath, "r");
8442
8442
  let sample = Buffer.allocUnsafe(opts.sampleSize);
8443
- const bytesRead = fs25.readSync(fd, sample, 0, opts.sampleSize, opts.offset);
8443
+ const bytesRead = fs26.readSync(fd, sample, 0, opts.sampleSize, opts.offset);
8444
8444
  if (bytesRead < opts.sampleSize) {
8445
8445
  sample = sample.subarray(0, bytesRead);
8446
8446
  }
8447
- fs25.closeSync(fd);
8447
+ fs26.closeSync(fd);
8448
8448
  return (0, exports2.detect)(sample);
8449
8449
  }
8450
- return (0, exports2.detect)(fs25.readFileSync(filepath));
8450
+ return (0, exports2.detect)(fs26.readFileSync(filepath));
8451
8451
  };
8452
8452
  exports2.detectFileSync = detectFileSync;
8453
8453
  exports2.default = {
@@ -10564,10 +10564,10 @@ function mergeDefs(...defs) {
10564
10564
  function cloneDef(schema) {
10565
10565
  return mergeDefs(schema._zod.def);
10566
10566
  }
10567
- function getElementAtPath(obj, path23) {
10568
- if (!path23)
10567
+ function getElementAtPath(obj, path24) {
10568
+ if (!path24)
10569
10569
  return obj;
10570
- return path23.reduce((acc, key) => acc?.[key], obj);
10570
+ return path24.reduce((acc, key) => acc?.[key], obj);
10571
10571
  }
10572
10572
  function promiseAllObject(promisesObj) {
10573
10573
  const keys = Object.keys(promisesObj);
@@ -10976,11 +10976,11 @@ function explicitlyAborted(x, startIndex = 0) {
10976
10976
  }
10977
10977
  return false;
10978
10978
  }
10979
- function prefixIssues(path23, issues) {
10979
+ function prefixIssues(path24, issues) {
10980
10980
  return issues.map((iss) => {
10981
10981
  var _a3;
10982
10982
  (_a3 = iss).path ?? (_a3.path = []);
10983
- iss.path.unshift(path23);
10983
+ iss.path.unshift(path24);
10984
10984
  return iss;
10985
10985
  });
10986
10986
  }
@@ -11127,16 +11127,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
11127
11127
  }
11128
11128
  function formatError(error51, mapper = (issue2) => issue2.message) {
11129
11129
  const fieldErrors = { _errors: [] };
11130
- const processError = (error52, path23 = []) => {
11130
+ const processError = (error52, path24 = []) => {
11131
11131
  for (const issue2 of error52.issues) {
11132
11132
  if (issue2.code === "invalid_union" && issue2.errors.length) {
11133
- issue2.errors.map((issues) => processError({ issues }, [...path23, ...issue2.path]));
11133
+ issue2.errors.map((issues) => processError({ issues }, [...path24, ...issue2.path]));
11134
11134
  } else if (issue2.code === "invalid_key") {
11135
- processError({ issues: issue2.issues }, [...path23, ...issue2.path]);
11135
+ processError({ issues: issue2.issues }, [...path24, ...issue2.path]);
11136
11136
  } else if (issue2.code === "invalid_element") {
11137
- processError({ issues: issue2.issues }, [...path23, ...issue2.path]);
11137
+ processError({ issues: issue2.issues }, [...path24, ...issue2.path]);
11138
11138
  } else {
11139
- const fullpath = [...path23, ...issue2.path];
11139
+ const fullpath = [...path24, ...issue2.path];
11140
11140
  if (fullpath.length === 0) {
11141
11141
  fieldErrors._errors.push(mapper(issue2));
11142
11142
  } else {
@@ -11163,17 +11163,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
11163
11163
  }
11164
11164
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
11165
11165
  const result = { errors: [] };
11166
- const processError = (error52, path23 = []) => {
11166
+ const processError = (error52, path24 = []) => {
11167
11167
  var _a3, _b;
11168
11168
  for (const issue2 of error52.issues) {
11169
11169
  if (issue2.code === "invalid_union" && issue2.errors.length) {
11170
- issue2.errors.map((issues) => processError({ issues }, [...path23, ...issue2.path]));
11170
+ issue2.errors.map((issues) => processError({ issues }, [...path24, ...issue2.path]));
11171
11171
  } else if (issue2.code === "invalid_key") {
11172
- processError({ issues: issue2.issues }, [...path23, ...issue2.path]);
11172
+ processError({ issues: issue2.issues }, [...path24, ...issue2.path]);
11173
11173
  } else if (issue2.code === "invalid_element") {
11174
- processError({ issues: issue2.issues }, [...path23, ...issue2.path]);
11174
+ processError({ issues: issue2.issues }, [...path24, ...issue2.path]);
11175
11175
  } else {
11176
- const fullpath = [...path23, ...issue2.path];
11176
+ const fullpath = [...path24, ...issue2.path];
11177
11177
  if (fullpath.length === 0) {
11178
11178
  result.errors.push(mapper(issue2));
11179
11179
  continue;
@@ -11205,8 +11205,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
11205
11205
  }
11206
11206
  function toDotPath(_path) {
11207
11207
  const segs = [];
11208
- const path23 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
11209
- for (const seg of path23) {
11208
+ const path24 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
11209
+ for (const seg of path24) {
11210
11210
  if (typeof seg === "number")
11211
11211
  segs.push(`[${seg}]`);
11212
11212
  else if (typeof seg === "symbol")
@@ -23898,13 +23898,13 @@ function resolveRef(ref, ctx) {
23898
23898
  if (!ref.startsWith("#")) {
23899
23899
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
23900
23900
  }
23901
- const path23 = ref.slice(1).split("/").filter(Boolean);
23902
- if (path23.length === 0) {
23901
+ const path24 = ref.slice(1).split("/").filter(Boolean);
23902
+ if (path24.length === 0) {
23903
23903
  return ctx.rootSchema;
23904
23904
  }
23905
23905
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
23906
- if (path23[0] === defsKey) {
23907
- const key = path23[1];
23906
+ if (path24[0] === defsKey) {
23907
+ const key = path24[1];
23908
23908
  if (!key || !ctx.defs[key]) {
23909
23909
  throw new Error(`Reference not found: ${ref}`);
23910
23910
  }
@@ -24470,11 +24470,12 @@ var getSystemPrompt = (params) => {
24470
24470
  const memoryPrompt = getUserMemoryPrompt(params.memoryFilePath);
24471
24471
  const agentRulesPrompt = getAgentRulesPrompt(params.agentRulesPath);
24472
24472
  return `
24473
- ${params.systemPrompt || `\u8FD9\u662FDeepfish Cli\u7CFB\u7EDF,\u4F60\u662F\u7CFB\u7EDF\u4E2D\u4E25\u683C\u6309\u89C4\u5219\u6267\u884C\u4EFB\u52A1\u7684\u667A\u80FD\u4F53,\u4E0D\u80FD\u8FDD\u53CD\u4EFB\u4F55\u7CFB\u7EDF\u9650\u5236\u3002
24473
+ ${params.systemPrompt + `
24474
+ \u8FD9\u662FDeepfish Cli\u7CFB\u7EDF,\u4F60\u662F\u7CFB\u7EDF\u4E2D\u4E25\u683C\u6309\u89C4\u5219\u6267\u884C\u4EFB\u52A1\u7684\u667A\u80FD\u4F53,\u4E0D\u80FD\u8FDD\u53CD\u4EFB\u4F55\u7CFB\u7EDF\u9650\u5236\u3002
24474
24475
  # \u6CE8\u610F\u6CE8\u610F\u4E8B\u9879:
24475
24476
  1.\u5982\u679C\u4EFB\u52A1\u6BD4\u8F83\u590D\u6742\uFF0C\u5E94\u8BE5\u5148\u8FDB\u884C\u62C6\u5206\uFF0C\u5206\u89E3\u6210\u591A\u4E2A\u6B65\u9AA4\uFF0C\u521B\u5EFA\u5B50\u667A\u80FD\u4F53\u6765\u9010\u6B65\u5B8C\u6210\u3002
24476
24477
  2.\u4E34\u65F6\u6587\u4EF6\u5FC5\u987B\u4F7F\u7528"tmp_"\u4F5C\u4E3A\u524D\u7F00\u547D\u540D\uFF0C\u5E76\u5728\u4EFB\u52A1\u7ED3\u675F\u540E\u5220\u9664\uFF0C\u4E0D\u80FD\u5728\u5DE5\u4F5C\u76EE\u5F55\u4E2D\u7559\u4E0B\u4EFB\u4F55\u4E34\u65F6\u6587\u4EF6\u3002
24477
- 3.\u5C3D\u91CF\u4F7F\u7528"execute_command"\u3001"execute_js_code"\u5DE5\u5177\u5B8C\u6210\u4EFB\u52A1
24478
+ 3.\u5C3D\u91CF\u4F7F\u7528"execute_command"\u3001"execute_js_code"\u5DE5\u5177\u7ED3\u5408Nodejs\u4EE3\u7801\u5B8C\u6210\u4EFB\u52A1
24478
24479
  4.\u786C\u6027\u89C4\u5219\uFF1A\u65E0\u8BBA\u6846\u67B6\u5185\u7F6E\u82F1\u6587\u6A21\u677F\uFF0C\u4F60\u7684\u6BCF\u4E00\u6B65\u601D\u8003\uFF08Thought\uFF09\u3001\u89C2\u5BDF\u5206\u6790\u3001\u7ED3\u8BBA\u56DE\u7B54\uFF0C**\u4E25\u683C\u4F7F\u7528\u7B80\u4F53\u4E2D\u6587**\uFF0C\u7981\u6B62\u82F1\u6587\u3002`}
24479
24480
 
24480
24481
  # \u57FA\u7840\u73AF\u5883\u4FE1\u606F
@@ -24486,21 +24487,24 @@ ${memoryPrompt}
24486
24487
  ${agentRulesPrompt}
24487
24488
  `;
24488
24489
  };
24489
- var subSystemPrompt = (workspace, osType, skills, excludeSkills) => {
24490
- let skillPrompt = getSkillPrompt(skills, excludeSkills);
24491
- return `
24490
+ var subSystemPrompt = (params) => {
24491
+ const skillPrompt = getSkillPrompt(params.skills, params.excludeSkills);
24492
+ const basePrompt = `
24492
24493
  \u8FD9\u662FDeepfish Cli\u7CFB\u7EDF,\u4F60\u662F\u7CFB\u7EDF\u4E2D\u4E25\u683C\u6309\u89C4\u5219\u6267\u884C\u4EFB\u52A1\u7684\u5B50\u667A\u80FD\u4F53,\u4E0D\u80FD\u8FDD\u53CD\u4EFB\u4F55\u7CFB\u7EDF\u9650\u5236\u3002
24493
24494
  ### \u57FA\u7840\u73AF\u5883\u4FE1\u606F
24494
- \u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\uFF1A${workspace}
24495
- \u64CD\u4F5C\u7CFB\u7EDF\u7C7B\u578B\uFF1A${osType}
24495
+ \u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\uFF1A${params.workspace}
24496
+ \u64CD\u4F5C\u7CFB\u7EDF\u7C7B\u578B\uFF1A${params.osType}
24496
24497
 
24497
24498
  \u6CE8\u610F:
24498
24499
  1.\u5B50\u667A\u80FD\u4F53\u53EA\u80FD\u5B8C\u6210\u5355\u4E2A\u4EFB\u52A1,\u4E0D\u80FD\u521B\u5EFA\u65B0\u7684\u5B50\u667A\u80FD\u4F53\u3002
24499
24500
  2.\u4E34\u65F6\u6587\u4EF6\u5FC5\u987B\u4F7F\u7528"tmp_"\u4F5C\u4E3A\u524D\u7F00\u547D\u540D\uFF0C\u5E76\u5728\u4EFB\u52A1\u7ED3\u675F\u540E\u5220\u9664\uFF0C\u4E0D\u80FD\u5728\u5DE5\u4F5C\u76EE\u5F55\u4E2D\u7559\u4E0B\u4EFB\u4F55\u4E34\u65F6\u6587\u4EF6\u3002
24500
- 3.\u5C3D\u91CF\u4F7F\u7528"execute_command"\u3001"execute_js_code"\u5DE5\u5177\u5B8C\u6210\u4EFB\u52A1
24501
+ 3.\u5C3D\u91CF\u4F7F\u7528"execute_command"\u3001"execute_js_code"\u5DE5\u5177\u7ED3\u5408Nodejs\u4EE3\u7801\u5B8C\u6210\u4EFB\u52A1
24501
24502
  4.\u786C\u6027\u89C4\u5219\uFF1A\u65E0\u8BBA\u6846\u67B6\u5185\u7F6E\u82F1\u6587\u6A21\u677F\uFF0C\u4F60\u7684\u6BCF\u4E00\u6B65\u601D\u8003\uFF08Thought\uFF09\u3001\u89C2\u5BDF\u5206\u6790\u3001\u7ED3\u8BBA\u56DE\u7B54\uFF0C**\u4E25\u683C\u4F7F\u7528\u7B80\u4F53\u4E2D\u6587**\uFF0C\u7981\u6B62\u82F1\u6587\u3002
24502
24503
 
24503
24504
  ${skillPrompt}
24505
+ `;
24506
+ return `
24507
+ ${params.systemPrompt + basePrompt}
24504
24508
  `;
24505
24509
  };
24506
24510
 
@@ -24737,9 +24741,8 @@ function toLangChainTool(func, description) {
24737
24741
  const wrappedFunc = async (args, runtime) => {
24738
24742
  try {
24739
24743
  const boundFunc = func.bind({
24740
- createSubAgent: async (prompt) => {
24741
- const subAgent = await runtime.context.curAgent.createSubAgent();
24742
- return subAgent.execute(prompt);
24744
+ createSubAgent: async (systemPrompt, prompt) => {
24745
+ return runtime.context.curAgent.subExecute(systemPrompt, prompt);
24743
24746
  },
24744
24747
  curAgent: runtime.context.curAgent
24745
24748
  });
@@ -24758,10 +24761,11 @@ function toLangChainTool(func, description) {
24758
24761
  schema
24759
24762
  });
24760
24763
  }
24761
- function scanUserTools(excludeTools) {
24762
- const files = _scanUserToolsFile();
24764
+ function scanUserTools(excludeTools, externalTools) {
24765
+ const files1 = _scanUserToolsFile();
24766
+ const files2 = _scanExternalToolsFile(externalTools);
24763
24767
  const tools = [];
24764
- files.forEach((toolFile) => {
24768
+ [...files1, ...files2].forEach((toolFile) => {
24765
24769
  _loadToolsFromFile(toolFile.filePath, tools, excludeTools);
24766
24770
  });
24767
24771
  return tools;
@@ -24792,6 +24796,52 @@ function getUserToolList() {
24792
24796
  });
24793
24797
  return toolOpts;
24794
24798
  }
24799
+ function _scanToolsFile(filePath) {
24800
+ let toolFile = null;
24801
+ if (import_fs_extra8.default.statSync(filePath).isDirectory()) {
24802
+ const subDirPath = import_path8.default.resolve(filePath);
24803
+ const subFiles = import_fs_extra8.default.readdirSync(subDirPath);
24804
+ const indexFile = subFiles.find((f) => f === "index.js" || f === "index.cjs");
24805
+ if (indexFile) {
24806
+ const filePath2 = _scanDeepFishJsFile(import_path8.default.resolve(subDirPath, indexFile));
24807
+ if (filePath2) {
24808
+ toolFile = {
24809
+ filePath: filePath2,
24810
+ dir: subDirPath
24811
+ };
24812
+ }
24813
+ } else {
24814
+ subFiles.forEach((subFile) => {
24815
+ const filePath2 = _scanDeepFishJsFile(import_path8.default.resolve(subDirPath, subFile));
24816
+ if (filePath2) {
24817
+ toolFile = {
24818
+ filePath: filePath2,
24819
+ dir: subDirPath
24820
+ };
24821
+ }
24822
+ });
24823
+ }
24824
+ } else {
24825
+ const toolfilePath = _scanDeepFishJsFile(filePath);
24826
+ if (toolfilePath) {
24827
+ toolFile = {
24828
+ filePath: toolfilePath,
24829
+ dir: null
24830
+ };
24831
+ }
24832
+ }
24833
+ return toolFile;
24834
+ }
24835
+ function _scanExternalToolsFile(externalTools) {
24836
+ const toolFiles = [];
24837
+ externalTools.forEach((filePath) => {
24838
+ const toolFile = _scanToolsFile(filePath);
24839
+ if (toolFile) {
24840
+ toolFiles.push(toolFile);
24841
+ }
24842
+ });
24843
+ return toolFiles;
24844
+ }
24795
24845
  function _scanUserToolsFile() {
24796
24846
  const toolFiles = [];
24797
24847
  const scanPaths = getScanDirPaths();
@@ -24803,45 +24853,18 @@ function _scanUserToolsFile() {
24803
24853
  if (import_fs_extra8.default.pathExistsSync(toolsDir)) {
24804
24854
  const files = import_fs_extra8.default.readdirSync(toolsDir);
24805
24855
  files.forEach((file2) => {
24806
- if (import_fs_extra8.default.statSync(import_path8.default.resolve(toolsDir, file2)).isDirectory()) {
24807
- const subDirPath = import_path8.default.resolve(toolsDir, file2);
24808
- const subFiles = import_fs_extra8.default.readdirSync(subDirPath);
24809
- const indexFile = subFiles.find((f) => f === "index.js" || f === "index.cjs");
24810
- if (indexFile) {
24811
- const filePath = _scanDeepFishJsFile(import_path8.default.resolve(subDirPath, indexFile), indexFile);
24812
- if (filePath) {
24813
- toolFiles.push({
24814
- filePath,
24815
- dir: subDirPath
24816
- });
24817
- }
24818
- } else {
24819
- subFiles.forEach((subFile) => {
24820
- const filePath = _scanDeepFishJsFile(import_path8.default.resolve(subDirPath, subFile), subFile);
24821
- if (filePath) {
24822
- toolFiles.push({
24823
- filePath,
24824
- dir: subDirPath
24825
- });
24826
- }
24827
- });
24828
- }
24829
- } else {
24830
- const filePath = _scanDeepFishJsFile(toolsDir, file2);
24831
- if (filePath) {
24832
- toolFiles.push({
24833
- filePath,
24834
- dir: null
24835
- });
24836
- }
24856
+ const filePath = import_path8.default.resolve(toolsDir, file2);
24857
+ const toolFile = _scanToolsFile(filePath);
24858
+ if (toolFile) {
24859
+ toolFiles.push(toolFile);
24837
24860
  }
24838
24861
  });
24839
24862
  }
24840
24863
  });
24841
24864
  return toolFiles;
24842
24865
  }
24843
- function _scanDeepFishJsFile(filePath, fileName) {
24844
- if (fileName.endsWith(".js") || fileName.endsWith(".cjs")) {
24866
+ function _scanDeepFishJsFile(filePath) {
24867
+ if (filePath.endsWith(".js") || filePath.endsWith(".cjs")) {
24845
24868
  const fileContent = import_fs_extra8.default.readFileSync(filePath, "utf-8");
24846
24869
  if (fileContent.includes("module.exports") && fileContent.includes("descriptions") && fileContent.includes("functions")) {
24847
24870
  return filePath;
@@ -24941,20 +24964,17 @@ var import_fs_extra9 = __toESM(require("fs-extra"));
24941
24964
 
24942
24965
  // src/agent/tools/subAgent.ts
24943
24966
  var import_langchain4 = require("langchain");
24944
- async function subAgentExec(prompt, runtime) {
24967
+ async function subAgentExec(systemPrompt, prompt, runtime) {
24945
24968
  const curAgent = runtime.context?.curAgent;
24946
- if (!curAgent || typeof curAgent.createSubAgent !== "function") {
24947
- throw new Error("\u5F53\u524D\u8FD0\u884C\u4E0A\u4E0B\u6587\u4E0D\u652F\u6301\u521B\u5EFA\u5B50 agent");
24948
- }
24949
- const subAgent = await curAgent.createSubAgent();
24950
- return subAgent.execute(prompt);
24969
+ return curAgent && curAgent.subExecute(systemPrompt, prompt);
24951
24970
  }
24952
24971
  var subAgentTool = (0, import_langchain4.tool)(
24953
- async ({ prompt }, runtime) => safeTool(() => subAgentExec(prompt, runtime)),
24972
+ async ({ systemPrompt, prompt }, runtime) => safeTool(() => subAgentExec(systemPrompt, prompt, runtime)),
24954
24973
  {
24955
24974
  name: "subAgent_exec",
24956
24975
  description: "\u521B\u5EFA\u4E00\u4E2A\u901A\u7528\u5B50 agent \u6765\u6267\u884C\u72EC\u7ACB\u4EFB\u52A1\uFF0C\u5E76\u8FD4\u56DE\u5B50 agent \u7684\u6267\u884C\u7ED3\u679C\u3002\u9002\u5408\u62C6\u5206\u590D\u6742\u4EFB\u52A1\u3001\u5E76\u884C\u8C03\u7814\u6216\u59D4\u6D3E\u5B50\u4EFB\u52A1\u3002",
24957
24976
  schema: external_exports.object({
24977
+ systemPrompt: external_exports.string().min(1).describe("\u5B50 agent \u7684\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF0C\u5B9A\u4E49\u5176\u89D2\u8272\u548C\u884C\u4E3A\u89C4\u8303"),
24958
24978
  prompt: external_exports.string().min(1).describe("\u4EA4\u7ED9\u901A\u7528\u5B50 agent \u6267\u884C\u7684\u5B8C\u6574\u4EFB\u52A1\u63CF\u8FF0")
24959
24979
  })
24960
24980
  }
@@ -25035,7 +25055,7 @@ var installPackageTool = (0, import_langchain5.tool)(
25035
25055
  );
25036
25056
  var executeJSCodeTool = (0, import_langchain5.tool)(async ({ code }, runtime) => safeTool(() => executeJSCode(code, runtime)), {
25037
25057
  name: "execute_js_code",
25038
- description: `\u6267\u884C\u4E00\u6BB5Node.js\u4EE3\u7801\u5E76\u8FD4\u56DE\u6267\u884C\u7ED3\u679C\u3002\u6CE8\u610F\uFF1A\u4EE3\u7801\u5FC5\u987B\u5305\u542B\u4E00\u4E2A__main()\u51FD\u6570\u4F5C\u4E3A\u6267\u884C\u5165\u53E3\uFF0C__main()\u51FD\u6570\u5185\u5FC5\u987B\u662F\u4E00\u4E2A\u4F7F\u7528async\u524D\u7F00\u7684\u51FD\u6570\u3002
25058
+ description: `\u6267\u884C\u4E00\u6BB5Node.js\u4EE3\u7801\u5E76\u8FD4\u56DE\u6267\u884C\u7ED3\u679C\u3002\u6CE8\u610F\uFF1A1.\u5982\u679C\u4EE3\u7801\u4E2D\u4F7F\u7528\u7B2C\u4E09\u65B9\u4F9D\u8D56\u5FC5\u987B\u5148\u4F7F\u7528check_package_installed\u5DE5\u5177\u68C0\u67E5\u5305\u662F\u5426\u5B89\u88C5\uFF0C\u5982\u679C\u672A\u5B89\u88C5\u9700\u8981\u6267\u884Cinstall_package\u5DE5\u5177\u5B89\u88C5\u6307\u5B9A\u7684npm\u5305;2.\u4EE3\u7801\u5FC5\u987B\u5305\u542B\u4E00\u4E2A__main()\u51FD\u6570\u4F5C\u4E3A\u6267\u884C\u5165\u53E3\uFF0C__main()\u51FD\u6570\u5185\u5FC5\u987B\u662F\u4E00\u4E2A\u4F7F\u7528async\u524D\u7F00\u7684\u51FD\u6570\u3002
25039
25059
  \u53EF\u7528\u5185\u7F6E\u51FD\u6570\uFF1A
25040
25060
  - agentExec(prompt: string): Promise<string>\uFF0C\u521B\u5EFA\u4E00\u4E2A\u901A\u7528\u5B50 agent \u6267\u884C\u6307\u5B9A\u4EFB\u52A1\u5E76\u8FD4\u56DE\u7ED3\u679C\uFF0C\u9002\u5408\u5C06\u590D\u6742\u4EFB\u52A1\u62C6\u5206\u7ED9\u5B50 agent \u5B8C\u6210\u3002
25041
25061
  \u793A\u4F8B\u4EE3\u7801\uFF1A
@@ -25731,7 +25751,10 @@ Commands:
25731
25751
  ai skills generate xxx \u6839\u636E\u63CF\u8FF0\u751F\u6210\u4E00\u4E2A\u65B0\u7684\u6280\u80FD\u6A21\u677F
25732
25752
 
25733
25753
  # Tools commands
25754
+ ai tools ls \u67E5\u770B\u5DF2\u5B89\u88C5\u6216\u5DF2\u914D\u7F6E\u7684\u5DE5\u5177\u5217\u8868
25734
25755
  ai tools dir \u6253\u5F00\u6216\u8F93\u51FA\u7528\u6237\u81EA\u5B9A\u4E49\u5DE5\u5177\u76EE\u5F55
25756
+ ai tools add <name> \u6DFB\u52A0\u6307\u5B9A\u540D\u79F0\u7684\u5DE5\u5177
25757
+ ai tools del <index> \u5220\u9664\u6307\u5B9A\u5E8F\u53F7\u7684\u81EA\u5B9A\u4E49\u5DE5\u5177
25735
25758
  ai tools generate xxx \u6839\u636E\u63CF\u8FF0\u751F\u6210\u4E00\u4E2A\u65B0\u7684\u5DE5\u5177\u6A21\u677F
25736
25759
 
25737
25760
  # Session commands
@@ -25743,9 +25766,16 @@ Commands:
25743
25766
  ai task add <task> \u5411\u4EFB\u52A1\u961F\u5217\u6DFB\u52A0\u4E00\u4E2A\u540E\u7EED\u4EFB\u52A1
25744
25767
  ai task del <index> \u5220\u9664\u6307\u5B9A\u5E8F\u53F7\u7684\u4EFB\u52A1
25745
25768
  ai task clear \u6E05\u7A7A\u5F53\u524D\u4EFB\u52A1\u961F\u5217
25769
+
25770
+ # Plan commands
25771
+ ai plan-do <\u4EFB\u52A1\u63CF\u8FF0> \u5C06\u590D\u6742\u4EFB\u52A1\u62C6\u89E3\u4E3A\u5B50\u4EFB\u52A1\u5E76\u9010\u6B65\u6267\u884C\u5B8C\u6210
25772
+ ai plan-continue \u7EE7\u7EED\u6267\u884C\u88AB\u4E2D\u65AD\u7684 plan-do \u4EFB\u52A1
25746
25773
 
25747
25774
  # MCP commands
25748
25775
  ai mcp edit \u6253\u5F00 MCP \u914D\u7F6E\u6587\u4EF6\u8FDB\u884C\u7F16\u8F91
25776
+ ai mcp ls \u67E5\u770B\u5DF2\u914D\u7F6E\u7684 MCP \u670D\u52A1\u5668\u5217\u8868
25777
+ ai mcp enable <name|index> \u542F\u7528\u6307\u5B9A\u540D\u79F0\u6216\u5E8F\u53F7\u7684 MCP \u670D\u52A1\u5668
25778
+ ai mcp disable <name|index> \u7981\u7528\u6307\u5B9A\u540D\u79F0\u6216\u5E8F\u53F7\u7684 MCP \u670D\u52A1\u5668
25749
25779
 
25750
25780
  # Serve commands
25751
25781
  ai serve \u542F\u52A8\u670D\u52A1\u6216\u8FDB\u5165\u670D\u52A1\u7BA1\u7406\u5165\u53E3
@@ -25833,14 +25863,14 @@ var builtinTools = [
25833
25863
  ...learnTools,
25834
25864
  ...fishInfoTools
25835
25865
  ];
25836
- async function getTools(excludeTools, excludeMCP) {
25837
- return [...builtinTools, ...await scanUserTools(excludeTools), ...await scanUserMcp(excludeMCP)];
25866
+ async function getTools(excludeTools, excludeMCP, externalTools = []) {
25867
+ return [...builtinTools, ...await scanUserTools(excludeTools, externalTools), ...await scanUserMcp(excludeMCP)];
25838
25868
  }
25839
25869
 
25840
25870
  // src/agent/skills/index.ts
25841
25871
  var import_path17 = __toESM(require("path"));
25842
25872
  function getSkills() {
25843
- return [...getRegisteredSkills(), import_path17.default.join(__dirname, "./view-learn-cache.md")];
25873
+ return [...getRegisteredSkills(), import_path17.default.join(__dirname, "./skills/view-learn-cache.md"), import_path17.default.join(__dirname, "./skills/generate-skill.md"), import_path17.default.join(__dirname, "./skills/generate-tool.md")];
25844
25874
  }
25845
25875
 
25846
25876
  // src/agent/AIAgent/index.ts
@@ -25897,8 +25927,8 @@ var SubAIAgent = class _SubAIAgent extends import_eventemitter_super.EventEmitte
25897
25927
  if (this.subLevel > 2) {
25898
25928
  this.excludeTools.push("subAgent_exec");
25899
25929
  }
25900
- this.tools = await getTools(this.excludeTools, this.excludeMCP);
25901
- this.skills = [...getSkills(), ...this.opt.skills || []];
25930
+ this.tools = await getTools(this.excludeTools, this.excludeMCP, this.opt.externalTools);
25931
+ this.skills = [...getSkills(), ...this.opt.externalSkills || []];
25902
25932
  const model = getModel(this.opt.modelOpt);
25903
25933
  const checkpointer = new FileSystemSaver({
25904
25934
  rootFolder: this.sessionDirPath
@@ -25919,7 +25949,13 @@ var SubAIAgent = class _SubAIAgent extends import_eventemitter_super.EventEmitte
25919
25949
  memoryFilePath: this.memoryFilePath,
25920
25950
  agentRulesPath: this.agentRulesPath,
25921
25951
  excludeSkills: this.excludeSkills
25922
- }) : subSystemPrompt(this.workspace, import_os3.default.platform(), this.skills, this.excludeSkills);
25952
+ }) : subSystemPrompt({
25953
+ systemPrompt: this.systemPrompt,
25954
+ workspace: this.workspace,
25955
+ osType: import_os3.default.platform(),
25956
+ skills: this.skills,
25957
+ excludeSkills: this.excludeSkills
25958
+ });
25923
25959
  const agent = (0, import_langchain18.createAgent)({
25924
25960
  model,
25925
25961
  checkpointer,
@@ -25932,14 +25968,6 @@ var SubAIAgent = class _SubAIAgent extends import_eventemitter_super.EventEmitte
25932
25968
  trigger: { tokens: this.opt.modelOpt.maxContextLength || 1e5 },
25933
25969
  keep: { messages: 50 }
25934
25970
  }),
25935
- (0, import_langchain18.humanInTheLoopMiddleware)({
25936
- interruptOn: {
25937
- install_package: {
25938
- allowedDecisions: ["approve", "reject"]
25939
- },
25940
- readEmailTool: false
25941
- }
25942
- }),
25943
25971
  (0, import_langchain18.todoListMiddleware)(),
25944
25972
  (0, import_deepagents.createPatchToolCallsMiddleware)()
25945
25973
  ],
@@ -25974,6 +26002,9 @@ var SubAIAgent = class _SubAIAgent extends import_eventemitter_super.EventEmitte
25974
26002
  resolve(msg);
25975
26003
  });
25976
26004
  for await (const [_namespace, mode, data] of stream) {
26005
+ if (Array.isArray(_namespace) && _namespace.length > 0) {
26006
+ continue;
26007
+ }
25977
26008
  if (mode === "messages") {
25978
26009
  const message = data[0].additional_kwargs.reasoning_content;
25979
26010
  this.emit("STREAM_CONTENT_OUTPUT" /* STREAM_CONTENT_OUTPUT */, message);
@@ -26089,8 +26120,8 @@ var AIAgent = class extends import_eventemitter_super2.EventEmitterSuper {
26089
26120
  this.maxSubAgentCount = opt.maxSubAgentCount || 2;
26090
26121
  }
26091
26122
  async init() {
26092
- this.tools = await getTools(this.excludeTools, this.excludeMCP);
26093
- this.skills = [...getSkills(), ...this.opt.skills || []];
26123
+ this.tools = await getTools(this.excludeTools, this.excludeMCP, this.opt.externalTools);
26124
+ this.skills = [...getSkills(), ...this.opt.externalSkills || []];
26094
26125
  const model = getModel(this.opt.modelOpt);
26095
26126
  const checkpointer = new FileSystemSaver({
26096
26127
  rootFolder: this.sessionDirPath
@@ -26115,14 +26146,6 @@ var AIAgent = class extends import_eventemitter_super2.EventEmitterSuper {
26115
26146
  trigger: { tokens: this.opt.modelOpt.maxContextLength || 1e5 },
26116
26147
  keep: { messages: 50 }
26117
26148
  }),
26118
- (0, import_langchain19.humanInTheLoopMiddleware)({
26119
- interruptOn: {
26120
- install_package: {
26121
- allowedDecisions: ["approve", "reject"]
26122
- },
26123
- readEmailTool: false
26124
- }
26125
- }),
26126
26149
  (0, import_langchain19.todoListMiddleware)(),
26127
26150
  (0, import_deepagents2.createPatchToolCallsMiddleware)()
26128
26151
  ],
@@ -26162,6 +26185,9 @@ var AIAgent = class extends import_eventemitter_super2.EventEmitterSuper {
26162
26185
  }
26163
26186
  );
26164
26187
  for await (const [_namespace, mode, data] of stream) {
26188
+ if (Array.isArray(_namespace) && _namespace.length > 0) {
26189
+ continue;
26190
+ }
26165
26191
  if (mode === "messages") {
26166
26192
  const message = data?.[0];
26167
26193
  const reasoning_content = message?.additional_kwargs?.reasoning_content;
@@ -26227,11 +26253,16 @@ var AIAgent = class extends import_eventemitter_super2.EventEmitterSuper {
26227
26253
  this.on("USE_TOOL_AFTER" /* USE_TOOL_AFTER */, (_toolId, _funcName, _funcArgs) => {
26228
26254
  });
26229
26255
  }
26230
- async createSubAgent() {
26256
+ async createSubAgent(systemPrompt) {
26231
26257
  const subAgent = new SubAIAgent(this.opt);
26258
+ systemPrompt && (subAgent.systemPrompt = systemPrompt);
26232
26259
  await subAgent.init();
26233
26260
  return subAgent;
26234
26261
  }
26262
+ async subExecute(systemPrompt, prompt) {
26263
+ const subAgent = await this.createSubAgent(systemPrompt);
26264
+ return subAgent.execute(prompt);
26265
+ }
26235
26266
  destory() {
26236
26267
  this.removeAllListeners();
26237
26268
  }
@@ -26484,7 +26515,7 @@ async function initAgent(config2, skills) {
26484
26515
  // CLI encoding format, can be set to utf-8, gbk, etc., or left empty for auto-detection
26485
26516
  maxSubAgentCount: config2.maxSubAgentCount,
26486
26517
  // Maximum parallel sub-agent execution count, -1 means unlimited
26487
- skills,
26518
+ externalSkills: skills,
26488
26519
  isPrintThinking: config2.isPrintThinking
26489
26520
  // Whether to print intermediate information during AI thinking, default is true
26490
26521
  });
@@ -26680,7 +26711,11 @@ function handleSkillsLs() {
26680
26711
  logInfo("No skills registered yet");
26681
26712
  } else {
26682
26713
  skills.forEach((skill, index) => {
26683
- logInfo(`[${index}] ${skill.name} (${skill.isEnabled ? "enabled" : "disabled"})`);
26714
+ if (skill.isEnabled) {
26715
+ logSuccess(`[${index}] ${skill.name} [\u221A]`);
26716
+ } else {
26717
+ logInfo(`[${index}] ${skill.name} [\xD7]`);
26718
+ }
26684
26719
  });
26685
26720
  }
26686
26721
  logInfo("=".repeat(50));
@@ -26814,7 +26849,7 @@ async function handleSkillsGenerate(target) {
26814
26849
  logError("Failed to start service, please check config or port availability");
26815
26850
  return;
26816
26851
  }
26817
- const generateSkillPath = import_path20.default.join(__dirname, "./generate-skill.md");
26852
+ const generateSkillPath = import_path20.default.join(__dirname, "./skills/generate-skill.md");
26818
26853
  const agent = await initAgent(config2, [generateSkillPath]);
26819
26854
  const prompt = `\u8BF7\u6839\u636E\u4EE5\u4E0B\u9700\u6C42\u751F\u6210\u4E00\u4E2ASkill\u6A21\u5757\uFF1A${target}
26820
26855
 
@@ -26848,11 +26883,13 @@ function _scanSkills(skillsDir) {
26848
26883
  }
26849
26884
  function _updateRegister(skillsDir) {
26850
26885
  const registerPath = _getRegisterPath(skillsDir);
26851
- if (import_fs_extra20.default.existsSync(skillsDir) && !import_fs_extra20.default.existsSync(registerPath)) {
26852
- import_fs_extra20.default.writeJSONSync(registerPath, [], { spaces: 2 });
26853
- } else if (!import_fs_extra20.default.existsSync(skillsDir)) {
26886
+ if (!import_fs_extra20.default.existsSync(skillsDir)) {
26854
26887
  return;
26855
26888
  }
26889
+ if (!import_fs_extra20.default.existsSync(registerPath)) {
26890
+ import_fs_extra20.default.ensureDirSync(import_path20.default.dirname(registerPath));
26891
+ import_fs_extra20.default.writeJSONSync(registerPath, [], { spaces: 2 });
26892
+ }
26856
26893
  const skills = _scanSkills(skillsDir);
26857
26894
  let register = import_fs_extra20.default.readJSONSync(registerPath);
26858
26895
  const newRegister = [];
@@ -26860,11 +26897,15 @@ function _updateRegister(skillsDir) {
26860
26897
  const skillName = import_path20.default.basename(skillPath);
26861
26898
  const existItem = register.find((item) => item.skillPath === skillPath);
26862
26899
  if (!existItem) {
26900
+ let skillFilePath = skillPath;
26901
+ if (import_fs_extra20.default.statSync(skillPath).isDirectory()) {
26902
+ skillFilePath = import_path20.default.join(skillFilePath, "SKILL.md");
26903
+ }
26863
26904
  newRegister.push({
26864
26905
  id: (0, import_crypto6.randomUUID)(),
26865
26906
  name: skillName,
26866
26907
  isEnabled: true,
26867
- skillPath
26908
+ skillPath: skillFilePath
26868
26909
  });
26869
26910
  }
26870
26911
  });
@@ -26876,8 +26917,9 @@ function getRegisteredSkills() {
26876
26917
  const scanPaths = getScanDirPaths();
26877
26918
  const skills = [];
26878
26919
  scanPaths.forEach((scanPath) => {
26879
- _updateRegister(scanPath);
26880
- const registerPath = _getRegisterPath(scanPath);
26920
+ const scanDir = import_path20.default.join(scanPath, "skills");
26921
+ _updateRegister(scanDir);
26922
+ const registerPath = _getRegisterPath(scanDir);
26881
26923
  if (import_fs_extra20.default.existsSync(registerPath)) {
26882
26924
  const register = import_fs_extra20.default.readJSONSync(registerPath);
26883
26925
  register.forEach((item) => {
@@ -26903,7 +26945,8 @@ function _getAllSkills() {
26903
26945
  const scanPaths = getScanDirPaths();
26904
26946
  let allSkills = [];
26905
26947
  scanPaths.forEach((scanPath) => {
26906
- const skills = _getSkillList(scanPath);
26948
+ const scanDir = import_path20.default.join(scanPath, "skills");
26949
+ const skills = _getSkillList(scanDir);
26907
26950
  skills.map((item) => {
26908
26951
  item.skillDir = scanPath;
26909
26952
  return item;
@@ -26913,10 +26956,12 @@ function _getAllSkills() {
26913
26956
  return allSkills;
26914
26957
  }
26915
26958
  function _getRegisterPath(skillsDir) {
26916
- if (skillsDir.endsWith("@deepfish-ai")) {
26917
- return import_path20.default.join(skillsDir, "register.json");
26959
+ const normalizedDir = import_path20.default.normalize(skillsDir);
26960
+ const baseName = import_path20.default.basename(normalizedDir).toLowerCase();
26961
+ if (baseName === "@deepfish-ai" || baseName === "skills") {
26962
+ return import_path20.default.join(normalizedDir, "register.json");
26918
26963
  }
26919
- return import_path20.default.join(skillsDir, "skills", "register.json");
26964
+ return import_path20.default.join(normalizedDir, "skills", "register.json");
26920
26965
  }
26921
26966
 
26922
26967
  // src/cli/cli-skills.ts
@@ -27034,7 +27079,7 @@ async function handleToolsGenerate(target) {
27034
27079
  logError("Failed to start service, please check config or port availability");
27035
27080
  return;
27036
27081
  }
27037
- const generateSkillPath = import_path21.default.join(__dirname, "./generate-tool.md");
27082
+ const generateSkillPath = import_path21.default.join(__dirname, "./skills/generate-tool.md");
27038
27083
  const agent = await initAgent(config2, [generateSkillPath]);
27039
27084
  const prompt = `Please use the "generate-tool" SKILL to generate a tool module according to the following requirements: ${target}
27040
27085
 
@@ -27170,21 +27215,92 @@ function registerTaskCommands(program) {
27170
27215
  }
27171
27216
 
27172
27217
  // src/cli/cli-core/mcp.ts
27218
+ var import_fs_extra22 = __toESM(require("fs-extra"));
27173
27219
  function handleMcpEdit() {
27174
27220
  const mcpPath = getMCPFilePath();
27175
27221
  editFile(mcpPath);
27176
27222
  }
27223
+ function readMcpConfig() {
27224
+ const mcpPath = getMCPFilePath();
27225
+ return import_fs_extra22.default.readJSONSync(mcpPath);
27226
+ }
27227
+ function writeMcpConfig(data) {
27228
+ const mcpPath = getMCPFilePath();
27229
+ import_fs_extra22.default.writeJSONSync(mcpPath, data, { spaces: 2 });
27230
+ }
27231
+ function handleMcpLs() {
27232
+ const config2 = readMcpConfig();
27233
+ const servers = config2.mcpServers || {};
27234
+ const entries = Object.entries(servers);
27235
+ if (entries.length === 0) {
27236
+ logWarning("No MCP servers configured yet");
27237
+ return;
27238
+ }
27239
+ logInfo("=".repeat(50));
27240
+ entries.forEach(([name, server], index) => {
27241
+ const disabled = server.disabled === true;
27242
+ if (disabled) {
27243
+ logInfo(`[${index}] ${name} [\xD7]`);
27244
+ } else {
27245
+ logSuccess(`[${index}] ${name} [\u221A]`);
27246
+ }
27247
+ });
27248
+ logInfo("=".repeat(50));
27249
+ }
27250
+ function handleMcpEnable(nameOrIndex) {
27251
+ const config2 = readMcpConfig();
27252
+ const servers = config2.mcpServers || {};
27253
+ const entries = Object.keys(servers);
27254
+ let targetIndex = -1;
27255
+ const index = parseInt(nameOrIndex, 10);
27256
+ if (!isNaN(index) && index >= 0 && index < entries.length) {
27257
+ targetIndex = index;
27258
+ } else {
27259
+ targetIndex = entries.findIndex((name) => name === nameOrIndex);
27260
+ }
27261
+ if (targetIndex === -1) {
27262
+ logError(`MCP server not found: ${nameOrIndex}`);
27263
+ return;
27264
+ }
27265
+ const serverName = entries[targetIndex];
27266
+ servers[serverName].disabled = false;
27267
+ writeMcpConfig(config2);
27268
+ logSuccess(`MCP server "${serverName}" enabled`);
27269
+ }
27270
+ function handleMcpDisable(nameOrIndex) {
27271
+ const config2 = readMcpConfig();
27272
+ const servers = config2.mcpServers || {};
27273
+ const entries = Object.keys(servers);
27274
+ let targetIndex = -1;
27275
+ const index = parseInt(nameOrIndex, 10);
27276
+ if (!isNaN(index) && index >= 0 && index < entries.length) {
27277
+ targetIndex = index;
27278
+ } else {
27279
+ targetIndex = entries.findIndex((name) => name === nameOrIndex);
27280
+ }
27281
+ if (targetIndex === -1) {
27282
+ logError(`MCP server not found: ${nameOrIndex}`);
27283
+ return;
27284
+ }
27285
+ const serverName = entries[targetIndex];
27286
+ servers[serverName].disabled = true;
27287
+ writeMcpConfig(config2);
27288
+ logSuccess(`MCP server "${serverName}" disabled`);
27289
+ }
27177
27290
 
27178
27291
  // src/cli/cli-mcp.ts
27179
27292
  function registerMcpCommands(program) {
27180
27293
  const mcp = program.command("mcp");
27181
27294
  mcp.command("edit").description("\u7F16\u8F91 MCP \u914D\u7F6E\u6587\u4EF6").action(handleMcpEdit);
27295
+ mcp.command("ls").description("\u5217\u51FA\u6240\u6709 MCP \u670D\u52A1\u5668").action(handleMcpLs);
27296
+ mcp.command("enable <nameOrIndex>").description("\u542F\u7528 MCP \u670D\u52A1\u5668").action(handleMcpEnable);
27297
+ mcp.command("disable <nameOrIndex>").description("\u7981\u7528 MCP \u670D\u52A1\u5668").action(handleMcpDisable);
27182
27298
  }
27183
27299
 
27184
27300
  // src/cli/cli-core/input.ts
27185
- var import_fs_extra22 = __toESM(require("fs-extra"));
27301
+ var import_fs_extra23 = __toESM(require("fs-extra"));
27186
27302
  var readline = __toESM(require("readline"));
27187
- async function handleInput(args) {
27303
+ async function handleInput(args, skills) {
27188
27304
  const input = args.join(" ");
27189
27305
  if (!input.trim()) {
27190
27306
  logError("Please enter content");
@@ -27192,7 +27308,7 @@ async function handleInput(args) {
27192
27308
  }
27193
27309
  try {
27194
27310
  const configPath = getConfigPath();
27195
- if (!import_fs_extra22.default.pathExistsSync(configPath)) {
27311
+ if (!import_fs_extra23.default.pathExistsSync(configPath)) {
27196
27312
  logError("Config file not found, please run init first");
27197
27313
  return;
27198
27314
  }
@@ -27207,7 +27323,7 @@ async function handleInput(args) {
27207
27323
  logError("Failed to start service, please check config or port availability");
27208
27324
  return;
27209
27325
  }
27210
- const agent = await initAgent(config2);
27326
+ const agent = await initAgent(config2, skills);
27211
27327
  const connResult = await connectAgentRoom(agent);
27212
27328
  if (!connResult.ok) {
27213
27329
  if (connResult.reason === "duplicate-id") {
@@ -27229,7 +27345,7 @@ async function handleInput(args) {
27229
27345
  async function multiInput() {
27230
27346
  try {
27231
27347
  const configPath = getConfigPath();
27232
- if (!import_fs_extra22.default.pathExistsSync(configPath)) {
27348
+ if (!import_fs_extra23.default.pathExistsSync(configPath)) {
27233
27349
  logError("Config file not found, please run init first");
27234
27350
  return;
27235
27351
  }
@@ -27286,6 +27402,53 @@ async function multiInput() {
27286
27402
  }
27287
27403
  }
27288
27404
 
27405
+ // src/cli/cli-core/plan.ts
27406
+ var import_path22 = __toESM(require("path"));
27407
+ async function handlePlan(args) {
27408
+ const input = args.join(" ");
27409
+ if (!input.trim()) {
27410
+ logError("Please enter content");
27411
+ return;
27412
+ }
27413
+ const skillPrompt = `\u4F7F\u7528SKILL-"planning-do"\u5C06\u7528\u6237\u4EFB\u52A1\u5206\u89E3\u5E76\u5B8C\u6210\uFF0C\u4EE5\u4E0B\u662F\u7528\u6237\u76EE\u6807\uFF1A${input}`;
27414
+ const skillPath = import_path22.default.join(__dirname, "./skills/planning-do.md");
27415
+ await handleInput([skillPrompt], [skillPath]);
27416
+ }
27417
+ async function handlePlanContinue() {
27418
+ const skillPrompt = `
27419
+ \u76EE\u524D\u4EFB\u52A1\u6267\u884C\u4E86\u4E00\u90E8\u5206\uFF0C\u9700\u8981\u7EE7\u7EED\u6267\u884C\u3002\u4F60\u8D1F\u8D23\u6309\u987A\u5E8F\u8C03\u5EA6\u6267\u884C tmp_tasklist.json \u4E2D\u7684\u5B50\u4EFB\u52A1\uFF0C\u5B8C\u6210 tmp_task_goal.md \u63CF\u8FF0\u7684\u6574\u4F53\u76EE\u6807\u3002
27420
+
27421
+ \u6267\u884C\u89C4\u5219\uFF1A
27422
+ 1. \u5148\u8BFB\u53D6 tmp_task_goal.md \u4E86\u89E3\u6574\u4F53\u76EE\u6807\uFF1B
27423
+ 2. \u8BFB\u53D6 tmp_tasklist.json\uFF0C\u4EC5\u5904\u7406 status \u4E3A "todo" \u6216 "doing" \u7684\u4EFB\u52A1\uFF1B
27424
+ 3. \u6BCF\u6B21\u901A\u8FC7\u521B\u5EFA\u5B50Agent\u53EA\u8C03\u5EA6\u4E00\u4E2A\u5B50\u4EFB\u52A1\uFF0C\u6309\u5217\u8868\u987A\u5E8F\u4F9D\u6B21\u6267\u884C\uFF1B
27425
+ 4. \u8C03\u5EA6\u524D\u5C06\u5F53\u524D\u4EFB\u52A1 status \u66F4\u65B0\u4E3A "doing" \u5E76\u5199\u56DE\u6587\u4EF6\uFF1B
27426
+ 5. \u5BF9\u6BCF\u4E2A\u5B50\u4EFB\u52A1\uFF0C\u5FC5\u987B\u521B\u5EFA\u4E00\u4E2A\u72EC\u7ACB\u7684\u5B50 Agent \u6765\u6267\u884C\uFF0C\u4E0D\u8981\u5728\u4E3B\u6D41\u7A0B\u4E2D\u76F4\u63A5\u5B8C\u6210\u5177\u4F53\u4EFB\u52A1\uFF1B
27427
+ 6. \u521B\u5EFA\u5B50 Agent \u65F6\uFF0C\u5C06\u6574\u4F53\u76EE\u6807\u3001\u5F53\u524D\u5B50\u4EFB\u52A1 id/name/description\u3001tmp_tasklist.json \u6587\u4EF6\u540D\u548C\u6267\u884C\u8981\u6C42\u4E00\u5E76\u4F20\u5165\uFF1B
27428
+ 7. \u5B50 Agent \u6267\u884C\u6210\u529F\u540E\uFF0C\u5C06\u5F53\u524D\u4EFB\u52A1 status \u66F4\u65B0\u4E3A "done"\uFF0C\u5E76\u8BB0\u5F55 finishedAt\uFF08ISO \u65F6\u95F4\uFF09\uFF1B
27429
+ 8. \u5B50 Agent \u6267\u884C\u5931\u8D25\u65F6\uFF0C\u5C06\u5F53\u524D\u4EFB\u52A1\u4FDD\u7559\u4E3A "doing" \u6216\u56DE\u9000\u4E3A "todo"\uFF0C\u5E76\u5728 note \u4E2D\u8BB0\u5F55\u5931\u8D25\u539F\u56E0\uFF1B
27430
+ 9. \u6BCF\u5B8C\u6210\u6216\u5931\u8D25\u4E00\u4E2A\u5B50\u4EFB\u52A1\uFF0C\u90FD\u5FC5\u987B\u7ACB\u5373\u5199\u56DE tmp_tasklist.json\uFF1B
27431
+ 10. \u5168\u90E8\u4EFB\u52A1\u5B8C\u6210\u540E\uFF0C\u5220\u9664 tmp_tasklist.json \u548C tmp_task_goal.md\u3002
27432
+
27433
+ \u5B50 Agent \u6267\u884C\u8981\u6C42\uFF1A
27434
+ - \u53EA\u6267\u884C\u5F53\u524D\u88AB\u5206\u914D\u7684\u4E00\u4E2A\u5B50\u4EFB\u52A1\uFF0C\u4E0D\u8981\u4FEE\u6539\u5176\u4ED6\u4EFB\u52A1\u72B6\u6001\uFF1B
27435
+ - \u6267\u884C\u524D\u9605\u8BFB tmp_task_goal.md\uFF0C\u7406\u89E3\u6574\u4F53\u76EE\u6807\uFF1B
27436
+ - \u5FC5\u8981\u65F6\u9605\u8BFB tmp_tasklist.json\uFF0C\u4E86\u89E3\u4E0A\u4E0B\u6587\u548C\u4EFB\u52A1\u4F9D\u8D56\uFF1B
27437
+ - \u5B8C\u6210\u540E\u5411\u4E3B Agent \u8FD4\u56DE\u6267\u884C\u7ED3\u679C\u3001\u4FEE\u6539\u7684\u6587\u4EF6\u3001\u5931\u8D25\u539F\u56E0\u6216\u540E\u7EED\u5EFA\u8BAE\u3002
27438
+
27439
+ \u8F93\u51FA\u8981\u6C42\uFF1A
27440
+ - \u8F93\u51FA\u5F53\u524D\u8C03\u5EA6\u7684\u4EFB\u52A1 id\u3001\u540D\u79F0\u3001\u6267\u884C\u7ED3\u679C\u72B6\u6001\u548C\u4E0B\u4E00\u6B65\u8BA1\u5212\uFF1B
27441
+ - \u4E0D\u8981\u8DF3\u8FC7\u72B6\u6001\u66F4\u65B0\u548C\u6587\u4EF6\u5199\u5165\u6B65\u9AA4\u3002
27442
+ `;
27443
+ await handleInput([skillPrompt]);
27444
+ }
27445
+
27446
+ // src/cli/cli-plan.ts
27447
+ function registerPlanCommands(program) {
27448
+ program.command("plan-do").description("\u5C06\u590D\u6742\u4EFB\u52A1\u62C6\u89E3\u4E3A\u5B50\u4EFB\u52A1\u5E76\u9010\u6B65\u6267\u884C\u5B8C\u6210").argument("[input...]", "\u4EFB\u52A1\u63CF\u8FF0").action((input) => handlePlan(input));
27449
+ program.command("plan-continue").description("\u7EE7\u7EED\u6267\u884C\u88AB\u4E2D\u65AD\u7684 plan-do \u4EFB\u52A1").action(() => handlePlanContinue());
27450
+ }
27451
+
27289
27452
  // src/cli/cli-input.ts
27290
27453
  function registerInputCommand(program) {
27291
27454
  program.argument("[inputs...]", "Natural language instruction or enter interactive mode").action(async (inputs) => {
@@ -27299,7 +27462,7 @@ function registerInputCommand(program) {
27299
27462
  }
27300
27463
 
27301
27464
  // src/cli/cli-core/cache.ts
27302
- var import_path22 = __toESM(require("path"));
27465
+ var import_path23 = __toESM(require("path"));
27303
27466
  var userCache2 = new UserCache();
27304
27467
  function resolveId(input) {
27305
27468
  const index = Number(input);
@@ -27333,7 +27496,7 @@ function handleCacheList() {
27333
27496
  function handleCacheEdit(input) {
27334
27497
  const id = resolveId(input);
27335
27498
  if (!id) return;
27336
- const filePath = import_path22.default.join(getUserStorePath(), `${id}.md`);
27499
+ const filePath = import_path23.default.join(getUserStorePath(), `${id}.md`);
27337
27500
  editFile(filePath);
27338
27501
  }
27339
27502
  function handleCacheDel(input) {
@@ -27378,6 +27541,7 @@ function main() {
27378
27541
  registerTaskCommands(program);
27379
27542
  registerCommonFlags(program);
27380
27543
  registerMcpCommands(program);
27544
+ registerPlanCommands(program);
27381
27545
  registerCacheCommands(program);
27382
27546
  registerHelpCommand(program);
27383
27547
  registerInputCommand(program);
@@ -23510,20 +23510,17 @@ var import_fs_extra7 = __toESM(require("fs-extra"));
23510
23510
 
23511
23511
  // src/agent/tools/subAgent.ts
23512
23512
  var import_langchain4 = require("langchain");
23513
- async function subAgentExec(prompt, runtime) {
23513
+ async function subAgentExec(systemPrompt, prompt, runtime) {
23514
23514
  const curAgent = runtime.context?.curAgent;
23515
- if (!curAgent || typeof curAgent.createSubAgent !== "function") {
23516
- throw new Error("\u5F53\u524D\u8FD0\u884C\u4E0A\u4E0B\u6587\u4E0D\u652F\u6301\u521B\u5EFA\u5B50 agent");
23517
- }
23518
- const subAgent = await curAgent.createSubAgent();
23519
- return subAgent.execute(prompt);
23515
+ return curAgent && curAgent.subExecute(systemPrompt, prompt);
23520
23516
  }
23521
23517
  var subAgentTool = (0, import_langchain4.tool)(
23522
- async ({ prompt }, runtime) => safeTool(() => subAgentExec(prompt, runtime)),
23518
+ async ({ systemPrompt, prompt }, runtime) => safeTool(() => subAgentExec(systemPrompt, prompt, runtime)),
23523
23519
  {
23524
23520
  name: "subAgent_exec",
23525
23521
  description: "\u521B\u5EFA\u4E00\u4E2A\u901A\u7528\u5B50 agent \u6765\u6267\u884C\u72EC\u7ACB\u4EFB\u52A1\uFF0C\u5E76\u8FD4\u56DE\u5B50 agent \u7684\u6267\u884C\u7ED3\u679C\u3002\u9002\u5408\u62C6\u5206\u590D\u6742\u4EFB\u52A1\u3001\u5E76\u884C\u8C03\u7814\u6216\u59D4\u6D3E\u5B50\u4EFB\u52A1\u3002",
23526
23522
  schema: external_exports.object({
23523
+ systemPrompt: external_exports.string().min(1).describe("\u5B50 agent \u7684\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF0C\u5B9A\u4E49\u5176\u89D2\u8272\u548C\u884C\u4E3A\u89C4\u8303"),
23527
23524
  prompt: external_exports.string().min(1).describe("\u4EA4\u7ED9\u901A\u7528\u5B50 agent \u6267\u884C\u7684\u5B8C\u6574\u4EFB\u52A1\u63CF\u8FF0")
23528
23525
  })
23529
23526
  }
@@ -23604,7 +23601,7 @@ var installPackageTool = (0, import_langchain5.tool)(
23604
23601
  );
23605
23602
  var executeJSCodeTool = (0, import_langchain5.tool)(async ({ code }, runtime) => safeTool(() => executeJSCode(code, runtime)), {
23606
23603
  name: "execute_js_code",
23607
- description: `\u6267\u884C\u4E00\u6BB5Node.js\u4EE3\u7801\u5E76\u8FD4\u56DE\u6267\u884C\u7ED3\u679C\u3002\u6CE8\u610F\uFF1A\u4EE3\u7801\u5FC5\u987B\u5305\u542B\u4E00\u4E2A__main()\u51FD\u6570\u4F5C\u4E3A\u6267\u884C\u5165\u53E3\uFF0C__main()\u51FD\u6570\u5185\u5FC5\u987B\u662F\u4E00\u4E2A\u4F7F\u7528async\u524D\u7F00\u7684\u51FD\u6570\u3002
23604
+ description: `\u6267\u884C\u4E00\u6BB5Node.js\u4EE3\u7801\u5E76\u8FD4\u56DE\u6267\u884C\u7ED3\u679C\u3002\u6CE8\u610F\uFF1A1.\u5982\u679C\u4EE3\u7801\u4E2D\u4F7F\u7528\u7B2C\u4E09\u65B9\u4F9D\u8D56\u5FC5\u987B\u5148\u4F7F\u7528check_package_installed\u5DE5\u5177\u68C0\u67E5\u5305\u662F\u5426\u5B89\u88C5\uFF0C\u5982\u679C\u672A\u5B89\u88C5\u9700\u8981\u6267\u884Cinstall_package\u5DE5\u5177\u5B89\u88C5\u6307\u5B9A\u7684npm\u5305;2.\u4EE3\u7801\u5FC5\u987B\u5305\u542B\u4E00\u4E2A__main()\u51FD\u6570\u4F5C\u4E3A\u6267\u884C\u5165\u53E3\uFF0C__main()\u51FD\u6570\u5185\u5FC5\u987B\u662F\u4E00\u4E2A\u4F7F\u7528async\u524D\u7F00\u7684\u51FD\u6570\u3002
23608
23605
  \u53EF\u7528\u5185\u7F6E\u51FD\u6570\uFF1A
23609
23606
  - agentExec(prompt: string): Promise<string>\uFF0C\u521B\u5EFA\u4E00\u4E2A\u901A\u7528\u5B50 agent \u6267\u884C\u6307\u5B9A\u4EFB\u52A1\u5E76\u8FD4\u56DE\u7ED3\u679C\uFF0C\u9002\u5408\u5C06\u590D\u6742\u4EFB\u52A1\u62C6\u5206\u7ED9\u5B50 agent \u5B8C\u6210\u3002
23610
23607
  \u793A\u4F8B\u4EE3\u7801\uFF1A
@@ -24218,7 +24215,10 @@ Commands:
24218
24215
  ai skills generate xxx \u6839\u636E\u63CF\u8FF0\u751F\u6210\u4E00\u4E2A\u65B0\u7684\u6280\u80FD\u6A21\u677F
24219
24216
 
24220
24217
  # Tools commands
24218
+ ai tools ls \u67E5\u770B\u5DF2\u5B89\u88C5\u6216\u5DF2\u914D\u7F6E\u7684\u5DE5\u5177\u5217\u8868
24221
24219
  ai tools dir \u6253\u5F00\u6216\u8F93\u51FA\u7528\u6237\u81EA\u5B9A\u4E49\u5DE5\u5177\u76EE\u5F55
24220
+ ai tools add <name> \u6DFB\u52A0\u6307\u5B9A\u540D\u79F0\u7684\u5DE5\u5177
24221
+ ai tools del <index> \u5220\u9664\u6307\u5B9A\u5E8F\u53F7\u7684\u81EA\u5B9A\u4E49\u5DE5\u5177
24222
24222
  ai tools generate xxx \u6839\u636E\u63CF\u8FF0\u751F\u6210\u4E00\u4E2A\u65B0\u7684\u5DE5\u5177\u6A21\u677F
24223
24223
 
24224
24224
  # Session commands
@@ -24230,9 +24230,16 @@ Commands:
24230
24230
  ai task add <task> \u5411\u4EFB\u52A1\u961F\u5217\u6DFB\u52A0\u4E00\u4E2A\u540E\u7EED\u4EFB\u52A1
24231
24231
  ai task del <index> \u5220\u9664\u6307\u5B9A\u5E8F\u53F7\u7684\u4EFB\u52A1
24232
24232
  ai task clear \u6E05\u7A7A\u5F53\u524D\u4EFB\u52A1\u961F\u5217
24233
+
24234
+ # Plan commands
24235
+ ai plan-do <\u4EFB\u52A1\u63CF\u8FF0> \u5C06\u590D\u6742\u4EFB\u52A1\u62C6\u89E3\u4E3A\u5B50\u4EFB\u52A1\u5E76\u9010\u6B65\u6267\u884C\u5B8C\u6210
24236
+ ai plan-continue \u7EE7\u7EED\u6267\u884C\u88AB\u4E2D\u65AD\u7684 plan-do \u4EFB\u52A1
24233
24237
 
24234
24238
  # MCP commands
24235
24239
  ai mcp edit \u6253\u5F00 MCP \u914D\u7F6E\u6587\u4EF6\u8FDB\u884C\u7F16\u8F91
24240
+ ai mcp ls \u67E5\u770B\u5DF2\u914D\u7F6E\u7684 MCP \u670D\u52A1\u5668\u5217\u8868
24241
+ ai mcp enable <name|index> \u542F\u7528\u6307\u5B9A\u540D\u79F0\u6216\u5E8F\u53F7\u7684 MCP \u670D\u52A1\u5668
24242
+ ai mcp disable <name|index> \u7981\u7528\u6307\u5B9A\u540D\u79F0\u6216\u5E8F\u53F7\u7684 MCP \u670D\u52A1\u5668
24236
24243
 
24237
24244
  # Serve commands
24238
24245
  ai serve \u542F\u52A8\u670D\u52A1\u6216\u8FDB\u5165\u670D\u52A1\u7BA1\u7406\u5165\u53E3
@@ -18,7 +18,7 @@ homepage: ''
18
18
 
19
19
  1. **目录创建**:在当前工作目录下新建一个子目录,目录名称应简洁明了地反映 Skill 功能(如 `web-scraper`、`code-reviewer`、`image-optimizer` 等)
20
20
  2. **核心文件**:目录中必须包含 `SKILL.md` 文件(文件名大小写敏感,必须为 `SKILL.md`)
21
- 3. **辅助文件**:如果 Skill 涉及复杂逻辑,可在目录中创建辅助脚本文件(如 `.js`、`.sh`、`.py` 等),并在 `SKILL.md` 中说明其用途和调用方式;如果是 js 文件,可以在函数中通过 `this.Tools` 调用内置函数,如直接使用 `this.Tools.createSubAgent(workGoal)`
21
+ 3. **辅助文件**:如果 Skill 涉及复杂逻辑,可在目录中创建辅助脚本文件(如 `.js`、`.sh`、`.py` 等),并在 `SKILL.md` 中说明其用途和调用方式;如果是 js 文件,可以在函数中通过 `this.Tools` 调用内置函数,如直接使用 `this.Tools.createSubAgent(systemPrompt:string, workGoal:string)`
22
22
 
23
23
  #### 标准目录结构
24
24
 
@@ -85,7 +85,7 @@ module.exports = { functions, descriptions };
85
85
  1. 理解用户要生成的工具功能
86
86
  2. 在当前工作目录下创建 `deepfish-tool-{功能名}/` 目录
87
87
  3. 编写 `index.js`,导出 `functions` 和 `descriptions`
88
- 4. 对于需要Agent参与的复杂任务,可以直接使用 `this.createSubAgent(prompt: string)` 创建子 Agent 执行任务,并将任务说明作为 `prompt` 传入
88
+ 4. 对于需要Agent参与的复杂任务,可以直接使用 `this.createSubAgent(systemPrompt: string, prompt: string)` 创建子 Agent 执行任务,并将任务说明作为 `prompt` 传入
89
89
  5. 需要引入第三方模块时,需要将该tool创建成NodeJs项目,在tool中引入模块
90
90
 
91
91
  ## 生成说明文档
@@ -0,0 +1,94 @@
1
+ ---
2
+ name: 'planning-do'
3
+ description: '将复杂长任务拆分为子任务,通过子 Agent 逐步执行完成'
4
+ homepage: ''
5
+ ---
6
+
7
+ # 长任务规划执行 Skill
8
+
9
+ 当你收到一个复杂的长任务时,使用本 Skill 将其拆分为可执行的子任务,并通过子 Agent 逐步执行完成。
10
+
11
+ ## 工作流程
12
+
13
+ 整个流程分为两个阶段,**必须按顺序执行**:
14
+
15
+ ### 阶段一:创建任务列表
16
+
17
+ 创建一个子 Agent,传入以下系统提示词,让子 Agent 负责将用户目标拆解为子任务:
18
+
19
+ **子 Agent 系统提示词:**
20
+
21
+ ```
22
+ 你是任务分析专家,负责将用户的目标拆解为可执行的子任务。
23
+
24
+ 工作流程:
25
+ 1. 分析用户的任务描述,判断是否足够清晰具体;
26
+ 2. 如果用户描述模糊、缺少关键信息或存在多种可能性,**必须与用户交互来收敛需求**:
27
+ - 使用选择题方式让用户选择(如:"项目类型是 A. 前端项目 B. 后端项目 C. 全栈项目?")
28
+ - 结合输入框让用户补充具体信息(如:"请描述项目的核心功能")
29
+ - 一次最多问8个问题,避免一次性问太多
30
+ - 持续交互直到需求足够清晰,能够拆解为具体的子任务
31
+ 3. 将收敛后的完整需求作为用户的原始任务描述;
32
+ 4. 在当前目录创建 tmp_task_goal.md,记录收敛后的完整需求描述;
33
+ 5. 创建 tmp_tasklist.json,包含拆解后的子任务列表。
34
+
35
+ tmp_tasklist.json 格式要求:
36
+ - 必须是合法的 JSON 数组
37
+ - 每个任务对象包含以下字段:
38
+ - id: 任务唯一标识(字符串或数字)
39
+ - name: 任务名称(简洁明了)
40
+ - description: 任务详细说明
41
+ - status: 任务状态,初始为 "todo"
42
+ - createdAt: 创建时间(ISO 字符串)
43
+ - finishedAt: 完成时间(未完成时为 null)
44
+ - note: 备注(可为空字符串)
45
+
46
+ 拆分原则:
47
+ - 任务尽量原子化,每个任务只做一件事
48
+ - 任务之间尽量独立,减少依赖
49
+ - 按执行顺序排列
50
+
51
+ 输出要求:仅输出合法 JSON,不要输出解释文字。
52
+ ```
53
+
54
+ **子 Agent 的用户提示词:** 用户的原始任务描述。
55
+
56
+ ### 阶段二:执行任务列表
57
+
58
+ 创建一个子 Agent 作为调度管理器Agent读取任务列表并负责调度。执行每个子任务时,必须为该子任务再创建一个独立的子 Agent,由子 Agent 完成具体执行工作,调度管理器Agent 只负责状态流转、结果记录和继续调度下一个任务。
59
+
60
+ **调度管理器子Agent提示词:**
61
+
62
+ ```
63
+ 你负责按顺序调度执行 tmp_tasklist.json 中的子任务,完成 tmp_task_goal.md 描述的整体目标。
64
+
65
+ 执行规则:
66
+ 1. 先读取 tmp_task_goal.md 了解整体目标;
67
+ 2. 读取 tmp_tasklist.json,仅处理 status 为 "todo" 或 "doing" 的任务;
68
+ 3. 每次通过创建子Agent只调度一个子任务,按列表顺序依次执行;
69
+ 4. 调度前将当前任务 status 更新为 "doing" 并写回文件;
70
+ 5. 对每个子任务,必须创建一个独立的子 Agent 来执行,不要在主流程中直接完成具体任务;
71
+ 6. 创建子 Agent 时,将整体目标、当前子任务 id/name/description、tmp_tasklist.json 文件名和执行要求一并传入;
72
+ 7. 子 Agent 执行成功后,将当前任务 status 更新为 "done",并记录 finishedAt(ISO 时间);
73
+ 8. 子 Agent 执行失败时,将当前任务保留为 "doing" 或回退为 "todo",并在 note 中记录失败原因;
74
+ 9. 每完成或失败一个子任务,都必须立即写回 tmp_tasklist.json;
75
+ 10. 全部任务完成后,删除 tmp_tasklist.json 和 tmp_task_goal.md。
76
+
77
+ 子 Agent 执行要求:
78
+ - 只执行当前被分配的一个子任务,不要修改其他任务状态;
79
+ - 执行前阅读 tmp_task_goal.md,理解整体目标;
80
+ - 必要时阅读 tmp_tasklist.json,了解上下文和任务依赖;
81
+ - 完成后向主 Agent 返回执行结果、修改的文件、失败原因或后续建议。
82
+
83
+ 输出要求:
84
+ - 输出当前调度的任务 id、名称、执行结果状态和下一步计划;
85
+ - 不要跳过状态更新和文件写入步骤。
86
+ ```
87
+
88
+ ## 注意事项
89
+
90
+ 1. **必须分两个阶段执行**:先创建任务列表,再执行任务列表,不能合并
91
+ 2. **子 Agent 只做一件事**:阶段一只负责拆解任务,阶段二只负责按顺序执行
92
+ 3. **文件持久化**:任务状态通过 `tmp_tasklist.json` 文件持久化,子 Agent 崩溃后可以重新读取继续执行
93
+ 4. **清理临时文件**:全部任务完成后必须删除 `tmp_tasklist.json` 和 `tmp_task_goal.md`
94
+ 5. **原子化执行**:每个子任务只做一件事,执行完立即更新状态并写回文件
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepfish-ai",
3
- "version": "2.0.11",
3
+ "version": "2.0.13",
4
4
  "private": false,
5
5
  "description": "An efficient AI-driven command-line tool designed to bridge the gap between natural language and operating system commands, file operations, and more. It enables non-developers to quickly generate executable instructions through simple natural language descriptions, significantly improving terminal operation efficiency.",
6
6
  "repository": {
@@ -27,7 +27,7 @@
27
27
  "dist/"
28
28
  ],
29
29
  "scripts": {
30
- "build": "tsup && npm run build:ui",
30
+ "build": "tsup && node -e \"const fs=require('fs-extra'),p=require('path');const src=p.join(process.cwd(),'src/agent/skills'),dst=p.join(process.cwd(),'dist/skills');fs.ensureDirSync(dst);fs.readdirSync(src).filter(f=>f.endsWith('.md')).forEach(f=>fs.copySync(p.join(src,f),p.join(dst,f)))\" && npm run build:ui",
31
31
  "build:ui": "vite build && vite build --config vite.server.config.ts",
32
32
  "dev": "tsx src/cli/index.ts",
33
33
  "format": "prettier --write \"src/**/*.{ts,js,json,css,md}\"",