deepfish-ai 2.0.12 → 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
@@ -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
@@ -26896,11 +26897,15 @@ function _updateRegister(skillsDir) {
26896
26897
  const skillName = import_path20.default.basename(skillPath);
26897
26898
  const existItem = register.find((item) => item.skillPath === skillPath);
26898
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
+ }
26899
26904
  newRegister.push({
26900
26905
  id: (0, import_crypto6.randomUUID)(),
26901
26906
  name: skillName,
26902
26907
  isEnabled: true,
26903
- skillPath
26908
+ skillPath: skillFilePath
26904
26909
  });
26905
26910
  }
26906
26911
  });
@@ -26912,8 +26917,9 @@ function getRegisteredSkills() {
26912
26917
  const scanPaths = getScanDirPaths();
26913
26918
  const skills = [];
26914
26919
  scanPaths.forEach((scanPath) => {
26915
- _updateRegister(scanPath);
26916
- const registerPath = _getRegisterPath(scanPath);
26920
+ const scanDir = import_path20.default.join(scanPath, "skills");
26921
+ _updateRegister(scanDir);
26922
+ const registerPath = _getRegisterPath(scanDir);
26917
26923
  if (import_fs_extra20.default.existsSync(registerPath)) {
26918
26924
  const register = import_fs_extra20.default.readJSONSync(registerPath);
26919
26925
  register.forEach((item) => {
@@ -26939,7 +26945,8 @@ function _getAllSkills() {
26939
26945
  const scanPaths = getScanDirPaths();
26940
26946
  let allSkills = [];
26941
26947
  scanPaths.forEach((scanPath) => {
26942
- const skills = _getSkillList(scanPath);
26948
+ const scanDir = import_path20.default.join(scanPath, "skills");
26949
+ const skills = _getSkillList(scanDir);
26943
26950
  skills.map((item) => {
26944
26951
  item.skillDir = scanPath;
26945
26952
  return item;
@@ -27407,10 +27414,39 @@ async function handlePlan(args) {
27407
27414
  const skillPath = import_path22.default.join(__dirname, "./skills/planning-do.md");
27408
27415
  await handleInput([skillPrompt], [skillPath]);
27409
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
+ }
27410
27445
 
27411
27446
  // src/cli/cli-plan.ts
27412
27447
  function registerPlanCommands(program) {
27413
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());
27414
27450
  }
27415
27451
 
27416
27452
  // 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.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": {