@herbcaudill/ralph 0.8.5 → 1.0.2

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 (187) hide show
  1. package/dist/index.js +2401 -5
  2. package/dist/index.js.map +1 -1
  3. package/package.json +9 -7
  4. package/templates/core-prompt.md +77 -0
  5. package/templates/skills/manage-tasks/SKILL.md +113 -0
  6. package/templates/workflow.md +46 -0
  7. package/dist/cli.d.ts +0 -3
  8. package/dist/cli.d.ts.map +0 -1
  9. package/dist/cli.js +0 -81
  10. package/dist/cli.js.map +0 -1
  11. package/dist/components/App.d.ts +0 -12
  12. package/dist/components/App.d.ts.map +0 -1
  13. package/dist/components/App.js +0 -14
  14. package/dist/components/App.js.map +0 -1
  15. package/dist/components/EnhancedTextInput.d.ts +0 -22
  16. package/dist/components/EnhancedTextInput.d.ts.map +0 -1
  17. package/dist/components/EnhancedTextInput.js +0 -164
  18. package/dist/components/EnhancedTextInput.js.map +0 -1
  19. package/dist/components/EnhancedTextInput.test.d.ts +0 -2
  20. package/dist/components/EnhancedTextInput.test.d.ts.map +0 -1
  21. package/dist/components/EnhancedTextInput.test.js +0 -107
  22. package/dist/components/EnhancedTextInput.test.js.map +0 -1
  23. package/dist/components/EventDisplay.d.ts +0 -14
  24. package/dist/components/EventDisplay.d.ts.map +0 -1
  25. package/dist/components/EventDisplay.js +0 -182
  26. package/dist/components/EventDisplay.js.map +0 -1
  27. package/dist/components/EventDisplay.replay.test.d.ts +0 -2
  28. package/dist/components/EventDisplay.replay.test.d.ts.map +0 -1
  29. package/dist/components/EventDisplay.replay.test.js +0 -413
  30. package/dist/components/EventDisplay.replay.test.js.map +0 -1
  31. package/dist/components/EventDisplay.test.d.ts +0 -2
  32. package/dist/components/EventDisplay.test.d.ts.map +0 -1
  33. package/dist/components/EventDisplay.test.js +0 -319
  34. package/dist/components/EventDisplay.test.js.map +0 -1
  35. package/dist/components/FullScreenLayout.d.ts +0 -14
  36. package/dist/components/FullScreenLayout.d.ts.map +0 -1
  37. package/dist/components/FullScreenLayout.js +0 -30
  38. package/dist/components/FullScreenLayout.js.map +0 -1
  39. package/dist/components/Header.d.ts +0 -9
  40. package/dist/components/Header.d.ts.map +0 -1
  41. package/dist/components/Header.js +0 -15
  42. package/dist/components/Header.js.map +0 -1
  43. package/dist/components/Header.test.d.ts +0 -2
  44. package/dist/components/Header.test.d.ts.map +0 -1
  45. package/dist/components/Header.test.js +0 -27
  46. package/dist/components/Header.test.js.map +0 -1
  47. package/dist/components/InitRalph.d.ts +0 -3
  48. package/dist/components/InitRalph.d.ts.map +0 -1
  49. package/dist/components/InitRalph.js +0 -154
  50. package/dist/components/InitRalph.js.map +0 -1
  51. package/dist/components/IterationRunner.d.ts +0 -17
  52. package/dist/components/IterationRunner.d.ts.map +0 -1
  53. package/dist/components/IterationRunner.js +0 -620
  54. package/dist/components/IterationRunner.js.map +0 -1
  55. package/dist/components/IterationRunner.test.d.ts +0 -2
  56. package/dist/components/IterationRunner.test.d.ts.map +0 -1
  57. package/dist/components/IterationRunner.test.js +0 -129
  58. package/dist/components/IterationRunner.test.js.map +0 -1
  59. package/dist/components/JsonOutput.d.ts +0 -14
  60. package/dist/components/JsonOutput.d.ts.map +0 -1
  61. package/dist/components/JsonOutput.js +0 -246
  62. package/dist/components/JsonOutput.js.map +0 -1
  63. package/dist/components/ProgressBar.d.ts +0 -18
  64. package/dist/components/ProgressBar.d.ts.map +0 -1
  65. package/dist/components/ProgressBar.js +0 -30
  66. package/dist/components/ProgressBar.js.map +0 -1
  67. package/dist/components/ProgressBar.test.d.ts +0 -2
  68. package/dist/components/ProgressBar.test.d.ts.map +0 -1
  69. package/dist/components/ProgressBar.test.js +0 -55
  70. package/dist/components/ProgressBar.test.js.map +0 -1
  71. package/dist/components/ReplayLog.d.ts +0 -7
  72. package/dist/components/ReplayLog.d.ts.map +0 -1
  73. package/dist/components/ReplayLog.js +0 -50
  74. package/dist/components/ReplayLog.js.map +0 -1
  75. package/dist/components/StreamingText.d.ts +0 -7
  76. package/dist/components/StreamingText.d.ts.map +0 -1
  77. package/dist/components/StreamingText.js +0 -36
  78. package/dist/components/StreamingText.js.map +0 -1
  79. package/dist/components/StreamingText.test.d.ts +0 -2
  80. package/dist/components/StreamingText.test.d.ts.map +0 -1
  81. package/dist/components/StreamingText.test.js +0 -86
  82. package/dist/components/StreamingText.test.js.map +0 -1
  83. package/dist/components/ToolUse.d.ts +0 -8
  84. package/dist/components/ToolUse.d.ts.map +0 -1
  85. package/dist/components/ToolUse.js +0 -10
  86. package/dist/components/ToolUse.js.map +0 -1
  87. package/dist/components/ToolUse.test.d.ts +0 -2
  88. package/dist/components/ToolUse.test.d.ts.map +0 -1
  89. package/dist/components/ToolUse.test.js +0 -43
  90. package/dist/components/ToolUse.test.js.map +0 -1
  91. package/dist/components/eventToBlocks.d.ts +0 -16
  92. package/dist/components/eventToBlocks.d.ts.map +0 -1
  93. package/dist/components/eventToBlocks.js +0 -160
  94. package/dist/components/eventToBlocks.js.map +0 -1
  95. package/dist/components/eventToBlocks.test.d.ts +0 -2
  96. package/dist/components/eventToBlocks.test.d.ts.map +0 -1
  97. package/dist/components/eventToBlocks.test.js +0 -466
  98. package/dist/components/eventToBlocks.test.js.map +0 -1
  99. package/dist/index.d.ts +0 -2
  100. package/dist/index.d.ts.map +0 -1
  101. package/dist/lib/MessageQueue.d.ts +0 -20
  102. package/dist/lib/MessageQueue.d.ts.map +0 -1
  103. package/dist/lib/MessageQueue.js +0 -89
  104. package/dist/lib/MessageQueue.js.map +0 -1
  105. package/dist/lib/MessageQueue.test.d.ts +0 -2
  106. package/dist/lib/MessageQueue.test.d.ts.map +0 -1
  107. package/dist/lib/MessageQueue.test.js +0 -224
  108. package/dist/lib/MessageQueue.test.js.map +0 -1
  109. package/dist/lib/StdinCommandHandler.d.ts +0 -42
  110. package/dist/lib/StdinCommandHandler.d.ts.map +0 -1
  111. package/dist/lib/StdinCommandHandler.js +0 -102
  112. package/dist/lib/StdinCommandHandler.js.map +0 -1
  113. package/dist/lib/StdinCommandHandler.test.d.ts +0 -2
  114. package/dist/lib/StdinCommandHandler.test.d.ts.map +0 -1
  115. package/dist/lib/StdinCommandHandler.test.js +0 -93
  116. package/dist/lib/StdinCommandHandler.test.js.map +0 -1
  117. package/dist/lib/addTodo.d.ts +0 -11
  118. package/dist/lib/addTodo.d.ts.map +0 -1
  119. package/dist/lib/addTodo.js +0 -65
  120. package/dist/lib/addTodo.js.map +0 -1
  121. package/dist/lib/beadsClient.d.ts +0 -52
  122. package/dist/lib/beadsClient.d.ts.map +0 -1
  123. package/dist/lib/beadsClient.js +0 -171
  124. package/dist/lib/beadsClient.js.map +0 -1
  125. package/dist/lib/debug.d.ts +0 -18
  126. package/dist/lib/debug.d.ts.map +0 -1
  127. package/dist/lib/debug.js +0 -44
  128. package/dist/lib/debug.js.map +0 -1
  129. package/dist/lib/formatContentBlock.d.ts +0 -10
  130. package/dist/lib/formatContentBlock.d.ts.map +0 -1
  131. package/dist/lib/formatContentBlock.js +0 -69
  132. package/dist/lib/formatContentBlock.js.map +0 -1
  133. package/dist/lib/getClaudeVersion.d.ts +0 -2
  134. package/dist/lib/getClaudeVersion.d.ts.map +0 -1
  135. package/dist/lib/getClaudeVersion.js +0 -17
  136. package/dist/lib/getClaudeVersion.js.map +0 -1
  137. package/dist/lib/getClaudeVersion.test.d.ts +0 -2
  138. package/dist/lib/getClaudeVersion.test.d.ts.map +0 -1
  139. package/dist/lib/getClaudeVersion.test.js +0 -39
  140. package/dist/lib/getClaudeVersion.test.js.map +0 -1
  141. package/dist/lib/getNextLogFile.d.ts +0 -12
  142. package/dist/lib/getNextLogFile.d.ts.map +0 -1
  143. package/dist/lib/getNextLogFile.js +0 -52
  144. package/dist/lib/getNextLogFile.js.map +0 -1
  145. package/dist/lib/getNextLogFile.test.d.ts +0 -2
  146. package/dist/lib/getNextLogFile.test.d.ts.map +0 -1
  147. package/dist/lib/getNextLogFile.test.js +0 -65
  148. package/dist/lib/getNextLogFile.test.js.map +0 -1
  149. package/dist/lib/getOpenIssueCount.d.ts +0 -11
  150. package/dist/lib/getOpenIssueCount.d.ts.map +0 -1
  151. package/dist/lib/getOpenIssueCount.js +0 -31
  152. package/dist/lib/getOpenIssueCount.js.map +0 -1
  153. package/dist/lib/getOpenIssueCount.test.d.ts +0 -2
  154. package/dist/lib/getOpenIssueCount.test.d.ts.map +0 -1
  155. package/dist/lib/getOpenIssueCount.test.js +0 -65
  156. package/dist/lib/getOpenIssueCount.test.js.map +0 -1
  157. package/dist/lib/getProgress.d.ts +0 -34
  158. package/dist/lib/getProgress.d.ts.map +0 -1
  159. package/dist/lib/getProgress.js +0 -131
  160. package/dist/lib/getProgress.js.map +0 -1
  161. package/dist/lib/getProgress.test.d.ts +0 -2
  162. package/dist/lib/getProgress.test.d.ts.map +0 -1
  163. package/dist/lib/getProgress.test.js +0 -217
  164. package/dist/lib/getProgress.test.js.map +0 -1
  165. package/dist/lib/rel.d.ts +0 -2
  166. package/dist/lib/rel.d.ts.map +0 -1
  167. package/dist/lib/rel.js +0 -10
  168. package/dist/lib/rel.js.map +0 -1
  169. package/dist/lib/rel.test.d.ts +0 -2
  170. package/dist/lib/rel.test.d.ts.map +0 -1
  171. package/dist/lib/rel.test.js +0 -36
  172. package/dist/lib/rel.test.js.map +0 -1
  173. package/dist/lib/shortenTempPaths.d.ts +0 -2
  174. package/dist/lib/shortenTempPaths.d.ts.map +0 -1
  175. package/dist/lib/shortenTempPaths.js +0 -7
  176. package/dist/lib/shortenTempPaths.js.map +0 -1
  177. package/dist/lib/shortenTempPaths.test.d.ts +0 -2
  178. package/dist/lib/shortenTempPaths.test.d.ts.map +0 -1
  179. package/dist/lib/shortenTempPaths.test.js +0 -46
  180. package/dist/lib/shortenTempPaths.test.js.map +0 -1
  181. package/dist/lib/useTerminalSize.d.ts +0 -5
  182. package/dist/lib/useTerminalSize.d.ts.map +0 -1
  183. package/dist/lib/useTerminalSize.js +0 -21
  184. package/dist/lib/useTerminalSize.js.map +0 -1
  185. package/templates/prompt-beads.md +0 -44
  186. package/templates/prompt-todos.md +0 -17
  187. package/templates/todo.md +0 -9
@@ -1,182 +0,0 @@
1
- import React, { useMemo, useState, useEffect, useRef } from "react";
2
- import { Box, Text, useInput } from "ink";
3
- import { eventToBlocks } from "./eventToBlocks.js";
4
- import { formatContentBlock, formatIterationHeader } from "../lib/formatContentBlock.js";
5
- // Process raw events into content blocks
6
- // With includePartialMessages: true, we receive multiple snapshots of the same message
7
- // as it builds up. Each snapshot may contain different parts of the message content,
8
- // so we need to merge them and deduplicate.
9
- const processEvents = (events) => {
10
- // Filter to only show complete assistant messages, not streaming events
11
- // streaming events are incomplete and cause duplicate/disappearing content
12
- const assistantEvents = events.filter(event => event.type === "assistant");
13
- // Collect all content blocks from all snapshots of the same message
14
- const messageMap = new Map();
15
- for (const event of assistantEvents) {
16
- const message = event.message;
17
- const messageId = message?.id;
18
- const content = message?.content;
19
- if (messageId && content) {
20
- if (!messageMap.has(messageId)) {
21
- messageMap.set(messageId, []);
22
- }
23
- messageMap.get(messageId).push(...content);
24
- }
25
- }
26
- // Create merged events with deduplicated content
27
- const mergedEvents = Array.from(messageMap.entries()).map(([messageId, allContent]) => {
28
- // Deduplicate content blocks by their ID (for tool_use) or text (for text blocks)
29
- const seenBlocks = new Set();
30
- const uniqueContent = [];
31
- for (const block of allContent) {
32
- const blockType = block.type;
33
- let blockKey;
34
- if (blockType === "tool_use") {
35
- // Tool use blocks are unique by their ID
36
- blockKey = `tool:${block.id}`;
37
- }
38
- else if (blockType === "text") {
39
- // For text blocks, check if this is a prefix of or prefixed by existing text
40
- // This handles incremental text updates where each snapshot has more content
41
- const text = block.text;
42
- let isDuplicate = false;
43
- for (const seenKey of seenBlocks) {
44
- if (seenKey.startsWith("text:")) {
45
- const seenText = seenKey.substring(5);
46
- // If existing text starts with this text, or this text starts with existing,
47
- // keep only the longer one
48
- if (seenText.startsWith(text)) {
49
- // Existing is longer, this is a duplicate
50
- isDuplicate = true;
51
- break;
52
- }
53
- else if (text.startsWith(seenText)) {
54
- // This is longer, remove the old one and add this
55
- seenBlocks.delete(seenKey);
56
- // Also remove from uniqueContent
57
- const idx = uniqueContent.findIndex(b => b.type === "text" && b.text === seenText);
58
- if (idx >= 0)
59
- uniqueContent.splice(idx, 1);
60
- break;
61
- }
62
- }
63
- }
64
- if (isDuplicate)
65
- continue;
66
- blockKey = `text:${text}`;
67
- }
68
- else {
69
- blockKey = JSON.stringify(block);
70
- }
71
- if (!seenBlocks.has(blockKey)) {
72
- seenBlocks.add(blockKey);
73
- uniqueContent.push(block);
74
- }
75
- }
76
- return {
77
- type: "assistant",
78
- message: {
79
- id: messageId,
80
- content: uniqueContent,
81
- },
82
- };
83
- });
84
- return mergedEvents.flatMap(event => eventToBlocks(event));
85
- };
86
- // Convert content blocks to lines of formatted text
87
- const blocksToLines = (blocks) => {
88
- const lines = [];
89
- for (const block of blocks) {
90
- const blockLines = formatContentBlock(block);
91
- lines.push(...blockLines);
92
- // Add blank line after each block
93
- lines.push("");
94
- }
95
- return lines;
96
- };
97
- export const EventDisplay = ({ events, iteration, completedIterations, height }) => {
98
- // Scroll offset from bottom (0 = at bottom, positive = scrolled up)
99
- const [scrollOffset, setScrollOffset] = useState(0);
100
- // Track if user has manually scrolled
101
- const userScrolledRef = useRef(false);
102
- // Track previous line count for auto-scroll
103
- const prevLineCountRef = useRef(0);
104
- // Convert all content to lines for virtual scrolling
105
- const allLines = useMemo(() => {
106
- const lines = [];
107
- // Add completed iterations
108
- for (const completed of completedIterations) {
109
- lines.push("");
110
- lines.push("");
111
- lines.push(formatIterationHeader(completed.iteration));
112
- lines.push("");
113
- const blocks = processEvents(completed.events);
114
- lines.push(...blocksToLines(blocks));
115
- }
116
- // Add current iteration
117
- lines.push("");
118
- lines.push("");
119
- lines.push(formatIterationHeader(iteration));
120
- lines.push("");
121
- const currentBlocks = processEvents(events);
122
- lines.push(...blocksToLines(currentBlocks));
123
- return lines;
124
- }, [events, iteration, completedIterations]);
125
- // Auto-scroll to bottom when new content arrives (unless user scrolled up)
126
- useEffect(() => {
127
- if (allLines.length > prevLineCountRef.current && !userScrolledRef.current) {
128
- setScrollOffset(0);
129
- }
130
- prevLineCountRef.current = allLines.length;
131
- }, [allLines.length]);
132
- // Handle keyboard input for scrolling
133
- useInput((input, key) => {
134
- if (!height)
135
- return;
136
- const maxOffset = Math.max(0, allLines.length - height);
137
- const pageSize = Math.max(1, height - 2);
138
- if (key.upArrow || input === "k") {
139
- userScrolledRef.current = true;
140
- setScrollOffset(prev => Math.min(maxOffset, prev + 1));
141
- }
142
- else if (key.downArrow || input === "j") {
143
- const newOffset = Math.max(0, scrollOffset - 1);
144
- setScrollOffset(newOffset);
145
- if (newOffset === 0) {
146
- userScrolledRef.current = false;
147
- }
148
- }
149
- else if (key.pageUp) {
150
- userScrolledRef.current = true;
151
- setScrollOffset(prev => Math.min(maxOffset, prev + pageSize));
152
- }
153
- else if (key.pageDown) {
154
- const newOffset = Math.max(0, scrollOffset - pageSize);
155
- setScrollOffset(newOffset);
156
- if (newOffset === 0) {
157
- userScrolledRef.current = false;
158
- }
159
- }
160
- else if (input === "g" && key.shift) {
161
- // Shift+G = go to bottom
162
- setScrollOffset(0);
163
- userScrolledRef.current = false;
164
- }
165
- else if (input === "g") {
166
- // g = go to top
167
- userScrolledRef.current = true;
168
- setScrollOffset(maxOffset);
169
- }
170
- });
171
- // Calculate visible lines based on scroll position
172
- const visibleLines = useMemo(() => {
173
- if (!height || allLines.length <= height) {
174
- return allLines;
175
- }
176
- const endIndex = allLines.length - scrollOffset;
177
- const startIndex = Math.max(0, endIndex - height);
178
- return allLines.slice(startIndex, endIndex);
179
- }, [allLines, height, scrollOffset]);
180
- return (React.createElement(Box, { flexDirection: "column" }, visibleLines.map((line, index) => (React.createElement(Text, { key: index, wrap: "wrap" }, line || " ")))));
181
- };
182
- //# sourceMappingURL=EventDisplay.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EventDisplay.js","sourceRoot":"","sources":["../../src/components/EventDisplay.tsx"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=EventDisplay.replay.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EventDisplay.replay.test.d.ts","sourceRoot":"","sources":["../../src/components/EventDisplay.replay.test.tsx"],"names":[],"mappings":""}
@@ -1,413 +0,0 @@
1
- import React from "react";
2
- import { render } from "ink-testing-library";
3
- import { describe, it, expect, vi } from "vitest";
4
- import { readFileSync } from "fs";
5
- import { join } from "path";
6
- import { EventDisplay } from "./EventDisplay.js";
7
- /**
8
- * Helper function to replay an event log file and return the rendered output
9
- */
10
- async function replay(logFile) {
11
- // Read the event log
12
- const logPath = join(process.cwd(), "test/event-logs", logFile);
13
- const logContent = readFileSync(logPath, "utf-8");
14
- // Parse JSON events (multi-line JSON objects separated by blank lines)
15
- const events = [];
16
- const jsonObjects = logContent.split("\n\n");
17
- for (const jsonStr of jsonObjects) {
18
- if (!jsonStr.trim())
19
- continue;
20
- try {
21
- const event = JSON.parse(jsonStr);
22
- events.push(event);
23
- }
24
- catch {
25
- // Skip invalid JSON
26
- }
27
- }
28
- // Render with all events
29
- const { lastFrame } = render(React.createElement(EventDisplay, { events: events, iteration: 1, completedIterations: [] }));
30
- // Wait for rendering
31
- await vi.waitFor(() => {
32
- const output = lastFrame() ?? "";
33
- expect(output.length).toBeGreaterThan(0);
34
- }, { timeout: 1000 });
35
- return lastFrame() ?? "";
36
- }
37
- describe("EventDisplay replay tests", () => {
38
- it("replays 1.txt", async () => {
39
- expect(await replay("1.txt")).toMatchInlineSnapshot(`
40
- "
41
-
42
- ─── Round 1 ───
43
-
44
- I'll start by checking the types, unit tests, and end-to-end tests as instructed.
45
-
46
- TodoWrite
47
- [~] Run typecheck to verify types
48
- [ ] Run unit tests via pnpm test
49
- [ ] Run end-to-end tests via pnpm test:pw
50
-
51
- $ pnpm typecheck
52
-
53
- Good! Types check successfully. Now let me run the unit tests.
54
-
55
- TodoWrite
56
- [x] Run typecheck to verify types
57
- [~] Run unit tests via pnpm test
58
- [ ] Run end-to-end tests via pnpm test:pw
59
-
60
- $ pnpm test
61
-
62
- Perfect! Unit tests pass. Now let me run the end-to-end tests.
63
-
64
- TodoWrite
65
- [x] Run typecheck to verify types
66
- [x] Run unit tests via pnpm test
67
- [~] Run end-to-end tests via pnpm test:pw
68
-
69
- $ pnpm test:pw
70
- "
71
- `);
72
- });
73
- it("replays 2.txt", async () => {
74
- expect(await replay("2.txt")).toMatchInlineSnapshot(`
75
- "
76
-
77
- ─── Round 1 ───
78
-
79
- I'll start by checking that the project builds successfully and running tests.
80
-
81
- $ pnpm build
82
-
83
- $ pnpm test
84
-
85
- Good! The build is successful and all tests pass. Now let me check the todo list to find the
86
- highest-priority task.
87
-
88
- Read ../.ralph/todo.md
89
-
90
- Looking at the todo list, I'll prioritize the "Inline code blocks are being put in separate
91
- paragraphs" issue. This is a functional bug affecting the display quality, whereas the others are
92
- enhancements. Let me investigate this issue first.
93
-
94
- Read ../src/components/StreamingText.tsx
95
-
96
- Let me check the tests to understand the expected behavior and see if there's a failing test case:
97
-
98
- Read ../src/components/StreamingText.test.tsx
99
-
100
- I need to understand where StreamingText is being used and what the actual problem is. Let me check
101
- where it's called from and look at some example output:
102
-
103
- Grep StreamingText
104
-
105
- Read ../src/components/EventDisplay.tsx
106
-
107
- I see the issue now! In EventDisplay.tsx:70, there's a <Box flexDirection="column" gap={1}> which
108
- wraps each StreamingText component. Each StreamingText (which represents text blocks) is being
109
- placed in its own box with a gap, causing inline code to appear in separate paragraphs.
110
-
111
- The problem is that each text block from Claude's message content is being rendered as a separate
112
- StreamingText component with gaps between them. This works fine for separate paragraphs, but inline
113
- code within a sentence gets split incorrectly.
114
-
115
- Let me look at how the events are being split into blocks:
116
-
117
- Read ../src/components/eventToBlocks.ts
118
-
119
- Now I understand the issue. Claude's message content can have multiple text blocks (e.g., "Here's
120
- the code: ", then a tool_use block, then " and that's it"). Each text block becomes a separate
121
- ContentBlock with type "text", and EventDisplay renders each one as a separate <StreamingText>
122
- component in a Box with gap={1}, causing unwanted spacing.
123
-
124
- The fix should be to merge consecutive text blocks together. Let me write a test first to
125
- demonstrate the problem:
126
-
127
- Read ../src/components/EventDisplay.test.tsx
128
-
129
- Now let me add a test that demonstrates the inline code block problem and then fix it:
130
-
131
- Edit ../src/components/EventDisplay.test.tsx
132
-
133
- Now let me run the test to confirm it fails (demonstrating the problem):
134
-
135
- $ pnpm test EventDisplay.test.tsx
136
-
137
- Perfect! The test fails as expected, confirming the bug. Now I need to fix it by modifying
138
- eventToBlocks to merge consecutive text blocks:
139
-
140
- Edit ../src/components/eventToBlocks.ts
141
-
142
- Now I need to also flush the text buffer at the end of the loop:
143
-
144
- Edit ../src/components/eventToBlocks.ts
145
-
146
- Now let me run the tests again to verify the fix works:
147
-
148
- $ pnpm test EventDisplay.test.tsx
149
-
150
- The test still fails. This suggests the problem might also be in EventDisplay, not just
151
- eventToBlocks. Let me debug by adding a simpler test to see what's happening in eventToBlocks:
152
-
153
- Read ../src/components/eventToBlocks.test.ts
154
-
155
- I see! The existing test "extracts multiple text blocks" expects them NOT to be merged. I need to
156
- update this test and add a new one specifically for consecutive text blocks:
157
-
158
- Edit ../src/components/eventToBlocks.test.ts
159
-
160
- Now let me add a test for text blocks separated by tool calls:
161
-
162
- Read ../src/components/eventToBlocks.test.ts
163
-
164
- Let me add a test that specifically checks text blocks separated by tool calls:
165
-
166
- Edit ../src/components/eventToBlocks.test.ts
167
-
168
- Now let me run all tests to verify my changes to eventToBlocks work:
169
-
170
- $ pnpm test eventToBlocks.test.ts
171
-
172
- I need to look at this failing test:
173
-
174
- Read ../src/components/eventToBlocks.test.ts
175
-
176
- This test expects 3 separate IDs for 3 text blocks, but my code now merges them into 1. I need to
177
- update this test to reflect the new behavior:
178
-
179
- Edit ../src/components/eventToBlocks.test.ts
180
-
181
- Now let me run the eventToBlocks tests again:
182
-
183
- $ pnpm test eventToBlocks.test.ts
184
-
185
- Great! Now let me run the EventDisplay test again:
186
-
187
- $ pnpm test EventDisplay.test.tsx
188
-
189
- The problem is still happening at the EventDisplay level. Let me check what's actually being
190
- rendered. The issue must be in how EventDisplay merges the events. Let me look more carefully at the
191
- EventDisplay logic:
192
-
193
- Read ../src/components/EventDisplay.tsx
194
-
195
- I see! The EventDisplay is doing its own deduplication, but it's NOT merging consecutive text
196
- blocks. The text blocks in the test data remain separate even after eventToBlocks merges them,
197
- because my test is creating a single event with 3 separate text blocks in content.
198
-
199
- Wait, let me re-check the flow. EventDisplay calls eventToBlocks on each merged event. So if
200
- eventToBlocks correctly merges text blocks, then EventDisplay should get a single merged text block.
201
- Let me debug by adding a console log or looking at what's actually happening.
202
-
203
- Let me write a simpler test to see what's going on:
204
-
205
- $ cat > test-merge.ts << 'EOF'
206
- import { eventToBlocks } from "./src/components/eventToBlocks.js"
207
-
208
- const event = {
209
- type: "assistant",
210
- message: {
211
- id: "msg_123",
212
- content: [
213
- { type: "text", text: "Use the " },
214
- { type: "text", text: "\`console.log()\`" },
215
- { type: "text", text: " function to debug." },
216
- ],
217
- },
218
- }
219
-
220
- const result = eventToBlocks(event)
221
- console.log("Result:", JSON.stringify(result, null, 2))
222
- EOF
223
- tsx test-merge.ts
224
-
225
- Let me check if my fix is actually working by looking at the eventToBlocks implementation more
226
- carefully. Actually, let me just trace through what should happen:
227
-
228
- 1. eventToBlocks receives an event with 3 text blocks
229
- 2. It loops through content
230
- 3. First text block: adds "Use the " to textBuffer
231
- 4. Second text block: adds "console.log()" to textBuffer (now "Use the console.log()")
232
- 5. Third text block: adds " function to debug." to textBuffer (now "Use the console.log() function
233
- to debug.")
234
- 6. After the loop, it flushes the textBuffer as one merged text block
235
-
236
- That should work! Let me check if there's an issue with my implementation. Let me re-read the code:
237
-
238
- Read ../src/components/eventToBlocks.ts
239
-
240
- The code looks correct. Let me check if the EventDisplay is receiving the correct merged content. I
241
- think the issue might be in how EventDisplay deduplicates and merges content before calling
242
- eventToBlocks. Let me look at that logic again:
243
-
244
- Read ../src/components/EventDisplay.tsx
245
-
246
- Ah! I see the problem now. In the test, we're providing a single event with one message containing 3
247
- text blocks. EventDisplay keeps the text blocks separate in uniqueContent (lines 36-54), so they
248
- stay as 3 separate blocks before being passed to eventToBlocks. Then eventToBlocks merges them. But
249
- there's still the Box with gap={1} that creates spacing.
250
-
251
- Wait, actually looking at the logic again - eventToBlocks should merge them, and return a single
252
- ContentBlock. Then that single block gets rendered as a single <StreamingText> component. So there
253
- should be no gaps.
254
-
255
- Let me add some logging to see what's actually happening. But actually, I think the problem is that
256
- the test is checking for newlines in the output. Ink's Box with flexDirection="column" adds newlines
257
- between elements. So even if I have 1 StreamingText, the Box might still add newlines around it.
258
-
259
- Actually wait - if eventToBlocks returns 1 block, then there's only 1 child in the Box, so there
260
- should be no gaps. Let me trace through more carefully what the test is doing:
261
-
262
- In the test, we render <EventDisplay events={[...]} />. The EventDisplay:
263
- 1. Filters to assistant messages
264
- 2. Merges by message ID (only 1 message)
265
- 3. Deduplicates (all 3 text blocks are unique)
266
- 4. Calls eventToBlocks on the merged event
267
- 5. eventToBlocks should merge the 3 text blocks into 1
268
- 6. Renders the blocks
269
-
270
- Let me print what lastFrame() actually returns by modifying the test temporarily:
271
-
272
- Edit ../src/components/EventDisplay.test.tsx
273
-
274
- $ pnpm test EventDisplay.test.tsx 2>&1 | grep -A 20 "merges consecutive"
275
-
276
- Aha! The output is "Use the\\n\\nconsole.log()\\n\\n function to debug." - there are TWO newlines
277
- between each part! This tells me that the 3 text blocks are NOT being merged by eventToBlocks.
278
- They're still coming through as 3 separate parts.
279
-
280
- This means the EventDisplay deduplication logic is keeping them separate, OR there's a bug in my
281
- eventToBlocks implementation. Let me add logging to eventToBlocks to see:
282
-
283
- Edit ../src/components/eventToBlocks.ts
284
-
285
- $ pnpm test EventDisplay.test.tsx 2>&1 | grep -A 30 "eventToBlocks content"
286
-
287
- Perfect! So eventToBlocks IS receiving the 3 separate text blocks:
288
- json
289
- [
290
- { "type": "text", "text": "Use the " },
291
- { "type": "text", "text": "console.log()" },
292
- { "type": "text", "text": " function to debug." }
293
- ]
294
-
295
-
296
- But the output still shows them on 3 separate lines. This means my merging logic isn't working. Let
297
- me add more logging to see what's happening in the loop:
298
-
299
- Edit ../src/components/eventToBlocks.ts
300
-
301
- Edit ../src/components/eventToBlocks.ts
302
-
303
- $ pnpm test EventDisplay.test.tsx 2>&1 | grep -A 50 "merges consecutive text blocks to prevent
304
- unwanted gaps"
305
-
306
- EXCELLENT! The merging IS working correctly:
307
- - eventToBlocks returns: [{ "type": "text", "content": "Use the console.log() function to debug.",
308
- "id": "msg_123-0" }]
309
-
310
- But the output is still: "Use the\\n\\nconsole.log()\\n\\n function to debug."
311
-
312
- This means the problem is in how StreamingText is rendering! The backticks in the merged text are
313
- being split up by StreamingText's markdown processing. Let me check the StreamingText component
314
- logic again - it must be detecting the backticks and rendering them as separate Text components, and
315
- those are getting newlines between them!
316
-
317
- Oh wait, I see it now! Look at EventDisplay:69-76:
318
-
319
- tsx
320
- <Box flexDirection="column" gap={1}>
321
- {contentBlocks.map(block =>
322
- block.type === "text" ?
323
- <StreamingText key={block.id} content={block.content} />
324
- : <ToolUse key={block.id} name={block.name} arg={block.arg} />,
325
- )}
326
- </Box>
327
-
328
-
329
- The Box has gap={1}, which adds gaps between CHILDREN. StreamingText renders multiple <Text>
330
- components (one for each formatted segment), and those become CHILDREN of the parent, not siblings.
331
- Wait, no - StreamingText returns a fragment <>...</> containing multiple Text components.
332
-
333
- Actually, I think the issue is that Ink is rendering the separate Text components with gaps. Let me
334
- check StreamingText more carefully - it returns a fragment with separate Text components. Those Text
335
- components might be getting wrapped or treated differently by Ink.
336
-
337
- Actually, I think the real fix is to render StreamingText as inline, not in a column layout. But
338
- wait, the Box flexDirection="column" affects the layout of contentBlocks (Text vs ToolUse), not the
339
- internal layout of StreamingText.
340
-
341
- Let me check if the problem is in how StreamingText uses fragments. When you return a fragment with
342
- multiple <Text> components in Ink, they might be rendered on separate lines. Let me check:
343
-
344
- Read ../src/components/StreamingText.tsx
345
-
346
- The issue is that StreamingText returns a fragment with multiple <Text> components. In Ink, these
347
- might be rendered as separate blocks. The fix is to wrap them in a single <Text> component or use
348
- the <Text wrap="wrap"> with inline rendering.
349
-
350
- Let me look at how Ink handles multiple Text components. Actually, the fix is simple - wrap all the
351
- text parts in a single Box or Text component with inline rendering:
352
-
353
- Edit ../src/components/StreamingText.tsx
354
-
355
- Edit ../src/components/StreamingText.tsx
356
-
357
- Now let me remove the console.log statements and test:
358
-
359
- Edit ../src/components/eventToBlocks.ts
360
-
361
- Edit ../src/components/eventToBlocks.ts
362
-
363
- Edit ../src/components/EventDisplay.test.tsx
364
-
365
- Now let me run all tests:
366
-
367
- $ pnpm test
368
-
369
- Perfect! All tests pass now. Let me verify the build still works:
370
-
371
- $ pnpm build
372
-
373
- Excellent! Now let me update the todo list and progress file, then commit:
374
-
375
- Read ../.ralph/todo.md
376
-
377
- Edit ../.ralph/todo.md
378
-
379
- Read ../.ralph/progress.md
380
-
381
- Edit ../.ralph/progress.md
382
-
383
- Now let me format the code with Prettier:
384
-
385
- $ pnpm format
386
-
387
- Good! Now let me commit all these changes:
388
-
389
- $ git add -A && git diff --cached --stat
390
-
391
- $ git commit -m "$(cat <<'EOF'
392
- Fix inline code blocks appearing in separate paragraphs
393
-
394
- - Modified eventToBlocks.ts to merge consecutive text blocks using a textBuffer
395
- - Wrapped StreamingText content in Box component for proper inline rendering
396
- - Added test case to verify consecutive text blocks are merged
397
- - Updated existing tests to reflect new merging behavior
398
-
399
- Fixes issue where inline code like \`console.log()\` was rendered on separate
400
- lines with gaps instead of flowing inline with surrounding text.
401
-
402
- Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
403
- EOF
404
- )"
405
-
406
- Perfect! Let me verify git status:
407
-
408
- $ git status
409
- "
410
- `);
411
- });
412
- });
413
- //# sourceMappingURL=EventDisplay.replay.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EventDisplay.replay.test.js","sourceRoot":"","sources":["../../src/components/EventDisplay.replay.test.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEhD;;GAEG;AACH,KAAK,UAAU,MAAM,CAAC,OAAe;IACnC,qBAAqB;IACrB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,iBAAiB,EAAE,OAAO,CAAC,CAAA;IAC/D,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAEjD,uEAAuE;IACvE,MAAM,MAAM,GAAmC,EAAE,CAAA;IACjD,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IAC5C,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;QAClC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;YAAE,SAAQ;QAC7B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YACjC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,oBAAoB;QACtB,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAC1B,oBAAC,YAAY,IAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,mBAAmB,EAAE,EAAE,GAAI,CACxE,CAAA;IAED,qBAAqB;IACrB,MAAM,EAAE,CAAC,OAAO,CACd,GAAG,EAAE;QACH,MAAM,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,CAAA;QAChC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;IAC1C,CAAC,EACD,EAAE,OAAO,EAAE,IAAI,EAAE,CAClB,CAAA;IAED,OAAO,SAAS,EAAE,IAAI,EAAE,CAAA;AAC1B,CAAC;AAED,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,eAAe,EAAE,KAAK,IAAI,EAAE;QAC7B,MAAM,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgCnD,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,eAAe,EAAE,KAAK,IAAI,EAAE;QAC7B,MAAM,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgVnD,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=EventDisplay.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EventDisplay.test.d.ts","sourceRoot":"","sources":["../../src/components/EventDisplay.test.tsx"],"names":[],"mappings":""}