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.
- package/README.md +372 -0
- package/dist/AchievementNotification.d.ts +28 -0
- package/dist/AchievementNotification.d.ts.map +1 -0
- package/dist/AchievementNotification.js +74 -0
- package/dist/AchievementNotification.js.map +1 -0
- package/dist/GameSelector.d.ts +25 -0
- package/dist/GameSelector.d.ts.map +1 -0
- package/dist/GameSelector.js +105 -0
- package/dist/GameSelector.js.map +1 -0
- package/dist/HelpOverlay.d.ts +15 -0
- package/dist/HelpOverlay.d.ts.map +1 -0
- package/dist/HelpOverlay.js +134 -0
- package/dist/HelpOverlay.js.map +1 -0
- package/dist/Layout.d.ts +49 -0
- package/dist/Layout.d.ts.map +1 -0
- package/dist/Layout.js +83 -0
- package/dist/Layout.js.map +1 -0
- package/dist/Leaderboard.d.ts +46 -0
- package/dist/Leaderboard.d.ts.map +1 -0
- package/dist/Leaderboard.js +68 -0
- package/dist/Leaderboard.js.map +1 -0
- package/dist/LogViewer.d.ts +33 -0
- package/dist/LogViewer.d.ts.map +1 -0
- package/dist/LogViewer.js +179 -0
- package/dist/LogViewer.js.map +1 -0
- package/dist/LoopAlertOverlay.d.ts +15 -0
- package/dist/LoopAlertOverlay.d.ts.map +1 -0
- package/dist/LoopAlertOverlay.js +17 -0
- package/dist/LoopAlertOverlay.js.map +1 -0
- package/dist/LoopManagementPanel.d.ts +44 -0
- package/dist/LoopManagementPanel.d.ts.map +1 -0
- package/dist/LoopManagementPanel.js +220 -0
- package/dist/LoopManagementPanel.js.map +1 -0
- package/dist/SettingsMenu.d.ts +22 -0
- package/dist/SettingsMenu.d.ts.map +1 -0
- package/dist/SettingsMenu.js +367 -0
- package/dist/SettingsMenu.js.map +1 -0
- package/dist/SplitPane.d.ts +63 -0
- package/dist/SplitPane.d.ts.map +1 -0
- package/dist/SplitPane.js +104 -0
- package/dist/SplitPane.js.map +1 -0
- package/dist/StatsMenu.d.ts +15 -0
- package/dist/StatsMenu.d.ts.map +1 -0
- package/dist/StatsMenu.js +230 -0
- package/dist/StatsMenu.js.map +1 -0
- package/dist/StatusBar.d.ts +58 -0
- package/dist/StatusBar.d.ts.map +1 -0
- package/dist/StatusBar.js +106 -0
- package/dist/StatusBar.js.map +1 -0
- package/dist/__tests__/ralph-loop-parser.test.d.ts +2 -0
- package/dist/__tests__/ralph-loop-parser.test.d.ts.map +1 -0
- package/dist/__tests__/ralph-loop-parser.test.js +143 -0
- package/dist/__tests__/ralph-loop-parser.test.js.map +1 -0
- package/dist/claude-code-process.d.ts +76 -0
- package/dist/claude-code-process.d.ts.map +1 -0
- package/dist/claude-code-process.js +221 -0
- package/dist/claude-code-process.js.map +1 -0
- package/dist/cli.d.ts +42 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +265 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +206 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +270 -0
- package/dist/config.js.map +1 -0
- package/dist/game-types.d.ts +177 -0
- package/dist/game-types.d.ts.map +1 -0
- package/dist/game-types.js +55 -0
- package/dist/game-types.js.map +1 -0
- package/dist/games/MinesweeperGame.d.ts +15 -0
- package/dist/games/MinesweeperGame.d.ts.map +1 -0
- package/dist/games/MinesweeperGame.js +555 -0
- package/dist/games/MinesweeperGame.js.map +1 -0
- package/dist/games/PongGame.d.ts +15 -0
- package/dist/games/PongGame.d.ts.map +1 -0
- package/dist/games/PongGame.js +379 -0
- package/dist/games/PongGame.js.map +1 -0
- package/dist/games/SnakeGame.d.ts +15 -0
- package/dist/games/SnakeGame.d.ts.map +1 -0
- package/dist/games/SnakeGame.js +333 -0
- package/dist/games/SnakeGame.js.map +1 -0
- package/dist/games/TetrisGame.d.ts +15 -0
- package/dist/games/TetrisGame.d.ts.map +1 -0
- package/dist/games/TetrisGame.js +654 -0
- package/dist/games/TetrisGame.js.map +1 -0
- package/dist/games/index.d.ts +23 -0
- package/dist/games/index.d.ts.map +1 -0
- package/dist/games/index.js +47 -0
- package/dist/games/index.js.map +1 -0
- package/dist/high-scores.d.ts +57 -0
- package/dist/high-scores.d.ts.map +1 -0
- package/dist/high-scores.js +230 -0
- package/dist/high-scores.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +264 -0
- package/dist/index.js.map +1 -0
- package/dist/ralph-loop-parser.d.ts +58 -0
- package/dist/ralph-loop-parser.d.ts.map +1 -0
- package/dist/ralph-loop-parser.js +315 -0
- package/dist/ralph-loop-parser.js.map +1 -0
- package/dist/stats.d.ts +142 -0
- package/dist/stats.d.ts.map +1 -0
- package/dist/stats.js +521 -0
- package/dist/stats.js.map +1 -0
- package/dist/styled-components.d.ts +231 -0
- package/dist/styled-components.d.ts.map +1 -0
- package/dist/styled-components.js +192 -0
- package/dist/styled-components.js.map +1 -0
- package/dist/theme.d.ts +301 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +372 -0
- package/dist/theme.js.map +1 -0
- package/dist/themes.d.ts +117 -0
- package/dist/themes.d.ts.map +1 -0
- package/dist/themes.js +296 -0
- package/dist/themes.js.map +1 -0
- package/dist/ui/index.d.ts +13 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +29 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/use-claude-code.d.ts +30 -0
- package/dist/use-claude-code.d.ts.map +1 -0
- package/dist/use-claude-code.js +84 -0
- package/dist/use-claude-code.js.map +1 -0
- package/dist/use-config.d.ts +58 -0
- package/dist/use-config.d.ts.map +1 -0
- package/dist/use-config.js +113 -0
- package/dist/use-config.js.map +1 -0
- package/dist/use-game-loop.d.ts +47 -0
- package/dist/use-game-loop.d.ts.map +1 -0
- package/dist/use-game-loop.js +136 -0
- package/dist/use-game-loop.js.map +1 -0
- package/dist/use-high-scores.d.ts +41 -0
- package/dist/use-high-scores.d.ts.map +1 -0
- package/dist/use-high-scores.js +94 -0
- package/dist/use-high-scores.js.map +1 -0
- package/dist/use-layout-state.d.ts +77 -0
- package/dist/use-layout-state.d.ts.map +1 -0
- package/dist/use-layout-state.js +160 -0
- package/dist/use-layout-state.js.map +1 -0
- package/dist/use-ralph-loop.d.ts +41 -0
- package/dist/use-ralph-loop.d.ts.map +1 -0
- package/dist/use-ralph-loop.js +106 -0
- package/dist/use-ralph-loop.js.map +1 -0
- package/dist/use-spinner.d.ts +46 -0
- package/dist/use-spinner.d.ts.map +1 -0
- package/dist/use-spinner.js +71 -0
- package/dist/use-spinner.js.map +1 -0
- package/dist/use-stats.d.ts +59 -0
- package/dist/use-stats.d.ts.map +1 -0
- package/dist/use-stats.js +150 -0
- package/dist/use-stats.js.map +1 -0
- package/dist/use-terminal-size.d.ts +29 -0
- package/dist/use-terminal-size.d.ts.map +1 -0
- package/dist/use-terminal-size.js +48 -0
- package/dist/use-terminal-size.js.map +1 -0
- package/dist/useTheme.d.ts +76 -0
- package/dist/useTheme.d.ts.map +1 -0
- package/dist/useTheme.js +136 -0
- package/dist/useTheme.js.map +1 -0
- 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
|