agentic-forge 0.0.0 → 0.7.1

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 (212) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +64 -24
  3. package/{src/claude → dist/authoring}/.claude/skills/workflow-builder/SKILL.md +2 -2
  4. package/{src/claude → dist/authoring}/.claude/skills/workflow-builder/references/REFERENCE.md +9 -3
  5. package/{src/claude → dist/authoring}/.claude/skills/workflow-builder/references/workflow-example.yaml +15 -8
  6. package/dist/checkpoints/manager.d.ts +5 -0
  7. package/dist/checkpoints/manager.js +87 -0
  8. package/dist/checkpoints/manager.js.map +1 -0
  9. package/{src → dist}/claude/.claude/skills/analyze/SKILL.md +1 -1
  10. package/{src → dist}/claude/.claude/skills/create-checkpoint/SKILL.md +1 -1
  11. package/{src → dist}/claude/.claude/skills/create-log/SKILL.md +1 -1
  12. package/{src → dist}/claude/.claude/skills/fix-analyze/SKILL.md +1 -1
  13. package/{src → dist}/claude/.claude/skills/git-branch/SKILL.md +1 -1
  14. package/{src → dist}/claude/.claude/skills/git-commit/SKILL.md +1 -1
  15. package/{src → dist}/claude/.claude/skills/git-pr/SKILL.md +1 -1
  16. package/{src → dist}/claude/.claude/skills/sdlc-plan/SKILL.md +1 -1
  17. package/{src → dist}/claude/.claude/skills/sdlc-review/SKILL.md +1 -1
  18. package/dist/cli.d.ts +3 -0
  19. package/dist/cli.js +173 -0
  20. package/dist/cli.js.map +1 -0
  21. package/dist/commands/authoring-dir.d.ts +2 -0
  22. package/dist/commands/authoring-dir.js +9 -0
  23. package/dist/commands/authoring-dir.js.map +1 -0
  24. package/dist/commands/config-cmd.d.ts +2 -0
  25. package/dist/commands/config-cmd.js +30 -0
  26. package/dist/commands/config-cmd.js.map +1 -0
  27. package/{src/commands/index.ts → dist/commands/index.d.ts} +2 -10
  28. package/dist/commands/index.js +14 -0
  29. package/dist/commands/index.js.map +1 -0
  30. package/dist/commands/init.d.ts +6 -0
  31. package/dist/commands/init.js +83 -0
  32. package/dist/commands/init.js.map +1 -0
  33. package/dist/commands/release-notes.d.ts +5 -0
  34. package/dist/commands/release-notes.js +68 -0
  35. package/dist/commands/release-notes.js.map +1 -0
  36. package/dist/commands/resume.d.ts +5 -0
  37. package/dist/commands/resume.js +79 -0
  38. package/dist/commands/resume.js.map +1 -0
  39. package/dist/commands/run.d.ts +27 -0
  40. package/dist/commands/run.js +243 -0
  41. package/dist/commands/run.js.map +1 -0
  42. package/dist/commands/shortcuts.d.ts +2 -0
  43. package/dist/commands/shortcuts.js +11 -0
  44. package/dist/commands/shortcuts.js.map +1 -0
  45. package/dist/commands/skills-dir.d.ts +2 -0
  46. package/dist/commands/skills-dir.js +9 -0
  47. package/dist/commands/skills-dir.js.map +1 -0
  48. package/dist/commands/status.d.ts +4 -0
  49. package/dist/commands/status.js +99 -0
  50. package/dist/commands/status.js.map +1 -0
  51. package/dist/commands/update.d.ts +4 -0
  52. package/dist/commands/update.js +65 -0
  53. package/dist/commands/update.js.map +1 -0
  54. package/dist/commands/version.d.ts +3 -0
  55. package/dist/commands/version.js +26 -0
  56. package/dist/commands/version.js.map +1 -0
  57. package/dist/commands/workflows.d.ts +4 -0
  58. package/dist/commands/workflows.js +111 -0
  59. package/dist/commands/workflows.js.map +1 -0
  60. package/dist/config.d.ts +8 -0
  61. package/dist/config.js +110 -0
  62. package/dist/config.js.map +1 -0
  63. package/dist/console.d.ts +103 -0
  64. package/dist/console.js +670 -0
  65. package/dist/console.js.map +1 -0
  66. package/dist/executor.d.ts +27 -0
  67. package/dist/executor.js +236 -0
  68. package/dist/executor.js.map +1 -0
  69. package/dist/git/worktree.d.ts +23 -0
  70. package/dist/git/worktree.js +170 -0
  71. package/dist/git/worktree.js.map +1 -0
  72. package/dist/logging/logger.d.ts +27 -0
  73. package/dist/logging/logger.js +69 -0
  74. package/dist/logging/logger.js.map +1 -0
  75. package/dist/orchestrator.d.ts +44 -0
  76. package/dist/orchestrator.js +587 -0
  77. package/dist/orchestrator.js.map +1 -0
  78. package/dist/parser.d.ts +17 -0
  79. package/dist/parser.js +184 -0
  80. package/dist/parser.js.map +1 -0
  81. package/dist/progress.d.ts +29 -0
  82. package/dist/progress.js +275 -0
  83. package/dist/progress.js.map +1 -0
  84. package/dist/ralph-loop.d.ts +26 -0
  85. package/dist/ralph-loop.js +194 -0
  86. package/dist/ralph-loop.js.map +1 -0
  87. package/dist/renderer.d.ts +15 -0
  88. package/dist/renderer.js +123 -0
  89. package/dist/renderer.js.map +1 -0
  90. package/dist/runner.d.ts +84 -0
  91. package/dist/runner.js +529 -0
  92. package/dist/runner.js.map +1 -0
  93. package/dist/signal-manager.d.ts +16 -0
  94. package/dist/signal-manager.js +50 -0
  95. package/dist/signal-manager.js.map +1 -0
  96. package/dist/steps/base.d.ts +28 -0
  97. package/dist/steps/base.js +23 -0
  98. package/dist/steps/base.js.map +1 -0
  99. package/dist/steps/conditional-step.d.ts +12 -0
  100. package/dist/steps/conditional-step.js +106 -0
  101. package/dist/steps/conditional-step.js.map +1 -0
  102. package/{src/steps/index.ts → dist/steps/index.d.ts} +1 -9
  103. package/dist/steps/index.js +8 -0
  104. package/dist/steps/index.js.map +1 -0
  105. package/dist/steps/parallel-step.d.ts +11 -0
  106. package/dist/steps/parallel-step.js +166 -0
  107. package/dist/steps/parallel-step.js.map +1 -0
  108. package/dist/steps/prompt-step.d.ts +8 -0
  109. package/dist/steps/prompt-step.js +94 -0
  110. package/dist/steps/prompt-step.js.map +1 -0
  111. package/dist/steps/ralph-loop-step.d.ts +8 -0
  112. package/dist/steps/ralph-loop-step.js +132 -0
  113. package/dist/steps/ralph-loop-step.js.map +1 -0
  114. package/dist/steps/serial-step.d.ts +10 -0
  115. package/dist/steps/serial-step.js +57 -0
  116. package/dist/steps/serial-step.js.map +1 -0
  117. package/dist/types.d.ts +118 -0
  118. package/dist/types.js +10 -0
  119. package/dist/types.js.map +1 -0
  120. package/package.json +59 -2
  121. package/.gitattributes +0 -24
  122. package/.github/workflows/ci.yml +0 -70
  123. package/.markdownlint-cli2.jsonc +0 -16
  124. package/.prettierignore +0 -3
  125. package/.prettierrc +0 -6
  126. package/.vscode/agentic-forge.code-workspace +0 -26
  127. package/CHANGELOG.md +0 -100
  128. package/CLAUDE.md +0 -158
  129. package/CONTRIBUTING.md +0 -152
  130. package/biome.json +0 -21
  131. package/scripts/copy-assets.js +0 -21
  132. package/src/checkpoints/manager.ts +0 -119
  133. package/src/cli.ts +0 -182
  134. package/src/commands/config-cmd.ts +0 -28
  135. package/src/commands/init.ts +0 -96
  136. package/src/commands/release-notes.ts +0 -85
  137. package/src/commands/resume.ts +0 -103
  138. package/src/commands/run.ts +0 -234
  139. package/src/commands/shortcuts.ts +0 -11
  140. package/src/commands/skills-dir.ts +0 -11
  141. package/src/commands/status.ts +0 -112
  142. package/src/commands/update.ts +0 -64
  143. package/src/commands/version.ts +0 -27
  144. package/src/commands/workflows.ts +0 -129
  145. package/src/config.ts +0 -129
  146. package/src/console.ts +0 -790
  147. package/src/executor.ts +0 -354
  148. package/src/git/worktree.ts +0 -236
  149. package/src/logging/logger.ts +0 -95
  150. package/src/orchestrator.ts +0 -815
  151. package/src/parser.ts +0 -225
  152. package/src/progress.ts +0 -306
  153. package/src/ralph-loop.ts +0 -260
  154. package/src/renderer.ts +0 -164
  155. package/src/runner.ts +0 -634
  156. package/src/signal-manager.ts +0 -55
  157. package/src/steps/base.ts +0 -71
  158. package/src/steps/conditional-step.ts +0 -144
  159. package/src/steps/parallel-step.ts +0 -213
  160. package/src/steps/prompt-step.ts +0 -121
  161. package/src/steps/ralph-loop-step.ts +0 -186
  162. package/src/steps/serial-step.ts +0 -84
  163. package/src/types.ts +0 -141
  164. package/tests/config.test.ts +0 -219
  165. package/tests/console.test.ts +0 -506
  166. package/tests/executor.test.ts +0 -339
  167. package/tests/init.test.ts +0 -86
  168. package/tests/logger.test.ts +0 -110
  169. package/tests/parser.test.ts +0 -290
  170. package/tests/progress.test.ts +0 -345
  171. package/tests/ralph-loop.test.ts +0 -418
  172. package/tests/renderer.test.ts +0 -350
  173. package/tests/runner.test.ts +0 -497
  174. package/tests/setup.test.ts +0 -7
  175. package/tests/signal-manager.test.ts +0 -26
  176. package/tests/steps.test.ts +0 -412
  177. package/tests/worktree.test.ts +0 -411
  178. package/tsconfig.json +0 -18
  179. package/vitest.config.ts +0 -8
  180. /package/{src → dist}/agents/explorer.md +0 -0
  181. /package/{src → dist}/agents/reviewer.md +0 -0
  182. /package/{src → dist}/claude/.claude/skills/analyze/references/bug.md +0 -0
  183. /package/{src → dist}/claude/.claude/skills/analyze/references/debt.md +0 -0
  184. /package/{src → dist}/claude/.claude/skills/analyze/references/doc.md +0 -0
  185. /package/{src → dist}/claude/.claude/skills/analyze/references/security.md +0 -0
  186. /package/{src → dist}/claude/.claude/skills/analyze/references/style.md +0 -0
  187. /package/{src → dist}/claude/.claude/skills/orchestrate/SKILL.md +0 -0
  188. /package/{src → dist}/claude/.claude/skills/sdlc-plan/references/bug.md +0 -0
  189. /package/{src → dist}/claude/.claude/skills/sdlc-plan/references/chore.md +0 -0
  190. /package/{src → dist}/claude/.claude/skills/sdlc-plan/references/feature.md +0 -0
  191. /package/{src → dist}/prompts/agentic-system.md +0 -0
  192. /package/{src → dist}/templates/analysis/bug.md.j2 +0 -0
  193. /package/{src → dist}/templates/analysis/debt.md.j2 +0 -0
  194. /package/{src → dist}/templates/analysis/doc.md.j2 +0 -0
  195. /package/{src → dist}/templates/analysis/security.md.j2 +0 -0
  196. /package/{src → dist}/templates/analysis/style.md.j2 +0 -0
  197. /package/{src → dist}/templates/analysis-summary.md.j2 +0 -0
  198. /package/{src → dist}/templates/checkpoint.md.j2 +0 -0
  199. /package/{src → dist}/templates/implementation-report.md.j2 +0 -0
  200. /package/{src → dist}/templates/memory.md.j2 +0 -0
  201. /package/{src → dist}/templates/plan-bug.md.j2 +0 -0
  202. /package/{src → dist}/templates/plan-chore.md.j2 +0 -0
  203. /package/{src → dist}/templates/plan-feature.md.j2 +0 -0
  204. /package/{src → dist}/templates/progress.json.j2 +0 -0
  205. /package/{src → dist}/templates/ralph-report.md.j2 +0 -0
  206. /package/{src → dist}/workflows/analyze-codebase-merge.yaml +0 -0
  207. /package/{src → dist}/workflows/analyze-codebase.yaml +0 -0
  208. /package/{src → dist}/workflows/analyze-single.yaml +0 -0
  209. /package/{src → dist}/workflows/demo.yaml +0 -0
  210. /package/{src → dist}/workflows/one-shot.yaml +0 -0
  211. /package/{src → dist}/workflows/plan-build-review.yaml +0 -0
  212. /package/{src → dist}/workflows/ralph-loop.yaml +0 -0
@@ -0,0 +1,670 @@
1
+ /** Console output utilities for workflow execution. */
2
+ // --- Enums and constants ---
3
+ export const OutputLevel = {
4
+ BASE: "base",
5
+ ALL: "all",
6
+ };
7
+ export const Color = {
8
+ RESET: "\x1b[0m",
9
+ BOLD: "\x1b[1m",
10
+ DIM: "\x1b[2m",
11
+ RED: "\x1b[31m",
12
+ GREEN: "\x1b[32m",
13
+ YELLOW: "\x1b[33m",
14
+ BLUE: "\x1b[34m",
15
+ MAGENTA: "\x1b[35m",
16
+ CYAN: "\x1b[36m",
17
+ WHITE: "\x1b[37m",
18
+ BRIGHT_RED: "\x1b[91m",
19
+ BRIGHT_GREEN: "\x1b[92m",
20
+ BRIGHT_YELLOW: "\x1b[93m",
21
+ BRIGHT_BLUE: "\x1b[94m",
22
+ BRIGHT_CYAN: "\x1b[96m",
23
+ };
24
+ /** Maximum characters to accumulate in BASE mode before truncating (1MB). */
25
+ const MAX_ACCUMULATED_TEXT = 1024 * 1024;
26
+ // --- Utility functions ---
27
+ export function supportsColor() {
28
+ if (typeof process.stdout.isTTY !== "boolean") {
29
+ return false;
30
+ }
31
+ return process.stdout.isTTY;
32
+ }
33
+ export function colorize(text, ...colors) {
34
+ if (!supportsColor()) {
35
+ return text;
36
+ }
37
+ const colorCodes = colors.join("");
38
+ return `${colorCodes}${text}${Color.RESET}`;
39
+ }
40
+ // --- ParallelOutputHandler ---
41
+ export class ParallelOutputHandler {
42
+ stream;
43
+ level;
44
+ printFn;
45
+ branches = [];
46
+ branchIndex = new Map();
47
+ branchDone = new Map();
48
+ deferredMessages = [];
49
+ linesPerBranch = 4;
50
+ active = false;
51
+ // Per-branch accumulation (single-threaded, so we use maps instead of thread-local)
52
+ currentBranch = null;
53
+ accumulatedText = "";
54
+ accumulatedRole = "";
55
+ accumulatedModel = null;
56
+ baseAccumulatedText = "";
57
+ // Message queue for ALL mode parallel
58
+ messageQueue = [];
59
+ constructor(stream = process.stdout, level = OutputLevel.BASE, printFn) {
60
+ this.stream = stream;
61
+ this.level = level;
62
+ this.printFn = printFn ?? null;
63
+ }
64
+ print(message) {
65
+ if (this.printFn) {
66
+ this.printFn(message);
67
+ }
68
+ else {
69
+ this.stream.write(`${message}\n`);
70
+ }
71
+ }
72
+ get isActive() {
73
+ return this.active;
74
+ }
75
+ get hasBranches() {
76
+ return this.branches.length > 0;
77
+ }
78
+ registerBranches(branches) {
79
+ this.branches = [...branches];
80
+ this.branchIndex = new Map(branches.map((name, idx) => [name, idx]));
81
+ this.branchDone = new Map(branches.map((name) => [name, false]));
82
+ this.deferredMessages = [];
83
+ if (this.level === OutputLevel.BASE && supportsColor()) {
84
+ for (const branch of branches) {
85
+ const prefix = colorize(`[${branch}]`, Color.CYAN, Color.BOLD);
86
+ this.print(prefix);
87
+ const waiting = colorize("waiting...", Color.DIM);
88
+ this.print(` ${waiting}`);
89
+ this.print(""); // Message line 2
90
+ this.print(""); // Blank line
91
+ }
92
+ }
93
+ }
94
+ updateBranchLine(branch, text, maxWidth = 100) {
95
+ if (!supportsColor() || !this.branchIndex.has(branch))
96
+ return;
97
+ if (this.branchDone.get(branch))
98
+ return;
99
+ const idx = this.branchIndex.get(branch) ?? 0;
100
+ const totalBranches = this.branches.length;
101
+ const totalLines = totalBranches * this.linesPerBranch;
102
+ const branchStartLine = idx * this.linesPerBranch;
103
+ const messageLine1 = branchStartLine + 1;
104
+ const messageLine2 = branchStartLine + 2;
105
+ const linesUpToMsg1 = totalLines - messageLine1;
106
+ const linesUpToMsg2 = totalLines - messageLine2;
107
+ const trimmed = text.trim();
108
+ let line1;
109
+ let line2 = "";
110
+ if (trimmed.length <= maxWidth) {
111
+ line1 = trimmed;
112
+ }
113
+ else {
114
+ let breakPoint = trimmed.lastIndexOf(" ", maxWidth);
115
+ if (breakPoint === -1)
116
+ breakPoint = maxWidth;
117
+ line1 = trimmed.slice(0, breakPoint).trim();
118
+ line2 = trimmed.slice(breakPoint).trim();
119
+ if (line2.length > maxWidth) {
120
+ line2 = `${line2.slice(0, maxWidth - 3)}...`;
121
+ }
122
+ }
123
+ const prefix = colorize("...", Color.DIM);
124
+ const w = this.stream;
125
+ w.write("\x1b[s"); // Save cursor
126
+ w.write(`\x1b[${linesUpToMsg1}A`); // Move up
127
+ w.write("\x1b[K"); // Clear line
128
+ w.write(` ${prefix} ${line1}`);
129
+ w.write(`\x1b[${linesUpToMsg1 - linesUpToMsg2}B`); // Move down to line 2
130
+ w.write("\r\x1b[K"); // Clear line
131
+ if (line2) {
132
+ w.write(` ${prefix} ${line2}`);
133
+ }
134
+ w.write("\x1b[u"); // Restore cursor
135
+ }
136
+ markBranchDone(branch, success = true) {
137
+ if (!supportsColor() || !this.branchIndex.has(branch))
138
+ return;
139
+ this.branchDone.set(branch, true);
140
+ const idx = this.branchIndex.get(branch) ?? 0;
141
+ const totalBranches = this.branches.length;
142
+ const totalLines = totalBranches * this.linesPerBranch;
143
+ const branchStartLine = idx * this.linesPerBranch;
144
+ const linesUpToHeader = totalLines - branchStartLine;
145
+ const messageLine1 = branchStartLine + 1;
146
+ const messageLine2 = branchStartLine + 2;
147
+ const linesUpToMsg1 = totalLines - messageLine1;
148
+ const linesUpToMsg2 = totalLines - messageLine2;
149
+ const branchPrefix = colorize(`[${branch}]`, Color.CYAN, Color.BOLD);
150
+ const status = success
151
+ ? colorize("[Done]", Color.BRIGHT_GREEN, Color.BOLD)
152
+ : colorize("[Failed]", Color.BRIGHT_RED, Color.BOLD);
153
+ const w = this.stream;
154
+ w.write("\x1b[s");
155
+ w.write(`\x1b[${linesUpToHeader}A`);
156
+ w.write("\x1b[K");
157
+ w.write(`${branchPrefix} ${status}`);
158
+ w.write(`\x1b[${linesUpToHeader - linesUpToMsg1}B`);
159
+ w.write("\r\x1b[K");
160
+ w.write(`\x1b[${linesUpToMsg1 - linesUpToMsg2}B`);
161
+ w.write("\r\x1b[K");
162
+ w.write("\x1b[u");
163
+ }
164
+ clearDisplay() {
165
+ if (this.branches.length === 0 || !supportsColor()) {
166
+ this.branches = [];
167
+ this.branchIndex = new Map();
168
+ this.branchDone = new Map();
169
+ return;
170
+ }
171
+ const totalLines = this.branches.length * this.linesPerBranch;
172
+ for (let i = 0; i < totalLines; i++) {
173
+ this.stream.write("\x1b[A\x1b[2K");
174
+ }
175
+ this.branches = [];
176
+ this.branchIndex = new Map();
177
+ this.branchDone = new Map();
178
+ }
179
+ enter() {
180
+ this.active = true;
181
+ if (this.level === OutputLevel.ALL) {
182
+ this.messageQueue = [];
183
+ }
184
+ }
185
+ exit() {
186
+ if (this.level === OutputLevel.BASE) {
187
+ if (this.branches.length > 0) {
188
+ this.clearDisplay();
189
+ }
190
+ for (const msg of this.deferredMessages) {
191
+ this.print(msg);
192
+ }
193
+ this.deferredMessages = [];
194
+ }
195
+ // Flush remaining messages in ALL mode
196
+ if (this.level === OutputLevel.ALL) {
197
+ for (const [branch, role, text, model] of this.messageQueue) {
198
+ this.printBranchMessage(branch, role, text, model);
199
+ }
200
+ this.messageQueue = [];
201
+ }
202
+ this.active = false;
203
+ }
204
+ deferMessage(message) {
205
+ this.deferredMessages.push(message);
206
+ }
207
+ setBranch(branchName) {
208
+ this.currentBranch = branchName;
209
+ this.accumulatedText = "";
210
+ this.accumulatedRole = "";
211
+ this.accumulatedModel = null;
212
+ this.baseAccumulatedText = "";
213
+ }
214
+ getCurrentBranch() {
215
+ return this.currentBranch;
216
+ }
217
+ enqueueCurrentMessage() {
218
+ if (this.level === OutputLevel.ALL &&
219
+ this.active &&
220
+ this.accumulatedText.trim() &&
221
+ this.accumulatedRole &&
222
+ this.currentBranch) {
223
+ this.messageQueue.push([
224
+ this.currentBranch,
225
+ this.accumulatedRole,
226
+ this.accumulatedText.trim(),
227
+ this.accumulatedModel,
228
+ ]);
229
+ }
230
+ this.accumulatedText = "";
231
+ this.accumulatedRole = "";
232
+ this.accumulatedModel = null;
233
+ }
234
+ printBranchMessage(branch, role, text, model, formatModelName) {
235
+ const formattedModel = formatModelName && model ? formatModelName(model) : null;
236
+ const branchPrefix = colorize(`[${branch}] `, Color.CYAN, Color.BOLD);
237
+ if (role === "user") {
238
+ const prefix = colorize(">", Color.BRIGHT_CYAN, Color.BOLD);
239
+ const label = colorize(" [user]", Color.DIM);
240
+ this.print(`\n${branchPrefix}${prefix}${label}`);
241
+ for (const line of text.split("\n")) {
242
+ const coloredLine = colorize(line, Color.GREEN);
243
+ this.print(` ${coloredLine}`);
244
+ }
245
+ }
246
+ else {
247
+ const bullet = colorize("*", Color.BRIGHT_GREEN, Color.BOLD);
248
+ let modelLabel = "";
249
+ if (formattedModel) {
250
+ modelLabel = ` ${colorize(`[${formattedModel}]`, Color.DIM)}`;
251
+ }
252
+ const lines = text.split("\n");
253
+ this.print(`\n${branchPrefix}${bullet}${modelLabel} ${lines[0]}`);
254
+ for (const line of lines.slice(1)) {
255
+ this.print(` ${line}`);
256
+ }
257
+ }
258
+ }
259
+ accumulateText(text, role, model) {
260
+ if (this.accumulatedRole && this.accumulatedRole !== role && this.accumulatedText.trim()) {
261
+ this.enqueueCurrentMessage();
262
+ }
263
+ this.accumulatedText += text;
264
+ this.accumulatedRole = role;
265
+ if (model) {
266
+ this.accumulatedModel = model;
267
+ }
268
+ }
269
+ accumulateBaseText(text) {
270
+ this.baseAccumulatedText += text;
271
+ const accumulated = this.baseAccumulatedText.trim();
272
+ if (accumulated) {
273
+ const lines = accumulated.split("\n");
274
+ return lines[lines.length - 1];
275
+ }
276
+ return "";
277
+ }
278
+ }
279
+ // --- ConsoleOutput ---
280
+ export class ConsoleOutput {
281
+ level;
282
+ stream;
283
+ _baseAccumulatedText = "";
284
+ baseLastDisplayLines = 0;
285
+ _parallelHandler;
286
+ formatModelName = null;
287
+ constructor(level = OutputLevel.BASE, stream = process.stdout) {
288
+ this.level = level;
289
+ this.stream = stream;
290
+ this._parallelHandler = new ParallelOutputHandler(stream, level, (msg) => this.printLine(msg));
291
+ }
292
+ /** Set model name formatter to avoid circular imports with runner. */
293
+ setModelFormatter(fn) {
294
+ this.formatModelName = fn;
295
+ }
296
+ printLine(message, end = "\n") {
297
+ this.stream.write(`${message}${end}`);
298
+ }
299
+ printInplace(message) {
300
+ const lines = message.trim().split("\n");
301
+ const numLines = lines.length;
302
+ if (supportsColor()) {
303
+ if (this.baseLastDisplayLines > 0) {
304
+ this.stream.write(`\x1b[${this.baseLastDisplayLines}A`);
305
+ this.stream.write("\x1b[J");
306
+ }
307
+ const content = `${lines.join("\n")}\n`;
308
+ this.stream.write(content);
309
+ }
310
+ else {
311
+ const lastLine = lines[lines.length - 1] ?? "";
312
+ const truncated = lastLine.length > 80 ? `${lastLine.slice(0, 80)}...` : lastLine;
313
+ this.printLine(` ... ${truncated}`);
314
+ }
315
+ this.baseLastDisplayLines = numLines;
316
+ }
317
+ clearInplace() {
318
+ if (this.baseLastDisplayLines > 0 && supportsColor()) {
319
+ this.stream.write(`\x1b[${this.baseLastDisplayLines}A\x1b[J`);
320
+ }
321
+ this.baseLastDisplayLines = 0;
322
+ }
323
+ // --- Parallel mode delegation ---
324
+ registerParallelBranches(branches) {
325
+ this._parallelHandler.registerBranches(branches);
326
+ }
327
+ enterParallelMode() {
328
+ this._parallelHandler.enter();
329
+ }
330
+ exitParallelMode() {
331
+ this._parallelHandler.exit();
332
+ }
333
+ setParallelBranch(branchName) {
334
+ this._parallelHandler.setBranch(branchName);
335
+ }
336
+ markParallelBranchDone(branch, success = true) {
337
+ this._parallelHandler.markBranchDone(branch, success);
338
+ }
339
+ isParallelMode() {
340
+ return this._parallelHandler.isActive;
341
+ }
342
+ shouldDeferMessage() {
343
+ return (this._parallelHandler.isActive &&
344
+ this.level === OutputLevel.BASE &&
345
+ this._parallelHandler.hasBranches);
346
+ }
347
+ deferMessage(message) {
348
+ this._parallelHandler.deferMessage(message);
349
+ }
350
+ // --- Workflow-level messages ---
351
+ workflowStart(workflowName, workflowId) {
352
+ const header = colorize(`Workflow: ${workflowName}`, Color.BOLD, Color.BRIGHT_CYAN);
353
+ const idStr = colorize(`[${workflowId}]`, Color.DIM);
354
+ this.printLine(`\n${header} ${idStr}`);
355
+ this.printLine(colorize("-".repeat(50), Color.DIM));
356
+ }
357
+ workflowComplete(workflowName, status) {
358
+ this.printLine(colorize("-".repeat(50), Color.DIM));
359
+ const statusStr = status === "completed"
360
+ ? colorize("COMPLETED", Color.BOLD, Color.BRIGHT_GREEN)
361
+ : colorize(status.toUpperCase(), Color.BOLD, Color.BRIGHT_RED);
362
+ this.printLine(`Workflow ${workflowName}: ${statusStr}\n`);
363
+ }
364
+ // --- Step-level messages ---
365
+ stepStart(stepName, stepType, model) {
366
+ let modelStr = "";
367
+ if (this.level === OutputLevel.BASE && model) {
368
+ const formattedModel = this.formatModelName ? this.formatModelName(model) : model;
369
+ if (formattedModel) {
370
+ modelStr = `${colorize(`[${formattedModel}] `, Color.DIM)}`;
371
+ }
372
+ }
373
+ const stepStr = colorize(`Step: ${stepName}`, Color.BOLD);
374
+ const typeStr = stepType ? colorize(`[${stepType}]`, Color.DIM) : "";
375
+ const formatted = `\n${modelStr}${stepStr} ${typeStr}`;
376
+ if (this.shouldDeferMessage()) {
377
+ this.deferMessage(formatted);
378
+ }
379
+ else {
380
+ this.printLine(formatted);
381
+ }
382
+ }
383
+ stepComplete(stepName, summary) {
384
+ if (this.level === OutputLevel.BASE && !this.isParallelMode()) {
385
+ this.baseLastDisplayLines = 0;
386
+ this._baseAccumulatedText = "";
387
+ }
388
+ const check = colorize("[OK]", Color.BRIGHT_GREEN);
389
+ const name = colorize(stepName, Color.GREEN);
390
+ const mainLine = `${check} ${name} completed`;
391
+ const lines = [mainLine];
392
+ if (summary && this.level === OutputLevel.BASE) {
393
+ const summaryLines = summary.trim().split("\n");
394
+ for (const line of summaryLines.slice(0, 5)) {
395
+ const truncated = line.length > 200 ? `${line.slice(0, 200)}...` : line;
396
+ lines.push(colorize(` ${truncated}`, Color.DIM));
397
+ }
398
+ if (summaryLines.length > 5) {
399
+ lines.push(colorize(` ... (${summaryLines.length - 5} more lines)`, Color.DIM));
400
+ }
401
+ }
402
+ if (this.shouldDeferMessage()) {
403
+ const branch = this._parallelHandler.getCurrentBranch();
404
+ if (branch) {
405
+ this.markParallelBranchDone(branch);
406
+ }
407
+ for (const line of lines) {
408
+ this.deferMessage(line);
409
+ }
410
+ }
411
+ else {
412
+ for (const line of lines) {
413
+ this.printLine(line);
414
+ }
415
+ }
416
+ }
417
+ stepFailed(stepName, error) {
418
+ if (this.level === OutputLevel.BASE && !this.isParallelMode()) {
419
+ this.baseLastDisplayLines = 0;
420
+ this._baseAccumulatedText = "";
421
+ }
422
+ const cross = colorize("[FAIL]", Color.BRIGHT_RED);
423
+ const name = colorize(stepName, Color.RED);
424
+ const mainLine = `${cross} ${name} failed`;
425
+ const lines = [mainLine];
426
+ if (error) {
427
+ const errorLines = error.trim().split("\n");
428
+ for (const line of errorLines.slice(0, 10)) {
429
+ const truncated = line.length > 200 ? `${line.slice(0, 200)}...` : line;
430
+ lines.push(colorize(` ${truncated}`, Color.RED));
431
+ }
432
+ if (errorLines.length > 10) {
433
+ lines.push(colorize(` ... (${errorLines.length - 10} more lines)`, Color.DIM));
434
+ }
435
+ }
436
+ if (this.shouldDeferMessage()) {
437
+ const branch = this._parallelHandler.getCurrentBranch();
438
+ if (branch) {
439
+ this.markParallelBranchDone(branch, false);
440
+ }
441
+ for (const line of lines) {
442
+ this.deferMessage(line);
443
+ }
444
+ }
445
+ else {
446
+ for (const line of lines) {
447
+ this.printLine(line);
448
+ }
449
+ }
450
+ }
451
+ stepRetry(stepName, attempt, maxAttempts, error) {
452
+ const retry = colorize(`[RETRY ${attempt}/${maxAttempts}]`, Color.YELLOW);
453
+ const name = colorize(stepName, Color.YELLOW);
454
+ const mainLine = `${retry} ${name}`;
455
+ const lines = [mainLine];
456
+ if (error) {
457
+ const firstLine = error.trim().split("\n")[0].slice(0, 100);
458
+ lines.push(colorize(` Reason: ${firstLine}`, Color.DIM));
459
+ }
460
+ if (this.shouldDeferMessage()) {
461
+ for (const line of lines) {
462
+ this.deferMessage(line);
463
+ }
464
+ }
465
+ else {
466
+ for (const line of lines) {
467
+ this.printLine(line);
468
+ }
469
+ }
470
+ }
471
+ // --- Ralph loop messages ---
472
+ ralphIterationStart(stepName, iteration, maxIterations) {
473
+ if (this.level === OutputLevel.BASE && !this.isParallelMode()) {
474
+ this.baseLastDisplayLines = 0;
475
+ this._baseAccumulatedText = "";
476
+ }
477
+ const progress = colorize(`[${iteration}/${maxIterations}]`, Color.CYAN);
478
+ const name = colorize(stepName, Color.CYAN);
479
+ this.printLine(`${progress} ${name} iteration`);
480
+ }
481
+ ralphIteration(_stepName, _iteration, _maxIterations, summary) {
482
+ if (this.level === OutputLevel.BASE && !this.isParallelMode()) {
483
+ return;
484
+ }
485
+ if (summary && this.level === OutputLevel.ALL) {
486
+ const summaryLines = summary.trim().split("\n");
487
+ for (const line of summaryLines.slice(0, 3)) {
488
+ const truncated = line.length > 150 ? `${line.slice(0, 150)}...` : line;
489
+ this.printLine(colorize(` ${truncated}`, Color.DIM));
490
+ }
491
+ }
492
+ }
493
+ ralphComplete(stepName, iteration, maxIterations) {
494
+ if (this.level === OutputLevel.BASE && !this.isParallelMode()) {
495
+ this.baseLastDisplayLines = 0;
496
+ this._baseAccumulatedText = "";
497
+ }
498
+ const check = colorize("[OK]", Color.BRIGHT_GREEN);
499
+ const name = colorize(stepName, Color.GREEN);
500
+ this.printLine(`${check} ${name} completed at iteration ${iteration}/${maxIterations}`);
501
+ }
502
+ ralphMaxIterations(stepName, maxIterations) {
503
+ if (this.level === OutputLevel.BASE && !this.isParallelMode()) {
504
+ this.baseLastDisplayLines = 0;
505
+ this._baseAccumulatedText = "";
506
+ }
507
+ const warn = colorize("[WARN]", Color.YELLOW);
508
+ const name = colorize(stepName, Color.YELLOW);
509
+ this.printLine(`${warn} ${name} reached max iterations (${maxIterations})`);
510
+ }
511
+ // --- Generic messages ---
512
+ info(message) {
513
+ const infoPrefix = colorize("[INFO]", Color.BLUE);
514
+ const formatted = `${infoPrefix} ${message}`;
515
+ if (this.shouldDeferMessage()) {
516
+ this.deferMessage(formatted);
517
+ }
518
+ else {
519
+ this.printLine(formatted);
520
+ }
521
+ }
522
+ warning(message) {
523
+ const warn = colorize("[WARN]", Color.YELLOW);
524
+ const formatted = `${warn} ${message}`;
525
+ if (this.shouldDeferMessage()) {
526
+ this.deferMessage(formatted);
527
+ }
528
+ else {
529
+ this.printLine(formatted);
530
+ }
531
+ }
532
+ error(message) {
533
+ const err = colorize("[ERROR]", Color.BRIGHT_RED);
534
+ const formatted = `${err} ${message}`;
535
+ if (this.shouldDeferMessage()) {
536
+ this.deferMessage(formatted);
537
+ }
538
+ else {
539
+ this.printLine(formatted);
540
+ }
541
+ }
542
+ // --- Streaming ---
543
+ streamText(text, role = "assistant", model) {
544
+ const formattedModel = this.formatModelName && model ? this.formatModelName(model) : null;
545
+ if (this.level === OutputLevel.ALL) {
546
+ if (!text || !text.trim())
547
+ return;
548
+ if (this.isParallelMode()) {
549
+ this._parallelHandler.accumulateText(text, role, model);
550
+ return;
551
+ }
552
+ if (role === "user") {
553
+ const prefix = colorize(">", Color.BRIGHT_CYAN, Color.BOLD);
554
+ const label = colorize(" [user]", Color.DIM);
555
+ this.printLine("");
556
+ this.printLine(`${prefix}${label}`);
557
+ for (const line of text.split("\n")) {
558
+ const coloredLine = colorize(line, Color.GREEN);
559
+ this.printLine(` ${coloredLine}`);
560
+ }
561
+ }
562
+ else {
563
+ const bullet = colorize("*", Color.BRIGHT_GREEN, Color.BOLD);
564
+ let modelLabel = "";
565
+ if (formattedModel) {
566
+ modelLabel = ` ${colorize(`[${formattedModel}]`, Color.DIM)}`;
567
+ }
568
+ const lines = text.split("\n");
569
+ this.printLine("");
570
+ this.printLine(`${bullet}${modelLabel} ${lines[0]}`);
571
+ for (const line of lines.slice(1)) {
572
+ this.printLine(` ${line}`);
573
+ }
574
+ }
575
+ }
576
+ else if (this.level === OutputLevel.BASE) {
577
+ if (role === "user")
578
+ return;
579
+ if (this.isParallelMode()) {
580
+ const branch = this._parallelHandler.getCurrentBranch();
581
+ if (branch && this._parallelHandler.hasBranches) {
582
+ const lastLine = this._parallelHandler.accumulateBaseText(text);
583
+ if (lastLine) {
584
+ this._parallelHandler.updateBranchLine(branch, lastLine);
585
+ }
586
+ }
587
+ return;
588
+ }
589
+ this._baseAccumulatedText += text;
590
+ if (this._baseAccumulatedText.length > MAX_ACCUMULATED_TEXT) {
591
+ this._baseAccumulatedText = this._baseAccumulatedText.slice(-MAX_ACCUMULATED_TEXT);
592
+ }
593
+ if (this._baseAccumulatedText.trim()) {
594
+ const prefix = colorize("...", Color.DIM);
595
+ const lines = this._baseAccumulatedText.trim().split("\n");
596
+ const formattedLines = [`${prefix} ${lines[0]}`];
597
+ for (const line of lines.slice(1)) {
598
+ formattedLines.push(` ${line}`);
599
+ }
600
+ const displayText = formattedLines.join("\n");
601
+ this.printInplace(displayText);
602
+ }
603
+ }
604
+ }
605
+ streamComplete() {
606
+ if (this.level === OutputLevel.ALL && this.isParallelMode()) {
607
+ this._parallelHandler.enqueueCurrentMessage();
608
+ }
609
+ this._baseAccumulatedText = "";
610
+ }
611
+ }
612
+ // --- Standalone utility functions ---
613
+ export function extractJson(output) {
614
+ if (!output || !output.trim())
615
+ return null;
616
+ const pattern = /```json\s*([\s\S]*?)```/g;
617
+ const matches = [...output.matchAll(pattern)];
618
+ if (matches.length === 0)
619
+ return null;
620
+ const jsonStr = matches[matches.length - 1][1].trim();
621
+ try {
622
+ return JSON.parse(jsonStr);
623
+ }
624
+ catch (e) {
625
+ const msg = e instanceof Error ? e.message : String(e);
626
+ process.stderr.write(`[WARN] Failed to parse JSON from output: ${msg}\n`);
627
+ return null;
628
+ }
629
+ }
630
+ export function extractSummary(output, maxLines = 5, maxChars = 500) {
631
+ if (!output || !output.trim())
632
+ return "";
633
+ const trimmed = output.trim();
634
+ const summaryMarkers = [
635
+ "## Summary",
636
+ "### Summary",
637
+ "Summary:",
638
+ "Result:",
639
+ "Completed:",
640
+ "Done:",
641
+ ];
642
+ for (const marker of summaryMarkers) {
643
+ if (trimmed.includes(marker)) {
644
+ const idx = trimmed.indexOf(marker);
645
+ const summarySection = trimmed.slice(idx);
646
+ const lines = summarySection.split("\n");
647
+ const resultLines = [];
648
+ for (let i = 1; i < lines.length; i++) {
649
+ if (i > maxLines)
650
+ break;
651
+ if (lines[i].startsWith("#") && i > 1)
652
+ break;
653
+ resultLines.push(lines[i]);
654
+ }
655
+ if (resultLines.length > 0) {
656
+ return resultLines.join("\n").trim().slice(0, maxChars);
657
+ }
658
+ }
659
+ }
660
+ const nonEmptyLines = trimmed.split("\n").filter((line) => line.trim());
661
+ if (nonEmptyLines.length === 0)
662
+ return "";
663
+ const lastLines = nonEmptyLines.slice(-maxLines);
664
+ let summary = lastLines.join("\n");
665
+ if (summary.length > maxChars) {
666
+ summary = `${summary.slice(0, maxChars)}...`;
667
+ }
668
+ return summary;
669
+ }
670
+ //# sourceMappingURL=console.js.map