@zzclub/pipeline 0.3.0 → 0.4.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 (194) hide show
  1. package/README.md +366 -170
  2. package/package.json +4 -7
  3. package/src/adapter-loader.ts +138 -0
  4. package/src/adapter-types.ts +172 -0
  5. package/src/adapters/builtin-image-renderer.ts +353 -0
  6. package/src/adapters/builtin-markdown-renderer.ts +63 -0
  7. package/src/adapters/index.ts +2 -0
  8. package/src/args.test.ts +118 -0
  9. package/src/args.ts +90 -0
  10. package/src/cli.ts +51 -0
  11. package/src/commands/abandon.test.ts +104 -0
  12. package/src/commands/abandon.ts +202 -0
  13. package/src/commands/attach-body-images.ts +88 -0
  14. package/src/commands/attach-body.ts +86 -0
  15. package/src/commands/attach-newspic-spec.ts +41 -0
  16. package/src/commands/checkpoint.test.ts +91 -0
  17. package/src/commands/checkpoint.ts +66 -0
  18. package/src/commands/config.ts +106 -0
  19. package/src/commands/cos-upload.ts +62 -0
  20. package/src/commands/doctor.ts +66 -0
  21. package/src/commands/find-run.ts +55 -0
  22. package/src/commands/hermes-metrics.ts +226 -0
  23. package/src/commands/imgx.ts +60 -0
  24. package/src/commands/ingest-handoff.ts +509 -0
  25. package/src/commands/init.ts +126 -0
  26. package/src/commands/prepare-finalize.ts +348 -0
  27. package/src/commands/prepare.ts +310 -0
  28. package/src/commands/publish.ts +147 -0
  29. package/src/commands/reconcile.ts +36 -0
  30. package/src/commands/render.ts +244 -0
  31. package/src/commands/reset.test.ts +151 -0
  32. package/src/commands/reset.ts +159 -0
  33. package/src/commands/review.ts +77 -0
  34. package/src/commands/status.ts +68 -0
  35. package/src/commands/sync-blog.ts +39 -0
  36. package/src/commands/tasks.ts +50 -0
  37. package/src/commands/wechat-export.ts +68 -0
  38. package/src/config.ts +0 -0
  39. package/src/imgx/ascii-portrait.ts +77 -0
  40. package/src/imgx/assets/fonts/AlimamaShuHeiTi-Bold.ttf +0 -0
  41. package/src/imgx/assets/fonts/LXGWNeoZhiSongPlus.ttf +0 -0
  42. package/src/imgx/assets/fonts/LXGWWenKai-Regular.ttf +0 -0
  43. package/src/imgx/assets/icons/logo.png +0 -0
  44. package/src/imgx/assets/icons/logo.svg +8 -0
  45. package/{dist/assets → src}/imgx/assets/templates/longform-3-4.html +1 -1
  46. package/{dist/assets → src}/imgx/assets/templates/poster-3-4.html +69 -30
  47. package/{dist/assets → src}/imgx/assets/templates/wechat-cover-split.html +58 -27
  48. package/src/imgx/cli.ts +57 -0
  49. package/src/imgx/geometry.ts +68 -0
  50. package/src/imgx/index.ts +5 -0
  51. package/src/imgx/longform-theme.ts +243 -0
  52. package/src/imgx/poster-recipe.ts +81 -0
  53. package/src/imgx/pretext-adapter.ts +14 -0
  54. package/src/imgx/pretext-runtime.ts +61 -0
  55. package/src/imgx/references/ascii-portrait-3-4.md +59 -0
  56. package/src/imgx/references/longform-3-4.md +173 -0
  57. package/src/imgx/references/poster-3-4.md +87 -0
  58. package/src/imgx/references/tips-3-4.md +69 -0
  59. package/src/imgx/references/wechat-cover-split.md +89 -0
  60. package/src/imgx/references/x-like-posts.md +139 -0
  61. package/src/imgx/render-article.test.ts +53 -0
  62. package/src/imgx/render-article.ts +1364 -0
  63. package/src/imgx/render-ascii-portrait.ts +53 -0
  64. package/src/imgx/render-card.ts +232 -0
  65. package/src/imgx/render-x-like-posts.ts +235 -0
  66. package/src/imgx/runtime.ts +403 -0
  67. package/src/imgx/typographic-scale.test.ts +56 -0
  68. package/src/imgx/typographic-scale.ts +44 -0
  69. package/src/output.ts +632 -0
  70. package/src/plugins.ts +101 -0
  71. package/src/profiles.ts +149 -0
  72. package/src/providers/blog.test.ts +58 -0
  73. package/src/providers/blog.ts +154 -0
  74. package/src/providers/cos.ts +183 -0
  75. package/src/providers/index.test.ts +26 -0
  76. package/src/providers/index.ts +185 -0
  77. package/src/providers/wechat.test.ts +215 -0
  78. package/src/providers/wechat.ts +548 -0
  79. package/src/routes.ts +287 -0
  80. package/src/runtime-paths.ts +179 -0
  81. package/src/schema/config.ts +133 -0
  82. package/src/schema/state.ts +376 -0
  83. package/src/spawn.ts +103 -0
  84. package/src/state.ts +265 -0
  85. package/src/task-manager.ts +657 -0
  86. package/src/task-views.ts +222 -0
  87. package/src/text.test.ts +689 -0
  88. package/src/text.ts +683 -0
  89. package/src/wechat-preview/assets/fonts/SweiCurveLegCJKsc-Regular.woff +0 -0
  90. package/src/wechat-preview/browser/editor-export.css +241 -0
  91. package/src/wechat-preview/browser/editor-export.ts +103 -0
  92. package/src/wechat-preview/frontmatter-handler.ts +73 -0
  93. package/src/wechat-preview/index.test.ts +154 -0
  94. package/src/wechat-preview/index.ts +294 -0
  95. package/src/wechat-preview/themes.ts +141 -0
  96. package/src/wechat-preview/wechat-formatter.test.ts +288 -0
  97. package/src/wechat-preview/wechat-formatter.ts +1506 -0
  98. package/src/wechat-preview.test.ts +73 -0
  99. package/src/workflow-materials.test.ts +225 -0
  100. package/src/workflow-materials.ts +217 -0
  101. package/src/workflow.test.ts +2087 -0
  102. package/dist/assets/imgx/assets/icons/avatar_jinx_cartoon.jpg +0 -0
  103. package/dist/assets/imgx/assets/icons/fishbone-logo-square.png +0 -0
  104. package/dist/assets/imgx/assets/icons/fishbone-logo.jpg +0 -0
  105. package/dist/assets/imgx/assets/icons/fishbone-logo.png +0 -0
  106. package/dist/assets/imgx/assets/icons/openclaw-logo.svg +0 -22
  107. package/dist/assets/imgx/assets/icons/zzclub-logo-black.jpg +0 -0
  108. package/dist/assets/imgx/assets/icons/zzclub-logo-gray.svg +0 -25
  109. package/dist/cli.js +0 -431
  110. package/dist/node_modules/@chenglou/pretext/dist/analysis.d.ts +0 -33
  111. package/dist/node_modules/@chenglou/pretext/dist/analysis.js +0 -1063
  112. package/dist/node_modules/@chenglou/pretext/dist/bidi.d.ts +0 -1
  113. package/dist/node_modules/@chenglou/pretext/dist/bidi.js +0 -175
  114. package/dist/node_modules/@chenglou/pretext/dist/generated/bidi-data.d.ts +0 -4
  115. package/dist/node_modules/@chenglou/pretext/dist/generated/bidi-data.js +0 -979
  116. package/dist/node_modules/@chenglou/pretext/dist/layout.d.ts +0 -70
  117. package/dist/node_modules/@chenglou/pretext/dist/layout.js +0 -496
  118. package/dist/node_modules/@chenglou/pretext/dist/line-break.d.ts +0 -36
  119. package/dist/node_modules/@chenglou/pretext/dist/line-break.js +0 -820
  120. package/dist/node_modules/@chenglou/pretext/dist/measurement.d.ts +0 -28
  121. package/dist/node_modules/@chenglou/pretext/dist/measurement.js +0 -219
  122. package/dist/node_modules/@chenglou/pretext/dist/rich-inline.d.ts +0 -51
  123. package/dist/node_modules/@chenglou/pretext/dist/rich-inline.js +0 -401
  124. /package/{dist/assets → src}/imgx/assets/browser/obstacle-flow.d.ts +0 -0
  125. /package/{dist/assets → src}/imgx/assets/browser/obstacle-flow.js +0 -0
  126. /package/{dist/assets → src}/imgx/assets/icons/clover.svg +0 -0
  127. /package/{dist/assets → src}/imgx/assets/templates/ascii-portrait-3-4.html +0 -0
  128. /package/{dist/assets → src}/imgx/assets/templates/ascii-portrait-tile.html +0 -0
  129. /package/{dist/assets → src}/imgx/assets/templates/tips-3-4.html +0 -0
  130. /package/{dist/assets → src}/imgx/assets/templates/x-like-posts.html +0 -0
  131. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/.vite/manifest.json +0 -0
  132. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  133. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  134. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  135. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  136. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  137. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  138. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  139. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  140. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  141. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  142. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  143. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  144. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  145. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  146. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  147. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  148. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  149. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  150. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  151. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  152. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  153. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  154. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  155. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  156. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  157. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  158. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  159. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  160. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  161. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  162. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  163. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  164. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  165. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  166. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  167. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  168. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  169. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  170. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  171. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  172. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  173. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  174. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  175. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  176. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  177. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  178. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  179. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  180. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  181. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  182. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  183. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  184. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  185. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  186. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  187. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  188. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  189. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  190. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  191. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/SweiCurveLegCJKsc-Regular-B3Ut5bwH.woff +0 -0
  192. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/style-BYNXnUvc.css +0 -0
  193. /package/{dist/assets → src}/wechat-preview/assets/browser-dist/editor-export.js +0 -0
  194. /package/{dist/assets → src}/wechat-preview/assets/templates/export-shell.html +0 -0
@@ -0,0 +1,222 @@
1
+ import type { ListedTask, TaskGap, TaskStatusReport } from "./task-manager";
2
+
3
+ export type TaskViewMode = "json" | "markdown" | "agent" | "agent-json";
4
+
5
+ function formatValue(value: string | null | undefined): string {
6
+ return value && value.trim() ? value : "-";
7
+ }
8
+
9
+ function describeAccount(account: string): string {
10
+ switch (account) {
11
+ case "default":
12
+ return "default (大号 / 早早集市)";
13
+ case "ancientone":
14
+ return "ancientone (小号 / 古一)";
15
+ default:
16
+ return account;
17
+ }
18
+ }
19
+
20
+ function formatGapList(items: TaskGap[]): string {
21
+ if (items.length === 0) {
22
+ return "- none";
23
+ }
24
+ return items
25
+ .map((item) => `- ${item.message} (\`${item.field}\`)`)
26
+ .join("\n");
27
+ }
28
+
29
+ function buildSuggestedCommand(task: TaskStatusReport): string | null {
30
+ return task.next_action.command;
31
+ }
32
+
33
+ function describePublishResults(task: TaskStatusReport): string {
34
+ const results = task.summary.publish.results;
35
+ if (results.length === 0) {
36
+ return "none";
37
+ }
38
+ return results
39
+ .map((result) => `${result.route}:${result.status}`)
40
+ .join(", ");
41
+ }
42
+
43
+ export function parseTaskViewMode(raw: string | undefined): TaskViewMode {
44
+ if (!raw || raw === "json") {
45
+ return "json";
46
+ }
47
+ if (raw === "markdown" || raw === "agent" || raw === "agent-json") {
48
+ return raw;
49
+ }
50
+ throw new Error(`Unsupported view: ${raw}. Use json, markdown, agent, or agent-json.`);
51
+ }
52
+
53
+ export function renderTaskStatusMarkdown(
54
+ task: TaskStatusReport,
55
+ mode: Exclude<TaskViewMode, "json">,
56
+ ): string {
57
+ const heading = mode === "agent" ? "# Current Task" : "# Task Status";
58
+ const suggestedCommand = buildSuggestedCommand(task);
59
+ const sections = [
60
+ heading,
61
+ "",
62
+ `- Task: \`${task.summary.run_id}\``,
63
+ `- Mode: \`${task.summary.mode}\``,
64
+ `- Phase: \`${task.summary.phase.current}\``,
65
+ `- Route: \`${task.summary.route.primary}\``,
66
+ `- Account: \`${describeAccount(task.summary.route.account)}\``,
67
+ `- Title: \`${formatValue(task.summary.metadata.title)}\``,
68
+ `- Source: \`${task.summary.source}\``,
69
+ `- Publish Results: \`${describePublishResults(task)}\``,
70
+ "",
71
+ "## Missing",
72
+ formatGapList(task.gaps),
73
+ "",
74
+ "## Blockers",
75
+ formatGapList(task.blockers),
76
+ "",
77
+ "## Next Action",
78
+ `- \`${task.next_action.action}\`: ${task.next_action.reason}`,
79
+ `- Executor: \`${task.next_action.executor}\``,
80
+ ];
81
+
82
+ // In agent mode, surface next_action.params as an explicit block so the
83
+ // orchestrator can read them without inspecting the state file.
84
+ if (mode === "agent" && task.next_action.params) {
85
+ const params = task.next_action.params;
86
+ const paramLines: string[] = [];
87
+ if (params.state_path) {
88
+ paramLines.push(`- state_path: \`${params.state_path}\``);
89
+ }
90
+ if (params.spawn) {
91
+ paramLines.push(`- spawn: \`true\``);
92
+ }
93
+ if (params.requires_research) {
94
+ paramLines.push(`- requires_research: \`true\``);
95
+ }
96
+ if (params.source_body_path) {
97
+ paramLines.push(`- source_body_path: \`${params.source_body_path}\``);
98
+ }
99
+ if (params.source_materials_path) {
100
+ paramLines.push(`- source_materials_path: \`${params.source_materials_path}\``);
101
+ }
102
+ if (params.formatted_body_path) {
103
+ paramLines.push(`- formatted_body_path: \`${params.formatted_body_path}\``);
104
+ }
105
+ if (params.feedback !== undefined && params.feedback !== null) {
106
+ paramLines.push(`- feedback: ${params.feedback}`);
107
+ }
108
+ if (params.worker_profile) {
109
+ paramLines.push(`- worker_profile: \`${params.worker_profile}\``);
110
+ }
111
+ if (params.worker_mode) {
112
+ paramLines.push(`- worker_mode: \`${params.worker_mode}\``);
113
+ }
114
+ if (params.research_policy && params.research_policy !== "default") {
115
+ paramLines.push(`- research_policy: \`${params.research_policy}\``);
116
+ }
117
+ if (params.authoring_policy && params.authoring_policy !== "default") {
118
+ paramLines.push(`- authoring_policy: \`${params.authoring_policy}\``);
119
+ }
120
+ if (params.review_policy && params.review_policy !== "default") {
121
+ paramLines.push(`- review_policy: \`${params.review_policy}\``);
122
+ }
123
+ if (params.required_inputs && params.required_inputs.length > 0) {
124
+ paramLines.push(`- required_inputs: \`${params.required_inputs.join(", ")}\``);
125
+ }
126
+ if (params.body_source) {
127
+ paramLines.push(`- body_source: \`${params.body_source}\``);
128
+ }
129
+ if (params.handoff_alt) {
130
+ paramLines.push(`- handoff_alt: \`${params.handoff_alt}\``);
131
+ }
132
+ if (params.on_complete) {
133
+ paramLines.push(`- on_complete: ${params.on_complete}`);
134
+ }
135
+ if (paramLines.length > 0) {
136
+ sections.push("", "**Params**", ...paramLines);
137
+ }
138
+ }
139
+
140
+ if (suggestedCommand) {
141
+ sections.push(
142
+ "",
143
+ "## Suggested Command",
144
+ "```bash",
145
+ suggestedCommand,
146
+ "```",
147
+ );
148
+ }
149
+
150
+ return sections.join("\n");
151
+ }
152
+
153
+ function renderTasksMarkdownTable(tasks: ListedTask[]): string {
154
+ const lines = [
155
+ "# Task List",
156
+ "",
157
+ "| Run ID | Title | Route | Account | Mode | Phase | Next |",
158
+ "| --- | --- | --- | --- | --- | --- | --- |",
159
+ ];
160
+
161
+ for (const task of tasks) {
162
+ lines.push(
163
+ `| \`${task.summary.run_id}\` | ${formatValue(task.summary.metadata.title)} | \`${task.summary.route.primary}\` | \`${task.summary.route.account}\` | \`${task.summary.mode}\` | \`${task.summary.phase.current}\` | \`${task.next_action.action}\` |`,
164
+ );
165
+ }
166
+
167
+ if (tasks.length === 0) {
168
+ lines.push("| - | - | - | - | - | - | - |");
169
+ }
170
+
171
+ return lines.join("\n");
172
+ }
173
+
174
+ function renderTasksAgentList(tasks: ListedTask[]): string {
175
+ const lines = ["# Active Tasks", ""];
176
+
177
+ if (tasks.length === 0) {
178
+ lines.push("- No matching tasks.");
179
+ return lines.join("\n");
180
+ }
181
+
182
+ for (const task of tasks) {
183
+ lines.push(`## \`${task.summary.run_id}\``);
184
+ lines.push(`- Title: \`${formatValue(task.summary.metadata.title)}\``);
185
+ lines.push(`- Route: \`${task.summary.route.primary}\``);
186
+ lines.push(`- Account: \`${describeAccount(task.summary.route.account)}\``);
187
+ lines.push(`- Mode: \`${task.summary.mode}\``);
188
+ lines.push(`- Phase: \`${task.summary.phase.current}\``);
189
+ lines.push(`- Next: \`${task.next_action.action}\` - ${task.next_action.reason}`);
190
+ lines.push(`- Executor: \`${task.next_action.executor}\``);
191
+ if (task.blockers.length > 0) {
192
+ lines.push(`- Blockers: ${task.blockers.map((item) => item.message).join("; ")}`);
193
+ } else if (task.gaps.length > 0) {
194
+ lines.push(`- Missing: ${task.gaps.map((item) => item.message).join("; ")}`);
195
+ }
196
+ lines.push("");
197
+ }
198
+
199
+ return lines.join("\n").trimEnd();
200
+ }
201
+
202
+ export function renderTasksView(
203
+ tasks: ListedTask[],
204
+ mode: Exclude<TaskViewMode, "json">,
205
+ ): string {
206
+ return mode === "markdown"
207
+ ? renderTasksMarkdownTable(tasks)
208
+ : renderTasksAgentList(tasks);
209
+ }
210
+
211
+ export function buildAgentTaskShape(task: TaskStatusReport): Record<string, unknown> {
212
+ return {
213
+ summary: task.summary,
214
+ gaps: task.gaps,
215
+ blockers: task.blockers,
216
+ next_action: task.next_action,
217
+ };
218
+ }
219
+
220
+ export function buildAgentTasksShape(tasks: ListedTask[]): Record<string, unknown>[] {
221
+ return tasks.map((task) => buildAgentTaskShape(task));
222
+ }