deepfish-ai 2.0.12 → 2.0.14

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
@@ -189,6 +189,7 @@ ai "我刚问了一个什么问题"
189
189
  | 命令 | 说明 |
190
190
  | ------------------------- | ------------------------------------------ |
191
191
  | `ai plan-do <任务描述>` | 将复杂任务拆解为子任务并逐步执行完成 |
192
+ | `ai plan-continue` | 继续执行被中断的 plan-do 任务 |
192
193
 
193
194
  ### MCP 管理
194
195
 
package/dist/index.js CHANGED
@@ -25769,6 +25769,7 @@ Commands:
25769
25769
 
25770
25770
  # Plan commands
25771
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
25772
25773
 
25773
25774
  # MCP commands
25774
25775
  ai mcp edit \u6253\u5F00 MCP \u914D\u7F6E\u6587\u4EF6\u8FDB\u884C\u7F16\u8F91
@@ -26748,6 +26749,17 @@ async function handleSkillsAdd(name) {
26748
26749
  }
26749
26750
  const targetDir = scope === "local" ? localSkillDir : globalSkillDir;
26750
26751
  const targetPath = import_path20.default.join(targetDir, name);
26752
+ const { action } = await import_inquirer3.default.prompt([
26753
+ {
26754
+ type: "select",
26755
+ name: "action",
26756
+ message: "Select add action:",
26757
+ choices: [
26758
+ { name: "Move (cut)", value: "move" },
26759
+ { name: "Copy", value: "copy" }
26760
+ ]
26761
+ }
26762
+ ]);
26751
26763
  if (import_fs_extra20.default.existsSync(targetPath)) {
26752
26764
  const { overwrite } = await import_inquirer3.default.prompt([
26753
26765
  {
@@ -26763,8 +26775,12 @@ async function handleSkillsAdd(name) {
26763
26775
  }
26764
26776
  import_fs_extra20.default.removeSync(targetPath);
26765
26777
  }
26766
- import_fs_extra20.default.moveSync(skillDir, targetPath, { overwrite: true });
26767
- logSuccess(`Skill ${scope === "local" ? "locally" : "globally"} added: ${targetPath}`);
26778
+ if (action === "move") {
26779
+ import_fs_extra20.default.moveSync(skillDir, targetPath, { overwrite: true });
26780
+ } else {
26781
+ import_fs_extra20.default.copySync(skillDir, targetPath, { overwrite: true });
26782
+ }
26783
+ logSuccess(`Skill ${scope === "local" ? "locally" : "globally"} ${action === "move" ? "moved" : "copied"}: ${targetPath}`);
26768
26784
  _updateRegister(targetDir);
26769
26785
  }
26770
26786
  function handleSkillsDel(index) {
@@ -26896,11 +26912,15 @@ function _updateRegister(skillsDir) {
26896
26912
  const skillName = import_path20.default.basename(skillPath);
26897
26913
  const existItem = register.find((item) => item.skillPath === skillPath);
26898
26914
  if (!existItem) {
26915
+ let skillFilePath = skillPath;
26916
+ if (import_fs_extra20.default.statSync(skillPath).isDirectory()) {
26917
+ skillFilePath = import_path20.default.join(skillFilePath, "SKILL.md");
26918
+ }
26899
26919
  newRegister.push({
26900
26920
  id: (0, import_crypto6.randomUUID)(),
26901
26921
  name: skillName,
26902
26922
  isEnabled: true,
26903
- skillPath
26923
+ skillPath: skillFilePath
26904
26924
  });
26905
26925
  }
26906
26926
  });
@@ -26912,8 +26932,9 @@ function getRegisteredSkills() {
26912
26932
  const scanPaths = getScanDirPaths();
26913
26933
  const skills = [];
26914
26934
  scanPaths.forEach((scanPath) => {
26915
- _updateRegister(scanPath);
26916
- const registerPath = _getRegisterPath(scanPath);
26935
+ const scanDir = import_path20.default.join(scanPath, "skills");
26936
+ _updateRegister(scanDir);
26937
+ const registerPath = _getRegisterPath(scanDir);
26917
26938
  if (import_fs_extra20.default.existsSync(registerPath)) {
26918
26939
  const register = import_fs_extra20.default.readJSONSync(registerPath);
26919
26940
  register.forEach((item) => {
@@ -26939,7 +26960,8 @@ function _getAllSkills() {
26939
26960
  const scanPaths = getScanDirPaths();
26940
26961
  let allSkills = [];
26941
26962
  scanPaths.forEach((scanPath) => {
26942
- const skills = _getSkillList(scanPath);
26963
+ const scanDir = import_path20.default.join(scanPath, "skills");
26964
+ const skills = _getSkillList(scanDir);
26943
26965
  skills.map((item) => {
26944
26966
  item.skillDir = scanPath;
26945
26967
  return item;
@@ -27032,6 +27054,17 @@ async function handleToolsAdd(name) {
27032
27054
  const localToolDir = import_path21.default.join(workspace, ".deepfish-ai", "tools");
27033
27055
  const targetDir = scope === "local" ? localToolDir : globalToolDir;
27034
27056
  const targetPath = import_path21.default.join(targetDir, name);
27057
+ const { action } = await import_inquirer4.default.prompt([
27058
+ {
27059
+ type: "select",
27060
+ name: "action",
27061
+ message: "Select add action:",
27062
+ choices: [
27063
+ { name: "Move (cut)", value: "move" },
27064
+ { name: "Copy", value: "copy" }
27065
+ ]
27066
+ }
27067
+ ]);
27035
27068
  import_fs_extra21.default.ensureDirSync(targetDir);
27036
27069
  if (import_fs_extra21.default.existsSync(targetPath)) {
27037
27070
  const { overwrite } = await import_inquirer4.default.prompt([
@@ -27048,8 +27081,12 @@ async function handleToolsAdd(name) {
27048
27081
  }
27049
27082
  import_fs_extra21.default.removeSync(targetPath);
27050
27083
  }
27051
- import_fs_extra21.default.moveSync(toolDir, targetPath, { overwrite: true });
27052
- logSuccess(`Tool ${scope === "local" ? "locally" : "globally"} added: ${targetPath}`);
27084
+ if (action === "move") {
27085
+ import_fs_extra21.default.moveSync(toolDir, targetPath, { overwrite: true });
27086
+ } else {
27087
+ import_fs_extra21.default.copySync(toolDir, targetPath, { overwrite: true });
27088
+ }
27089
+ logSuccess(`Tool ${scope === "local" ? "locally" : "globally"} ${action === "move" ? "moved" : "copied"}: ${targetPath}`);
27053
27090
  }
27054
27091
  async function handleToolsGenerate(target) {
27055
27092
  if (!target.trim()) {
@@ -27407,10 +27444,39 @@ async function handlePlan(args) {
27407
27444
  const skillPath = import_path22.default.join(__dirname, "./skills/planning-do.md");
27408
27445
  await handleInput([skillPrompt], [skillPath]);
27409
27446
  }
27447
+ async function handlePlanContinue() {
27448
+ const skillPrompt = `
27449
+ \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
27450
+
27451
+ \u6267\u884C\u89C4\u5219\uFF1A
27452
+ 1. \u5148\u8BFB\u53D6 tmp_task_goal.md \u4E86\u89E3\u6574\u4F53\u76EE\u6807\uFF1B
27453
+ 2. \u8BFB\u53D6 tmp_tasklist.json\uFF0C\u4EC5\u5904\u7406 status \u4E3A "todo" \u6216 "doing" \u7684\u4EFB\u52A1\uFF1B
27454
+ 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
27455
+ 4. \u8C03\u5EA6\u524D\u5C06\u5F53\u524D\u4EFB\u52A1 status \u66F4\u65B0\u4E3A "doing" \u5E76\u5199\u56DE\u6587\u4EF6\uFF1B
27456
+ 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
27457
+ 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
27458
+ 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
27459
+ 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
27460
+ 9. \u6BCF\u5B8C\u6210\u6216\u5931\u8D25\u4E00\u4E2A\u5B50\u4EFB\u52A1\uFF0C\u90FD\u5FC5\u987B\u7ACB\u5373\u5199\u56DE tmp_tasklist.json\uFF1B
27461
+ 10. \u5168\u90E8\u4EFB\u52A1\u5B8C\u6210\u540E\uFF0C\u5220\u9664 tmp_tasklist.json \u548C tmp_task_goal.md\u3002
27462
+
27463
+ \u5B50 Agent \u6267\u884C\u8981\u6C42\uFF1A
27464
+ - \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
27465
+ - \u6267\u884C\u524D\u9605\u8BFB tmp_task_goal.md\uFF0C\u7406\u89E3\u6574\u4F53\u76EE\u6807\uFF1B
27466
+ - \u5FC5\u8981\u65F6\u9605\u8BFB tmp_tasklist.json\uFF0C\u4E86\u89E3\u4E0A\u4E0B\u6587\u548C\u4EFB\u52A1\u4F9D\u8D56\uFF1B
27467
+ - \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
27468
+
27469
+ \u8F93\u51FA\u8981\u6C42\uFF1A
27470
+ - \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
27471
+ - \u4E0D\u8981\u8DF3\u8FC7\u72B6\u6001\u66F4\u65B0\u548C\u6587\u4EF6\u5199\u5165\u6B65\u9AA4\u3002
27472
+ `;
27473
+ await handleInput([skillPrompt]);
27474
+ }
27410
27475
 
27411
27476
  // src/cli/cli-plan.ts
27412
27477
  function registerPlanCommands(program) {
27413
27478
  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));
27479
+ program.command("plan-continue").description("\u7EE7\u7EED\u6267\u884C\u88AB\u4E2D\u65AD\u7684 plan-do \u4EFB\u52A1").action(() => handlePlanContinue());
27414
27480
  }
27415
27481
 
27416
27482
  // src/cli/cli-input.ts
@@ -24233,6 +24233,7 @@ Commands:
24233
24233
 
24234
24234
  # Plan commands
24235
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
24236
24237
 
24237
24238
  # MCP commands
24238
24239
  ai mcp edit \u6253\u5F00 MCP \u914D\u7F6E\u6587\u4EF6\u8FDB\u884C\u7F16\u8F91
@@ -55,32 +55,36 @@ tmp_tasklist.json 格式要求:
55
55
 
56
56
  ### 阶段二:执行任务列表
57
57
 
58
- 创建一个子 Agent,传入以下系统提示词,让子 Agent 负责按顺序执行子任务:
58
+ 创建一个子 Agent 作为调度管理器Agent读取任务列表并负责调度。执行每个子任务时,必须为该子任务再创建一个独立的子 Agent,由子 Agent 完成具体执行工作,调度管理器Agent 只负责状态流转、结果记录和继续调度下一个任务。
59
59
 
60
- **子 Agent 系统提示词:**
60
+ **调度管理器子Agent提示词:**
61
61
 
62
62
  ```
63
- 你负责按顺序执行 tmp_tasklist.json 中的子任务,完成 tmp_task_goal.md 描述的整体目标。
63
+ 你负责按顺序调度执行 tmp_tasklist.json 中的子任务,完成 tmp_task_goal.md 描述的整体目标。
64
64
 
65
65
  执行规则:
66
66
  1. 先读取 tmp_task_goal.md 了解整体目标;
67
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;
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
75
  10. 全部任务完成后,删除 tmp_tasklist.json 和 tmp_task_goal.md。
76
76
 
77
+ 子 Agent 执行要求:
78
+ - 只执行当前被分配的一个子任务,不要修改其他任务状态;
79
+ - 执行前阅读 tmp_task_goal.md,理解整体目标;
80
+ - 必要时阅读 tmp_tasklist.json,了解上下文和任务依赖;
81
+ - 完成后向主 Agent 返回执行结果、修改的文件、失败原因或后续建议。
82
+
77
83
  输出要求:
78
- - 输出当前执行的任务 id、名称、结果状态和下一步计划;
84
+ - 输出当前调度的任务 id、名称、执行结果状态和下一步计划;
79
85
  - 不要跳过状态更新和文件写入步骤。
80
86
  ```
81
87
 
82
- **子 Agent 的用户提示词:** 用户的原始任务描述。
83
-
84
88
  ## 注意事项
85
89
 
86
90
  1. **必须分两个阶段执行**:先创建任务列表,再执行任务列表,不能合并
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepfish-ai",
3
- "version": "2.0.12",
3
+ "version": "2.0.14",
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": {