@herbcaudill/ralph 0.8.3 → 1.0.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.
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +26 -5
- package/dist/cli.js.map +1 -1
- package/dist/components/App.d.ts +6 -1
- package/dist/components/App.d.ts.map +1 -1
- package/dist/components/App.js +7 -3
- package/dist/components/App.js.map +1 -1
- package/dist/components/EnhancedTextInput.d.ts +8 -8
- package/dist/components/EnhancedTextInput.d.ts.map +1 -1
- package/dist/components/EnhancedTextInput.js +2 -36
- package/dist/components/EnhancedTextInput.js.map +1 -1
- package/dist/components/EnhancedTextInput.test.js +2 -10
- package/dist/components/EnhancedTextInput.test.js.map +1 -1
- package/dist/components/EventDisplay.d.ts +1 -1
- package/dist/components/EventDisplay.d.ts.map +1 -1
- package/dist/components/EventDisplay.js +3 -94
- package/dist/components/EventDisplay.js.map +1 -1
- package/dist/components/EventDisplay.replay.test.js +34 -68
- package/dist/components/EventDisplay.replay.test.js.map +1 -1
- package/dist/components/EventDisplay.test.js +30 -0
- package/dist/components/EventDisplay.test.js.map +1 -1
- package/dist/components/FullScreenLayout.d.ts +5 -4
- package/dist/components/FullScreenLayout.d.ts.map +1 -1
- package/dist/components/FullScreenLayout.js +2 -12
- package/dist/components/FullScreenLayout.js.map +1 -1
- package/dist/components/Header.d.ts +2 -1
- package/dist/components/Header.d.ts.map +1 -1
- package/dist/components/Header.js +8 -1
- package/dist/components/Header.js.map +1 -1
- package/dist/components/InitRalph.d.ts +6 -1
- package/dist/components/InitRalph.d.ts.map +1 -1
- package/dist/components/InitRalph.js +71 -89
- package/dist/components/InitRalph.js.map +1 -1
- package/dist/components/IterationRunner.d.ts +6 -13
- package/dist/components/IterationRunner.d.ts.map +1 -1
- package/dist/components/IterationRunner.js +84 -168
- package/dist/components/IterationRunner.js.map +1 -1
- package/dist/components/IterationRunner.test.d.ts +44 -0
- package/dist/components/IterationRunner.test.d.ts.map +1 -1
- package/dist/components/IterationRunner.test.js +66 -126
- package/dist/components/IterationRunner.test.js.map +1 -1
- package/dist/components/IterationRunner.types.d.ts +30 -0
- package/dist/components/IterationRunner.types.d.ts.map +1 -0
- package/dist/components/IterationRunner.types.js +2 -0
- package/dist/components/IterationRunner.types.js.map +1 -0
- package/dist/components/JsonOutput.d.ts +5 -6
- package/dist/components/JsonOutput.d.ts.map +1 -1
- package/dist/components/JsonOutput.js +57 -34
- package/dist/components/JsonOutput.js.map +1 -1
- package/dist/components/JsonOutput.test.d.ts +2 -0
- package/dist/components/JsonOutput.test.d.ts.map +1 -0
- package/dist/components/JsonOutput.test.js +39 -0
- package/dist/components/JsonOutput.test.js.map +1 -0
- package/dist/components/ReplayLog.d.ts +1 -1
- package/dist/components/ReplayLog.d.ts.map +1 -1
- package/dist/components/ReplayLog.js +9 -2
- package/dist/components/ReplayLog.js.map +1 -1
- package/dist/components/StreamingText.d.ts +4 -0
- package/dist/components/StreamingText.d.ts.map +1 -1
- package/dist/components/StreamingText.js +4 -3
- package/dist/components/StreamingText.js.map +1 -1
- package/dist/components/StreamingText.test.js +39 -0
- package/dist/components/StreamingText.test.js.map +1 -1
- package/dist/components/ToolUse.d.ts +8 -0
- package/dist/components/ToolUse.d.ts.map +1 -1
- package/dist/components/ToolUse.js +1 -0
- package/dist/components/ToolUse.js.map +1 -1
- package/dist/components/blocksToLines.d.ts +6 -0
- package/dist/components/blocksToLines.d.ts.map +1 -0
- package/dist/components/blocksToLines.js +15 -0
- package/dist/components/blocksToLines.js.map +1 -0
- package/dist/components/eventToBlocks.d.ts +7 -1
- package/dist/components/eventToBlocks.d.ts.map +1 -1
- package/dist/components/eventToBlocks.js +7 -1
- package/dist/components/eventToBlocks.js.map +1 -1
- package/dist/components/findNextWordBoundary.d.ts +10 -0
- package/dist/components/findNextWordBoundary.d.ts.map +1 -0
- package/dist/components/findNextWordBoundary.js +23 -0
- package/dist/components/findNextWordBoundary.js.map +1 -0
- package/dist/components/findPreviousWordBoundary.d.ts +10 -0
- package/dist/components/findPreviousWordBoundary.d.ts.map +1 -0
- package/dist/components/findPreviousWordBoundary.js +23 -0
- package/dist/components/findPreviousWordBoundary.js.map +1 -0
- package/dist/components/processEvents.d.ts +11 -0
- package/dist/components/processEvents.d.ts.map +1 -0
- package/dist/components/processEvents.js +87 -0
- package/dist/components/processEvents.js.map +1 -0
- package/dist/components/renderStaticItem.d.ts +7 -0
- package/dist/components/renderStaticItem.d.ts.map +1 -0
- package/dist/components/renderStaticItem.js +23 -0
- package/dist/components/renderStaticItem.js.map +1 -0
- package/dist/components/replay.d.ts +5 -0
- package/dist/components/replay.d.ts.map +1 -0
- package/dist/components/replay.js +49 -0
- package/dist/components/replay.js.map +1 -0
- package/dist/components/test-helpers/ControlledInput.d.ts +14 -0
- package/dist/components/test-helpers/ControlledInput.d.ts.map +1 -0
- package/dist/components/test-helpers/ControlledInput.js +15 -0
- package/dist/components/test-helpers/ControlledInput.js.map +1 -0
- package/dist/components/useContentHeight.d.ts +9 -0
- package/dist/components/useContentHeight.d.ts.map +1 -0
- package/dist/components/useContentHeight.js +16 -0
- package/dist/components/useContentHeight.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/MessageQueue.d.ts +18 -5
- package/dist/lib/MessageQueue.d.ts.map +1 -1
- package/dist/lib/MessageQueue.js +21 -14
- package/dist/lib/MessageQueue.js.map +1 -1
- package/dist/lib/StdinCommandHandler.d.ts +26 -20
- package/dist/lib/StdinCommandHandler.js +78 -85
- package/dist/lib/StdinCommandHandler.test.d.ts +2 -2
- package/dist/lib/StdinCommandHandler.test.js +92 -92
- package/dist/lib/WorktreeManager.d.ts +114 -0
- package/dist/lib/WorktreeManager.d.ts.map +1 -0
- package/dist/lib/WorktreeManager.js +350 -0
- package/dist/lib/WorktreeManager.js.map +1 -0
- package/dist/lib/WorktreeManager.test.d.ts +2 -0
- package/dist/lib/WorktreeManager.test.d.ts.map +1 -0
- package/dist/lib/WorktreeManager.test.js +261 -0
- package/dist/lib/WorktreeManager.test.js.map +1 -0
- package/dist/lib/addTodo.d.ts +5 -5
- package/dist/lib/addTodo.d.ts.map +1 -1
- package/dist/lib/addTodo.js +6 -20
- package/dist/lib/addTodo.js.map +1 -1
- package/dist/lib/beadsClient.d.ts +6 -12
- package/dist/lib/beadsClient.d.ts.map +1 -1
- package/dist/lib/beadsClient.js +3 -2
- package/dist/lib/beadsClient.js.map +1 -1
- package/dist/lib/captureBeadsSnapshot.d.ts +4 -0
- package/dist/lib/captureBeadsSnapshot.d.ts.map +1 -0
- package/dist/lib/captureBeadsSnapshot.js +24 -0
- package/dist/lib/captureBeadsSnapshot.js.map +1 -0
- package/dist/lib/captureStartupSnapshot.d.ts +10 -0
- package/dist/lib/captureStartupSnapshot.d.ts.map +1 -0
- package/dist/lib/captureStartupSnapshot.js +29 -0
- package/dist/lib/captureStartupSnapshot.js.map +1 -0
- package/dist/lib/captureTodoSnapshot.d.ts +4 -0
- package/dist/lib/captureTodoSnapshot.d.ts.map +1 -0
- package/dist/lib/captureTodoSnapshot.js +24 -0
- package/dist/lib/captureTodoSnapshot.js.map +1 -0
- package/dist/lib/copyTemplates.d.ts +22 -0
- package/dist/lib/copyTemplates.d.ts.map +1 -0
- package/dist/lib/copyTemplates.js +32 -0
- package/dist/lib/copyTemplates.js.map +1 -0
- package/dist/lib/createStdinCommandHandler.d.ts +28 -0
- package/dist/lib/createStdinCommandHandler.d.ts.map +1 -0
- package/dist/lib/createStdinCommandHandler.js +67 -0
- package/dist/lib/createStdinCommandHandler.js.map +1 -0
- package/dist/lib/createUserMessage.d.ts +6 -0
- package/dist/lib/createUserMessage.d.ts.map +1 -0
- package/dist/lib/createUserMessage.js +13 -0
- package/dist/lib/createUserMessage.js.map +1 -0
- package/dist/lib/debug.d.ts +17 -16
- package/dist/lib/debug.d.ts.map +1 -1
- package/dist/lib/debug.js +25 -15
- package/dist/lib/debug.js.map +1 -1
- package/dist/lib/findMaxLogNumber.d.ts +6 -0
- package/dist/lib/findMaxLogNumber.d.ts.map +1 -0
- package/dist/lib/findMaxLogNumber.js +26 -0
- package/dist/lib/findMaxLogNumber.js.map +1 -0
- package/dist/lib/findMaxLogNumber.test.d.ts +2 -0
- package/dist/lib/findMaxLogNumber.test.d.ts.map +1 -0
- package/dist/lib/findMaxLogNumber.test.js +39 -0
- package/dist/lib/findMaxLogNumber.test.js.map +1 -0
- package/dist/lib/formatContentBlock.d.ts +4 -8
- package/dist/lib/formatContentBlock.d.ts.map +1 -1
- package/dist/lib/formatContentBlock.js +7 -58
- package/dist/lib/formatContentBlock.js.map +1 -1
- package/dist/lib/formatIterationHeader.d.ts +5 -0
- package/dist/lib/formatIterationHeader.d.ts.map +1 -0
- package/dist/lib/formatIterationHeader.js +8 -0
- package/dist/lib/formatIterationHeader.js.map +1 -0
- package/dist/lib/formatText.d.ts +5 -0
- package/dist/lib/formatText.d.ts.map +1 -0
- package/dist/lib/formatText.js +33 -0
- package/dist/lib/formatText.js.map +1 -0
- package/dist/lib/formatToolUse.d.ts +7 -0
- package/dist/lib/formatToolUse.d.ts.map +1 -0
- package/dist/lib/formatToolUse.js +14 -0
- package/dist/lib/formatToolUse.js.map +1 -0
- package/dist/lib/formatUserMessage.d.ts +5 -0
- package/dist/lib/formatUserMessage.d.ts.map +1 -0
- package/dist/lib/formatUserMessage.js +8 -0
- package/dist/lib/formatUserMessage.js.map +1 -0
- package/dist/lib/getBaseCwd.d.ts +6 -0
- package/dist/lib/getBaseCwd.d.ts.map +1 -0
- package/dist/lib/getBaseCwd.js +6 -0
- package/dist/lib/getBaseCwd.js.map +1 -0
- package/dist/lib/getBeadsProgress.d.ts +8 -0
- package/dist/lib/getBeadsProgress.d.ts.map +1 -0
- package/dist/lib/getBeadsProgress.js +35 -0
- package/dist/lib/getBeadsProgress.js.map +1 -0
- package/dist/lib/getClaudeVersion.d.ts +4 -0
- package/dist/lib/getClaudeVersion.d.ts.map +1 -1
- package/dist/lib/getClaudeVersion.js +4 -0
- package/dist/lib/getClaudeVersion.js.map +1 -1
- package/dist/lib/getDefaultIterations.d.ts +6 -0
- package/dist/lib/getDefaultIterations.d.ts.map +1 -0
- package/dist/lib/getDefaultIterations.js +14 -0
- package/dist/lib/getDefaultIterations.js.map +1 -0
- package/dist/lib/getDefaultIterations.test.d.ts +2 -0
- package/dist/lib/getDefaultIterations.test.d.ts.map +1 -0
- package/dist/lib/getDefaultIterations.test.js +39 -0
- package/dist/lib/getDefaultIterations.test.js.map +1 -0
- package/dist/lib/getLatestLogFile.d.ts +6 -0
- package/dist/lib/getLatestLogFile.d.ts.map +1 -0
- package/dist/lib/getLatestLogFile.js +15 -0
- package/dist/lib/getLatestLogFile.js.map +1 -0
- package/dist/lib/getNextLogFile.d.ts +0 -5
- package/dist/lib/getNextLogFile.d.ts.map +1 -1
- package/dist/lib/getNextLogFile.js +2 -36
- package/dist/lib/getNextLogFile.js.map +1 -1
- package/dist/lib/getNextLogFile.test.js +2 -1
- package/dist/lib/getNextLogFile.test.js.map +1 -1
- package/dist/lib/getOpenIssueCount.d.ts +0 -5
- package/dist/lib/getOpenIssueCount.d.ts.map +1 -1
- package/dist/lib/getOpenIssueCount.js +0 -12
- package/dist/lib/getOpenIssueCount.js.map +1 -1
- package/dist/lib/getOpenIssueCount.test.js +1 -35
- package/dist/lib/getOpenIssueCount.test.js.map +1 -1
- package/dist/lib/getProgress.d.ts +6 -26
- package/dist/lib/getProgress.d.ts.map +1 -1
- package/dist/lib/getProgress.js +8 -109
- package/dist/lib/getProgress.js.map +1 -1
- package/dist/lib/getProgress.test.js +2 -1
- package/dist/lib/getProgress.test.js.map +1 -1
- package/dist/lib/getPromptContent.d.ts +8 -0
- package/dist/lib/getPromptContent.d.ts.map +1 -0
- package/dist/lib/getPromptContent.js +31 -0
- package/dist/lib/getPromptContent.js.map +1 -0
- package/dist/lib/getTerminalSize.d.ts +8 -0
- package/dist/lib/getTerminalSize.d.ts.map +1 -0
- package/dist/lib/getTerminalSize.js +10 -0
- package/dist/lib/getTerminalSize.js.map +1 -0
- package/dist/lib/getTodoProgress.d.ts +4 -0
- package/dist/lib/getTodoProgress.d.ts.map +1 -0
- package/dist/lib/getTodoProgress.js +22 -0
- package/dist/lib/getTodoProgress.js.map +1 -0
- package/dist/lib/insertTodo.d.ts +7 -0
- package/dist/lib/insertTodo.d.ts.map +1 -0
- package/dist/lib/insertTodo.js +22 -0
- package/dist/lib/insertTodo.js.map +1 -0
- package/dist/lib/outputEvent.d.ts +5 -0
- package/dist/lib/outputEvent.d.ts.map +1 -0
- package/dist/lib/outputEvent.js +7 -0
- package/dist/lib/outputEvent.js.map +1 -0
- package/dist/lib/parseStdinCommand.d.ts +25 -0
- package/dist/lib/parseStdinCommand.d.ts.map +1 -0
- package/dist/lib/parseStdinCommand.js +43 -0
- package/dist/lib/parseStdinCommand.js.map +1 -0
- package/dist/lib/parseStdinCommand.test.d.ts +2 -0
- package/dist/lib/parseStdinCommand.test.d.ts.map +1 -0
- package/dist/lib/parseStdinCommand.test.js +93 -0
- package/dist/lib/parseStdinCommand.test.js.map +1 -0
- package/dist/lib/parseTaskLifecycle.d.ts +18 -0
- package/dist/lib/parseTaskLifecycle.d.ts.map +1 -0
- package/dist/lib/parseTaskLifecycle.js +30 -0
- package/dist/lib/parseTaskLifecycle.js.map +1 -0
- package/dist/lib/parseTaskLifecycle.test.d.ts +2 -0
- package/dist/lib/parseTaskLifecycle.test.d.ts.map +1 -0
- package/dist/lib/parseTaskLifecycle.test.js +122 -0
- package/dist/lib/parseTaskLifecycle.test.js.map +1 -0
- package/dist/lib/parseWorktreeFromBranch.d.ts +13 -0
- package/dist/lib/parseWorktreeFromBranch.d.ts.map +1 -0
- package/dist/lib/parseWorktreeFromBranch.js +19 -0
- package/dist/lib/parseWorktreeFromBranch.js.map +1 -0
- package/dist/lib/processEvents.d.ts +12 -0
- package/dist/lib/processEvents.d.ts.map +1 -0
- package/dist/lib/processEvents.js +113 -0
- package/dist/lib/processEvents.js.map +1 -0
- package/dist/lib/rel.d.ts +7 -1
- package/dist/lib/rel.d.ts.map +1 -1
- package/dist/lib/rel.js +13 -4
- package/dist/lib/rel.js.map +1 -1
- package/dist/lib/rel.test.js +16 -1
- package/dist/lib/rel.test.js.map +1 -1
- package/dist/lib/sdkMessageToEvent.d.ts +6 -0
- package/dist/lib/sdkMessageToEvent.d.ts.map +1 -0
- package/dist/lib/sdkMessageToEvent.js +12 -0
- package/dist/lib/sdkMessageToEvent.js.map +1 -0
- package/dist/lib/shortenTempPaths.d.ts +7 -1
- package/dist/lib/shortenTempPaths.d.ts.map +1 -1
- package/dist/lib/shortenTempPaths.js +7 -2
- package/dist/lib/shortenTempPaths.js.map +1 -1
- package/dist/lib/types.d.ts +19 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +2 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/useTerminalSize.d.ts +3 -2
- package/dist/lib/useTerminalSize.d.ts.map +1 -1
- package/dist/lib/useTerminalSize.js +4 -6
- package/dist/lib/useTerminalSize.js.map +1 -1
- package/package.json +4 -3
- package/templates/core-prompt.md +77 -0
- package/templates/skills/manage-tasks/SKILL.md +113 -0
- package/templates/workflow.md +46 -0
- package/templates/prompt-beads.md +0 -44
- package/templates/prompt-todos.md +0 -17
- package/templates/todo.md +0 -9
|
@@ -1,58 +1,60 @@
|
|
|
1
1
|
import { Text, Box } from "ink";
|
|
2
|
-
import SelectInput from "ink-select-input";
|
|
3
2
|
import React, { useEffect, useState } from "react";
|
|
4
|
-
import { existsSync,
|
|
3
|
+
import { existsSync, readFileSync, appendFileSync, writeFileSync } from "fs";
|
|
5
4
|
import { join, dirname } from "path";
|
|
6
5
|
import { fileURLToPath } from "url";
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import { copyTemplates } from "../lib/copyTemplates.js";
|
|
7
|
+
/**
|
|
8
|
+
* Initializes Ralph by copying workflow templates and agent configurations to the project.
|
|
9
|
+
* Creates .ralph/workflow.md, .claude/skills/, and .claude/agents/ directories with default files.
|
|
10
|
+
* Also adds .ralph/events-*.jsonl to .gitignore.
|
|
11
|
+
*/
|
|
12
|
+
export function InitRalph() {
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
14
|
const [status, setStatus] = useState("checking");
|
|
10
|
-
const [taskMode, setTaskMode] = useState(null);
|
|
11
15
|
const [createdFiles, setCreatedFiles] = useState([]);
|
|
16
|
+
const [skippedFiles, setSkippedFiles] = useState([]);
|
|
12
17
|
const [errors, setErrors] = useState([]);
|
|
13
|
-
// Check if .ralph already exists
|
|
18
|
+
// Check if .ralph already exists and run initialization
|
|
14
19
|
useEffect(() => {
|
|
15
20
|
const ralphDir = join(process.cwd(), ".ralph");
|
|
16
|
-
|
|
21
|
+
const claudeDir = join(process.cwd(), ".claude");
|
|
22
|
+
// Check if already initialized
|
|
23
|
+
if (existsSync(join(ralphDir, "workflow.md"))) {
|
|
17
24
|
setStatus("exists");
|
|
18
|
-
}
|
|
19
|
-
else {
|
|
20
|
-
setStatus("selecting");
|
|
21
|
-
}
|
|
22
|
-
}, []);
|
|
23
|
-
// Run initialization when task mode is selected
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
if (!taskMode)
|
|
26
25
|
return;
|
|
26
|
+
}
|
|
27
|
+
// Run initialization
|
|
27
28
|
const initialize = async () => {
|
|
28
|
-
const ralphDir = join(process.cwd(), ".ralph");
|
|
29
29
|
const templatesDir = join(__dirname, "..", "..", "templates");
|
|
30
|
-
// Select templates based on task mode
|
|
31
|
-
const templates = taskMode === "beads" ?
|
|
32
|
-
[{ src: "prompt-beads.md", dest: "prompt.md" }]
|
|
33
|
-
: [
|
|
34
|
-
{ src: "prompt-todos.md", dest: "prompt.md" },
|
|
35
|
-
{ src: "todo.md", dest: "todo.md" },
|
|
36
|
-
];
|
|
37
30
|
setStatus("creating");
|
|
38
31
|
try {
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
32
|
+
const allCreated = [];
|
|
33
|
+
const allSkipped = [];
|
|
34
|
+
const allErrors = [];
|
|
35
|
+
// Copy workflow to .ralph/
|
|
36
|
+
const ralphResult = copyTemplates(templatesDir, ralphDir, [
|
|
37
|
+
{ src: "workflow.md", dest: "workflow.md" },
|
|
38
|
+
]);
|
|
39
|
+
allCreated.push(...ralphResult.created.map(f => `.ralph/${f}`));
|
|
40
|
+
allSkipped.push(...ralphResult.skipped.map(f => `.ralph/${f}`));
|
|
41
|
+
allErrors.push(...ralphResult.errors);
|
|
42
|
+
// Copy skills to .claude/skills/
|
|
43
|
+
const skillsResult = copyTemplates(templatesDir, claudeDir, [
|
|
44
|
+
{ src: "skills/manage-tasks/SKILL.md", dest: "skills/manage-tasks/SKILL.md" },
|
|
45
|
+
]);
|
|
46
|
+
allCreated.push(...skillsResult.created.map(f => `.claude/${f}`));
|
|
47
|
+
allSkipped.push(...skillsResult.skipped.map(f => `.claude/${f}`));
|
|
48
|
+
allErrors.push(...skillsResult.errors);
|
|
49
|
+
// Copy agents to .claude/agents/
|
|
50
|
+
const agentsResult = copyTemplates(templatesDir, claudeDir, [
|
|
51
|
+
{ src: "agents/make-tests.md", dest: "agents/make-tests.md" },
|
|
52
|
+
{ src: "agents/write-docs.md", dest: "agents/write-docs.md" },
|
|
53
|
+
{ src: "agents/run-tests.md", dest: "agents/run-tests.md" },
|
|
54
|
+
]);
|
|
55
|
+
allCreated.push(...agentsResult.created.map(f => `.claude/${f}`));
|
|
56
|
+
allSkipped.push(...agentsResult.skipped.map(f => `.claude/${f}`));
|
|
57
|
+
allErrors.push(...agentsResult.errors);
|
|
56
58
|
// Add events log pattern to .gitignore
|
|
57
59
|
const gitignorePath = join(process.cwd(), ".gitignore");
|
|
58
60
|
const eventsLogEntry = ".ralph/events-*.jsonl";
|
|
@@ -61,15 +63,16 @@ export const InitRalph = () => {
|
|
|
61
63
|
if (!content.includes(eventsLogEntry)) {
|
|
62
64
|
const newline = content.endsWith("\n") ? "" : "\n";
|
|
63
65
|
appendFileSync(gitignorePath, `${newline}${eventsLogEntry}\n`);
|
|
64
|
-
|
|
66
|
+
allCreated.push("(added .ralph/events-*.jsonl to .gitignore)");
|
|
65
67
|
}
|
|
66
68
|
}
|
|
67
69
|
else {
|
|
68
70
|
writeFileSync(gitignorePath, `${eventsLogEntry}\n`);
|
|
69
|
-
|
|
71
|
+
allCreated.push("(created .gitignore with .ralph/events-*.jsonl)");
|
|
70
72
|
}
|
|
71
|
-
setCreatedFiles(
|
|
72
|
-
|
|
73
|
+
setCreatedFiles(allCreated);
|
|
74
|
+
setSkippedFiles(allSkipped);
|
|
75
|
+
setErrors(allErrors);
|
|
73
76
|
setStatus("done");
|
|
74
77
|
// Exit after a brief delay so user can see success message
|
|
75
78
|
setTimeout(() => process.exit(0), 100);
|
|
@@ -81,26 +84,14 @@ export const InitRalph = () => {
|
|
|
81
84
|
}
|
|
82
85
|
};
|
|
83
86
|
initialize();
|
|
84
|
-
}, [
|
|
85
|
-
const handleModeSelect = (item) => {
|
|
86
|
-
setTaskMode(item.value);
|
|
87
|
-
};
|
|
87
|
+
}, []);
|
|
88
88
|
if (status === "checking") {
|
|
89
|
-
return React.createElement(Text, null, "Checking
|
|
89
|
+
return React.createElement(Text, null, "Checking directories...");
|
|
90
90
|
}
|
|
91
91
|
if (status === "exists") {
|
|
92
92
|
return (React.createElement(Box, { flexDirection: "column" },
|
|
93
|
-
React.createElement(Text, { color: "yellow" }, "
|
|
94
|
-
React.createElement(Text, { dimColor: true }, "To reinitialize, remove the
|
|
95
|
-
}
|
|
96
|
-
if (status === "selecting") {
|
|
97
|
-
return (React.createElement(Box, { flexDirection: "column" },
|
|
98
|
-
React.createElement(Text, { bold: true }, "How will you manage tasks?"),
|
|
99
|
-
React.createElement(Box, { marginTop: 1 },
|
|
100
|
-
React.createElement(SelectInput, { items: [
|
|
101
|
-
{ label: "todo.md - Simple markdown checklist", value: "todo" },
|
|
102
|
-
{ label: "beads - Git-backed issue tracker", value: "beads" },
|
|
103
|
-
], onSelect: handleModeSelect }))));
|
|
93
|
+
React.createElement(Text, { color: "yellow" }, "Ralph is already initialized"),
|
|
94
|
+
React.createElement(Text, { dimColor: true }, "To reinitialize, remove the workflow first: rm .ralph/workflow.md")));
|
|
104
95
|
}
|
|
105
96
|
if (status === "creating") {
|
|
106
97
|
return React.createElement(Text, { color: "cyan" }, "Initializing ralph...");
|
|
@@ -109,9 +100,12 @@ export const InitRalph = () => {
|
|
|
109
100
|
createdFiles.map(file => (React.createElement(Text, { key: file },
|
|
110
101
|
React.createElement(Text, { color: "green" }, "\u2713"),
|
|
111
102
|
" Created ",
|
|
112
|
-
React.createElement(Text, { dimColor: true },
|
|
113
|
-
|
|
114
|
-
|
|
103
|
+
React.createElement(Text, { dimColor: true }, file)))),
|
|
104
|
+
skippedFiles.map(file => (React.createElement(Text, { key: file },
|
|
105
|
+
React.createElement(Text, { color: "yellow" }, "\u25CB"),
|
|
106
|
+
" Skipped ",
|
|
107
|
+
React.createElement(Text, { dimColor: true }, file),
|
|
108
|
+
React.createElement(Text, { dimColor: true }, " (already exists)")))),
|
|
115
109
|
errors.map((error, i) => (React.createElement(Text, { key: i },
|
|
116
110
|
React.createElement(Text, { color: "red" }, "\u2717"),
|
|
117
111
|
" ",
|
|
@@ -119,36 +113,24 @@ export const InitRalph = () => {
|
|
|
119
113
|
errors.length === 0 && (React.createElement(React.Fragment, null,
|
|
120
114
|
React.createElement(Text, { color: "green" },
|
|
121
115
|
"\n",
|
|
122
|
-
"
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
React.createElement(Text, { bold: true },
|
|
136
|
-
"\n",
|
|
137
|
-
"Before running ralph, you need to:"),
|
|
138
|
-
React.createElement(Text, null,
|
|
139
|
-
React.createElement(Text, { color: "cyan" }, " 1. Edit .ralph/prompt.md"),
|
|
140
|
-
React.createElement(Text, { dimColor: true }, " - Customize build commands and workflow for your project")),
|
|
141
|
-
React.createElement(Text, null,
|
|
142
|
-
React.createElement(Text, { color: "cyan" }, " 2. Initialize beads"),
|
|
143
|
-
React.createElement(Text, { dimColor: true }, " - Run `bd init` to set up the issue tracker")),
|
|
144
|
-
React.createElement(Text, null,
|
|
145
|
-
React.createElement(Text, { color: "cyan" }, " 3. Create issues"),
|
|
146
|
-
React.createElement(Text, { dimColor: true }, " - Run `bd create --title=\"...\" --type=task` to add work"))),
|
|
116
|
+
"Ralph initialized successfully!"),
|
|
117
|
+
React.createElement(Text, { bold: true },
|
|
118
|
+
"\n",
|
|
119
|
+
"Next steps:"),
|
|
120
|
+
React.createElement(Text, null,
|
|
121
|
+
React.createElement(Text, { color: "cyan" }, " 1. Edit .ralph/workflow.md"),
|
|
122
|
+
React.createElement(Text, { dimColor: true }, " - Customize build commands for your project")),
|
|
123
|
+
React.createElement(Text, null,
|
|
124
|
+
React.createElement(Text, { color: "cyan" }, " 2. Initialize beads"),
|
|
125
|
+
React.createElement(Text, { dimColor: true }, " - Run `bd init` to set up the issue tracker")),
|
|
126
|
+
React.createElement(Text, null,
|
|
127
|
+
React.createElement(Text, { color: "cyan" }, " 3. Create issues"),
|
|
128
|
+
React.createElement(Text, { dimColor: true }, " - Run `bd create --title=\"...\" --type=task` to add work")),
|
|
147
129
|
React.createElement(Text, null,
|
|
148
130
|
React.createElement(Text, { bold: true },
|
|
149
131
|
"\n",
|
|
150
132
|
"Then run: "),
|
|
151
133
|
React.createElement(Text, { color: "cyan" }, "ralph"),
|
|
152
134
|
"\n")))));
|
|
153
|
-
}
|
|
135
|
+
}
|
|
154
136
|
//# sourceMappingURL=InitRalph.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InitRalph.js","sourceRoot":"","sources":["../../src/components/InitRalph.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAC/B,OAAO,
|
|
1
|
+
{"version":3,"file":"InitRalph.js","sourceRoot":"","sources":["../../src/components/InitRalph.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { type IterationRunnerProps } from "./IterationRunner.types.js";
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Orchestrates the iterative execution of Claude AI iterations.
|
|
5
|
+
*
|
|
6
|
+
* Spawns Claude CLI with prompts, captures streaming output, displays formatted UI,
|
|
7
|
+
* and handles user input during iteration execution.
|
|
7
8
|
*/
|
|
8
|
-
export declare const
|
|
9
|
-
export declare const IterationRunner: ({ totalIterations, claudeVersion, ralphVersion, watch }: Props) => React.JSX.Element;
|
|
10
|
-
type Props = {
|
|
11
|
-
totalIterations: number;
|
|
12
|
-
claudeVersion: string;
|
|
13
|
-
ralphVersion: string;
|
|
14
|
-
watch?: boolean;
|
|
15
|
-
};
|
|
16
|
-
export {};
|
|
9
|
+
export declare const IterationRunner: ({ totalIterations, claudeVersion, ralphVersion, watch, agent, }: IterationRunnerProps) => React.JSX.Element;
|
|
17
10
|
//# sourceMappingURL=IterationRunner.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IterationRunner.d.ts","sourceRoot":"","sources":["../../src/components/IterationRunner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"IterationRunner.d.ts","sourceRoot":"","sources":["../../src/components/IterationRunner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAA;AAuB1D,OAAO,EAAmB,KAAK,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAcvF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,iEAM7B,oBAAoB,sBA0lBtB,CAAA"}
|
|
@@ -1,169 +1,39 @@
|
|
|
1
1
|
import React, { useState, useEffect, useRef } from "react";
|
|
2
2
|
import { Box, Text, useApp, Static, useInput } from "ink";
|
|
3
3
|
import Spinner from "ink-spinner";
|
|
4
|
-
import BigText from "ink-big-text";
|
|
5
|
-
import Gradient from "ink-gradient";
|
|
6
4
|
import { EnhancedTextInput } from "./EnhancedTextInput.js";
|
|
7
5
|
import { appendFileSync, writeFileSync, readFileSync, existsSync } from "fs";
|
|
8
|
-
import { join,
|
|
9
|
-
import { fileURLToPath } from "url";
|
|
10
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
import { join, basename } from "path";
|
|
11
7
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
12
|
-
import { Header } from "./Header.js";
|
|
13
|
-
import { eventToBlocks } from "./eventToBlocks.js";
|
|
14
|
-
import { formatContentBlock } from "../lib/formatContentBlock.js";
|
|
15
8
|
import { addTodo } from "../lib/addTodo.js";
|
|
16
|
-
import { getProgress
|
|
9
|
+
import { getProgress } from "../lib/getProgress.js";
|
|
10
|
+
import { captureStartupSnapshot } from "../lib/captureStartupSnapshot.js";
|
|
17
11
|
import { ProgressBar } from "./ProgressBar.js";
|
|
18
12
|
import { watchForNewIssues } from "../lib/beadsClient.js";
|
|
19
13
|
import { MessageQueue, createUserMessage } from "../lib/MessageQueue.js";
|
|
20
14
|
import { createDebugLogger } from "../lib/debug.js";
|
|
21
15
|
import { useTerminalSize } from "../lib/useTerminalSize.js";
|
|
22
16
|
import { getNextLogFile } from "../lib/getNextLogFile.js";
|
|
17
|
+
import { parseTaskLifecycleEvent } from "../lib/parseTaskLifecycle.js";
|
|
18
|
+
import { getPromptContent } from "../lib/getPromptContent.js";
|
|
19
|
+
import { sdkMessageToEvent } from "../lib/sdkMessageToEvent.js";
|
|
20
|
+
import { processEvents } from "../lib/processEvents.js";
|
|
21
|
+
import { renderStaticItem } from "./renderStaticItem.js";
|
|
22
|
+
/** Debug logger for iteration lifecycle events */
|
|
23
23
|
const log = createDebugLogger("iteration");
|
|
24
|
+
/** The .ralph directory path in the current working directory */
|
|
24
25
|
const ralphDir = join(process.cwd(), ".ralph");
|
|
25
|
-
|
|
26
|
+
/** Path to the todo.md file in the .ralph directory */
|
|
26
27
|
const todoFile = join(ralphDir, "todo.md");
|
|
27
|
-
|
|
28
|
-
const templatesDir = join(__dirname, "..", "..", "templates");
|
|
28
|
+
/** The name of the current repository (basename of cwd) */
|
|
29
29
|
const repoName = basename(process.cwd());
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
31
|
+
* Orchestrates the iterative execution of Claude AI iterations.
|
|
32
|
+
*
|
|
33
|
+
* Spawns Claude CLI with prompts, captures streaming output, displays formatted UI,
|
|
34
|
+
* and handles user input during iteration execution.
|
|
35
35
|
*/
|
|
36
|
-
export const
|
|
37
|
-
// First, try to read from .ralph/prompt.md
|
|
38
|
-
if (existsSync(promptFile)) {
|
|
39
|
-
return readFileSync(promptFile, "utf-8");
|
|
40
|
-
}
|
|
41
|
-
// Fall back to templates based on project setup
|
|
42
|
-
const useBeadsTemplate = existsSync(beadsDir) || !existsSync(todoFile);
|
|
43
|
-
const templateFile = useBeadsTemplate ? "prompt-beads.md" : "prompt-todos.md";
|
|
44
|
-
const templatePath = join(templatesDir, templateFile);
|
|
45
|
-
if (existsSync(templatePath)) {
|
|
46
|
-
return readFileSync(templatePath, "utf-8");
|
|
47
|
-
}
|
|
48
|
-
// Last resort: return a minimal prompt
|
|
49
|
-
return "Work on the highest-priority task.";
|
|
50
|
-
};
|
|
51
|
-
// Convert SDK message to event format for display
|
|
52
|
-
const sdkMessageToEvent = (message) => {
|
|
53
|
-
// Pass through messages that have the structure we expect
|
|
54
|
-
if (message.type === "assistant" || message.type === "user" || message.type === "result") {
|
|
55
|
-
return message;
|
|
56
|
-
}
|
|
57
|
-
// Skip system and stream_event messages for display
|
|
58
|
-
return null;
|
|
59
|
-
};
|
|
60
|
-
// Process raw events into content blocks (moved from EventDisplay)
|
|
61
|
-
// With includePartialMessages: true, we receive multiple snapshots of the same message
|
|
62
|
-
// as it builds up. Each snapshot may contain different parts of the message content,
|
|
63
|
-
// so we need to merge them and deduplicate.
|
|
64
|
-
const processEvents = (events) => {
|
|
65
|
-
const blocks = [];
|
|
66
|
-
// First pass: collect all assistant message content and track message order
|
|
67
|
-
const assistantEvents = events.filter(event => event.type === "assistant");
|
|
68
|
-
// Collect all content blocks from all snapshots of the same message
|
|
69
|
-
const messageMap = new Map();
|
|
70
|
-
for (const event of assistantEvents) {
|
|
71
|
-
const message = event.message;
|
|
72
|
-
const messageId = message?.id;
|
|
73
|
-
const content = message?.content;
|
|
74
|
-
if (messageId && content) {
|
|
75
|
-
if (!messageMap.has(messageId)) {
|
|
76
|
-
messageMap.set(messageId, []);
|
|
77
|
-
}
|
|
78
|
-
messageMap.get(messageId).push(...content);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
// Create merged events with deduplicated content
|
|
82
|
-
const mergedEvents = Array.from(messageMap.entries()).map(([messageId, allContent]) => {
|
|
83
|
-
// Deduplicate content blocks by their ID (for tool_use) or text (for text blocks)
|
|
84
|
-
const seenBlocks = new Set();
|
|
85
|
-
const uniqueContent = [];
|
|
86
|
-
for (const block of allContent) {
|
|
87
|
-
const blockType = block.type;
|
|
88
|
-
let blockKey;
|
|
89
|
-
if (blockType === "tool_use") {
|
|
90
|
-
// Tool use blocks are unique by their ID
|
|
91
|
-
blockKey = `tool:${block.id}`;
|
|
92
|
-
}
|
|
93
|
-
else if (blockType === "text") {
|
|
94
|
-
// For text blocks, check if this is a prefix of or prefixed by existing text
|
|
95
|
-
// This handles incremental text updates where each snapshot has more content
|
|
96
|
-
const text = block.text;
|
|
97
|
-
let isDuplicate = false;
|
|
98
|
-
for (const seenKey of seenBlocks) {
|
|
99
|
-
if (seenKey.startsWith("text:")) {
|
|
100
|
-
const seenText = seenKey.substring(5);
|
|
101
|
-
// If existing text starts with this text, or this text starts with existing,
|
|
102
|
-
// keep only the longer one
|
|
103
|
-
if (seenText.startsWith(text)) {
|
|
104
|
-
// Existing is longer, this is a duplicate
|
|
105
|
-
isDuplicate = true;
|
|
106
|
-
break;
|
|
107
|
-
}
|
|
108
|
-
else if (text.startsWith(seenText)) {
|
|
109
|
-
// This is longer, remove the old one and add this
|
|
110
|
-
seenBlocks.delete(seenKey);
|
|
111
|
-
// Also remove from uniqueContent
|
|
112
|
-
const idx = uniqueContent.findIndex(b => b.type === "text" && b.text === seenText);
|
|
113
|
-
if (idx >= 0)
|
|
114
|
-
uniqueContent.splice(idx, 1);
|
|
115
|
-
break;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
if (isDuplicate)
|
|
120
|
-
continue;
|
|
121
|
-
blockKey = `text:${text}`;
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
blockKey = JSON.stringify(block);
|
|
125
|
-
}
|
|
126
|
-
if (!seenBlocks.has(blockKey)) {
|
|
127
|
-
seenBlocks.add(blockKey);
|
|
128
|
-
uniqueContent.push(block);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return {
|
|
132
|
-
type: "assistant",
|
|
133
|
-
message: {
|
|
134
|
-
id: messageId,
|
|
135
|
-
content: uniqueContent,
|
|
136
|
-
},
|
|
137
|
-
};
|
|
138
|
-
});
|
|
139
|
-
const assistantBlocks = mergedEvents.flatMap(event => eventToBlocks(event));
|
|
140
|
-
// Second pass: process events in order, including user messages
|
|
141
|
-
// Track which user messages and assistant messages we've already seen
|
|
142
|
-
const processedUserIds = new Set();
|
|
143
|
-
const processedAssistantIds = new Set();
|
|
144
|
-
for (const event of events) {
|
|
145
|
-
if (event.type === "user") {
|
|
146
|
-
const message = event.message;
|
|
147
|
-
const messageId = message?.id ?? `user-${Date.now()}`;
|
|
148
|
-
if (!processedUserIds.has(messageId)) {
|
|
149
|
-
processedUserIds.add(messageId);
|
|
150
|
-
blocks.push(...eventToBlocks(event));
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
else if (event.type === "assistant") {
|
|
154
|
-
const message = event.message;
|
|
155
|
-
const messageId = message?.id;
|
|
156
|
-
if (messageId && !processedAssistantIds.has(messageId)) {
|
|
157
|
-
processedAssistantIds.add(messageId);
|
|
158
|
-
// Find the merged version of this message
|
|
159
|
-
const merged = assistantBlocks.filter(b => b.id.startsWith(messageId));
|
|
160
|
-
blocks.push(...merged);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return blocks;
|
|
165
|
-
};
|
|
166
|
-
export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion, watch }) => {
|
|
36
|
+
export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion, watch, agent, }) => {
|
|
167
37
|
const { exit } = useApp();
|
|
168
38
|
const { columns } = useTerminalSize();
|
|
169
39
|
const [currentIteration, setCurrentIteration] = useState(1);
|
|
@@ -192,6 +62,8 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
|
|
|
192
62
|
const stopAfterCurrentRef = useRef(false); // Ref to access in async callbacks
|
|
193
63
|
const [isPaused, setIsPaused] = useState(false); // Pause after current iteration completes
|
|
194
64
|
const isPausedRef = useRef(false); // Ref to access in async callbacks
|
|
65
|
+
const [currentTaskId, setCurrentTaskId] = useState(null);
|
|
66
|
+
const [currentTaskTitle, setCurrentTaskTitle] = useState(null);
|
|
195
67
|
// Track static items that have been rendered (for Ink's Static component)
|
|
196
68
|
const [staticItems, setStaticItems] = useState([
|
|
197
69
|
{ type: "header", claudeVersion, ralphVersion, key: "header" },
|
|
@@ -202,10 +74,14 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
|
|
|
202
74
|
const messageQueueRef = useRef(null);
|
|
203
75
|
// Log file path for this run (set once at startup, persisted across iterations)
|
|
204
76
|
const logFileRef = useRef(null);
|
|
205
|
-
|
|
77
|
+
/** Whether stdin supports raw mode (required for keyboard input handling) */
|
|
206
78
|
const stdinSupportsRawMode = process.stdin.isTTY === true;
|
|
207
|
-
|
|
208
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Handle adding a new todo when Ctrl-T is pressed.
|
|
81
|
+
*/
|
|
82
|
+
const handleTodoSubmit = (
|
|
83
|
+
/** The todo text to add */
|
|
84
|
+
text) => {
|
|
209
85
|
const trimmed = text.trim();
|
|
210
86
|
if (!trimmed) {
|
|
211
87
|
setIsAddingTodo(false);
|
|
@@ -231,8 +107,12 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
|
|
|
231
107
|
setTimeout(() => setTodoMessage(null), 5000);
|
|
232
108
|
}
|
|
233
109
|
};
|
|
234
|
-
|
|
235
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Handle submitting a user message to Claude during iteration.
|
|
112
|
+
*/
|
|
113
|
+
const handleUserMessageSubmit = (
|
|
114
|
+
/** The message text from the user */
|
|
115
|
+
text) => {
|
|
236
116
|
const trimmed = text.trim();
|
|
237
117
|
if (!trimmed) {
|
|
238
118
|
setUserMessageText("");
|
|
@@ -264,8 +144,14 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
|
|
|
264
144
|
// Clear status message after 3 seconds
|
|
265
145
|
setTimeout(() => setUserMessageStatus(null), 3000);
|
|
266
146
|
};
|
|
267
|
-
|
|
268
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Handle keyboard input for Ctrl-T (todo), Ctrl-S (stop), Ctrl-P (pause), and Escape (cancel).
|
|
149
|
+
*/
|
|
150
|
+
useInput((
|
|
151
|
+
/** The input character */
|
|
152
|
+
input,
|
|
153
|
+
/** The key information including modifiers */
|
|
154
|
+
key) => {
|
|
269
155
|
// Ctrl-T to start adding a todo (only if todo.md exists)
|
|
270
156
|
if (key.ctrl && input === "t" && hasTodoFile) {
|
|
271
157
|
setIsAddingTodo(true);
|
|
@@ -430,6 +316,9 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
|
|
|
430
316
|
messageQueueRef.current = messageQueue;
|
|
431
317
|
// Push the initial prompt as the first message
|
|
432
318
|
messageQueue.push(createUserMessage(fullPrompt));
|
|
319
|
+
/**
|
|
320
|
+
* Execute a query to Claude and handle the streaming response.
|
|
321
|
+
*/
|
|
433
322
|
const runQuery = async () => {
|
|
434
323
|
let finalResult = "";
|
|
435
324
|
log(`Starting iteration ${currentIteration}`);
|
|
@@ -446,6 +335,8 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
|
|
|
446
335
|
...process.env,
|
|
447
336
|
// Disable LSP plugins to avoid crashes when TypeScript LSP server errors
|
|
448
337
|
ENABLE_LSP_TOOL: "0",
|
|
338
|
+
// Signal that tests should use minimal reporters (dots)
|
|
339
|
+
RALPH_QUIET: "1",
|
|
449
340
|
},
|
|
450
341
|
},
|
|
451
342
|
})) {
|
|
@@ -457,6 +348,45 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
|
|
|
457
348
|
if (event) {
|
|
458
349
|
setEvents(prev => [...prev, event]);
|
|
459
350
|
}
|
|
351
|
+
// Check for task lifecycle events in assistant messages
|
|
352
|
+
if (message.type === "assistant") {
|
|
353
|
+
const assistantMessage = message.message;
|
|
354
|
+
const content = assistantMessage?.content;
|
|
355
|
+
if (content) {
|
|
356
|
+
for (const block of content) {
|
|
357
|
+
if (block.type === "text" && typeof block.text === "string") {
|
|
358
|
+
const taskInfo = parseTaskLifecycleEvent(block.text);
|
|
359
|
+
if (taskInfo) {
|
|
360
|
+
if (taskInfo.action === "starting") {
|
|
361
|
+
setCurrentTaskId(taskInfo.taskId ?? null);
|
|
362
|
+
setCurrentTaskTitle(taskInfo.taskTitle ?? null);
|
|
363
|
+
log(`Task started: ${taskInfo.taskId}${taskInfo.taskTitle ? ` - ${taskInfo.taskTitle}` : ""}`);
|
|
364
|
+
// Emit ralph_task_started event to log file
|
|
365
|
+
const taskStartedEvent = {
|
|
366
|
+
type: "ralph_task_started",
|
|
367
|
+
taskId: taskInfo.taskId,
|
|
368
|
+
taskTitle: taskInfo.taskTitle,
|
|
369
|
+
iteration: currentIteration,
|
|
370
|
+
};
|
|
371
|
+
appendFileSync(logFile, JSON.stringify(taskStartedEvent) + "\n");
|
|
372
|
+
}
|
|
373
|
+
else if (taskInfo.action === "completed") {
|
|
374
|
+
log(`Task completed: ${taskInfo.taskId}${taskInfo.taskTitle ? ` - ${taskInfo.taskTitle}` : ""}`);
|
|
375
|
+
// Emit ralph_task_completed event to log file
|
|
376
|
+
const taskCompletedEvent = {
|
|
377
|
+
type: "ralph_task_completed",
|
|
378
|
+
taskId: taskInfo.taskId,
|
|
379
|
+
taskTitle: taskInfo.taskTitle,
|
|
380
|
+
iteration: currentIteration,
|
|
381
|
+
};
|
|
382
|
+
appendFileSync(logFile, JSON.stringify(taskCompletedEvent) + "\n");
|
|
383
|
+
// Keep tracking the same task until a new one starts
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
460
390
|
// Capture the final result message
|
|
461
391
|
if (message.type === "result" &&
|
|
462
392
|
"result" in message &&
|
|
@@ -536,20 +466,6 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
|
|
|
536
466
|
return (React.createElement(Box, { flexDirection: "column" },
|
|
537
467
|
React.createElement(Text, { color: "red" }, error)));
|
|
538
468
|
}
|
|
539
|
-
// Render a static item (header, iteration header, or content block)
|
|
540
|
-
const renderStaticItem = (item) => {
|
|
541
|
-
if (item.type === "header") {
|
|
542
|
-
return React.createElement(Header, { claudeVersion: item.claudeVersion, ralphVersion: item.ralphVersion });
|
|
543
|
-
}
|
|
544
|
-
if (item.type === "iteration") {
|
|
545
|
-
return (React.createElement(Box, { flexDirection: "column", marginTop: 1 },
|
|
546
|
-
React.createElement(Gradient, { colors: ["#30A6E4", "#EBC635"] },
|
|
547
|
-
React.createElement(BigText, { text: `R${item.iteration}`, font: "tiny" }))));
|
|
548
|
-
}
|
|
549
|
-
// Content block
|
|
550
|
-
const lines = formatContentBlock(item.block);
|
|
551
|
-
return (React.createElement(Box, { flexDirection: "column", marginBottom: 1 }, lines.map((line, i) => (React.createElement(Text, { key: i }, line || " ")))));
|
|
552
|
-
};
|
|
553
469
|
return (React.createElement(Box, { flexDirection: "column" },
|
|
554
470
|
React.createElement(Static, { items: staticItems }, item => (React.createElement(Box, { key: item.key, flexDirection: "column" }, renderStaticItem(item)))),
|
|
555
471
|
isAddingTodo && (React.createElement(Box, { flexDirection: "column", marginTop: 1 },
|