minimal-agent 0.11.0 → 0.13.0

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.
Files changed (181) hide show
  1. package/package.json +5 -1
  2. package/plugins/workflow-runner/plugin.js +27 -15
  3. package/plugins/workflow-runner/plugin.ts +34 -20
  4. package/plugins/workflow-runner/src/agentCommon.js +13 -12
  5. package/plugins/workflow-runner/src/agentCommon.ts +22 -13
  6. package/plugins/workflow-runner/src/expressions.js +29 -8
  7. package/plugins/workflow-runner/src/expressions.ts +28 -10
  8. package/plugins/workflow-runner/src/index.js +50 -20
  9. package/plugins/workflow-runner/src/index.ts +75 -31
  10. package/plugins/workflow-runner/src/multimodal.js +2 -1
  11. package/plugins/workflow-runner/src/multimodal.ts +2 -1
  12. package/plugins/workflow-runner/src/recovery.js +9 -2
  13. package/plugins/workflow-runner/src/recovery.ts +9 -2
  14. package/plugins/workflow-runner/src/runner.js +31 -5
  15. package/plugins/workflow-runner/src/runner.ts +33 -5
  16. package/plugins/workflow-runner/src/stepExecutors/assert.js +2 -1
  17. package/plugins/workflow-runner/src/stepExecutors/assert.ts +3 -1
  18. package/plugins/workflow-runner/src/stepExecutors/skill.js +5 -6
  19. package/plugins/workflow-runner/src/stepExecutors/skill.ts +12 -7
  20. package/plugins/workflow-runner/src/stepExecutors/tool.js +91 -61
  21. package/plugins/workflow-runner/src/stepExecutors/tool.ts +111 -71
  22. package/plugins/workflow-runner/src/stepExecutors/verify.js +6 -3
  23. package/plugins/workflow-runner/src/stepExecutors/verify.ts +7 -3
  24. package/plugins/workflow-runner/src/taskIdentity.js +197 -21
  25. package/plugins/workflow-runner/src/taskIdentity.ts +201 -20
  26. package/plugins/workflow-runner/src/toolRuntime.js +48 -0
  27. package/plugins/workflow-runner/src/toolRuntime.ts +64 -0
  28. package/plugins/workflow-runner/src/types.js +113 -7
  29. package/plugins/workflow-runner/src/types.ts +137 -14
  30. package/plugins/workflow-runner/src/workflowState.js +455 -54
  31. package/plugins/workflow-runner/src/workflowState.ts +508 -63
  32. package/plugins/workflow-runner/test/cli.e2e.test.ts +20 -0
  33. package/plugins/workflow-runner/test/context-files.test.ts +47 -16
  34. package/plugins/workflow-runner/test/e2eNewLayout.test.ts +314 -0
  35. package/plugins/workflow-runner/test/engineRobustness.test.ts +9 -1
  36. package/plugins/workflow-runner/test/expressions.test.ts +42 -0
  37. package/plugins/workflow-runner/test/hostCapability.test.ts +9 -3
  38. package/plugins/workflow-runner/test/illustrate.load.test.ts +2 -2
  39. package/plugins/workflow-runner/test/multimodal.test.ts +61 -10
  40. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +19 -0
  41. package/plugins/workflow-runner/test/ppt.load.test.ts +15 -15
  42. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +3 -2
  43. package/plugins/workflow-runner/test/research.load.test.ts +328 -0
  44. package/plugins/workflow-runner/test/runnerPreflight.test.ts +68 -11
  45. package/plugins/workflow-runner/test/stateLifecycle.test.ts +60 -12
  46. package/plugins/workflow-runner/test/taskArbitration.test.ts +19 -3
  47. package/plugins/workflow-runner/test/taskLifecycle.test.ts +61 -7
  48. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +168 -0
  49. package/plugins/workflow-runner/test/webppt.load.test.ts +4 -4
  50. package/plugins/workflow-runner/test/word.load.test.ts +9 -9
  51. package/skills/skill-creator/scripts/run_eval.py +3 -2
  52. package/src/cli/print.js +36 -4
  53. package/src/cli/print.ts +42 -4
  54. package/src/cli/streamJson.js +19 -4
  55. package/src/cli/streamJson.ts +17 -4
  56. package/src/config/configDefaults.js +25 -0
  57. package/src/config/configDefaults.ts +33 -0
  58. package/src/config/configFile.js +2 -21
  59. package/src/config/configFile.ts +11 -24
  60. package/src/config/configManagement.js +1 -1
  61. package/src/config/configManagement.ts +2 -2
  62. package/src/config/configService.js +24 -0
  63. package/src/config/configService.ts +23 -0
  64. package/src/context/compact.js +4 -0
  65. package/src/context/compact.ts +4 -0
  66. package/src/context/contextBundle.js +38 -13
  67. package/src/context/contextBundle.ts +47 -13
  68. package/src/harness/stallGuard.js +19 -4
  69. package/src/harness/stallGuard.ts +30 -7
  70. package/src/infra/verification.js +25 -18
  71. package/src/infra/verification.ts +50 -18
  72. package/src/loop.js +95 -11
  73. package/src/loop.ts +125 -16
  74. package/src/main.js +8 -1
  75. package/src/main.tsx +7 -1
  76. package/src/memory/constants.js +10 -0
  77. package/src/memory/constants.ts +13 -0
  78. package/src/memory/episodicMemory.js +274 -2
  79. package/src/memory/episodicMemory.ts +306 -1
  80. package/src/memory/fileStore.js +24 -4
  81. package/src/memory/fileStore.ts +22 -2
  82. package/src/memory/memoryService.js +79 -12
  83. package/src/memory/memoryService.ts +108 -9
  84. package/src/memory/repository.js +415 -85
  85. package/src/memory/repository.ts +437 -86
  86. package/src/memory/turnJournal.js +95 -0
  87. package/src/memory/turnJournal.ts +120 -0
  88. package/src/memory/types.ts +16 -0
  89. package/src/plugins/pluginApi.ts +30 -6
  90. package/src/plugins/pluginRunner.js +23 -8
  91. package/src/plugins/pluginRunner.ts +32 -13
  92. package/src/prompts/policyRegistry.js +55 -1
  93. package/src/prompts/policyRegistry.ts +55 -1
  94. package/src/prompts/promptAssembly.js +39 -7
  95. package/src/prompts/promptAssembly.ts +145 -59
  96. package/src/session/runAgentTurn.js +43 -21
  97. package/src/session/runAgentTurn.ts +68 -26
  98. package/src/session/runTurn.js +11 -46
  99. package/src/session/runTurn.ts +12 -46
  100. package/src/session/runtimeStore.js +149 -0
  101. package/src/session/runtimeStore.ts +197 -0
  102. package/src/session/sessionState.js +5 -0
  103. package/src/session/sessionState.ts +14 -0
  104. package/src/tools/advisor/advisor.js +76 -9
  105. package/src/tools/advisor/advisor.ts +79 -9
  106. package/src/tools/agent/agent.js +143 -14
  107. package/src/tools/agent/agent.ts +149 -14
  108. package/src/tools/agent/agentTaskService.js +60 -0
  109. package/src/tools/agent/agentTaskService.ts +113 -0
  110. package/src/tools/agent/agentTypes.js +5 -0
  111. package/src/tools/agent/agentTypes.ts +5 -0
  112. package/src/tools/bash/bash.js +80 -15
  113. package/src/tools/bash/bash.ts +83 -15
  114. package/src/tools/capabilities.js +5 -0
  115. package/src/tools/capabilities.ts +11 -1
  116. package/src/tools/edit/edit.js +7 -4
  117. package/src/tools/edit/edit.ts +7 -4
  118. package/src/tools/edit/multi-edit.js +4 -2
  119. package/src/tools/edit/multi-edit.ts +4 -2
  120. package/src/tools/glob/glob.js +156 -40
  121. package/src/tools/glob/glob.ts +185 -46
  122. package/src/tools/index.js +35 -17
  123. package/src/tools/index.ts +81 -20
  124. package/src/tools/lsp/lsp.js +165 -22
  125. package/src/tools/lsp/lsp.ts +206 -36
  126. package/src/tools/powershell/powershell.js +134 -27
  127. package/src/tools/powershell/powershell.ts +171 -30
  128. package/src/tools/presentresult/presentresult.js +10 -0
  129. package/src/tools/presentresult/presentresult.ts +10 -0
  130. package/src/tools/read/read.js +249 -29
  131. package/src/tools/read/read.ts +396 -59
  132. package/src/tools/shared/diffSummary.js +44 -0
  133. package/src/tools/shared/diffSummary.ts +63 -0
  134. package/src/tools/shared/fileActivity.js +2 -1
  135. package/src/tools/shared/fileActivity.ts +3 -0
  136. package/src/tools/shared/permanentDeleteGuard.js +57 -0
  137. package/src/tools/shared/permanentDeleteGuard.ts +71 -0
  138. package/src/tools/shared/toolOutputStore.js +97 -0
  139. package/src/tools/shared/toolOutputStore.ts +110 -0
  140. package/src/tools/skill/skill.js +86 -0
  141. package/src/tools/skill/skill.ts +94 -0
  142. package/src/tools/snip/snip.js +67 -0
  143. package/src/tools/snip/snip.ts +80 -0
  144. package/src/tools/tasks/backgroundTaskService.js +79 -28
  145. package/src/tools/tasks/backgroundTaskService.ts +165 -49
  146. package/src/tools/tasks/taskManagement.js +163 -0
  147. package/src/tools/tasks/taskManagement.ts +180 -0
  148. package/src/tools/tasks/taskOutput.js +64 -14
  149. package/src/tools/tasks/taskOutput.ts +102 -23
  150. package/src/tools/tasks/taskStop.js +48 -8
  151. package/src/tools/tasks/taskStop.ts +69 -9
  152. package/src/tools/tasks/taskStore.js +46 -0
  153. package/src/tools/tasks/taskStore.ts +77 -0
  154. package/src/tools/terminal/terminalCapture.js +167 -0
  155. package/src/tools/terminal/terminalCapture.ts +179 -0
  156. package/src/tools/trash/trash.js +233 -0
  157. package/src/tools/trash/trash.ts +283 -0
  158. package/src/tools/webbrowser/browserControl.js +5 -1
  159. package/src/tools/webbrowser/browserControl.ts +7 -1
  160. package/src/tools/webbrowser/webbrowser.js +8 -4
  161. package/src/tools/webbrowser/webbrowser.ts +8 -4
  162. package/src/tools/worktree/sessionWorktree.js +128 -0
  163. package/src/tools/worktree/sessionWorktree.ts +158 -0
  164. package/src/tools/write/write.js +6 -2
  165. package/src/tools/write/write.ts +6 -2
  166. package/src/types.ts +22 -4
  167. package/src/ui/hooks/useChat.js +31 -11
  168. package/src/ui/hooks/useChat.ts +31 -13
  169. package/src/web/protocol.ts +78 -3
  170. package/workflows/adaptive-research.yaml +5 -5
  171. package/workflows/book-review-short.yaml +5 -5
  172. package/workflows/e2e-write-greet.yaml +2 -2
  173. package/workflows/illustrate.yaml +12 -12
  174. package/workflows/plan.yaml +18 -18
  175. package/workflows/ppt.yaml +201 -201
  176. package/workflows/ralph-loop.yaml +3 -1
  177. package/workflows/research.md +449 -0
  178. package/workflows/research.yaml +873 -0
  179. package/workflows/webppt.yaml +47 -47
  180. package/workflows/word.yaml +80 -80
  181. package/workflows/youtube-shorts.yaml +25 -25
@@ -10,7 +10,7 @@ description: >
10
10
  version: "0.1"
11
11
 
12
12
  artifacts:
13
- - "./out/article.docx"
13
+ - "out/word/${session}/article.docx"
14
14
 
15
15
  self_heal:
16
16
  max_retries: 2
@@ -28,7 +28,7 @@ inputs:
28
28
  description: "【素材文档·可选 --input】已有配图 Word、纯文字 Word、PPT、PDF、Excel、图片或混合素材路径。留空时解析 topic 中的文件线索,仍无明确素材则扫描当前目录支持格式。"
29
29
  - name: out
30
30
  type: string
31
- default: "./out/article.docx"
31
+ default: "out/word/${session}/article.docx"
32
32
  description: "【高级·可选 --input】输出 Word 文件路径。"
33
33
  - name: image_intensity
34
34
  type: enum
@@ -44,7 +44,7 @@ inputs:
44
44
  type: enum
45
45
  values: ["true", "false"]
46
46
  default: "true"
47
- description: "【调试·可选 --input】是否保留 ./build 中间产物。默认 true,便于检查 article.md、material.json、img_plan.json 和报告。"
47
+ description: "【调试·可选 --input】是否保留 out/word/${session}/build 中间产物。默认 true,便于检查 article.md、material.json、img_plan.json 和报告。"
48
48
 
49
49
  steps:
50
50
  - id: stage0_analyze
@@ -77,27 +77,27 @@ steps:
77
77
  args:
78
78
  command: |
79
79
  set -e
80
- mkdir -p ./build ./out
80
+ mkdir -p out/word/${session}/build out/word/${session}
81
81
  rm -f \
82
- ./build/article.md \
83
- ./build/article_outline.md \
84
- ./build/build_complete \
85
- ./build/export-summary.md \
86
- ./build/img_plan.json \
87
- ./build/image_map.json \
88
- ./build/material.md \
89
- ./build/material.json \
90
- ./build/source_resolution.json \
91
- ./build/source_assets.json \
92
- ./build/source.md \
93
- ./build/source_stats.json \
94
- ./build/user_request.md \
95
- ./build/word_topic_image_gate.json \
96
- ./build/word_topic_image_gate.md \
97
- ./build/word_customer_image_usage.json \
98
- ./build/word_customer_image_usage.md
99
- rm -rf ./build/assets ./build/vision ./build/generated-image-reviews
100
- mkdir -p ./build/assets ./build/vision
82
+ out/word/${session}/build/article.md \
83
+ out/word/${session}/build/article_outline.md \
84
+ out/word/${session}/build/build_complete \
85
+ out/word/${session}/build/export-summary.md \
86
+ out/word/${session}/build/img_plan.json \
87
+ out/word/${session}/build/image_map.json \
88
+ out/word/${session}/build/material.md \
89
+ out/word/${session}/build/material.json \
90
+ out/word/${session}/build/source_resolution.json \
91
+ out/word/${session}/build/source_assets.json \
92
+ out/word/${session}/build/source.md \
93
+ out/word/${session}/build/source_stats.json \
94
+ out/word/${session}/build/user_request.md \
95
+ out/word/${session}/build/word_topic_image_gate.json \
96
+ out/word/${session}/build/word_topic_image_gate.md \
97
+ out/word/${session}/build/word_customer_image_usage.json \
98
+ out/word/${session}/build/word_customer_image_usage.md
99
+ rm -rf out/word/${session}/build/assets out/word/${session}/build/vision out/word/${session}/build/generated-image-reviews
100
+ mkdir -p out/word/${session}/build/assets out/word/${session}/build/vision
101
101
 
102
102
  RESOLVE="skills/ui-design/scripts/resolve_source_input.py"
103
103
  EXTRACT="skills/ui-design/scripts/extract_source_assets.py"
@@ -114,16 +114,16 @@ steps:
114
114
  --source "$RAW_SOURCE" \
115
115
  --topic "$RAW_TOPIC" \
116
116
  --cwd . \
117
- --out ./build/source_resolution.json
118
- SOURCE="$(python3 -c 'import json; data=json.load(open("./build/source_resolution.json", encoding="utf-8")); print(data.get("resolved_path") or "")')"
117
+ --out out/word/${session}/build/source_resolution.json
118
+ SOURCE="$(python3 -c 'import json; data=json.load(open("out/word/${session}/build/source_resolution.json", encoding="utf-8")); print(data.get("resolved_path") or "")')"
119
119
  if [ -n "$SOURCE" ]; then
120
- python3 "$EXTRACT" "$SOURCE" --out ./build -v
120
+ python3 "$EXTRACT" "$SOURCE" --out out/word/${session}/build -v
121
121
  else
122
- python3 "$EXTRACT" . --scan --out ./build -v
122
+ python3 "$EXTRACT" . --scan --out out/word/${session}/build -v
123
123
  fi
124
- python3 -c 'import json,sys; r=json.load(open("./build/source_resolution.json", encoding="utf-8")); a=json.load(open("./build/source_assets.json", encoding="utf-8")); ok=not (r.get("requires_source") and not a.get("has_source")); print("WORD_SOURCE_REQUIRED_BUT_EMPTY: 用户明确要求使用素材文件,但抽取结果为空。", file=sys.stderr) if not ok else None; print(json.dumps(r, ensure_ascii=False, indent=2), file=sys.stderr) if not ok else None; sys.exit(0 if ok else 3)'
125
- python3 "$STATS" ./build/assets --scan --json > ./build/source_stats.json
126
- cat > ./build/user_request.md <<'EOF'
124
+ python3 -c 'import json,sys; r=json.load(open("out/word/${session}/build/source_resolution.json", encoding="utf-8")); a=json.load(open("out/word/${session}/build/source_assets.json", encoding="utf-8")); ok=not (r.get("requires_source") and not a.get("has_source")); print("WORD_SOURCE_REQUIRED_BUT_EMPTY: 用户明确要求使用素材文件,但抽取结果为空。", file=sys.stderr) if not ok else None; print(json.dumps(r, ensure_ascii=False, indent=2), file=sys.stderr) if not ok else None; sys.exit(0 if ok else 3)'
125
+ python3 "$STATS" out/word/${session}/build/assets --scan --json > out/word/${session}/build/source_stats.json
126
+ cat > out/word/${session}/build/user_request.md <<'EOF'
127
127
  # 用户原始输入与目标
128
128
 
129
129
  - 主题/指令:${inputs.topic}
@@ -144,14 +144,14 @@ steps:
144
144
  4. 文生图只服务章节理解,不做无上下文装饰图。
145
145
  EOF
146
146
  echo "WORD_SOURCE_EXTRACT_READY"
147
- test -f ./build/source_assets.json
147
+ test -f out/word/${session}/build/source_assets.json
148
148
  onError: halt
149
149
 
150
150
  - id: stage_vision_loop
151
151
  title: "阶段3/13·逐图识图:客户图内容与文章落点"
152
- when: "fileExists('./build/source_assets.json')"
152
+ when: "fileExists('out/word/${session}/build/source_assets.json')"
153
153
  type: loop
154
- over: "${asArray(readJson('./build/source_assets.json', 'images'))}"
154
+ over: "${asArray(readJson('out/word/${session}/build/source_assets.json', 'images'))}"
155
155
  as: img
156
156
  fresh_context: true
157
157
  do:
@@ -171,7 +171,7 @@ steps:
171
171
  - `enhance_recommended`:true/false。低清、比例不适合、背景杂乱、风格不统一时 true;信息密集图/截图/图表若增强会损失文字则 false。
172
172
  - `enhance_prompt`:如果需要图生图增强,写英文提示词;必须保留原始主体、信息语义和构图重点,只改善清晰度、比例、光线、背景整洁度和 Word 文章配图质感。
173
173
  - `use_rule`:必须写明“所有客户图必须使用,原图或增强后进入最终 Word”。
174
- images: ["./build/assets/${img.file}"]
174
+ images: ["out/word/${session}/build/assets/${img.file}"]
175
175
  image_detail: high
176
176
  capture:
177
177
  text: vision_json
@@ -183,17 +183,17 @@ steps:
183
183
  when: "length(vision_json) > 0"
184
184
  tool: Write
185
185
  args:
186
- file_path: "./build/vision/${img.file}.json"
186
+ file_path: "out/word/${session}/build/vision/${img.file}.json"
187
187
  content: "${vision_json}"
188
188
  onError: continue
189
189
 
190
190
  - id: sanitize_vision_json
191
191
  title: "阶段3/13·校验识图 JSON ${img.file}"
192
- when: "fileExists('./build/vision/${img.file}.json')"
192
+ when: "fileExists('out/word/${session}/build/vision/${img.file}.json')"
193
193
  tool: Bash
194
194
  args:
195
195
  command: |
196
- python3 - "./build/vision/${img.file}.json" <<'PYEOF'
196
+ python3 - "out/word/${session}/build/vision/${img.file}.json" <<'PYEOF'
197
197
  import json, sys, os
198
198
  path = sys.argv[1]
199
199
  try:
@@ -220,7 +220,7 @@ steps:
220
220
  import json, os
221
221
  from pathlib import Path
222
222
 
223
- build = Path("./build")
223
+ build = Path("out/word/${session}/build")
224
224
  assets = build / "assets"
225
225
  vision_dir = build / "vision"
226
226
 
@@ -285,17 +285,17 @@ steps:
285
285
  (build / "material.md").write_text("".join(md), encoding="utf-8")
286
286
  print(f"WORD_MATERIAL_READY images={len(images)} chars={len(source_text)}")
287
287
  PYEOF
288
- test -f ./build/material.md
289
- test -f ./build/material.json
288
+ test -f out/word/${session}/build/material.md
289
+ test -f out/word/${session}/build/material.json
290
290
  onError: halt
291
291
 
292
292
  - id: stage_outline
293
293
  title: "阶段5/13·总结扩写大纲:知乎深度长文结构"
294
294
  agent: |
295
- 基于以下材料写一份 Word 长文大纲,落盘到 `./build/article_outline.md`:
296
- - `./build/user_request.md`
297
- - `./build/material.md`
298
- - `./build/material.json`
295
+ 基于以下材料写一份 Word 长文大纲,落盘到 `out/word/${session}/build/article_outline.md`:
296
+ - `out/word/${session}/build/user_request.md`
297
+ - `out/word/${session}/build/material.md`
298
+ - `out/word/${session}/build/material.json`
299
299
 
300
300
  要求:
301
301
  - 文章定位为**知乎深度文章**:有观点、有论证、有转折、有解释、有结论。
@@ -310,14 +310,14 @@ steps:
310
310
  - 默认 `image_intensity=balanced` 至少 3 张;`rich` 至少 5 张;`minimal` 至少 1 张封面或核心概念图。
311
311
 
312
312
  写完后简短汇报。
313
- done_when: "fileExists('./build/article_outline.md')"
313
+ done_when: "fileExists('out/word/${session}/build/article_outline.md')"
314
314
  onError: halt
315
315
  maxTurns: 18
316
316
 
317
317
  - id: stage_write_article
318
318
  title: "阶段6/13·写作 article.md:知乎深度长文正文"
319
319
  agent: |
320
- 基于 `./build/article_outline.md`、`./build/material.md`、`./build/material.json` 写正文,落盘到 `./build/article.md`。
320
+ 基于 `out/word/${session}/build/article_outline.md`、`out/word/${session}/build/material.md`、`out/word/${session}/build/material.json` 写正文,落盘到 `out/word/${session}/build/article.md`。
321
321
 
322
322
  写作要求:
323
323
  - 风格是**知乎深度文章**,不是 PPT 文案,不是资料堆砌。
@@ -333,16 +333,16 @@ steps:
333
333
  - 每个占位必须贴近对应章节观点,写清 purpose 和 caption。
334
334
  - 图片附近必须有上下文解释,不能把图片孤零零塞进去。
335
335
  - 文章中避免出现“作为 AI”“根据材料可知”这类过程话。
336
- done_when: "fileExists('./build/article.md')"
336
+ done_when: "fileExists('out/word/${session}/build/article.md')"
337
337
  onError: halt
338
338
  maxTurns: 25
339
339
 
340
340
  - id: stage_img_plan
341
341
  title: "阶段7/13·图文混排计划 img_plan/image_map"
342
342
  agent: |
343
- 基于 `./build/article.md`、`./build/material.json`、`./build/material.md` 生成两个文件:
344
- 1. `./build/img_plan.json`
345
- 2. `./build/image_map.json`
343
+ 基于 `out/word/${session}/build/article.md`、`out/word/${session}/build/material.json`、`out/word/${session}/build/material.md` 生成两个文件:
344
+ 1. `out/word/${session}/build/img_plan.json`
345
+ 2. `out/word/${session}/build/image_map.json`
346
346
 
347
347
  `img_plan.json` 是给 GenerateImage 工具使用的数组,只放需要实际生成/增强的图:
348
348
  - 文生图:`{"file":"word_img_1.png","mode":"text-to-image","aspect":"16:9","prompt":"..."}`
@@ -371,7 +371,7 @@ steps:
371
371
  - 有客户图时也可以按 `${inputs.image_intensity}` 给关键章节补充文生图,但不能替代客户图使用。
372
372
 
373
373
  写完两个 JSON 后简短汇报。
374
- done_when: "fileExists('./build/img_plan.json') && fileExists('./build/image_map.json')"
374
+ done_when: "fileExists('out/word/${session}/build/img_plan.json') && fileExists('out/word/${session}/build/image_map.json')"
375
375
  onError: halt
376
376
  maxTurns: 18
377
377
 
@@ -384,7 +384,7 @@ steps:
384
384
  python3 - <<'PYEOF'
385
385
  import json, sys
386
386
  from pathlib import Path
387
- build = Path("./build")
387
+ build = Path("out/word/${session}/build")
388
388
  for name, expect_array in [("img_plan.json", True), ("image_map.json", True)]:
389
389
  path = build / name
390
390
  data = json.loads(path.read_text(encoding="utf-8-sig"))
@@ -397,11 +397,11 @@ steps:
397
397
 
398
398
  - id: stage_gen_images
399
399
  title: "阶段8/13·客户图增强与章节配图生成"
400
- when: "fileExists('./build/img_plan.json')"
400
+ when: "fileExists('out/word/${session}/build/img_plan.json')"
401
401
  tool: GenerateImage
402
402
  args:
403
- plan: ./build/img_plan.json
404
- assets: ./build/assets
403
+ plan: out/word/${session}/build/img_plan.json
404
+ assets: out/word/${session}/build/assets
405
405
  size: 2k
406
406
  timeout_ms: 300000
407
407
  wall_budget_ms: 3600000
@@ -411,15 +411,15 @@ steps:
411
411
 
412
412
  - id: stage_image_quality_gate
413
413
  title: "阶段8/13·补生成降级配图"
414
- when: "fileExists('./build/image_generation_report.json')"
414
+ when: "fileExists('out/word/${session}/build/image_generation_report.json')"
415
415
  tool: GenerateImage
416
416
  args:
417
- plan: ./build/img_plan.json
418
- assets: ./build/assets
417
+ plan: out/word/${session}/build/img_plan.json
418
+ assets: out/word/${session}/build/assets
419
419
  size: 2k
420
420
  timeout_ms: 300000
421
421
  wall_budget_ms: 3600000
422
- retry_degraded_report: ./build/image_generation_report.json
422
+ retry_degraded_report: out/word/${session}/build/image_generation_report.json
423
423
  max_rounds: 1
424
424
  concurrency: 2
425
425
  onError: continue
@@ -427,7 +427,7 @@ steps:
427
427
 
428
428
  - id: stage_generated_image_gate
429
429
  title: "阶段8/13·配图成品硬闸门"
430
- when: "fileExists('./build/image_generation_report.json')"
430
+ when: "fileExists('out/word/${session}/build/image_generation_report.json')"
431
431
  tool: Bash
432
432
  args:
433
433
  command: |
@@ -436,7 +436,7 @@ steps:
436
436
  import json
437
437
  from pathlib import Path
438
438
 
439
- build = Path("./build")
439
+ build = Path("out/word/${session}/build")
440
440
  report = json.loads((build / "image_generation_report.json").read_text(encoding="utf-8"))
441
441
  plan = json.loads((build / "img_plan.json").read_text(encoding="utf-8"))
442
442
  assets = build / "assets"
@@ -459,18 +459,18 @@ steps:
459
459
  - id: stage_finalize_markdown
460
460
  title: "阶段9/13·Markdown 图文混排收口"
461
461
  agent: |
462
- 更新 `./build/article.md`,把 `./build/image_map.json` 中的图片按章节插入最终位置。
462
+ 更新 `out/word/${session}/build/article.md`,把 `out/word/${session}/build/image_map.json` 中的图片按章节插入最终位置。
463
463
 
464
464
  要求:
465
- - 图片路径统一使用 `./build/assets/<final_file>`。
465
+ - 图片路径统一使用 `out/word/${session}/build/assets/<final_file>`。
466
466
  - 每张图必须有 Markdown 图片语法和紧随其后的图注,例如:
467
- `![alt](./build/assets/final.png)`
467
+ `![alt](out/word/${session}/build/assets/final.png)`
468
468
  `*图:caption*`
469
469
  - 删除临时 `<!-- image: ... -->` 占位。
470
470
  - 保持知乎深度文章风格:图片前后要有解释段,说明它支持了哪个观点或案例。
471
471
  - 统一标题层级、段落节奏、引用块、表格、结论。
472
472
  - 不要加入 PPT 术语,不要提网页 deck、页面 JSON 设计稿、构图门或 fixed canvas。
473
- done_when: "fileExists('./build/article.md')"
473
+ done_when: "fileExists('out/word/${session}/build/article.md')"
474
474
  onError: halt
475
475
  maxTurns: 18
476
476
 
@@ -484,7 +484,7 @@ steps:
484
484
  import json, sys
485
485
  from pathlib import Path
486
486
 
487
- build = Path("./build")
487
+ build = Path("out/word/${session}/build")
488
488
  material = json.loads((build / "material.json").read_text(encoding="utf-8"))
489
489
  customer = [img.get("file") for img in material.get("images", []) if img.get("file")]
490
490
  if customer:
@@ -565,7 +565,7 @@ steps:
565
565
  import json, re, sys
566
566
  from pathlib import Path
567
567
 
568
- build = Path("./build")
568
+ build = Path("out/word/${session}/build")
569
569
  material = json.loads((build / "material.json").read_text(encoding="utf-8"))
570
570
  image_map = json.loads((build / "image_map.json").read_text(encoding="utf-8"))
571
571
  article = (build / "article.md").read_text(encoding="utf-8")
@@ -598,15 +598,15 @@ steps:
598
598
  skill: docx
599
599
  input: |
600
600
  本步骤是 `skill: docx` 必要节点。
601
- 请严格按当前 minimal-agent 自带 `skills/docx/SKILL.md` 的指引,把 `./build/article.md` 转换为 Word 文件 `${inputs.out}`。
601
+ 请严格按当前 minimal-agent 自带 `skills/docx/SKILL.md` 的指引,把 `out/word/${session}/build/article.md` 转换为 Word 文件 `${inputs.out}`。
602
602
 
603
603
  硬性要求:
604
- - 优先使用 Markdown-first 路线:pandoc `./build/article.md -f markdown-implicit_figures -t docx -o ${inputs.out} --wrap=preserve --standalone`。
604
+ - 优先使用 Markdown-first 路线:pandoc `out/word/${session}/build/article.md -f markdown-implicit_figures -t docx -o ${inputs.out} --wrap=preserve --standalone`。
605
605
  - 必须关闭 pandoc implicit_figures,避免 Markdown 图片 alt 文本被渲染成额外可见图注;最终只保留 article.md 中显式的 `*图:...*` 图注。
606
606
  - 如果 pandoc 不可用或图片/表格转换失败,按 docx skill 指引回退到 python-docx 或 docx-js。
607
607
  - 若使用 docx-js,必须用 Node 运行脚本,不要用 Bun。
608
608
  - 保留 Markdown 标题层级、列表、表格、引用块、图片、图注和正文段落。
609
- - 图片来自 `./build/assets/<final_file>`,不要丢图。
609
+ - 图片来自 `out/word/${session}/build/assets/<final_file>`,不要丢图。
610
610
  - 最终必须生成 `${inputs.out}`。
611
611
  onError: halt
612
612
  maxTurns: 25
@@ -663,14 +663,14 @@ steps:
663
663
  python3 - <<'PYEOF'
664
664
  import json, os
665
665
  from pathlib import Path
666
- build = Path("./build")
666
+ build = Path("out/word/${session}/build")
667
667
  article = build / "article.md"
668
668
  image_map = json.loads((build / "image_map.json").read_text(encoding="utf-8")) if (build / "image_map.json").exists() else []
669
669
  usage = json.loads((build / "word_customer_image_usage.json").read_text(encoding="utf-8")) if (build / "word_customer_image_usage.json").exists() else {}
670
670
  summary = [
671
671
  "# Word 导出摘要\n\n",
672
672
  f"- 输出文件:${inputs.out}\n",
673
- f"- Markdown:./build/article.md\n",
673
+ f"- Markdown:out/word/${session}/build/article.md\n",
674
674
  f"- 文章字符数:{len(article.read_text(encoding='utf-8')) if article.exists() else 0}\n",
675
675
  f"- 图片映射数量:{len(image_map)}\n",
676
676
  f"- 客户图数量:{usage.get('customer_count', 0)}\n",
@@ -679,7 +679,7 @@ steps:
679
679
  (build / "export-summary.md").write_text("".join(summary), encoding="utf-8")
680
680
  print("WORD_DOCX_VERIFY_OK")
681
681
  PYEOF
682
- touch ./build/build_complete
682
+ touch out/word/${session}/build/build_complete
683
683
  onError: halt
684
684
 
685
685
  - id: cleanup_intermediates
@@ -689,9 +689,9 @@ steps:
689
689
  args:
690
690
  command: |
691
691
  set -e
692
- mkdir -p ./out
693
- cp ./build/export-summary.md ./out/word-export-summary.md 2>/dev/null || true
694
- rm -rf ./build
692
+ mkdir -p out/word/${session}
693
+ cp out/word/${session}/build/export-summary.md out/word/${session}/word-export-summary.md 2>/dev/null || true
694
+ rm -rf out/word/${session}/build
695
695
  echo "WORD_BUILD_CLEANED"
696
696
  onError: continue
697
697
 
@@ -712,9 +712,9 @@ steps:
712
712
  Word 长文已生成。
713
713
 
714
714
  - 输出 Word:[${inputs.out}](${inputs.out})
715
- - Markdown 草稿:./build/article.md
716
- - 统一材料:./build/material.md / ./build/material.json
717
- - 配图计划:./build/img_plan.json / ./build/image_map.json
718
- - 导出摘要:./build/export-summary.md
715
+ - Markdown 草稿:out/word/${session}/build/article.md
716
+ - 统一材料:out/word/${session}/build/material.md / out/word/${session}/build/material.json
717
+ - 配图计划:out/word/${session}/build/img_plan.json / out/word/${session}/build/image_map.json
718
+ - 导出摘要:out/word/${session}/build/export-summary.md
719
719
 
720
720
  流程:素材摄取 → 逐图识图 → 统一 material → 知乎深度文章大纲 → article.md 正文 → 图文混排计划 → 客户图增强/章节配图 → 客户图用尽闸门 → docx skill 导出 → OPC 校验。
@@ -10,8 +10,8 @@ version: "0.1"
10
10
  # 声明产物:new-task 启动清理残留 / completed 报实际产物 / 同任务 resume 重写不被
11
11
  # 内核「覆盖前先 Read」守卫挡(见 CLAUDE.md 任务身份语义)
12
12
  artifacts:
13
- - "./assets/script.json"
14
- - "./out/shorts.mp4"
13
+ - "out/youtube-shorts/${session}/assets/script.json"
14
+ - "out/youtube-shorts/${session}/shorts.mp4"
15
15
 
16
16
  inputs:
17
17
  - name: topic
@@ -59,9 +59,9 @@ steps:
59
59
  title: "2/11·脚本落盘 script.json"
60
60
  tool: Write
61
61
  artifacts:
62
- - "./assets/script.json"
62
+ - "out/youtube-shorts/${session}/assets/script.json"
63
63
  args:
64
- file_path: "./assets/script.json"
64
+ file_path: "out/youtube-shorts/${session}/assets/script.json"
65
65
  content: "${script_json_text}"
66
66
 
67
67
  # ---------- 3. 解析 script.json,拆出 prompts.txt / narrations.txt(每行一个) ----------
@@ -71,12 +71,12 @@ steps:
71
71
  args:
72
72
  command: |
73
73
  set -euo pipefail
74
- mkdir -p ./assets ./out
75
- jq -r '.scenes[].image_prompt' ./assets/script.json > ./assets/prompts.txt
76
- jq -r '.scenes[].text' ./assets/script.json > ./assets/narrations.txt
74
+ mkdir -p out/youtube-shorts/${session}/assets out/youtube-shorts/${session}
75
+ jq -r '.scenes[].image_prompt' out/youtube-shorts/${session}/assets/script.json > out/youtube-shorts/${session}/assets/prompts.txt
76
+ jq -r '.scenes[].text' out/youtube-shorts/${session}/assets/script.json > out/youtube-shorts/${session}/assets/narrations.txt
77
77
  # 把 narrations 转成 JSON 数组字符串,用于后续 subtitle-srt 调用
78
- jq -c '[.scenes[].text]' ./assets/script.json > ./assets/narrations_json.txt
79
- wc -l ./assets/prompts.txt ./assets/narrations.txt
78
+ jq -c '[.scenes[].text]' out/youtube-shorts/${session}/assets/script.json > out/youtube-shorts/${session}/assets/narrations_json.txt
79
+ wc -l out/youtube-shorts/${session}/assets/prompts.txt out/youtube-shorts/${session}/assets/narrations.txt
80
80
  capture:
81
81
  content: parse_log
82
82
 
@@ -84,9 +84,9 @@ steps:
84
84
  title: "4/11·校验脚本拆分产物"
85
85
  type: verify
86
86
  checks:
87
- - 'file_exists:./assets/prompts.txt'
88
- - 'file_exists:./assets/narrations.txt'
89
- onFail: "脚本解析失败:./assets/prompts.txt 或 ./assets/narrations.txt 不存在"
87
+ - 'file_exists:out/youtube-shorts/${session}/assets/prompts.txt'
88
+ - 'file_exists:out/youtube-shorts/${session}/assets/narrations.txt'
89
+ onFail: "脚本解析失败:out/youtube-shorts/${session}/assets/prompts.txt 或 out/youtube-shorts/${session}/assets/narrations.txt 不存在"
90
90
 
91
91
  # ---------- 4. 生成 5 张配图(loop 静态数组 + 每轮先读对应一行 prompt) ----------
92
92
  # ⚠️ Bash 引号 footgun:${i} 是引擎插值(shell 之前发生)。曾写 1 基算术
@@ -102,13 +102,13 @@ steps:
102
102
  title: "读第 ${i} 行画面提示词"
103
103
  tool: Bash
104
104
  args:
105
- command: 'sed -n "${i}p" ./assets/prompts.txt'
105
+ command: 'sed -n "${i}p" out/youtube-shorts/${session}/assets/prompts.txt'
106
106
  capture:
107
107
  content: prompt_text
108
108
  - id: gen_one_image
109
109
  title: "生成第 ${i} 张配图"
110
110
  skill: image-gen-openrouter
111
- input: 'prompt=${prompt_text} output=./assets/img_${i}.png aspect=${inputs.aspect} key=${inputs.openrouter_key}'
111
+ input: 'prompt=${prompt_text} output=out/youtube-shorts/${session}/assets/img_${i}.png aspect=${inputs.aspect} key=${inputs.openrouter_key}'
112
112
 
113
113
  # ---------- 5. 生成 5 段 TTS 音频(1 基序号,理由同 gen_images) ----------
114
114
  - id: gen_audio
@@ -121,13 +121,13 @@ steps:
121
121
  title: "读第 ${i} 句旁白"
122
122
  tool: Bash
123
123
  args:
124
- command: 'sed -n "${i}p" ./assets/narrations.txt'
124
+ command: 'sed -n "${i}p" out/youtube-shorts/${session}/assets/narrations.txt'
125
125
  capture:
126
126
  content: narration_text
127
127
  - id: gen_one_tts
128
128
  title: "合成第 ${i} 段语音"
129
129
  skill: tts-zh
130
- input: 'text=${narration_text} output=./assets/audio_${i}.mp3'
130
+ input: 'text=${narration_text} output=out/youtube-shorts/${session}/assets/audio_${i}.mp3'
131
131
 
132
132
  # ---------- 6. 探测各段音频时长,逗号串联 ----------
133
133
  - id: probe_durations
@@ -136,7 +136,7 @@ steps:
136
136
  args:
137
137
  command: |
138
138
  set -euo pipefail
139
- for f in $(ls ./assets/audio_*.mp3 | sort); do
139
+ for f in $(ls out/youtube-shorts/${session}/assets/audio_*.mp3 | sort); do
140
140
  ffprobe -v error -show_entries format=duration -of csv=p=0 "$f"
141
141
  done | paste -sd, -
142
142
  capture:
@@ -151,18 +151,18 @@ steps:
151
151
  set -euo pipefail
152
152
  LIST=/tmp/audio_concat.txt
153
153
  : > "$LIST"
154
- for f in $(ls ./assets/audio_*.mp3 | sort); do
154
+ for f in $(ls out/youtube-shorts/${session}/assets/audio_*.mp3 | sort); do
155
155
  echo "file '$(pwd)/${f}'" >> "$LIST"
156
156
  done
157
- ffmpeg -y -f concat -safe 0 -i "$LIST" -c copy ./assets/audio.mp3
158
- ls -la ./assets/audio.mp3
157
+ ffmpeg -y -f concat -safe 0 -i "$LIST" -c copy out/youtube-shorts/${session}/assets/audio.mp3
158
+ ls -la out/youtube-shorts/${session}/assets/audio.mp3
159
159
 
160
160
  # ---------- 8. 读 narrations_json(前面 parse_script 已写好),作 SRT 文本输入 ----------
161
161
  - id: read_narrations_json
162
162
  title: "9/11·读取旁白清单"
163
163
  tool: Read
164
164
  args:
165
- file_path: "./assets/narrations_json.txt"
165
+ file_path: "out/youtube-shorts/${session}/assets/narrations_json.txt"
166
166
  capture:
167
167
  content: narrations_json
168
168
 
@@ -170,21 +170,21 @@ steps:
170
170
  - id: make_srt
171
171
  title: "10/11·生成字幕"
172
172
  skill: subtitle-srt
173
- input: 'texts=${narrations_json} durations=${durations} output=./assets/subs.srt'
173
+ input: 'texts=${narrations_json} durations=${durations} output=out/youtube-shorts/${session}/assets/subs.srt'
174
174
 
175
175
  # ---------- 10. 合成最终 mp4 ----------
176
176
  - id: compose_video
177
177
  title: "11/11·合成最终视频"
178
178
  skill: video-compose
179
- input: 'images_glob=./assets/img_*.png audio=./assets/audio.mp3 srt=./assets/subs.srt output=./out/shorts.mp4 width=${inputs.width} height=${inputs.height}'
179
+ input: 'images_glob=out/youtube-shorts/${session}/assets/img_*.png audio=out/youtube-shorts/${session}/assets/audio.mp3 srt=out/youtube-shorts/${session}/assets/subs.srt output=out/youtube-shorts/${session}/shorts.mp4 width=${inputs.width} height=${inputs.height}'
180
180
 
181
181
  # ---------- 11. 守门 verify(升级自 assert) ----------
182
182
  - id: verify_output
183
183
  title: "完成·守门校验"
184
184
  type: verify
185
185
  checks:
186
- - 'file_exists:./out/shorts.mp4'
187
- onFail: "最终视频 ./out/shorts.mp4 未生成,请检查 video-compose 日志"
186
+ - 'file_exists:out/youtube-shorts/${session}/shorts.mp4'
187
+ onFail: "最终视频 out/youtube-shorts/${session}/shorts.mp4 未生成,请检查 video-compose 日志"
188
188
 
189
189
  __meta:
190
190
  layout: