brainrot-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/README.md +372 -0
  2. package/dist/AchievementNotification.d.ts +28 -0
  3. package/dist/AchievementNotification.d.ts.map +1 -0
  4. package/dist/AchievementNotification.js +74 -0
  5. package/dist/AchievementNotification.js.map +1 -0
  6. package/dist/GameSelector.d.ts +25 -0
  7. package/dist/GameSelector.d.ts.map +1 -0
  8. package/dist/GameSelector.js +105 -0
  9. package/dist/GameSelector.js.map +1 -0
  10. package/dist/HelpOverlay.d.ts +15 -0
  11. package/dist/HelpOverlay.d.ts.map +1 -0
  12. package/dist/HelpOverlay.js +134 -0
  13. package/dist/HelpOverlay.js.map +1 -0
  14. package/dist/Layout.d.ts +49 -0
  15. package/dist/Layout.d.ts.map +1 -0
  16. package/dist/Layout.js +83 -0
  17. package/dist/Layout.js.map +1 -0
  18. package/dist/Leaderboard.d.ts +46 -0
  19. package/dist/Leaderboard.d.ts.map +1 -0
  20. package/dist/Leaderboard.js +68 -0
  21. package/dist/Leaderboard.js.map +1 -0
  22. package/dist/LogViewer.d.ts +33 -0
  23. package/dist/LogViewer.d.ts.map +1 -0
  24. package/dist/LogViewer.js +179 -0
  25. package/dist/LogViewer.js.map +1 -0
  26. package/dist/LoopAlertOverlay.d.ts +15 -0
  27. package/dist/LoopAlertOverlay.d.ts.map +1 -0
  28. package/dist/LoopAlertOverlay.js +17 -0
  29. package/dist/LoopAlertOverlay.js.map +1 -0
  30. package/dist/LoopManagementPanel.d.ts +44 -0
  31. package/dist/LoopManagementPanel.d.ts.map +1 -0
  32. package/dist/LoopManagementPanel.js +220 -0
  33. package/dist/LoopManagementPanel.js.map +1 -0
  34. package/dist/SettingsMenu.d.ts +22 -0
  35. package/dist/SettingsMenu.d.ts.map +1 -0
  36. package/dist/SettingsMenu.js +367 -0
  37. package/dist/SettingsMenu.js.map +1 -0
  38. package/dist/SplitPane.d.ts +63 -0
  39. package/dist/SplitPane.d.ts.map +1 -0
  40. package/dist/SplitPane.js +104 -0
  41. package/dist/SplitPane.js.map +1 -0
  42. package/dist/StatsMenu.d.ts +15 -0
  43. package/dist/StatsMenu.d.ts.map +1 -0
  44. package/dist/StatsMenu.js +230 -0
  45. package/dist/StatsMenu.js.map +1 -0
  46. package/dist/StatusBar.d.ts +58 -0
  47. package/dist/StatusBar.d.ts.map +1 -0
  48. package/dist/StatusBar.js +106 -0
  49. package/dist/StatusBar.js.map +1 -0
  50. package/dist/__tests__/ralph-loop-parser.test.d.ts +2 -0
  51. package/dist/__tests__/ralph-loop-parser.test.d.ts.map +1 -0
  52. package/dist/__tests__/ralph-loop-parser.test.js +143 -0
  53. package/dist/__tests__/ralph-loop-parser.test.js.map +1 -0
  54. package/dist/claude-code-process.d.ts +76 -0
  55. package/dist/claude-code-process.d.ts.map +1 -0
  56. package/dist/claude-code-process.js +221 -0
  57. package/dist/claude-code-process.js.map +1 -0
  58. package/dist/cli.d.ts +42 -0
  59. package/dist/cli.d.ts.map +1 -0
  60. package/dist/cli.js +265 -0
  61. package/dist/cli.js.map +1 -0
  62. package/dist/config.d.ts +206 -0
  63. package/dist/config.d.ts.map +1 -0
  64. package/dist/config.js +270 -0
  65. package/dist/config.js.map +1 -0
  66. package/dist/game-types.d.ts +177 -0
  67. package/dist/game-types.d.ts.map +1 -0
  68. package/dist/game-types.js +55 -0
  69. package/dist/game-types.js.map +1 -0
  70. package/dist/games/MinesweeperGame.d.ts +15 -0
  71. package/dist/games/MinesweeperGame.d.ts.map +1 -0
  72. package/dist/games/MinesweeperGame.js +555 -0
  73. package/dist/games/MinesweeperGame.js.map +1 -0
  74. package/dist/games/PongGame.d.ts +15 -0
  75. package/dist/games/PongGame.d.ts.map +1 -0
  76. package/dist/games/PongGame.js +379 -0
  77. package/dist/games/PongGame.js.map +1 -0
  78. package/dist/games/SnakeGame.d.ts +15 -0
  79. package/dist/games/SnakeGame.d.ts.map +1 -0
  80. package/dist/games/SnakeGame.js +333 -0
  81. package/dist/games/SnakeGame.js.map +1 -0
  82. package/dist/games/TetrisGame.d.ts +15 -0
  83. package/dist/games/TetrisGame.d.ts.map +1 -0
  84. package/dist/games/TetrisGame.js +654 -0
  85. package/dist/games/TetrisGame.js.map +1 -0
  86. package/dist/games/index.d.ts +23 -0
  87. package/dist/games/index.d.ts.map +1 -0
  88. package/dist/games/index.js +47 -0
  89. package/dist/games/index.js.map +1 -0
  90. package/dist/high-scores.d.ts +57 -0
  91. package/dist/high-scores.d.ts.map +1 -0
  92. package/dist/high-scores.js +230 -0
  93. package/dist/high-scores.js.map +1 -0
  94. package/dist/index.d.ts +3 -0
  95. package/dist/index.d.ts.map +1 -0
  96. package/dist/index.js +264 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/ralph-loop-parser.d.ts +58 -0
  99. package/dist/ralph-loop-parser.d.ts.map +1 -0
  100. package/dist/ralph-loop-parser.js +315 -0
  101. package/dist/ralph-loop-parser.js.map +1 -0
  102. package/dist/stats.d.ts +142 -0
  103. package/dist/stats.d.ts.map +1 -0
  104. package/dist/stats.js +521 -0
  105. package/dist/stats.js.map +1 -0
  106. package/dist/styled-components.d.ts +231 -0
  107. package/dist/styled-components.d.ts.map +1 -0
  108. package/dist/styled-components.js +192 -0
  109. package/dist/styled-components.js.map +1 -0
  110. package/dist/theme.d.ts +301 -0
  111. package/dist/theme.d.ts.map +1 -0
  112. package/dist/theme.js +372 -0
  113. package/dist/theme.js.map +1 -0
  114. package/dist/themes.d.ts +117 -0
  115. package/dist/themes.d.ts.map +1 -0
  116. package/dist/themes.js +296 -0
  117. package/dist/themes.js.map +1 -0
  118. package/dist/ui/index.d.ts +13 -0
  119. package/dist/ui/index.d.ts.map +1 -0
  120. package/dist/ui/index.js +29 -0
  121. package/dist/ui/index.js.map +1 -0
  122. package/dist/use-claude-code.d.ts +30 -0
  123. package/dist/use-claude-code.d.ts.map +1 -0
  124. package/dist/use-claude-code.js +84 -0
  125. package/dist/use-claude-code.js.map +1 -0
  126. package/dist/use-config.d.ts +58 -0
  127. package/dist/use-config.d.ts.map +1 -0
  128. package/dist/use-config.js +113 -0
  129. package/dist/use-config.js.map +1 -0
  130. package/dist/use-game-loop.d.ts +47 -0
  131. package/dist/use-game-loop.d.ts.map +1 -0
  132. package/dist/use-game-loop.js +136 -0
  133. package/dist/use-game-loop.js.map +1 -0
  134. package/dist/use-high-scores.d.ts +41 -0
  135. package/dist/use-high-scores.d.ts.map +1 -0
  136. package/dist/use-high-scores.js +94 -0
  137. package/dist/use-high-scores.js.map +1 -0
  138. package/dist/use-layout-state.d.ts +77 -0
  139. package/dist/use-layout-state.d.ts.map +1 -0
  140. package/dist/use-layout-state.js +160 -0
  141. package/dist/use-layout-state.js.map +1 -0
  142. package/dist/use-ralph-loop.d.ts +41 -0
  143. package/dist/use-ralph-loop.d.ts.map +1 -0
  144. package/dist/use-ralph-loop.js +106 -0
  145. package/dist/use-ralph-loop.js.map +1 -0
  146. package/dist/use-spinner.d.ts +46 -0
  147. package/dist/use-spinner.d.ts.map +1 -0
  148. package/dist/use-spinner.js +71 -0
  149. package/dist/use-spinner.js.map +1 -0
  150. package/dist/use-stats.d.ts +59 -0
  151. package/dist/use-stats.d.ts.map +1 -0
  152. package/dist/use-stats.js +150 -0
  153. package/dist/use-stats.js.map +1 -0
  154. package/dist/use-terminal-size.d.ts +29 -0
  155. package/dist/use-terminal-size.d.ts.map +1 -0
  156. package/dist/use-terminal-size.js +48 -0
  157. package/dist/use-terminal-size.js.map +1 -0
  158. package/dist/useTheme.d.ts +76 -0
  159. package/dist/useTheme.d.ts.map +1 -0
  160. package/dist/useTheme.js +136 -0
  161. package/dist/useTheme.js.map +1 -0
  162. package/package.json +58 -0
package/dist/index.js ADDED
@@ -0,0 +1,264 @@
1
+ #!/usr/bin/env node
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { render, Box, Text, useInput, useApp } from "ink";
4
+ import { useState, useCallback, useMemo, useEffect, createContext, useContext } from "react";
5
+ import { useClaudeCode } from "./use-claude-code.js";
6
+ import { useRalphLoopWithClaudeOutput } from "./use-ralph-loop.js";
7
+ import { Layout, useTerminalSize } from "./Layout.js";
8
+ import { LoopManagementPanel } from "./LoopManagementPanel.js";
9
+ import { LogViewer } from "./LogViewer.js";
10
+ import { GameSelector } from "./GameSelector.js";
11
+ import { SettingsMenu } from "./SettingsMenu.js";
12
+ import { StatsMenu } from "./StatsMenu.js";
13
+ import { useAchievementNotifications } from "./AchievementNotification.js";
14
+ import { getGameList, getGameById } from "./games/index.js";
15
+ import { useConfig } from "./use-config.js";
16
+ import { getLayoutOptions, getClaudeCodeOptions, deepMerge, saveConfig } from "./config.js";
17
+ import { parseCLI, printHelp, printVersion, printError } from "./cli.js";
18
+ import { recordSessionStart } from "./stats.js";
19
+ import { ThemeProvider, useThemeColors } from "./useTheme.js";
20
+ import { StatusBar, GameStatusProvider, useGameStatus } from "./StatusBar.js";
21
+ import { HelpOverlay } from "./HelpOverlay.js";
22
+ // ============================================================================
23
+ // CLI OVERRIDE CONTEXT
24
+ // ============================================================================
25
+ /**
26
+ * Context for passing CLI overrides to the app
27
+ */
28
+ const CLIOverridesContext = createContext({});
29
+ /**
30
+ * Hook to access CLI overrides
31
+ */
32
+ function useCLIOverrides() {
33
+ return useContext(CLIOverridesContext);
34
+ }
35
+ /** Game area with mode switching between menu, logs, settings, stats, and active game */
36
+ function GameArea({ logs, hasFocus, dimensions, loopAttention, onLoopAlertDismiss, config, onConfigChange, onConfigSave, onAchievementUnlock: _onAchievementUnlock, onGameStateChange, }) {
37
+ const [mode, setMode] = useState("menu");
38
+ const [selectedGameId, setSelectedGameId] = useState(null);
39
+ const colors = useThemeColors();
40
+ const { setGameState, clearGameState } = useGameStatus();
41
+ const games = useMemo(() => getGameList(), []);
42
+ const handleSelectGame = useCallback((gameId) => {
43
+ setSelectedGameId(gameId);
44
+ setMode("game");
45
+ // Set game name in status bar
46
+ const gameInfo = getGameById(gameId);
47
+ if (gameInfo) {
48
+ setGameState({ gameId, gameName: gameInfo.info.name });
49
+ }
50
+ }, [setGameState]);
51
+ const handleExitGame = useCallback(() => {
52
+ setSelectedGameId(null);
53
+ setMode("menu");
54
+ // Clear game state from status bar
55
+ clearGameState();
56
+ }, [clearGameState]);
57
+ const handleCloseSettings = useCallback(() => {
58
+ setMode("menu");
59
+ }, []);
60
+ const handleOpenStats = useCallback(() => {
61
+ setMode("stats");
62
+ }, []);
63
+ const handleCloseStats = useCallback(() => {
64
+ setMode("menu");
65
+ }, []);
66
+ // Handle mode switching with keyboard
67
+ useInput((input, key) => {
68
+ if (!hasFocus)
69
+ return;
70
+ // Ctrl+, to open settings (from menu only)
71
+ if (key.ctrl && input === "," && mode === "menu") {
72
+ setMode("settings");
73
+ return;
74
+ }
75
+ // 'L' to switch to logs view
76
+ if ((input === "l" || input === "L") && mode !== "game" && mode !== "settings" && mode !== "stats") {
77
+ setMode(mode === "logs" ? "menu" : "logs");
78
+ return;
79
+ }
80
+ // 'Q' or Escape to go back to menu from logs
81
+ if ((input === "q" || input === "Q") && mode === "logs") {
82
+ setMode("menu");
83
+ return;
84
+ }
85
+ }, { isActive: hasFocus && mode !== "game" && mode !== "settings" && mode !== "stats" });
86
+ // Render based on current mode
87
+ if (mode === "logs") {
88
+ return (_jsxs(Box, { flexDirection: "column", height: "100%", children: [_jsxs(Box, { paddingX: 1, marginBottom: 1, children: [_jsx(Text, { bold: true, color: colors.primary, children: "Live Logs" }), _jsx(Text, { dimColor: true, children: " | L: Back to Games | Q: Menu" })] }), _jsx(LogViewer, { logs: logs, hasFocus: hasFocus, initialViewMode: "condensed" })] }));
89
+ }
90
+ if (mode === "settings") {
91
+ return (_jsx(SettingsMenu, { config: config, hasFocus: hasFocus, onConfigChange: onConfigChange, onSave: onConfigSave, onClose: handleCloseSettings }));
92
+ }
93
+ if (mode === "stats") {
94
+ return (_jsx(StatsMenu, { hasFocus: hasFocus, onClose: handleCloseStats }));
95
+ }
96
+ if (mode === "game" && selectedGameId) {
97
+ const gameEntry = getGameById(selectedGameId);
98
+ if (gameEntry) {
99
+ const GameComponent = gameEntry.component;
100
+ return (_jsx(GameComponent, { hasFocus: hasFocus, dimensions: dimensions, onExit: handleExitGame, loopAttention: loopAttention, onLoopAlertDismiss: onLoopAlertDismiss, onGameStateChange: onGameStateChange }));
101
+ }
102
+ }
103
+ // Default: show game selector menu
104
+ return (_jsxs(Box, { flexDirection: "column", height: "100%", children: [_jsx(GameSelector, { games: games, hasFocus: hasFocus, dimensions: dimensions, onSelectGame: handleSelectGame, onOpenStats: handleOpenStats }), _jsx(Box, { paddingX: 1, children: _jsx(Text, { dimColor: true, children: "L: View Logs | Ctrl+,: Settings" }) })] }));
105
+ }
106
+ /** Header component */
107
+ function Header() {
108
+ const colors = useThemeColors();
109
+ return (_jsxs(Box, { borderStyle: "round", borderColor: colors.primary, paddingX: 2, children: [_jsx(Text, { bold: true, color: colors.primary, children: "BRAINROT CLI" }), _jsx(Text, { children: " - " }), _jsx(Text, { children: "Play games while Claude Code works" })] }));
110
+ }
111
+ /** Status bar footer - needs to be inside GameStatusProvider */
112
+ function StatusBarFooter({ loopStatus, needsAttention }) {
113
+ return (_jsx(StatusBar, { loopStatus: loopStatus, needsAttention: needsAttention, condensed: true }));
114
+ }
115
+ function AppContent() {
116
+ const { exit } = useApp();
117
+ const { config: fileConfig } = useConfig();
118
+ const cliOverrides = useCLIOverrides();
119
+ const { addAchievements, NotificationComponent, hasNotifications } = useAchievementNotifications();
120
+ // Local config state for live preview (before saving)
121
+ const [localConfigOverrides, setLocalConfigOverrides] = useState({});
122
+ // Record session start on mount
123
+ useEffect(() => {
124
+ void recordSessionStart();
125
+ }, []);
126
+ // Merge: file config -> local overrides -> CLI overrides (CLI takes precedence)
127
+ const config = useMemo(() => deepMerge(deepMerge(fileConfig, localConfigOverrides), cliOverrides), [fileConfig, localConfigOverrides, cliOverrides]);
128
+ // Handle config changes from settings menu (immediate preview)
129
+ const handleConfigChange = useCallback((updates) => {
130
+ setLocalConfigOverrides((prev) => deepMerge(prev, updates));
131
+ }, []);
132
+ // Handle saving config to disk
133
+ const handleConfigSave = useCallback(async () => {
134
+ // Merge current file config with local overrides and save
135
+ const configToSave = deepMerge(fileConfig, localConfigOverrides);
136
+ await saveConfig(configToSave);
137
+ // Clear local overrides since they're now persisted
138
+ setLocalConfigOverrides({});
139
+ }, [fileConfig, localConfigOverrides]);
140
+ // Get config-derived options
141
+ const layoutOptions = useMemo(() => getLayoutOptions(config), [config]);
142
+ const claudeCodeOptions = useMemo(() => getClaudeCodeOptions(config), [config]);
143
+ const { status, output, spawn, stop } = useClaudeCode(claudeCodeOptions);
144
+ const [focusedPane, setFocusedPane] = useState(0);
145
+ const [loopAlertDismissed, setLoopAlertDismissed] = useState(false);
146
+ const [showHelpOverlay, setShowHelpOverlay] = useState(false);
147
+ const terminalSize = useTerminalSize();
148
+ // Use Ralph loop parsing for the output
149
+ const ralphLoop = useRalphLoopWithClaudeOutput(output);
150
+ // Calculate game area dimensions (accounting for layout chrome)
151
+ const gameDimensions = useMemo(() => {
152
+ // Account for header (3), footer (2), help (1), borders, and split pane divider
153
+ const availableHeight = Math.max(terminalSize.height - 8, 10);
154
+ const availableWidth = Math.max(Math.floor(terminalSize.width * 0.5) - 4, 20);
155
+ return { width: availableWidth, height: availableHeight };
156
+ }, [terminalSize.width, terminalSize.height]);
157
+ // Create loop attention object for games
158
+ const loopAttention = useMemo(() => ({
159
+ needsAttention: ralphLoop.needsAttention && !loopAlertDismissed,
160
+ reason: ralphLoop.state.userAttention.reason,
161
+ type: ralphLoop.state.userAttention.type,
162
+ prompt: ralphLoop.state.userAttention.prompt,
163
+ }), [ralphLoop.needsAttention, ralphLoop.state.userAttention, loopAlertDismissed]);
164
+ // Reset dismiss state when attention changes
165
+ const handleLoopAlertDismiss = useCallback(() => {
166
+ setLoopAlertDismissed(true);
167
+ }, []);
168
+ // Toggle help overlay
169
+ const handleToggleHelp = useCallback(() => {
170
+ setShowHelpOverlay((prev) => !prev);
171
+ }, []);
172
+ // Close help overlay
173
+ const handleCloseHelp = useCallback(() => {
174
+ setShowHelpOverlay(false);
175
+ }, []);
176
+ // Reset dismiss state when a new attention request comes in
177
+ useEffect(() => {
178
+ if (ralphLoop.needsAttention) {
179
+ setLoopAlertDismissed(false);
180
+ }
181
+ }, [ralphLoop.needsAttention, ralphLoop.state.userAttention.reason, ralphLoop.state.userAttention.prompt]);
182
+ useInput((input, key) => {
183
+ // Ctrl+C always works to exit
184
+ if (key.ctrl && input === "c") {
185
+ void stop().then(() => exit());
186
+ return;
187
+ }
188
+ // Help overlay toggle with ? key (works globally)
189
+ if (input === "?") {
190
+ handleToggleHelp();
191
+ return;
192
+ }
193
+ // When help overlay is shown, only handle escape and ? to close
194
+ if (showHelpOverlay) {
195
+ if (key.escape) {
196
+ handleCloseHelp();
197
+ }
198
+ return;
199
+ }
200
+ if (key.ctrl && input === "s") {
201
+ // Toggle start/stop with Ctrl+S
202
+ if (status === "idle" || status === "stopped" || status === "crashed") {
203
+ spawn();
204
+ }
205
+ else if (status === "running") {
206
+ void stop();
207
+ }
208
+ return;
209
+ }
210
+ // Track focus changes via Tab key
211
+ if (key.tab) {
212
+ setFocusedPane((current) => (current === 0 ? 1 : 0));
213
+ return;
214
+ }
215
+ });
216
+ // Handler for game state updates from games
217
+ const { setGameState } = useGameStatus();
218
+ const handleGameStateChange = useCallback((update) => {
219
+ setGameState(update);
220
+ }, [setGameState]);
221
+ // Determine effective loop status for status bar
222
+ const effectiveLoopStatus = useMemo(() => {
223
+ // If process is running, use ralph loop status, otherwise use process status
224
+ if (status === "running") {
225
+ return ralphLoop.state.status;
226
+ }
227
+ return status;
228
+ }, [status, ralphLoop.state.status]);
229
+ return (_jsxs(ThemeProvider, { config: config, children: [showHelpOverlay && (_jsx(Box, { position: "absolute", marginTop: 1, marginLeft: 2, children: _jsx(HelpOverlay, { hasFocus: showHelpOverlay, onClose: handleCloseHelp }) })), hasNotifications && (_jsx(Box, { position: "absolute", marginTop: 3, marginLeft: 5, children: NotificationComponent })), _jsx(Layout, { gameArea: _jsx(GameArea, { logs: output, hasFocus: focusedPane === 0 && !showHelpOverlay, dimensions: gameDimensions, loopAttention: loopAttention, onLoopAlertDismiss: handleLoopAlertDismiss, config: config, onConfigChange: handleConfigChange, onConfigSave: handleConfigSave, onAchievementUnlock: addAchievements, onGameStateChange: handleGameStateChange }), managementArea: _jsx(LoopManagementPanel, { loopState: ralphLoop.state, needsAttention: ralphLoop.needsAttention, statusMessage: ralphLoop.statusMessage, progressString: ralphLoop.progressString, processStatus: status, onStart: spawn, onStop: () => void stop() }), gameTitle: "Games", managementTitle: "Loop Management", header: _jsx(Header, {}), footer: _jsx(StatusBarFooter, { loopStatus: effectiveLoopStatus, needsAttention: ralphLoop.needsAttention }), layoutOptions: layoutOptions, handleInput: !showHelpOverlay })] }));
230
+ }
231
+ /** App wrapper that provides GameStatusProvider context */
232
+ function App() {
233
+ return (_jsx(GameStatusProvider, { children: _jsx(AppContent, {}) }));
234
+ }
235
+ // ============================================================================
236
+ // CLI PARSING AND STARTUP
237
+ // ============================================================================
238
+ /**
239
+ * Main entry point - parses CLI args and renders the app
240
+ */
241
+ function main() {
242
+ // Parse CLI arguments
243
+ const { args, error } = parseCLI();
244
+ // Handle parsing errors
245
+ if (error) {
246
+ printError(error);
247
+ process.exit(1);
248
+ }
249
+ // Handle --help flag
250
+ if (args.help) {
251
+ printHelp();
252
+ process.exit(0);
253
+ }
254
+ // Handle --version flag
255
+ if (args.version) {
256
+ printVersion();
257
+ process.exit(0);
258
+ }
259
+ // Render the app with CLI overrides
260
+ render(_jsx(CLIOverridesContext.Provider, { value: args.overrides, children: _jsx(App, {}) }));
261
+ }
262
+ // Run main
263
+ main();
264
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Ralph Loop Status Parser
3
+ *
4
+ * Parses Claude Code output to extract Ralph loop status information
5
+ * for display in the UI.
6
+ */
7
+ export type RalphLoopStatus = "idle" | "running" | "paused" | "completed" | "errored" | "waiting_for_input";
8
+ export interface RalphLoopProgress {
9
+ currentStep: number;
10
+ totalSteps: number | null;
11
+ percentage: number | null;
12
+ description: string | null;
13
+ }
14
+ export interface AgentActivity {
15
+ isActive: boolean;
16
+ currentAction: string | null;
17
+ toolName: string | null;
18
+ timestamp: Date;
19
+ }
20
+ export interface UserAttentionNeeded {
21
+ needed: boolean;
22
+ reason: string | null;
23
+ type: "question" | "confirmation" | "error" | "permission" | null;
24
+ prompt: string | null;
25
+ }
26
+ export interface RalphLoopState {
27
+ status: RalphLoopStatus;
28
+ progress: RalphLoopProgress;
29
+ agentActivity: AgentActivity;
30
+ userAttention: UserAttentionNeeded;
31
+ lastUpdated: Date;
32
+ rawOutput: string | null;
33
+ }
34
+ /**
35
+ * Creates an initial/default Ralph loop state
36
+ */
37
+ export declare function createInitialState(): RalphLoopState;
38
+ /**
39
+ * Main parser function - parses a single output chunk and updates state
40
+ */
41
+ export declare function parseOutput(output: string, currentState: RalphLoopState): RalphLoopState;
42
+ /**
43
+ * Parse multiple output lines and return accumulated state
44
+ */
45
+ export declare function parseOutputLines(outputs: string[], initialState?: RalphLoopState): RalphLoopState;
46
+ /**
47
+ * Check if the loop needs user attention
48
+ */
49
+ export declare function needsUserAttention(state: RalphLoopState): boolean;
50
+ /**
51
+ * Get a human-readable status message
52
+ */
53
+ export declare function getStatusMessage(state: RalphLoopState): string;
54
+ /**
55
+ * Get progress as a formatted string
56
+ */
57
+ export declare function getProgressString(state: RalphLoopState): string | null;
58
+ //# sourceMappingURL=ralph-loop-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ralph-loop-parser.d.ts","sourceRoot":"","sources":["../src/ralph-loop-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,SAAS,GACT,QAAQ,GACR,WAAW,GACX,SAAS,GACT,mBAAmB,CAAC;AAExB,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,UAAU,GAAG,cAAc,GAAG,OAAO,GAAG,YAAY,GAAG,IAAI,CAAC;IAClE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,aAAa,EAAE,aAAa,CAAC;IAC7B,aAAa,EAAE,mBAAmB,CAAC;IACnC,WAAW,EAAE,IAAI,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAqCD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,cAAc,CAwBnD;AAuOD;;GAEG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,cAAc,GAC3B,cAAc,CAehB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EAAE,EACjB,YAAY,CAAC,EAAE,cAAc,GAC5B,cAAc,CAQhB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAMjE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAuB9D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAYtE"}
@@ -0,0 +1,315 @@
1
+ /**
2
+ * Ralph Loop Status Parser
3
+ *
4
+ * Parses Claude Code output to extract Ralph loop status information
5
+ * for display in the UI.
6
+ */
7
+ // Patterns for detecting Ralph loop status from Claude Code output
8
+ const PATTERNS = {
9
+ // Loop status patterns
10
+ loopStarted: /(?:ralph[- ]?loop|loop)\s*(?:started|running|active)/i,
11
+ loopPaused: /(?:ralph[- ]?loop|loop)\s*(?:paused|suspended)/i,
12
+ loopCompleted: /(?:ralph[- ]?loop|loop)\s*(?:completed|finished|done)/i,
13
+ loopErrored: /(?:ralph[- ]?loop|loop)\s*(?:error|failed|crashed)/i,
14
+ loopWaiting: /(?:waiting\s*for\s*(?:user\s*)?input|needs?\s*input|awaiting\s*response)/i,
15
+ // Progress patterns
16
+ stepProgress: /(?:step|task)\s*(\d+)\s*(?:of|\/)\s*(\d+)/i,
17
+ percentProgress: /(\d+(?:\.\d+)?)\s*%\s*(?:complete|done|progress)/i,
18
+ todoProgress: /(?:todo|task)(?:s)?:\s*(\d+)\s*(?:of|\/)\s*(\d+)/i,
19
+ completingTask: /(?:completing|working\s*on|processing)\s*[:=-]?\s*(.+)/i,
20
+ // Agent activity patterns
21
+ toolUse: /(?:using|calling|invoking)\s*(?:tool\s*)?[:=-]?\s*(\w+)/i,
22
+ toolName: /(?:tool|function)\s*[:=-]?\s*["']?(\w+)["']?/i,
23
+ agentThinking: /(?:thinking|analyzing|processing|reading|writing|searching)/i,
24
+ agentAction: /(?:creating|updating|modifying|deleting|reading|writing|running|executing)\s+(.+)/i,
25
+ // User attention patterns
26
+ question: /\?\s*$/,
27
+ questionPrompt: /(?:what|which|how|should|would|do\s*you|can\s*you)\s+.+\?/i,
28
+ confirmation: /(?:confirm|proceed|continue|approve|accept)\s*\?/i,
29
+ permissionRequest: /(?:permission|allow|authorize|grant|enable)/i,
30
+ errorMessage: /(?:error|failed|exception|cannot|unable|invalid)[:\s]/i,
31
+ userPrompt: /(?:enter|input|provide|specify|type)\s*[:=-]?\s*(.+)/i,
32
+ waitingInput: /(?:>|>>|\$|input:)\s*$/,
33
+ // ANSI escape sequence for cleaning
34
+ // eslint-disable-next-line no-control-regex
35
+ ansiEscape: /\x1b\[[0-9;]*[a-zA-Z]/g,
36
+ };
37
+ /**
38
+ * Creates an initial/default Ralph loop state
39
+ */
40
+ export function createInitialState() {
41
+ return {
42
+ status: "idle",
43
+ progress: {
44
+ currentStep: 0,
45
+ totalSteps: null,
46
+ percentage: null,
47
+ description: null,
48
+ },
49
+ agentActivity: {
50
+ isActive: false,
51
+ currentAction: null,
52
+ toolName: null,
53
+ timestamp: new Date(),
54
+ },
55
+ userAttention: {
56
+ needed: false,
57
+ reason: null,
58
+ type: null,
59
+ prompt: null,
60
+ },
61
+ lastUpdated: new Date(),
62
+ rawOutput: null,
63
+ };
64
+ }
65
+ /**
66
+ * Clean ANSI escape sequences from output
67
+ */
68
+ function cleanOutput(output) {
69
+ return output.replace(PATTERNS.ansiEscape, "").trim();
70
+ }
71
+ /**
72
+ * Parse loop status from output
73
+ */
74
+ function parseLoopStatus(output, currentStatus) {
75
+ const cleanedOutput = cleanOutput(output);
76
+ if (PATTERNS.loopErrored.test(cleanedOutput)) {
77
+ return "errored";
78
+ }
79
+ if (PATTERNS.loopCompleted.test(cleanedOutput)) {
80
+ return "completed";
81
+ }
82
+ if (PATTERNS.loopPaused.test(cleanedOutput)) {
83
+ return "paused";
84
+ }
85
+ if (PATTERNS.loopWaiting.test(cleanedOutput) ||
86
+ PATTERNS.waitingInput.test(cleanedOutput)) {
87
+ return "waiting_for_input";
88
+ }
89
+ if (PATTERNS.loopStarted.test(cleanedOutput)) {
90
+ return "running";
91
+ }
92
+ // If we detect agent activity, assume running
93
+ if (PATTERNS.agentThinking.test(cleanedOutput) ||
94
+ PATTERNS.toolUse.test(cleanedOutput) ||
95
+ PATTERNS.agentAction.test(cleanedOutput)) {
96
+ return currentStatus === "idle" ? "running" : currentStatus;
97
+ }
98
+ return currentStatus;
99
+ }
100
+ /**
101
+ * Parse progress information from output
102
+ */
103
+ function parseProgress(output, currentProgress) {
104
+ const cleanedOutput = cleanOutput(output);
105
+ const progress = { ...currentProgress };
106
+ // Check for step progress (e.g., "Step 2 of 5")
107
+ const stepMatch = cleanedOutput.match(PATTERNS.stepProgress);
108
+ if (stepMatch) {
109
+ progress.currentStep = parseInt(stepMatch[1], 10);
110
+ progress.totalSteps = parseInt(stepMatch[2], 10);
111
+ progress.percentage = Math.round((progress.currentStep / progress.totalSteps) * 100);
112
+ }
113
+ // Check for todo progress (e.g., "Todos: 3/10")
114
+ const todoMatch = cleanedOutput.match(PATTERNS.todoProgress);
115
+ if (todoMatch) {
116
+ progress.currentStep = parseInt(todoMatch[1], 10);
117
+ progress.totalSteps = parseInt(todoMatch[2], 10);
118
+ progress.percentage = Math.round((progress.currentStep / progress.totalSteps) * 100);
119
+ }
120
+ // Check for percentage progress
121
+ const percentMatch = cleanedOutput.match(PATTERNS.percentProgress);
122
+ if (percentMatch) {
123
+ progress.percentage = parseFloat(percentMatch[1]);
124
+ }
125
+ // Check for task description
126
+ const taskMatch = cleanedOutput.match(PATTERNS.completingTask);
127
+ if (taskMatch) {
128
+ progress.description = taskMatch[1].trim();
129
+ }
130
+ return progress;
131
+ }
132
+ /**
133
+ * Parse agent activity from output
134
+ */
135
+ function parseAgentActivity(output, currentActivity) {
136
+ const cleanedOutput = cleanOutput(output);
137
+ const activity = { ...currentActivity, timestamp: new Date() };
138
+ // Check for tool usage
139
+ const toolUseMatch = cleanedOutput.match(PATTERNS.toolUse);
140
+ if (toolUseMatch) {
141
+ activity.isActive = true;
142
+ activity.toolName = toolUseMatch[1];
143
+ activity.currentAction = `Using ${toolUseMatch[1]}`;
144
+ return activity;
145
+ }
146
+ // Check for explicit tool name
147
+ const toolNameMatch = cleanedOutput.match(PATTERNS.toolName);
148
+ if (toolNameMatch) {
149
+ activity.isActive = true;
150
+ activity.toolName = toolNameMatch[1];
151
+ }
152
+ // Check for agent action
153
+ const actionMatch = cleanedOutput.match(PATTERNS.agentAction);
154
+ if (actionMatch) {
155
+ activity.isActive = true;
156
+ activity.currentAction = actionMatch[0].trim();
157
+ return activity;
158
+ }
159
+ // Check for thinking/processing
160
+ if (PATTERNS.agentThinking.test(cleanedOutput)) {
161
+ activity.isActive = true;
162
+ // Extract the matching word
163
+ const thinkingMatch = cleanedOutput.match(PATTERNS.agentThinking);
164
+ if (thinkingMatch) {
165
+ activity.currentAction = thinkingMatch[0].charAt(0).toUpperCase() +
166
+ thinkingMatch[0].slice(1).toLowerCase() + "...";
167
+ }
168
+ return activity;
169
+ }
170
+ return activity;
171
+ }
172
+ /**
173
+ * Parse user attention needs from output
174
+ */
175
+ function parseUserAttention(output, currentAttention) {
176
+ const cleanedOutput = cleanOutput(output);
177
+ const attention = { ...currentAttention };
178
+ // Check for error messages
179
+ if (PATTERNS.errorMessage.test(cleanedOutput)) {
180
+ attention.needed = true;
181
+ attention.type = "error";
182
+ attention.reason = "An error occurred";
183
+ attention.prompt = cleanedOutput;
184
+ return attention;
185
+ }
186
+ // Check for permission requests
187
+ if (PATTERNS.permissionRequest.test(cleanedOutput)) {
188
+ attention.needed = true;
189
+ attention.type = "permission";
190
+ attention.reason = "Permission required";
191
+ attention.prompt = cleanedOutput;
192
+ return attention;
193
+ }
194
+ // Check for confirmation prompts
195
+ if (PATTERNS.confirmation.test(cleanedOutput)) {
196
+ attention.needed = true;
197
+ attention.type = "confirmation";
198
+ attention.reason = "Confirmation needed";
199
+ attention.prompt = cleanedOutput;
200
+ return attention;
201
+ }
202
+ // Check for question prompts
203
+ if (PATTERNS.questionPrompt.test(cleanedOutput) ||
204
+ PATTERNS.question.test(cleanedOutput)) {
205
+ attention.needed = true;
206
+ attention.type = "question";
207
+ attention.reason = "Question for user";
208
+ attention.prompt = cleanedOutput;
209
+ return attention;
210
+ }
211
+ // Check for explicit user prompts
212
+ const userPromptMatch = cleanedOutput.match(PATTERNS.userPrompt);
213
+ if (userPromptMatch) {
214
+ attention.needed = true;
215
+ attention.type = "question";
216
+ attention.reason = "Input required";
217
+ attention.prompt = userPromptMatch[1] || cleanedOutput;
218
+ return attention;
219
+ }
220
+ // Check for waiting input indicator
221
+ if (PATTERNS.waitingInput.test(cleanedOutput)) {
222
+ attention.needed = true;
223
+ attention.type = "question";
224
+ attention.reason = "Waiting for input";
225
+ attention.prompt = null;
226
+ return attention;
227
+ }
228
+ // Reset attention if no patterns match and output seems like normal processing
229
+ if (PATTERNS.agentThinking.test(cleanedOutput) ||
230
+ PATTERNS.agentAction.test(cleanedOutput)) {
231
+ return {
232
+ needed: false,
233
+ reason: null,
234
+ type: null,
235
+ prompt: null,
236
+ };
237
+ }
238
+ return attention;
239
+ }
240
+ /**
241
+ * Main parser function - parses a single output chunk and updates state
242
+ */
243
+ export function parseOutput(output, currentState) {
244
+ const cleanedOutput = cleanOutput(output);
245
+ if (!cleanedOutput) {
246
+ return currentState;
247
+ }
248
+ return {
249
+ status: parseLoopStatus(cleanedOutput, currentState.status),
250
+ progress: parseProgress(cleanedOutput, currentState.progress),
251
+ agentActivity: parseAgentActivity(cleanedOutput, currentState.agentActivity),
252
+ userAttention: parseUserAttention(cleanedOutput, currentState.userAttention),
253
+ lastUpdated: new Date(),
254
+ rawOutput: output,
255
+ };
256
+ }
257
+ /**
258
+ * Parse multiple output lines and return accumulated state
259
+ */
260
+ export function parseOutputLines(outputs, initialState) {
261
+ let state = initialState ?? createInitialState();
262
+ for (const output of outputs) {
263
+ state = parseOutput(output, state);
264
+ }
265
+ return state;
266
+ }
267
+ /**
268
+ * Check if the loop needs user attention
269
+ */
270
+ export function needsUserAttention(state) {
271
+ return (state.userAttention.needed ||
272
+ state.status === "waiting_for_input" ||
273
+ state.status === "errored");
274
+ }
275
+ /**
276
+ * Get a human-readable status message
277
+ */
278
+ export function getStatusMessage(state) {
279
+ switch (state.status) {
280
+ case "idle":
281
+ return "Ready to start";
282
+ case "running":
283
+ if (state.agentActivity.currentAction) {
284
+ return state.agentActivity.currentAction;
285
+ }
286
+ if (state.progress.description) {
287
+ return state.progress.description;
288
+ }
289
+ return "Running...";
290
+ case "paused":
291
+ return "Paused";
292
+ case "completed":
293
+ return "Completed";
294
+ case "errored":
295
+ return state.userAttention.prompt ?? "Error occurred";
296
+ case "waiting_for_input":
297
+ return state.userAttention.reason ?? "Waiting for input";
298
+ default:
299
+ return "Unknown status";
300
+ }
301
+ }
302
+ /**
303
+ * Get progress as a formatted string
304
+ */
305
+ export function getProgressString(state) {
306
+ const { progress } = state;
307
+ if (progress.totalSteps !== null) {
308
+ return `${progress.currentStep}/${progress.totalSteps}`;
309
+ }
310
+ if (progress.percentage !== null) {
311
+ return `${progress.percentage}%`;
312
+ }
313
+ return null;
314
+ }
315
+ //# sourceMappingURL=ralph-loop-parser.js.map