aicodeman 0.2.8
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/LICENSE +21 -0
- package/README.md +403 -0
- package/dist/ai-checker-base.d.ts +175 -0
- package/dist/ai-checker-base.d.ts.map +1 -0
- package/dist/ai-checker-base.js +424 -0
- package/dist/ai-checker-base.js.map +1 -0
- package/dist/ai-idle-checker.d.ts +53 -0
- package/dist/ai-idle-checker.d.ts.map +1 -0
- package/dist/ai-idle-checker.js +141 -0
- package/dist/ai-idle-checker.js.map +1 -0
- package/dist/ai-plan-checker.d.ts +52 -0
- package/dist/ai-plan-checker.d.ts.map +1 -0
- package/dist/ai-plan-checker.js +103 -0
- package/dist/ai-plan-checker.js.map +1 -0
- package/dist/bash-tool-parser.d.ts +191 -0
- package/dist/bash-tool-parser.d.ts.map +1 -0
- package/dist/bash-tool-parser.js +598 -0
- package/dist/bash-tool-parser.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +460 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/buffer-limits.d.ts +59 -0
- package/dist/config/buffer-limits.d.ts.map +1 -0
- package/dist/config/buffer-limits.js +74 -0
- package/dist/config/buffer-limits.js.map +1 -0
- package/dist/config/map-limits.d.ts +40 -0
- package/dist/config/map-limits.d.ts.map +1 -0
- package/dist/config/map-limits.js +52 -0
- package/dist/config/map-limits.js.map +1 -0
- package/dist/file-stream-manager.d.ts +148 -0
- package/dist/file-stream-manager.d.ts.map +1 -0
- package/dist/file-stream-manager.js +351 -0
- package/dist/file-stream-manager.js.map +1 -0
- package/dist/hooks-config.d.ts +31 -0
- package/dist/hooks-config.d.ts.map +1 -0
- package/dist/hooks-config.js +115 -0
- package/dist/hooks-config.js.map +1 -0
- package/dist/image-watcher.d.ts +86 -0
- package/dist/image-watcher.d.ts.map +1 -0
- package/dist/image-watcher.js +275 -0
- package/dist/image-watcher.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/dist/mux-factory.d.ts +13 -0
- package/dist/mux-factory.d.ts.map +1 -0
- package/dist/mux-factory.js +19 -0
- package/dist/mux-factory.js.map +1 -0
- package/dist/mux-interface.d.ts +145 -0
- package/dist/mux-interface.d.ts.map +1 -0
- package/dist/mux-interface.js +9 -0
- package/dist/mux-interface.js.map +1 -0
- package/dist/plan-orchestrator.d.ts +123 -0
- package/dist/plan-orchestrator.d.ts.map +1 -0
- package/dist/plan-orchestrator.js +500 -0
- package/dist/plan-orchestrator.js.map +1 -0
- package/dist/prompts/index.d.ts +9 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +9 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/planner.d.ts +14 -0
- package/dist/prompts/planner.d.ts.map +1 -0
- package/dist/prompts/planner.js +83 -0
- package/dist/prompts/planner.js.map +1 -0
- package/dist/prompts/research-agent.d.ts +10 -0
- package/dist/prompts/research-agent.d.ts.map +1 -0
- package/dist/prompts/research-agent.js +143 -0
- package/dist/prompts/research-agent.js.map +1 -0
- package/dist/push-store.d.ts +41 -0
- package/dist/push-store.d.ts.map +1 -0
- package/dist/push-store.js +168 -0
- package/dist/push-store.js.map +1 -0
- package/dist/ralph-config.d.ts +67 -0
- package/dist/ralph-config.d.ts.map +1 -0
- package/dist/ralph-config.js +134 -0
- package/dist/ralph-config.js.map +1 -0
- package/dist/ralph-loop.d.ts +124 -0
- package/dist/ralph-loop.d.ts.map +1 -0
- package/dist/ralph-loop.js +418 -0
- package/dist/ralph-loop.js.map +1 -0
- package/dist/ralph-tracker.d.ts +1081 -0
- package/dist/ralph-tracker.d.ts.map +1 -0
- package/dist/ralph-tracker.js +3343 -0
- package/dist/ralph-tracker.js.map +1 -0
- package/dist/respawn-controller.d.ts +1182 -0
- package/dist/respawn-controller.d.ts.map +1 -0
- package/dist/respawn-controller.js +2754 -0
- package/dist/respawn-controller.js.map +1 -0
- package/dist/run-summary.d.ts +123 -0
- package/dist/run-summary.d.ts.map +1 -0
- package/dist/run-summary.js +325 -0
- package/dist/run-summary.js.map +1 -0
- package/dist/session-lifecycle-log.d.ts +36 -0
- package/dist/session-lifecycle-log.d.ts.map +1 -0
- package/dist/session-lifecycle-log.js +101 -0
- package/dist/session-lifecycle-log.js.map +1 -0
- package/dist/session-manager.d.ts +97 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +224 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/session.d.ts +686 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +2025 -0
- package/dist/session.js.map +1 -0
- package/dist/state-store.d.ts +189 -0
- package/dist/state-store.d.ts.map +1 -0
- package/dist/state-store.js +730 -0
- package/dist/state-store.js.map +1 -0
- package/dist/subagent-watcher.d.ts +345 -0
- package/dist/subagent-watcher.d.ts.map +1 -0
- package/dist/subagent-watcher.js +1469 -0
- package/dist/subagent-watcher.js.map +1 -0
- package/dist/task-queue.d.ts +108 -0
- package/dist/task-queue.d.ts.map +1 -0
- package/dist/task-queue.js +235 -0
- package/dist/task-queue.js.map +1 -0
- package/dist/task-tracker.d.ts +306 -0
- package/dist/task-tracker.d.ts.map +1 -0
- package/dist/task-tracker.js +488 -0
- package/dist/task-tracker.js.map +1 -0
- package/dist/task.d.ts +73 -0
- package/dist/task.d.ts.map +1 -0
- package/dist/task.js +177 -0
- package/dist/task.js.map +1 -0
- package/dist/team-watcher.d.ts +53 -0
- package/dist/team-watcher.d.ts.map +1 -0
- package/dist/team-watcher.js +313 -0
- package/dist/team-watcher.js.map +1 -0
- package/dist/templates/case-template.md +461 -0
- package/dist/templates/claude-md.d.ts +26 -0
- package/dist/templates/claude-md.d.ts.map +1 -0
- package/dist/templates/claude-md.js +74 -0
- package/dist/templates/claude-md.js.map +1 -0
- package/dist/tmux-manager.d.ts +181 -0
- package/dist/tmux-manager.d.ts.map +1 -0
- package/dist/tmux-manager.js +1405 -0
- package/dist/tmux-manager.js.map +1 -0
- package/dist/transcript-watcher.d.ts +110 -0
- package/dist/transcript-watcher.d.ts.map +1 -0
- package/dist/transcript-watcher.js +338 -0
- package/dist/transcript-watcher.js.map +1 -0
- package/dist/tunnel-manager.d.ts +54 -0
- package/dist/tunnel-manager.d.ts.map +1 -0
- package/dist/tunnel-manager.js +251 -0
- package/dist/tunnel-manager.js.map +1 -0
- package/dist/types.d.ts +1139 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +215 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/buffer-accumulator.d.ts +111 -0
- package/dist/utils/buffer-accumulator.d.ts.map +1 -0
- package/dist/utils/buffer-accumulator.js +172 -0
- package/dist/utils/buffer-accumulator.js.map +1 -0
- package/dist/utils/claude-cli-resolver.d.ts +26 -0
- package/dist/utils/claude-cli-resolver.d.ts.map +1 -0
- package/dist/utils/claude-cli-resolver.js +78 -0
- package/dist/utils/claude-cli-resolver.js.map +1 -0
- package/dist/utils/cleanup-manager.d.ts +165 -0
- package/dist/utils/cleanup-manager.d.ts.map +1 -0
- package/dist/utils/cleanup-manager.js +274 -0
- package/dist/utils/cleanup-manager.js.map +1 -0
- package/dist/utils/index.d.ts +19 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +19 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/lru-map.d.ts +140 -0
- package/dist/utils/lru-map.d.ts.map +1 -0
- package/dist/utils/lru-map.js +234 -0
- package/dist/utils/lru-map.js.map +1 -0
- package/dist/utils/nice-wrapper.d.ts +13 -0
- package/dist/utils/nice-wrapper.d.ts.map +1 -0
- package/dist/utils/nice-wrapper.js +17 -0
- package/dist/utils/nice-wrapper.js.map +1 -0
- package/dist/utils/opencode-cli-resolver.d.ts +21 -0
- package/dist/utils/opencode-cli-resolver.d.ts.map +1 -0
- package/dist/utils/opencode-cli-resolver.js +67 -0
- package/dist/utils/opencode-cli-resolver.js.map +1 -0
- package/dist/utils/regex-patterns.d.ts +64 -0
- package/dist/utils/regex-patterns.d.ts.map +1 -0
- package/dist/utils/regex-patterns.js +74 -0
- package/dist/utils/regex-patterns.js.map +1 -0
- package/dist/utils/stale-expiration-map.d.ts +159 -0
- package/dist/utils/stale-expiration-map.d.ts.map +1 -0
- package/dist/utils/stale-expiration-map.js +277 -0
- package/dist/utils/stale-expiration-map.js.map +1 -0
- package/dist/utils/string-similarity.d.ts +108 -0
- package/dist/utils/string-similarity.d.ts.map +1 -0
- package/dist/utils/string-similarity.js +189 -0
- package/dist/utils/string-similarity.js.map +1 -0
- package/dist/utils/token-validation.d.ts +39 -0
- package/dist/utils/token-validation.d.ts.map +1 -0
- package/dist/utils/token-validation.js +59 -0
- package/dist/utils/token-validation.js.map +1 -0
- package/dist/utils/type-safety.d.ts +33 -0
- package/dist/utils/type-safety.d.ts.map +1 -0
- package/dist/utils/type-safety.js +35 -0
- package/dist/utils/type-safety.js.map +1 -0
- package/dist/web/public/app.js +491 -0
- package/dist/web/public/app.js.br +0 -0
- package/dist/web/public/app.js.gz +0 -0
- package/dist/web/public/index.html +1675 -0
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/manifest.json +8 -0
- package/dist/web/public/mobile.css +1 -0
- package/dist/web/public/mobile.css.br +0 -0
- package/dist/web/public/mobile.css.gz +0 -0
- package/dist/web/public/ralph-wizard.js +1037 -0
- package/dist/web/public/ralph-wizard.js.br +0 -0
- package/dist/web/public/ralph-wizard.js.gz +0 -0
- package/dist/web/public/styles.css +1 -0
- package/dist/web/public/styles.css.br +0 -0
- package/dist/web/public/styles.css.gz +0 -0
- package/dist/web/public/sw.js +67 -0
- package/dist/web/public/sw.js.br +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/upload.html +155 -0
- package/dist/web/public/upload.html.br +0 -0
- package/dist/web/public/upload.html.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js +1 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.br +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js +1 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.br +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js +2 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.br +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css +209 -0
- package/dist/web/public/vendor/xterm.css.br +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js +9 -0
- package/dist/web/public/vendor/xterm.min.js.br +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/schemas.d.ts +479 -0
- package/dist/web/schemas.d.ts.map +1 -0
- package/dist/web/schemas.js +448 -0
- package/dist/web/schemas.js.map +1 -0
- package/dist/web/server.d.ts +207 -0
- package/dist/web/server.d.ts.map +1 -0
- package/dist/web/server.js +5784 -0
- package/dist/web/server.js.map +1 -0
- package/package.json +110 -0
- package/scripts/postinstall.js +390 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Ralph Loop - Autonomous task execution engine
|
|
3
|
+
*
|
|
4
|
+
* The Ralph Loop orchestrates autonomous Claude sessions by:
|
|
5
|
+
* - Polling for available tasks from the task queue
|
|
6
|
+
* - Assigning tasks to idle sessions
|
|
7
|
+
* - Monitoring completion and handling failures
|
|
8
|
+
* - Auto-generating follow-up tasks when min duration not reached
|
|
9
|
+
*
|
|
10
|
+
* Named after Ralph Wiggum's persistence ("I'm in danger!"),
|
|
11
|
+
* this loop keeps Claude working until all tasks are done.
|
|
12
|
+
*
|
|
13
|
+
* @module ralph-loop
|
|
14
|
+
*/
|
|
15
|
+
import { EventEmitter } from 'node:events';
|
|
16
|
+
import { RalphLoopStatus } from './types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Events emitted by RalphLoop
|
|
19
|
+
*/
|
|
20
|
+
export interface RalphLoopEvents {
|
|
21
|
+
started: () => void;
|
|
22
|
+
stopped: () => void;
|
|
23
|
+
taskAssigned: (taskId: string, sessionId: string) => void;
|
|
24
|
+
taskCompleted: (taskId: string) => void;
|
|
25
|
+
taskFailed: (taskId: string, error: string) => void;
|
|
26
|
+
error: (error: Error) => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Configuration options for RalphLoop
|
|
30
|
+
*/
|
|
31
|
+
export interface RalphLoopOptions {
|
|
32
|
+
/** How often to check for new tasks (default from config) */
|
|
33
|
+
pollIntervalMs?: number;
|
|
34
|
+
/** Minimum time to run before stopping (null = no minimum) */
|
|
35
|
+
minDurationMs?: number;
|
|
36
|
+
/** Auto-generate follow-up tasks when queue is empty */
|
|
37
|
+
autoGenerateTasks?: boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Autonomous task execution loop.
|
|
41
|
+
*
|
|
42
|
+
* @description
|
|
43
|
+
* Manages the lifecycle of task execution:
|
|
44
|
+
* 1. Start: Begin polling and task assignment
|
|
45
|
+
* 2. Run: Assign tasks to idle sessions, monitor completion
|
|
46
|
+
* 3. Stop: When all tasks done and min duration reached
|
|
47
|
+
*
|
|
48
|
+
* Supports time-aware loops that continue generating tasks
|
|
49
|
+
* until a minimum duration is reached.
|
|
50
|
+
*
|
|
51
|
+
* @extends EventEmitter
|
|
52
|
+
*/
|
|
53
|
+
export declare class RalphLoop extends EventEmitter {
|
|
54
|
+
private sessionManager;
|
|
55
|
+
private taskQueue;
|
|
56
|
+
private store;
|
|
57
|
+
private pollIntervalMs;
|
|
58
|
+
private minDurationMs;
|
|
59
|
+
private autoGenerateTasks;
|
|
60
|
+
private loopTimer;
|
|
61
|
+
private _status;
|
|
62
|
+
private startedAt;
|
|
63
|
+
private tasksCompleted;
|
|
64
|
+
private tasksGenerated;
|
|
65
|
+
/** Bound event handlers for cleanup (prevents memory leaks) */
|
|
66
|
+
private sessionEventHandlers;
|
|
67
|
+
constructor(options?: RalphLoopOptions);
|
|
68
|
+
private setupEventHandlers;
|
|
69
|
+
/** Remove event listeners to prevent memory leaks */
|
|
70
|
+
private cleanupEventHandlers;
|
|
71
|
+
get status(): RalphLoopStatus;
|
|
72
|
+
isRunning(): boolean;
|
|
73
|
+
getElapsedMs(): number;
|
|
74
|
+
getElapsedHours(): number;
|
|
75
|
+
isMinDurationReached(): boolean;
|
|
76
|
+
getStats(): {
|
|
77
|
+
activeSessions: number;
|
|
78
|
+
idleSessions: number;
|
|
79
|
+
busySessions: number;
|
|
80
|
+
total: number;
|
|
81
|
+
pending: number;
|
|
82
|
+
running: number;
|
|
83
|
+
completed: number;
|
|
84
|
+
failed: number;
|
|
85
|
+
status: RalphLoopStatus;
|
|
86
|
+
elapsedMs: number;
|
|
87
|
+
elapsedHours: number;
|
|
88
|
+
minDurationMs: number | null;
|
|
89
|
+
minDurationReached: boolean;
|
|
90
|
+
tasksCompleted: number;
|
|
91
|
+
tasksGenerated: number;
|
|
92
|
+
};
|
|
93
|
+
/** Starts the task execution loop. */
|
|
94
|
+
start(): Promise<void>;
|
|
95
|
+
/** Stops the task execution loop. */
|
|
96
|
+
stop(): void;
|
|
97
|
+
/** Pauses the loop (can be resumed). */
|
|
98
|
+
pause(): void;
|
|
99
|
+
/** Resumes a paused loop. */
|
|
100
|
+
resume(): void;
|
|
101
|
+
private runLoop;
|
|
102
|
+
private tick;
|
|
103
|
+
private assignTasks;
|
|
104
|
+
private assignTaskToSession;
|
|
105
|
+
private checkTimeouts;
|
|
106
|
+
private handleSessionCompletion;
|
|
107
|
+
private handleSessionError;
|
|
108
|
+
private handleSessionStopped;
|
|
109
|
+
private handleSessionTaskError;
|
|
110
|
+
private shouldGenerateTasks;
|
|
111
|
+
private generateFollowUpTasks;
|
|
112
|
+
private shouldStop;
|
|
113
|
+
/** Sets the minimum duration in hours before the loop can stop. */
|
|
114
|
+
setMinDuration(hours: number): void;
|
|
115
|
+
/**
|
|
116
|
+
* Destroys the loop and cleans up all resources.
|
|
117
|
+
* Use this for complete cleanup (e.g., in tests or before creating a new instance).
|
|
118
|
+
* After calling destroy(), the instance should not be reused.
|
|
119
|
+
*/
|
|
120
|
+
destroy(): void;
|
|
121
|
+
}
|
|
122
|
+
/** Gets or creates the singleton RalphLoop instance. */
|
|
123
|
+
export declare function getRalphLoop(options?: RalphLoopOptions): RalphLoop;
|
|
124
|
+
//# sourceMappingURL=ralph-loop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ralph-loop.d.ts","sourceRoot":"","sources":["../src/ralph-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAM3C,OAAO,EAAE,eAAe,EAAmB,MAAM,YAAY,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,SAAU,SAAQ,YAAY;IACzC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,cAAc,CAAa;IACnC,OAAO,CAAC,cAAc,CAAa;IAEnC,+DAA+D;IAC/D,OAAO,CAAC,oBAAoB,CAKZ;gBAEJ,OAAO,GAAE,gBAAqB;IA2B1C,OAAO,CAAC,kBAAkB;IAuB1B,qDAAqD;IACrD,OAAO,CAAC,oBAAoB;IAU5B,IAAI,MAAM,IAAI,eAAe,CAE5B;IAED,SAAS,IAAI,OAAO;IAIpB,YAAY,IAAI,MAAM;IAOtB,eAAe,IAAI,MAAM;IAIzB,oBAAoB,IAAI,OAAO;IAO/B,QAAQ;;;;;;;;;;;;;;;;;IAiBR,sCAAsC;IAChC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA2B5B,qCAAqC;IACrC,IAAI,IAAI,IAAI;IAuBZ,wCAAwC;IACxC,KAAK,IAAI,IAAI;IAeb,6BAA6B;IAC7B,MAAM,IAAI,IAAI;IAUd,OAAO,CAAC,OAAO;YAqBD,IAAI;YAoBJ,WAAW;YAiBX,mBAAmB;YAkBnB,aAAa;IAgB3B,OAAO,CAAC,uBAAuB;IA6B/B,OAAO,CAAC,kBAAkB;IAoB1B,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,sBAAsB;IAW9B,OAAO,CAAC,mBAAmB;YASb,qBAAqB;IA6BnC,OAAO,CAAC,UAAU;IAiBlB,mEAAmE;IACnE,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKnC;;;;OAIG;IACH,OAAO,IAAI,IAAI;CAKhB;AAKD,wDAAwD;AACxD,wBAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAKlE"}
|
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Ralph Loop - Autonomous task execution engine
|
|
3
|
+
*
|
|
4
|
+
* The Ralph Loop orchestrates autonomous Claude sessions by:
|
|
5
|
+
* - Polling for available tasks from the task queue
|
|
6
|
+
* - Assigning tasks to idle sessions
|
|
7
|
+
* - Monitoring completion and handling failures
|
|
8
|
+
* - Auto-generating follow-up tasks when min duration not reached
|
|
9
|
+
*
|
|
10
|
+
* Named after Ralph Wiggum's persistence ("I'm in danger!"),
|
|
11
|
+
* this loop keeps Claude working until all tasks are done.
|
|
12
|
+
*
|
|
13
|
+
* @module ralph-loop
|
|
14
|
+
*/
|
|
15
|
+
import { EventEmitter } from 'node:events';
|
|
16
|
+
import { getSessionManager } from './session-manager.js';
|
|
17
|
+
import { getTaskQueue } from './task-queue.js';
|
|
18
|
+
import { getStore } from './state-store.js';
|
|
19
|
+
import { getErrorMessage } from './types.js';
|
|
20
|
+
/**
|
|
21
|
+
* Autonomous task execution loop.
|
|
22
|
+
*
|
|
23
|
+
* @description
|
|
24
|
+
* Manages the lifecycle of task execution:
|
|
25
|
+
* 1. Start: Begin polling and task assignment
|
|
26
|
+
* 2. Run: Assign tasks to idle sessions, monitor completion
|
|
27
|
+
* 3. Stop: When all tasks done and min duration reached
|
|
28
|
+
*
|
|
29
|
+
* Supports time-aware loops that continue generating tasks
|
|
30
|
+
* until a minimum duration is reached.
|
|
31
|
+
*
|
|
32
|
+
* @extends EventEmitter
|
|
33
|
+
*/
|
|
34
|
+
export class RalphLoop extends EventEmitter {
|
|
35
|
+
sessionManager;
|
|
36
|
+
taskQueue;
|
|
37
|
+
store;
|
|
38
|
+
pollIntervalMs;
|
|
39
|
+
minDurationMs;
|
|
40
|
+
autoGenerateTasks;
|
|
41
|
+
loopTimer = null;
|
|
42
|
+
_status = 'stopped';
|
|
43
|
+
startedAt = null;
|
|
44
|
+
tasksCompleted = 0;
|
|
45
|
+
tasksGenerated = 0;
|
|
46
|
+
/** Bound event handlers for cleanup (prevents memory leaks) */
|
|
47
|
+
sessionEventHandlers = null;
|
|
48
|
+
constructor(options = {}) {
|
|
49
|
+
super();
|
|
50
|
+
this.sessionManager = getSessionManager();
|
|
51
|
+
this.taskQueue = getTaskQueue();
|
|
52
|
+
this.store = getStore();
|
|
53
|
+
const config = this.store.getConfig();
|
|
54
|
+
this.pollIntervalMs = options.pollIntervalMs ?? config.pollIntervalMs;
|
|
55
|
+
this.minDurationMs = options.minDurationMs ?? null;
|
|
56
|
+
this.autoGenerateTasks = options.autoGenerateTasks ?? true;
|
|
57
|
+
// Load state from store
|
|
58
|
+
const savedState = this.store.getRalphLoopState();
|
|
59
|
+
if (savedState.status === 'running') {
|
|
60
|
+
// If we crashed while running, reset to stopped
|
|
61
|
+
this._status = 'stopped';
|
|
62
|
+
this.store.setRalphLoopState({ status: 'stopped' });
|
|
63
|
+
// Reset orphaned in_progress tasks back to pending
|
|
64
|
+
for (const task of this.taskQueue.getRunningTasks()) {
|
|
65
|
+
task.reset();
|
|
66
|
+
this.taskQueue.updateTask(task);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
this.setupEventHandlers();
|
|
70
|
+
}
|
|
71
|
+
setupEventHandlers() {
|
|
72
|
+
// Store bound handlers for later cleanup
|
|
73
|
+
this.sessionEventHandlers = {
|
|
74
|
+
completion: (sessionId, phrase) => {
|
|
75
|
+
this.handleSessionCompletion(sessionId, phrase);
|
|
76
|
+
},
|
|
77
|
+
error: (sessionId, error) => {
|
|
78
|
+
this.handleSessionError(sessionId, error);
|
|
79
|
+
},
|
|
80
|
+
stopped: (sessionId) => {
|
|
81
|
+
this.handleSessionStopped(sessionId);
|
|
82
|
+
},
|
|
83
|
+
taskError: (sessionId, taskId, error) => {
|
|
84
|
+
this.handleSessionTaskError(sessionId, taskId, error);
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
this.sessionManager.on('sessionCompletion', this.sessionEventHandlers.completion);
|
|
88
|
+
this.sessionManager.on('sessionError', this.sessionEventHandlers.error);
|
|
89
|
+
this.sessionManager.on('sessionStopped', this.sessionEventHandlers.stopped);
|
|
90
|
+
this.sessionManager.on('sessionTaskError', this.sessionEventHandlers.taskError);
|
|
91
|
+
}
|
|
92
|
+
/** Remove event listeners to prevent memory leaks */
|
|
93
|
+
cleanupEventHandlers() {
|
|
94
|
+
if (this.sessionEventHandlers) {
|
|
95
|
+
this.sessionManager.off('sessionCompletion', this.sessionEventHandlers.completion);
|
|
96
|
+
this.sessionManager.off('sessionError', this.sessionEventHandlers.error);
|
|
97
|
+
this.sessionManager.off('sessionStopped', this.sessionEventHandlers.stopped);
|
|
98
|
+
this.sessionManager.off('sessionTaskError', this.sessionEventHandlers.taskError);
|
|
99
|
+
this.sessionEventHandlers = null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
get status() {
|
|
103
|
+
return this._status;
|
|
104
|
+
}
|
|
105
|
+
isRunning() {
|
|
106
|
+
return this._status === 'running';
|
|
107
|
+
}
|
|
108
|
+
getElapsedMs() {
|
|
109
|
+
if (!this.startedAt) {
|
|
110
|
+
return 0;
|
|
111
|
+
}
|
|
112
|
+
return Date.now() - this.startedAt;
|
|
113
|
+
}
|
|
114
|
+
getElapsedHours() {
|
|
115
|
+
return this.getElapsedMs() / (1000 * 60 * 60);
|
|
116
|
+
}
|
|
117
|
+
isMinDurationReached() {
|
|
118
|
+
if (!this.minDurationMs) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
return this.getElapsedMs() >= this.minDurationMs;
|
|
122
|
+
}
|
|
123
|
+
getStats() {
|
|
124
|
+
const taskCounts = this.taskQueue.getCount();
|
|
125
|
+
return {
|
|
126
|
+
status: this._status,
|
|
127
|
+
elapsedMs: this.getElapsedMs(),
|
|
128
|
+
elapsedHours: this.getElapsedHours(),
|
|
129
|
+
minDurationMs: this.minDurationMs,
|
|
130
|
+
minDurationReached: this.isMinDurationReached(),
|
|
131
|
+
tasksCompleted: this.tasksCompleted,
|
|
132
|
+
tasksGenerated: this.tasksGenerated,
|
|
133
|
+
...taskCounts,
|
|
134
|
+
activeSessions: this.sessionManager.getSessionCount(),
|
|
135
|
+
idleSessions: this.sessionManager.getIdleSessions().length,
|
|
136
|
+
busySessions: this.sessionManager.getBusySessions().length,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/** Starts the task execution loop. */
|
|
140
|
+
async start() {
|
|
141
|
+
if (this._status === 'running') {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
this._status = 'running';
|
|
145
|
+
this.startedAt = Date.now();
|
|
146
|
+
this.tasksCompleted = 0;
|
|
147
|
+
this.tasksGenerated = 0;
|
|
148
|
+
// Re-setup event handlers if they were cleaned up during stop()
|
|
149
|
+
if (!this.sessionEventHandlers) {
|
|
150
|
+
this.setupEventHandlers();
|
|
151
|
+
}
|
|
152
|
+
this.store.setRalphLoopState({
|
|
153
|
+
status: 'running',
|
|
154
|
+
startedAt: this.startedAt,
|
|
155
|
+
minDurationMs: this.minDurationMs,
|
|
156
|
+
tasksCompleted: 0,
|
|
157
|
+
tasksGenerated: 0,
|
|
158
|
+
});
|
|
159
|
+
this.emit('started');
|
|
160
|
+
this.runLoop();
|
|
161
|
+
}
|
|
162
|
+
/** Stops the task execution loop. */
|
|
163
|
+
stop() {
|
|
164
|
+
if (this._status === 'stopped') {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
this._status = 'stopped';
|
|
168
|
+
if (this.loopTimer) {
|
|
169
|
+
clearTimeout(this.loopTimer);
|
|
170
|
+
this.loopTimer = null;
|
|
171
|
+
}
|
|
172
|
+
// Clean up event handlers to prevent memory leaks
|
|
173
|
+
this.cleanupEventHandlers();
|
|
174
|
+
this.store.setRalphLoopState({
|
|
175
|
+
status: 'stopped',
|
|
176
|
+
lastCheckAt: Date.now(),
|
|
177
|
+
});
|
|
178
|
+
this.emit('stopped');
|
|
179
|
+
}
|
|
180
|
+
/** Pauses the loop (can be resumed). */
|
|
181
|
+
pause() {
|
|
182
|
+
if (this._status !== 'running') {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
this._status = 'paused';
|
|
186
|
+
if (this.loopTimer) {
|
|
187
|
+
clearTimeout(this.loopTimer);
|
|
188
|
+
this.loopTimer = null;
|
|
189
|
+
}
|
|
190
|
+
this.store.setRalphLoopState({ status: 'paused' });
|
|
191
|
+
}
|
|
192
|
+
/** Resumes a paused loop. */
|
|
193
|
+
resume() {
|
|
194
|
+
if (this._status !== 'paused') {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
this._status = 'running';
|
|
198
|
+
this.store.setRalphLoopState({ status: 'running' });
|
|
199
|
+
this.runLoop();
|
|
200
|
+
}
|
|
201
|
+
runLoop() {
|
|
202
|
+
if (this._status !== 'running') {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
this.tick()
|
|
206
|
+
.catch((err) => {
|
|
207
|
+
// Only emit if still running (stop() may have been called during tick())
|
|
208
|
+
if (this._status === 'running') {
|
|
209
|
+
this.emit('error', err);
|
|
210
|
+
}
|
|
211
|
+
})
|
|
212
|
+
.finally(() => {
|
|
213
|
+
// Guard: only reschedule if still running AND no timer is pending
|
|
214
|
+
// (prevents race where stop() clears timer between our check and setTimeout)
|
|
215
|
+
if (this._status === 'running' && this.loopTimer === null) {
|
|
216
|
+
this.loopTimer = setTimeout(() => this.runLoop(), this.pollIntervalMs);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
async tick() {
|
|
221
|
+
this.store.setRalphLoopState({ lastCheckAt: Date.now() });
|
|
222
|
+
// Run sequentially: timeouts first so timed-out tasks are cleaned up
|
|
223
|
+
// before assignTasks() picks new work (prevents race where both
|
|
224
|
+
// mutate the same task concurrently)
|
|
225
|
+
await this.checkTimeouts();
|
|
226
|
+
await this.assignTasks();
|
|
227
|
+
// Check if we should auto-generate tasks (depends on assignment results)
|
|
228
|
+
if (this.autoGenerateTasks && this.shouldGenerateTasks()) {
|
|
229
|
+
await this.generateFollowUpTasks();
|
|
230
|
+
}
|
|
231
|
+
// Check if we're done
|
|
232
|
+
if (this.shouldStop()) {
|
|
233
|
+
this.stop();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async assignTasks() {
|
|
237
|
+
const idleSessions = this.sessionManager.getIdleSessions();
|
|
238
|
+
for (const session of idleSessions) {
|
|
239
|
+
const task = this.taskQueue.next();
|
|
240
|
+
if (!task) {
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
await this.assignTaskToSession(task, session);
|
|
245
|
+
}
|
|
246
|
+
catch (err) {
|
|
247
|
+
console.error(`[RalphLoop] Failed to assign task ${task.id} to session ${session.id}:`, err);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
async assignTaskToSession(task, session) {
|
|
252
|
+
try {
|
|
253
|
+
task.assign(session.id);
|
|
254
|
+
session.assignTask(task.id);
|
|
255
|
+
this.taskQueue.updateTask(task);
|
|
256
|
+
// Send the prompt to the session
|
|
257
|
+
await session.sendInput(task.prompt);
|
|
258
|
+
this.emit('taskAssigned', task.id, session.id);
|
|
259
|
+
}
|
|
260
|
+
catch (err) {
|
|
261
|
+
task.fail(getErrorMessage(err));
|
|
262
|
+
session.clearTask();
|
|
263
|
+
this.taskQueue.updateTask(task);
|
|
264
|
+
this.emit('taskFailed', task.id, getErrorMessage(err));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
async checkTimeouts() {
|
|
268
|
+
for (const task of this.taskQueue.getRunningTasks()) {
|
|
269
|
+
if (task.isTimedOut()) {
|
|
270
|
+
task.fail('Task timed out');
|
|
271
|
+
this.taskQueue.updateTask(task);
|
|
272
|
+
const session = this.sessionManager.getSession(task.assignedSessionId);
|
|
273
|
+
if (session) {
|
|
274
|
+
session.clearTask();
|
|
275
|
+
}
|
|
276
|
+
this.emit('taskFailed', task.id, 'Task timed out');
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
handleSessionCompletion(sessionId, phrase) {
|
|
281
|
+
const session = this.sessionManager.getSession(sessionId);
|
|
282
|
+
if (!session) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
const taskId = session.currentTaskId;
|
|
286
|
+
if (!taskId) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const task = this.taskQueue.getTask(taskId);
|
|
290
|
+
if (!task) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
// Append output and check for completion
|
|
294
|
+
task.appendOutput(session.getOutput());
|
|
295
|
+
if (task.checkCompletion(session.getOutput()) || phrase) {
|
|
296
|
+
task.complete();
|
|
297
|
+
this.taskQueue.updateTask(task);
|
|
298
|
+
session.clearTask();
|
|
299
|
+
this.tasksCompleted++;
|
|
300
|
+
this.store.setRalphLoopState({ tasksCompleted: this.tasksCompleted });
|
|
301
|
+
this.emit('taskCompleted', task.id);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
handleSessionError(sessionId, error) {
|
|
305
|
+
const session = this.sessionManager.getSession(sessionId);
|
|
306
|
+
if (!session) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
const taskId = session.currentTaskId;
|
|
310
|
+
if (!taskId) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
const task = this.taskQueue.getTask(taskId);
|
|
314
|
+
if (!task) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
task.setError(error);
|
|
318
|
+
// Don't fail the task immediately on stderr - some tools write to stderr normally
|
|
319
|
+
}
|
|
320
|
+
handleSessionStopped(sessionId) {
|
|
321
|
+
const task = this.taskQueue.getRunningTaskForSession(sessionId);
|
|
322
|
+
if (task) {
|
|
323
|
+
task.fail('Session stopped unexpectedly');
|
|
324
|
+
this.taskQueue.updateTask(task);
|
|
325
|
+
this.emit('taskFailed', task.id, 'Session stopped unexpectedly');
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
handleSessionTaskError(_sessionId, taskId, error) {
|
|
329
|
+
const task = this.taskQueue.getTask(taskId);
|
|
330
|
+
if (!task) {
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
task.fail(error);
|
|
334
|
+
this.taskQueue.updateTask(task);
|
|
335
|
+
this.emit('taskFailed', task.id, error);
|
|
336
|
+
}
|
|
337
|
+
shouldGenerateTasks() {
|
|
338
|
+
// Generate tasks if:
|
|
339
|
+
// 1. No pending tasks
|
|
340
|
+
// 2. Min duration not reached
|
|
341
|
+
// 3. We have idle sessions
|
|
342
|
+
const counts = this.taskQueue.getCount();
|
|
343
|
+
return counts.pending === 0 && !this.isMinDurationReached() && this.sessionManager.getIdleSessions().length > 0;
|
|
344
|
+
}
|
|
345
|
+
async generateFollowUpTasks() {
|
|
346
|
+
// This is a placeholder for auto-generating follow-up tasks
|
|
347
|
+
// In a real implementation, this could:
|
|
348
|
+
// - Analyze completed tasks to find optimization opportunities
|
|
349
|
+
// - Generate tasks for code cleanup, tests, documentation
|
|
350
|
+
// - Use Claude to suggest improvements
|
|
351
|
+
const suggestions = [
|
|
352
|
+
'Review and optimize recently changed code',
|
|
353
|
+
'Add tests for uncovered code paths',
|
|
354
|
+
'Update documentation for changed APIs',
|
|
355
|
+
'Check for security vulnerabilities',
|
|
356
|
+
'Run linting and fix any issues',
|
|
357
|
+
];
|
|
358
|
+
// Only generate one task at a time
|
|
359
|
+
const suggestion = suggestions[this.tasksGenerated % suggestions.length];
|
|
360
|
+
const defaultDir = process.cwd();
|
|
361
|
+
this.taskQueue.addTask({
|
|
362
|
+
prompt: suggestion,
|
|
363
|
+
workingDir: defaultDir,
|
|
364
|
+
priority: -1, // Lower priority than user-added tasks
|
|
365
|
+
});
|
|
366
|
+
this.tasksGenerated++;
|
|
367
|
+
this.store.setRalphLoopState({ tasksGenerated: this.tasksGenerated });
|
|
368
|
+
}
|
|
369
|
+
shouldStop() {
|
|
370
|
+
const counts = this.taskQueue.getCount();
|
|
371
|
+
// Don't stop if there are pending or running tasks
|
|
372
|
+
if (counts.pending > 0 || counts.running > 0) {
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
// Don't stop if min duration not reached and auto-generate is on
|
|
376
|
+
if (!this.isMinDurationReached() && this.autoGenerateTasks) {
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
// All tasks done and conditions met
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
/** Sets the minimum duration in hours before the loop can stop. */
|
|
383
|
+
setMinDuration(hours) {
|
|
384
|
+
this.minDurationMs = hours * 60 * 60 * 1000;
|
|
385
|
+
this.store.setRalphLoopState({ minDurationMs: this.minDurationMs });
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Destroys the loop and cleans up all resources.
|
|
389
|
+
* Use this for complete cleanup (e.g., in tests or before creating a new instance).
|
|
390
|
+
* After calling destroy(), the instance should not be reused.
|
|
391
|
+
*/
|
|
392
|
+
destroy() {
|
|
393
|
+
this.stop();
|
|
394
|
+
this.cleanupEventHandlers();
|
|
395
|
+
this.removeAllListeners();
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
// Singleton instance
|
|
399
|
+
let loopInstance = null;
|
|
400
|
+
/** Gets or creates the singleton RalphLoop instance. */
|
|
401
|
+
export function getRalphLoop(options) {
|
|
402
|
+
if (!loopInstance) {
|
|
403
|
+
loopInstance = new RalphLoop(options);
|
|
404
|
+
}
|
|
405
|
+
return loopInstance;
|
|
406
|
+
}
|
|
407
|
+
/** Destroys the singleton instance. Use in tests or for cleanup. */
|
|
408
|
+
function destroyRalphLoop() {
|
|
409
|
+
if (loopInstance) {
|
|
410
|
+
loopInstance.destroy();
|
|
411
|
+
loopInstance = null;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
// Ensure cleanup on process exit (prevents orphaned event handlers and circular references)
|
|
415
|
+
process.on('exit', () => {
|
|
416
|
+
destroyRalphLoop();
|
|
417
|
+
});
|
|
418
|
+
//# sourceMappingURL=ralph-loop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ralph-loop.js","sourceRoot":"","sources":["../src/ralph-loop.ts"],"names":[],"mappings":"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"}
|