deepfish-ai 2.0.11 → 2.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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,20 @@ ai "我刚问了一个什么问题"
183
184
  | `ai tasks del <index>` | 删除指定任务 |
184
185
  | `ai tasks clear` | 清除所有任务 |
185
186
 
187
+ ### 长任务规划
188
+
189
+ | 命令 | 说明 |
190
+ | ------------------------- | ------------------------------------------ |
191
+ | `ai plan-do <任务描述>` | 将复杂任务拆解为子任务并逐步执行完成 |
192
+
186
193
  ### MCP 管理
187
194
 
188
- | 命令 | 说明 |
189
- | ------------- | ------------- |
190
- | `ai mcp edit` | 编辑 MCP 配置 |
195
+ | 命令 | 说明 |
196
+ | --------------------------------- | ---------------- |
197
+ | `ai mcp ls` | 列出所有 MCP 服务器 |
198
+ | `ai mcp edit` | 编辑 MCP 配置 |
199
+ | `ai mcp enable <name\|index>` | 启用 MCP 服务器 |
200
+ | `ai mcp disable <name\|index>` | 禁用 MCP 服务器 |
191
201
 
192
202
  ### 服务管理
193
203
 
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,15 @@ 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
25746
25772
 
25747
25773
  # MCP commands
25748
25774
  ai mcp edit \u6253\u5F00 MCP \u914D\u7F6E\u6587\u4EF6\u8FDB\u884C\u7F16\u8F91
25775
+ ai mcp ls \u67E5\u770B\u5DF2\u914D\u7F6E\u7684 MCP \u670D\u52A1\u5668\u5217\u8868
25776
+ ai mcp enable <name|index> \u542F\u7528\u6307\u5B9A\u540D\u79F0\u6216\u5E8F\u53F7\u7684 MCP \u670D\u52A1\u5668
25777
+ ai mcp disable <name|index> \u7981\u7528\u6307\u5B9A\u540D\u79F0\u6216\u5E8F\u53F7\u7684 MCP \u670D\u52A1\u5668
25749
25778
 
25750
25779
  # Serve commands
25751
25780
  ai serve \u542F\u52A8\u670D\u52A1\u6216\u8FDB\u5165\u670D\u52A1\u7BA1\u7406\u5165\u53E3
@@ -25833,14 +25862,14 @@ var builtinTools = [
25833
25862
  ...learnTools,
25834
25863
  ...fishInfoTools
25835
25864
  ];
25836
- async function getTools(excludeTools, excludeMCP) {
25837
- return [...builtinTools, ...await scanUserTools(excludeTools), ...await scanUserMcp(excludeMCP)];
25865
+ async function getTools(excludeTools, excludeMCP, externalTools = []) {
25866
+ return [...builtinTools, ...await scanUserTools(excludeTools, externalTools), ...await scanUserMcp(excludeMCP)];
25838
25867
  }
25839
25868
 
25840
25869
  // src/agent/skills/index.ts
25841
25870
  var import_path17 = __toESM(require("path"));
25842
25871
  function getSkills() {
25843
- return [...getRegisteredSkills(), import_path17.default.join(__dirname, "./view-learn-cache.md")];
25872
+ 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
25873
  }
25845
25874
 
25846
25875
  // src/agent/AIAgent/index.ts
@@ -25897,8 +25926,8 @@ var SubAIAgent = class _SubAIAgent extends import_eventemitter_super.EventEmitte
25897
25926
  if (this.subLevel > 2) {
25898
25927
  this.excludeTools.push("subAgent_exec");
25899
25928
  }
25900
- this.tools = await getTools(this.excludeTools, this.excludeMCP);
25901
- this.skills = [...getSkills(), ...this.opt.skills || []];
25929
+ this.tools = await getTools(this.excludeTools, this.excludeMCP, this.opt.externalTools);
25930
+ this.skills = [...getSkills(), ...this.opt.externalSkills || []];
25902
25931
  const model = getModel(this.opt.modelOpt);
25903
25932
  const checkpointer = new FileSystemSaver({
25904
25933
  rootFolder: this.sessionDirPath
@@ -25919,7 +25948,13 @@ var SubAIAgent = class _SubAIAgent extends import_eventemitter_super.EventEmitte
25919
25948
  memoryFilePath: this.memoryFilePath,
25920
25949
  agentRulesPath: this.agentRulesPath,
25921
25950
  excludeSkills: this.excludeSkills
25922
- }) : subSystemPrompt(this.workspace, import_os3.default.platform(), this.skills, this.excludeSkills);
25951
+ }) : subSystemPrompt({
25952
+ systemPrompt: this.systemPrompt,
25953
+ workspace: this.workspace,
25954
+ osType: import_os3.default.platform(),
25955
+ skills: this.skills,
25956
+ excludeSkills: this.excludeSkills
25957
+ });
25923
25958
  const agent = (0, import_langchain18.createAgent)({
25924
25959
  model,
25925
25960
  checkpointer,
@@ -25932,14 +25967,6 @@ var SubAIAgent = class _SubAIAgent extends import_eventemitter_super.EventEmitte
25932
25967
  trigger: { tokens: this.opt.modelOpt.maxContextLength || 1e5 },
25933
25968
  keep: { messages: 50 }
25934
25969
  }),
25935
- (0, import_langchain18.humanInTheLoopMiddleware)({
25936
- interruptOn: {
25937
- install_package: {
25938
- allowedDecisions: ["approve", "reject"]
25939
- },
25940
- readEmailTool: false
25941
- }
25942
- }),
25943
25970
  (0, import_langchain18.todoListMiddleware)(),
25944
25971
  (0, import_deepagents.createPatchToolCallsMiddleware)()
25945
25972
  ],
@@ -25974,6 +26001,9 @@ var SubAIAgent = class _SubAIAgent extends import_eventemitter_super.EventEmitte
25974
26001
  resolve(msg);
25975
26002
  });
25976
26003
  for await (const [_namespace, mode, data] of stream) {
26004
+ if (Array.isArray(_namespace) && _namespace.length > 0) {
26005
+ continue;
26006
+ }
25977
26007
  if (mode === "messages") {
25978
26008
  const message = data[0].additional_kwargs.reasoning_content;
25979
26009
  this.emit("STREAM_CONTENT_OUTPUT" /* STREAM_CONTENT_OUTPUT */, message);
@@ -26089,8 +26119,8 @@ var AIAgent = class extends import_eventemitter_super2.EventEmitterSuper {
26089
26119
  this.maxSubAgentCount = opt.maxSubAgentCount || 2;
26090
26120
  }
26091
26121
  async init() {
26092
- this.tools = await getTools(this.excludeTools, this.excludeMCP);
26093
- this.skills = [...getSkills(), ...this.opt.skills || []];
26122
+ this.tools = await getTools(this.excludeTools, this.excludeMCP, this.opt.externalTools);
26123
+ this.skills = [...getSkills(), ...this.opt.externalSkills || []];
26094
26124
  const model = getModel(this.opt.modelOpt);
26095
26125
  const checkpointer = new FileSystemSaver({
26096
26126
  rootFolder: this.sessionDirPath
@@ -26115,14 +26145,6 @@ var AIAgent = class extends import_eventemitter_super2.EventEmitterSuper {
26115
26145
  trigger: { tokens: this.opt.modelOpt.maxContextLength || 1e5 },
26116
26146
  keep: { messages: 50 }
26117
26147
  }),
26118
- (0, import_langchain19.humanInTheLoopMiddleware)({
26119
- interruptOn: {
26120
- install_package: {
26121
- allowedDecisions: ["approve", "reject"]
26122
- },
26123
- readEmailTool: false
26124
- }
26125
- }),
26126
26148
  (0, import_langchain19.todoListMiddleware)(),
26127
26149
  (0, import_deepagents2.createPatchToolCallsMiddleware)()
26128
26150
  ],
@@ -26162,6 +26184,9 @@ var AIAgent = class extends import_eventemitter_super2.EventEmitterSuper {
26162
26184
  }
26163
26185
  );
26164
26186
  for await (const [_namespace, mode, data] of stream) {
26187
+ if (Array.isArray(_namespace) && _namespace.length > 0) {
26188
+ continue;
26189
+ }
26165
26190
  if (mode === "messages") {
26166
26191
  const message = data?.[0];
26167
26192
  const reasoning_content = message?.additional_kwargs?.reasoning_content;
@@ -26227,11 +26252,16 @@ var AIAgent = class extends import_eventemitter_super2.EventEmitterSuper {
26227
26252
  this.on("USE_TOOL_AFTER" /* USE_TOOL_AFTER */, (_toolId, _funcName, _funcArgs) => {
26228
26253
  });
26229
26254
  }
26230
- async createSubAgent() {
26255
+ async createSubAgent(systemPrompt) {
26231
26256
  const subAgent = new SubAIAgent(this.opt);
26257
+ systemPrompt && (subAgent.systemPrompt = systemPrompt);
26232
26258
  await subAgent.init();
26233
26259
  return subAgent;
26234
26260
  }
26261
+ async subExecute(systemPrompt, prompt) {
26262
+ const subAgent = await this.createSubAgent(systemPrompt);
26263
+ return subAgent.execute(prompt);
26264
+ }
26235
26265
  destory() {
26236
26266
  this.removeAllListeners();
26237
26267
  }
@@ -26484,7 +26514,7 @@ async function initAgent(config2, skills) {
26484
26514
  // CLI encoding format, can be set to utf-8, gbk, etc., or left empty for auto-detection
26485
26515
  maxSubAgentCount: config2.maxSubAgentCount,
26486
26516
  // Maximum parallel sub-agent execution count, -1 means unlimited
26487
- skills,
26517
+ externalSkills: skills,
26488
26518
  isPrintThinking: config2.isPrintThinking
26489
26519
  // Whether to print intermediate information during AI thinking, default is true
26490
26520
  });
@@ -26680,7 +26710,11 @@ function handleSkillsLs() {
26680
26710
  logInfo("No skills registered yet");
26681
26711
  } else {
26682
26712
  skills.forEach((skill, index) => {
26683
- logInfo(`[${index}] ${skill.name} (${skill.isEnabled ? "enabled" : "disabled"})`);
26713
+ if (skill.isEnabled) {
26714
+ logSuccess(`[${index}] ${skill.name} [\u221A]`);
26715
+ } else {
26716
+ logInfo(`[${index}] ${skill.name} [\xD7]`);
26717
+ }
26684
26718
  });
26685
26719
  }
26686
26720
  logInfo("=".repeat(50));
@@ -26814,7 +26848,7 @@ async function handleSkillsGenerate(target) {
26814
26848
  logError("Failed to start service, please check config or port availability");
26815
26849
  return;
26816
26850
  }
26817
- const generateSkillPath = import_path20.default.join(__dirname, "./generate-skill.md");
26851
+ const generateSkillPath = import_path20.default.join(__dirname, "./skills/generate-skill.md");
26818
26852
  const agent = await initAgent(config2, [generateSkillPath]);
26819
26853
  const prompt = `\u8BF7\u6839\u636E\u4EE5\u4E0B\u9700\u6C42\u751F\u6210\u4E00\u4E2ASkill\u6A21\u5757\uFF1A${target}
26820
26854
 
@@ -26848,11 +26882,13 @@ function _scanSkills(skillsDir) {
26848
26882
  }
26849
26883
  function _updateRegister(skillsDir) {
26850
26884
  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)) {
26885
+ if (!import_fs_extra20.default.existsSync(skillsDir)) {
26854
26886
  return;
26855
26887
  }
26888
+ if (!import_fs_extra20.default.existsSync(registerPath)) {
26889
+ import_fs_extra20.default.ensureDirSync(import_path20.default.dirname(registerPath));
26890
+ import_fs_extra20.default.writeJSONSync(registerPath, [], { spaces: 2 });
26891
+ }
26856
26892
  const skills = _scanSkills(skillsDir);
26857
26893
  let register = import_fs_extra20.default.readJSONSync(registerPath);
26858
26894
  const newRegister = [];
@@ -26913,10 +26949,12 @@ function _getAllSkills() {
26913
26949
  return allSkills;
26914
26950
  }
26915
26951
  function _getRegisterPath(skillsDir) {
26916
- if (skillsDir.endsWith("@deepfish-ai")) {
26917
- return import_path20.default.join(skillsDir, "register.json");
26952
+ const normalizedDir = import_path20.default.normalize(skillsDir);
26953
+ const baseName = import_path20.default.basename(normalizedDir).toLowerCase();
26954
+ if (baseName === "@deepfish-ai" || baseName === "skills") {
26955
+ return import_path20.default.join(normalizedDir, "register.json");
26918
26956
  }
26919
- return import_path20.default.join(skillsDir, "skills", "register.json");
26957
+ return import_path20.default.join(normalizedDir, "skills", "register.json");
26920
26958
  }
26921
26959
 
26922
26960
  // src/cli/cli-skills.ts
@@ -27034,7 +27072,7 @@ async function handleToolsGenerate(target) {
27034
27072
  logError("Failed to start service, please check config or port availability");
27035
27073
  return;
27036
27074
  }
27037
- const generateSkillPath = import_path21.default.join(__dirname, "./generate-tool.md");
27075
+ const generateSkillPath = import_path21.default.join(__dirname, "./skills/generate-tool.md");
27038
27076
  const agent = await initAgent(config2, [generateSkillPath]);
27039
27077
  const prompt = `Please use the "generate-tool" SKILL to generate a tool module according to the following requirements: ${target}
27040
27078
 
@@ -27170,21 +27208,92 @@ function registerTaskCommands(program) {
27170
27208
  }
27171
27209
 
27172
27210
  // src/cli/cli-core/mcp.ts
27211
+ var import_fs_extra22 = __toESM(require("fs-extra"));
27173
27212
  function handleMcpEdit() {
27174
27213
  const mcpPath = getMCPFilePath();
27175
27214
  editFile(mcpPath);
27176
27215
  }
27216
+ function readMcpConfig() {
27217
+ const mcpPath = getMCPFilePath();
27218
+ return import_fs_extra22.default.readJSONSync(mcpPath);
27219
+ }
27220
+ function writeMcpConfig(data) {
27221
+ const mcpPath = getMCPFilePath();
27222
+ import_fs_extra22.default.writeJSONSync(mcpPath, data, { spaces: 2 });
27223
+ }
27224
+ function handleMcpLs() {
27225
+ const config2 = readMcpConfig();
27226
+ const servers = config2.mcpServers || {};
27227
+ const entries = Object.entries(servers);
27228
+ if (entries.length === 0) {
27229
+ logWarning("No MCP servers configured yet");
27230
+ return;
27231
+ }
27232
+ logInfo("=".repeat(50));
27233
+ entries.forEach(([name, server], index) => {
27234
+ const disabled = server.disabled === true;
27235
+ if (disabled) {
27236
+ logInfo(`[${index}] ${name} [\xD7]`);
27237
+ } else {
27238
+ logSuccess(`[${index}] ${name} [\u221A]`);
27239
+ }
27240
+ });
27241
+ logInfo("=".repeat(50));
27242
+ }
27243
+ function handleMcpEnable(nameOrIndex) {
27244
+ const config2 = readMcpConfig();
27245
+ const servers = config2.mcpServers || {};
27246
+ const entries = Object.keys(servers);
27247
+ let targetIndex = -1;
27248
+ const index = parseInt(nameOrIndex, 10);
27249
+ if (!isNaN(index) && index >= 0 && index < entries.length) {
27250
+ targetIndex = index;
27251
+ } else {
27252
+ targetIndex = entries.findIndex((name) => name === nameOrIndex);
27253
+ }
27254
+ if (targetIndex === -1) {
27255
+ logError(`MCP server not found: ${nameOrIndex}`);
27256
+ return;
27257
+ }
27258
+ const serverName = entries[targetIndex];
27259
+ servers[serverName].disabled = false;
27260
+ writeMcpConfig(config2);
27261
+ logSuccess(`MCP server "${serverName}" enabled`);
27262
+ }
27263
+ function handleMcpDisable(nameOrIndex) {
27264
+ const config2 = readMcpConfig();
27265
+ const servers = config2.mcpServers || {};
27266
+ const entries = Object.keys(servers);
27267
+ let targetIndex = -1;
27268
+ const index = parseInt(nameOrIndex, 10);
27269
+ if (!isNaN(index) && index >= 0 && index < entries.length) {
27270
+ targetIndex = index;
27271
+ } else {
27272
+ targetIndex = entries.findIndex((name) => name === nameOrIndex);
27273
+ }
27274
+ if (targetIndex === -1) {
27275
+ logError(`MCP server not found: ${nameOrIndex}`);
27276
+ return;
27277
+ }
27278
+ const serverName = entries[targetIndex];
27279
+ servers[serverName].disabled = true;
27280
+ writeMcpConfig(config2);
27281
+ logSuccess(`MCP server "${serverName}" disabled`);
27282
+ }
27177
27283
 
27178
27284
  // src/cli/cli-mcp.ts
27179
27285
  function registerMcpCommands(program) {
27180
27286
  const mcp = program.command("mcp");
27181
27287
  mcp.command("edit").description("\u7F16\u8F91 MCP \u914D\u7F6E\u6587\u4EF6").action(handleMcpEdit);
27288
+ mcp.command("ls").description("\u5217\u51FA\u6240\u6709 MCP \u670D\u52A1\u5668").action(handleMcpLs);
27289
+ mcp.command("enable <nameOrIndex>").description("\u542F\u7528 MCP \u670D\u52A1\u5668").action(handleMcpEnable);
27290
+ mcp.command("disable <nameOrIndex>").description("\u7981\u7528 MCP \u670D\u52A1\u5668").action(handleMcpDisable);
27182
27291
  }
27183
27292
 
27184
27293
  // src/cli/cli-core/input.ts
27185
- var import_fs_extra22 = __toESM(require("fs-extra"));
27294
+ var import_fs_extra23 = __toESM(require("fs-extra"));
27186
27295
  var readline = __toESM(require("readline"));
27187
- async function handleInput(args) {
27296
+ async function handleInput(args, skills) {
27188
27297
  const input = args.join(" ");
27189
27298
  if (!input.trim()) {
27190
27299
  logError("Please enter content");
@@ -27192,7 +27301,7 @@ async function handleInput(args) {
27192
27301
  }
27193
27302
  try {
27194
27303
  const configPath = getConfigPath();
27195
- if (!import_fs_extra22.default.pathExistsSync(configPath)) {
27304
+ if (!import_fs_extra23.default.pathExistsSync(configPath)) {
27196
27305
  logError("Config file not found, please run init first");
27197
27306
  return;
27198
27307
  }
@@ -27207,7 +27316,7 @@ async function handleInput(args) {
27207
27316
  logError("Failed to start service, please check config or port availability");
27208
27317
  return;
27209
27318
  }
27210
- const agent = await initAgent(config2);
27319
+ const agent = await initAgent(config2, skills);
27211
27320
  const connResult = await connectAgentRoom(agent);
27212
27321
  if (!connResult.ok) {
27213
27322
  if (connResult.reason === "duplicate-id") {
@@ -27229,7 +27338,7 @@ async function handleInput(args) {
27229
27338
  async function multiInput() {
27230
27339
  try {
27231
27340
  const configPath = getConfigPath();
27232
- if (!import_fs_extra22.default.pathExistsSync(configPath)) {
27341
+ if (!import_fs_extra23.default.pathExistsSync(configPath)) {
27233
27342
  logError("Config file not found, please run init first");
27234
27343
  return;
27235
27344
  }
@@ -27286,6 +27395,24 @@ async function multiInput() {
27286
27395
  }
27287
27396
  }
27288
27397
 
27398
+ // src/cli/cli-core/plan.ts
27399
+ var import_path22 = __toESM(require("path"));
27400
+ async function handlePlan(args) {
27401
+ const input = args.join(" ");
27402
+ if (!input.trim()) {
27403
+ logError("Please enter content");
27404
+ return;
27405
+ }
27406
+ 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}`;
27407
+ const skillPath = import_path22.default.join(__dirname, "./skills/planning-do.md");
27408
+ await handleInput([skillPrompt], [skillPath]);
27409
+ }
27410
+
27411
+ // src/cli/cli-plan.ts
27412
+ function registerPlanCommands(program) {
27413
+ 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));
27414
+ }
27415
+
27289
27416
  // src/cli/cli-input.ts
27290
27417
  function registerInputCommand(program) {
27291
27418
  program.argument("[inputs...]", "Natural language instruction or enter interactive mode").action(async (inputs) => {
@@ -27299,7 +27426,7 @@ function registerInputCommand(program) {
27299
27426
  }
27300
27427
 
27301
27428
  // src/cli/cli-core/cache.ts
27302
- var import_path22 = __toESM(require("path"));
27429
+ var import_path23 = __toESM(require("path"));
27303
27430
  var userCache2 = new UserCache();
27304
27431
  function resolveId(input) {
27305
27432
  const index = Number(input);
@@ -27333,7 +27460,7 @@ function handleCacheList() {
27333
27460
  function handleCacheEdit(input) {
27334
27461
  const id = resolveId(input);
27335
27462
  if (!id) return;
27336
- const filePath = import_path22.default.join(getUserStorePath(), `${id}.md`);
27463
+ const filePath = import_path23.default.join(getUserStorePath(), `${id}.md`);
27337
27464
  editFile(filePath);
27338
27465
  }
27339
27466
  function handleCacheDel(input) {
@@ -27378,6 +27505,7 @@ function main() {
27378
27505
  registerTaskCommands(program);
27379
27506
  registerCommonFlags(program);
27380
27507
  registerMcpCommands(program);
27508
+ registerPlanCommands(program);
27381
27509
  registerCacheCommands(program);
27382
27510
  registerHelpCommand(program);
27383
27511
  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,15 @@ 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
24233
24236
 
24234
24237
  # MCP commands
24235
24238
  ai mcp edit \u6253\u5F00 MCP \u914D\u7F6E\u6587\u4EF6\u8FDB\u884C\u7F16\u8F91
24239
+ ai mcp ls \u67E5\u770B\u5DF2\u914D\u7F6E\u7684 MCP \u670D\u52A1\u5668\u5217\u8868
24240
+ ai mcp enable <name|index> \u542F\u7528\u6307\u5B9A\u540D\u79F0\u6216\u5E8F\u53F7\u7684 MCP \u670D\u52A1\u5668
24241
+ ai mcp disable <name|index> \u7981\u7528\u6307\u5B9A\u540D\u79F0\u6216\u5E8F\u53F7\u7684 MCP \u670D\u52A1\u5668
24236
24242
 
24237
24243
  # Serve commands
24238
24244
  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,90 @@
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 负责按顺序执行子任务:
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. 每次只执行一个子任务,按列表顺序依次执行;
69
+ 4. 执行前将当前任务 status 更新为 "doing" 并写回文件;
70
+ 5. 执行成功后更新 status 为 "done",并记录 finishedAt(ISO 时间);
71
+ 6. 执行失败时保留为 "doing" 或回退为 "todo",在 note 中记录失败原因;
72
+ 7. 每完成一个子任务必须立即写回 tmp_tasklist.json;
73
+ 8. 尽量将具体执行工作交给子 agent 完成,主流程只负责调度和状态管理;
74
+ 9. 告知子 agent 任务列表的文件名为 tmp_tasklist.json;
75
+ 10. 全部任务完成后,删除 tmp_tasklist.json 和 tmp_task_goal.md。
76
+
77
+ 输出要求:
78
+ - 输出当前执行的任务 id、名称、结果状态和下一步计划;
79
+ - 不要跳过状态更新和文件写入步骤。
80
+ ```
81
+
82
+ **子 Agent 的用户提示词:** 用户的原始任务描述。
83
+
84
+ ## 注意事项
85
+
86
+ 1. **必须分两个阶段执行**:先创建任务列表,再执行任务列表,不能合并
87
+ 2. **子 Agent 只做一件事**:阶段一只负责拆解任务,阶段二只负责按顺序执行
88
+ 3. **文件持久化**:任务状态通过 `tmp_tasklist.json` 文件持久化,子 Agent 崩溃后可以重新读取继续执行
89
+ 4. **清理临时文件**:全部任务完成后必须删除 `tmp_tasklist.json` 和 `tmp_task_goal.md`
90
+ 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.12",
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}\"",