rlph-cli 1.2.1 → 1.3.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/dist/agents/base.d.ts +7 -0
- package/dist/agents/base.d.ts.map +1 -1
- package/dist/agents/base.js.map +1 -1
- package/dist/agents/claude.d.ts.map +1 -1
- package/dist/agents/claude.js +11 -1
- package/dist/agents/claude.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +139 -33
- package/dist/commands/run.js.map +1 -1
- package/dist/stream/persister.d.ts +61 -0
- package/dist/stream/persister.d.ts.map +1 -0
- package/dist/stream/persister.js +205 -0
- package/dist/stream/persister.js.map +1 -0
- package/dist/stream/types.d.ts +49 -0
- package/dist/stream/types.d.ts.map +1 -0
- package/dist/stream/types.js +2 -0
- package/dist/stream/types.js.map +1 -0
- package/package.json +1 -1
package/dist/agents/base.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ChildProcess } from 'node:child_process';
|
|
1
2
|
export interface AgentResult {
|
|
2
3
|
output: string;
|
|
3
4
|
exitCode: number;
|
|
@@ -5,6 +6,12 @@ export interface AgentResult {
|
|
|
5
6
|
}
|
|
6
7
|
export interface ExecuteOptions {
|
|
7
8
|
onOutput?: (chunk: string) => void;
|
|
9
|
+
/** Called for each formatted event for persistence. isEventBoundary signals event completion. */
|
|
10
|
+
onPersist?: (chunk: string, isEventBoundary: boolean) => void;
|
|
11
|
+
/** Called for stderr content */
|
|
12
|
+
onStderr?: (chunk: string) => void;
|
|
13
|
+
/** Called with spawned process for signal handling */
|
|
14
|
+
onProcess?: (proc: ChildProcess) => void;
|
|
8
15
|
}
|
|
9
16
|
export interface Agent {
|
|
10
17
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/agents/base.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/agents/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEtD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,iGAAiG;IACjG,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,KAAK,IAAI,CAAA;IAC7D,gCAAgC;IAChC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,sDAAsD;IACtD,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAA;CACzC;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;CACrF;AAED,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAA;AAEhC,eAAO,MAAM,gBAAgB,EAAE,SAAS,EAAe,CAAA;AAEvD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,SAAS,CAE9D"}
|
package/dist/agents/base.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/agents/base.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/agents/base.ts"],"names":[],"mappings":"AAyBA,MAAM,CAAC,MAAM,gBAAgB,GAAgB,CAAC,QAAQ,CAAC,CAAA;AAEvD,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,gBAAgB,CAAC,QAAQ,CAAC,KAAkB,CAAC,CAAA;AACtD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAA+B,MAAM,WAAW,CAAA;AAKnE,eAAO,MAAM,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAA+B,MAAM,WAAW,CAAA;AAKnE,eAAO,MAAM,MAAM,EAAE,KAqFpB,CAAA"}
|
package/dist/agents/claude.js
CHANGED
|
@@ -7,6 +7,9 @@ export const claude = {
|
|
|
7
7
|
async execute(prompt, cwd, options) {
|
|
8
8
|
const startTime = Date.now();
|
|
9
9
|
const onOutput = options?.onOutput;
|
|
10
|
+
const onPersist = options?.onPersist;
|
|
11
|
+
const onStderr = options?.onStderr;
|
|
12
|
+
const onProcess = options?.onProcess;
|
|
10
13
|
return new Promise((resolve, reject) => {
|
|
11
14
|
const proc = spawn('claude', [
|
|
12
15
|
'-p',
|
|
@@ -18,6 +21,8 @@ export const claude = {
|
|
|
18
21
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
19
22
|
shell: true,
|
|
20
23
|
});
|
|
24
|
+
// Expose process for signal handling
|
|
25
|
+
onProcess?.(proc);
|
|
21
26
|
let rawOutput = '';
|
|
22
27
|
let textOutput = '';
|
|
23
28
|
let stderr = '';
|
|
@@ -25,6 +30,8 @@ export const claude = {
|
|
|
25
30
|
const formatted = formatEvent(event);
|
|
26
31
|
if (formatted) {
|
|
27
32
|
onOutput?.(formatted + '\n');
|
|
33
|
+
// Persist with event boundary flag (event is complete)
|
|
34
|
+
onPersist?.(formatted + '\n', true);
|
|
28
35
|
}
|
|
29
36
|
// Accumulate text content for completion marker detection
|
|
30
37
|
if (event.type === 'assistant') {
|
|
@@ -35,7 +42,9 @@ export const claude = {
|
|
|
35
42
|
}
|
|
36
43
|
}
|
|
37
44
|
}, (_error, line) => {
|
|
38
|
-
|
|
45
|
+
const warning = chalk.yellow(`[warn] malformed JSON: ${line.slice(0, 100)}\n`);
|
|
46
|
+
onOutput?.(warning);
|
|
47
|
+
onPersist?.(warning, false);
|
|
39
48
|
});
|
|
40
49
|
proc.stdout.on('data', (data) => {
|
|
41
50
|
const chunk = data.toString();
|
|
@@ -46,6 +55,7 @@ export const claude = {
|
|
|
46
55
|
const chunk = data.toString();
|
|
47
56
|
stderr += chunk;
|
|
48
57
|
onOutput?.(chalk.red(chunk));
|
|
58
|
+
onStderr?.(chunk);
|
|
49
59
|
});
|
|
50
60
|
proc.on('error', (err) => {
|
|
51
61
|
reject(new Error(`Failed to spawn claude: ${err.message}`));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAGnD,MAAM,CAAC,MAAM,MAAM,GAAU;IAC3B,IAAI,EAAE,QAAQ;IAEd,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,GAAW,EAAE,OAAwB;QACjE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC5B,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;CACnB;AAmGD,wBAAsB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA4H1E"}
|
package/dist/commands/run.js
CHANGED
|
@@ -1,10 +1,92 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import { mkdir
|
|
2
|
+
import { mkdir } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { getAgent, isValidAgent } from '../agents/index.js';
|
|
5
5
|
import { getPrd, getPrdDir, prdExists } from '../prd/index.js';
|
|
6
|
+
import { StreamPersisterImpl } from '../stream/persister.js';
|
|
6
7
|
import { ensureTemplates, loadTemplate, substituteVars } from '../templates/index.js';
|
|
7
8
|
const TASKS_COMPLETE_MARKER = '<tasks>COMPLETE</tasks>';
|
|
9
|
+
const SIGNAL_EXIT_CODES = {
|
|
10
|
+
SIGINT: 130, // 128 + 2
|
|
11
|
+
SIGTERM: 143, // 128 + 15
|
|
12
|
+
SIGHUP: 129, // 128 + 1
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Signal handler manager for graceful interruption
|
|
16
|
+
*/
|
|
17
|
+
class SignalHandlers {
|
|
18
|
+
activePersister = null;
|
|
19
|
+
activeProcess = null;
|
|
20
|
+
handlers = new Map();
|
|
21
|
+
aborted = false;
|
|
22
|
+
handling = false; // re-entrancy guard
|
|
23
|
+
register() {
|
|
24
|
+
const signals = ['SIGINT', 'SIGTERM', 'SIGHUP'];
|
|
25
|
+
for (const signal of signals) {
|
|
26
|
+
const handler = () => void this.handleSignal(signal);
|
|
27
|
+
this.handlers.set(signal, handler);
|
|
28
|
+
process.addListener(signal, handler);
|
|
29
|
+
}
|
|
30
|
+
const exceptionHandler = (err) => void this.handleCrash(err instanceof Error ? err : new Error(String(err)));
|
|
31
|
+
this.handlers.set('uncaughtException', exceptionHandler);
|
|
32
|
+
process.addListener('uncaughtException', exceptionHandler);
|
|
33
|
+
}
|
|
34
|
+
unregister() {
|
|
35
|
+
const signals = ['SIGINT', 'SIGTERM', 'SIGHUP'];
|
|
36
|
+
for (const signal of signals) {
|
|
37
|
+
const handler = this.handlers.get(signal);
|
|
38
|
+
if (handler)
|
|
39
|
+
process.removeListener(signal, handler);
|
|
40
|
+
}
|
|
41
|
+
const exceptionHandler = this.handlers.get('uncaughtException');
|
|
42
|
+
if (exceptionHandler)
|
|
43
|
+
process.removeListener('uncaughtException', exceptionHandler);
|
|
44
|
+
this.handlers.clear();
|
|
45
|
+
}
|
|
46
|
+
setPersister(persister) {
|
|
47
|
+
this.activePersister = persister;
|
|
48
|
+
}
|
|
49
|
+
setProcess(proc) {
|
|
50
|
+
this.activeProcess = proc;
|
|
51
|
+
}
|
|
52
|
+
wasAborted() {
|
|
53
|
+
return this.aborted;
|
|
54
|
+
}
|
|
55
|
+
async handleSignal(signal) {
|
|
56
|
+
if (this.handling)
|
|
57
|
+
return; // re-entrancy guard
|
|
58
|
+
this.handling = true;
|
|
59
|
+
this.aborted = true;
|
|
60
|
+
// Kill child process first
|
|
61
|
+
if (this.activeProcess && !this.activeProcess.killed) {
|
|
62
|
+
this.activeProcess.kill(signal);
|
|
63
|
+
this.activeProcess = null;
|
|
64
|
+
}
|
|
65
|
+
if (this.activePersister) {
|
|
66
|
+
await this.activePersister.abort(signal);
|
|
67
|
+
this.activePersister = null;
|
|
68
|
+
}
|
|
69
|
+
this.unregister();
|
|
70
|
+
process.exit(SIGNAL_EXIT_CODES[signal]);
|
|
71
|
+
}
|
|
72
|
+
async handleCrash(error) {
|
|
73
|
+
if (this.handling)
|
|
74
|
+
return; // re-entrancy guard
|
|
75
|
+
this.handling = true;
|
|
76
|
+
// Kill child process
|
|
77
|
+
if (this.activeProcess && !this.activeProcess.killed) {
|
|
78
|
+
this.activeProcess.kill();
|
|
79
|
+
this.activeProcess = null;
|
|
80
|
+
}
|
|
81
|
+
if (this.activePersister) {
|
|
82
|
+
await this.activePersister.crash(error);
|
|
83
|
+
this.activePersister = null;
|
|
84
|
+
}
|
|
85
|
+
this.unregister();
|
|
86
|
+
console.error(chalk.red(`Uncaught exception: ${error.message}`));
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
8
90
|
export async function run(prdName, opts) {
|
|
9
91
|
// Validate agent
|
|
10
92
|
if (!isValidAgent(opts.agent)) {
|
|
@@ -46,31 +128,67 @@ export async function run(prdName, opts) {
|
|
|
46
128
|
console.log(chalk.gray(`Pending tasks: ${pendingTasks}/${prd.tasks.length}`));
|
|
47
129
|
console.log(chalk.gray(`Iterations: ${iterations}`));
|
|
48
130
|
console.log();
|
|
131
|
+
// Set up signal handlers for graceful interruption
|
|
132
|
+
const signalHandlers = new SignalHandlers();
|
|
133
|
+
signalHandlers.register();
|
|
49
134
|
// Run loop
|
|
50
135
|
let completed = false;
|
|
51
136
|
let actualIterations = 0;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
137
|
+
try {
|
|
138
|
+
for (let i = 0; i < iterations; i++) {
|
|
139
|
+
actualIterations++;
|
|
140
|
+
console.log(chalk.yellow(`[${i + 1}/${iterations}] Running ${agent.name}...`));
|
|
141
|
+
console.log();
|
|
142
|
+
const logPath = join(iterationsDir, `${i}.log`);
|
|
143
|
+
const persister = new StreamPersisterImpl({ logPath });
|
|
144
|
+
signalHandlers.setPersister(persister);
|
|
145
|
+
let result;
|
|
146
|
+
try {
|
|
147
|
+
result = await agent.execute(prompt, process.cwd(), {
|
|
148
|
+
onOutput: (chunk) => process.stdout.write(chunk),
|
|
149
|
+
onPersist: (chunk, isEventBoundary) => {
|
|
150
|
+
void persister.append(chunk, isEventBoundary);
|
|
151
|
+
},
|
|
152
|
+
onStderr: (chunk) => {
|
|
153
|
+
void persister.appendStderr(chunk);
|
|
154
|
+
},
|
|
155
|
+
onProcess: (proc) => signalHandlers.setProcess(proc),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
// Execution failed - persist crash state and re-throw
|
|
160
|
+
await persister.crash(err instanceof Error ? err : new Error(String(err)));
|
|
161
|
+
signalHandlers.setPersister(null);
|
|
162
|
+
signalHandlers.setProcess(null);
|
|
163
|
+
throw err;
|
|
164
|
+
}
|
|
165
|
+
signalHandlers.setProcess(null);
|
|
166
|
+
// Complete THEN clear persister (fixes race with signal handlers)
|
|
167
|
+
await persister.complete(result.exitCode, result.duration);
|
|
168
|
+
signalHandlers.setPersister(null);
|
|
169
|
+
// Check for persistence errors
|
|
170
|
+
const persistError = persister.getError();
|
|
171
|
+
if (persistError) {
|
|
172
|
+
console.log(chalk.yellow(` Warning: log write error: ${persistError.message}`));
|
|
173
|
+
}
|
|
174
|
+
console.log();
|
|
175
|
+
if (result.exitCode !== 0) {
|
|
176
|
+
console.log(chalk.red(` Exit code: ${result.exitCode}`));
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
console.log(chalk.green(` Done (${result.duration}ms)`));
|
|
180
|
+
}
|
|
181
|
+
// Check for completion marker
|
|
182
|
+
if (result.output.includes(TASKS_COMPLETE_MARKER)) {
|
|
183
|
+
console.log(chalk.cyan(` All tasks complete`));
|
|
184
|
+
completed = true;
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
72
187
|
}
|
|
73
188
|
}
|
|
189
|
+
finally {
|
|
190
|
+
signalHandlers.unregister();
|
|
191
|
+
}
|
|
74
192
|
console.log();
|
|
75
193
|
if (completed) {
|
|
76
194
|
console.log(chalk.green(`PRD completed after ${actualIterations} iteration(s)`));
|
|
@@ -80,16 +198,4 @@ export async function run(prdName, opts) {
|
|
|
80
198
|
}
|
|
81
199
|
console.log(chalk.gray(`Logs: ${iterationsDir}`));
|
|
82
200
|
}
|
|
83
|
-
async function writeIterationLog(iterationsDir, iteration, result) {
|
|
84
|
-
const logPath = join(iterationsDir, `${iteration}.log`);
|
|
85
|
-
const header = [
|
|
86
|
-
`# Iteration ${iteration}`,
|
|
87
|
-
`Timestamp: ${new Date().toISOString()}`,
|
|
88
|
-
`Duration: ${result.duration}ms`,
|
|
89
|
-
`Exit Code: ${result.exitCode}`,
|
|
90
|
-
'---',
|
|
91
|
-
'',
|
|
92
|
-
].join('\n');
|
|
93
|
-
await writeFile(logPath, header + result.output);
|
|
94
|
-
}
|
|
95
201
|
//# sourceMappingURL=run.js.map
|
package/dist/commands/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { StreamPersister, StreamPersisterOptions } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Persists streamed output incrementally with buffering
|
|
4
|
+
*/
|
|
5
|
+
export declare class StreamPersisterImpl implements StreamPersister {
|
|
6
|
+
private buffer;
|
|
7
|
+
private logPath;
|
|
8
|
+
private status;
|
|
9
|
+
private startTime;
|
|
10
|
+
private headerWritten;
|
|
11
|
+
private writeError;
|
|
12
|
+
private fileHandle;
|
|
13
|
+
private flushTimer;
|
|
14
|
+
private flushIntervalMs;
|
|
15
|
+
private flushing;
|
|
16
|
+
private finalized;
|
|
17
|
+
constructor(options: StreamPersisterOptions);
|
|
18
|
+
/**
|
|
19
|
+
* Starts the auto-flush timer if not already running
|
|
20
|
+
*/
|
|
21
|
+
private startFlushTimer;
|
|
22
|
+
/**
|
|
23
|
+
* Stops the auto-flush timer
|
|
24
|
+
*/
|
|
25
|
+
private stopFlushTimer;
|
|
26
|
+
/**
|
|
27
|
+
* Ensures file handle is open and header is written
|
|
28
|
+
*/
|
|
29
|
+
private ensureFile;
|
|
30
|
+
/**
|
|
31
|
+
* Writes the log header with in_progress status
|
|
32
|
+
*/
|
|
33
|
+
private writeHeader;
|
|
34
|
+
/**
|
|
35
|
+
* Writes content to file atomically (complete string only)
|
|
36
|
+
*/
|
|
37
|
+
private writeToFile;
|
|
38
|
+
append(content: string, isEventBoundary?: boolean): Promise<void>;
|
|
39
|
+
appendStderr(content: string): Promise<void>;
|
|
40
|
+
flush(): Promise<void>;
|
|
41
|
+
complete(exitCode: number, duration: number): Promise<void>;
|
|
42
|
+
abort(signal: string): Promise<void>;
|
|
43
|
+
crash(error: Error): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Writes final metadata section
|
|
46
|
+
*/
|
|
47
|
+
private writeMetadata;
|
|
48
|
+
/**
|
|
49
|
+
* Closes the file handle
|
|
50
|
+
*/
|
|
51
|
+
private close;
|
|
52
|
+
/**
|
|
53
|
+
* Cleanup method for cases where persister is abandoned without complete/abort/crash
|
|
54
|
+
*/
|
|
55
|
+
destroy(): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Returns any write error that occurred
|
|
58
|
+
*/
|
|
59
|
+
getError(): Error | null;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=persister.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persister.d.ts","sourceRoot":"","sources":["../../src/stream/persister.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAgB,MAAM,YAAY,CAAA;AAElF;;GAEG;AACH,qBAAa,mBAAoB,YAAW,eAAe;IACzD,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,SAAS,CAAQ;gBAEb,OAAO,EAAE,sBAAsB;IAM3C;;OAEG;IACH,OAAO,CAAC,eAAe;IAQvB;;OAEG;IACH,OAAO,CAAC,cAAc;IAOtB;;OAEG;YACW,UAAU;IAwBxB;;OAEG;YACW,WAAW;IAYzB;;OAEG;YACW,WAAW;IAWnB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAS/D,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU3D,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUpC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAUxC;;OAEG;YACW,aAAa;IA2B3B;;OAEG;YACW,KAAK;IAWnB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAK9B;;OAEG;IACH,QAAQ,IAAI,KAAK,GAAG,IAAI;CAGzB"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Persists streamed output incrementally with buffering
|
|
5
|
+
*/
|
|
6
|
+
export class StreamPersisterImpl {
|
|
7
|
+
buffer = '';
|
|
8
|
+
logPath;
|
|
9
|
+
status = 'in_progress';
|
|
10
|
+
startTime;
|
|
11
|
+
headerWritten = false;
|
|
12
|
+
writeError = null;
|
|
13
|
+
fileHandle = null;
|
|
14
|
+
flushTimer = null;
|
|
15
|
+
flushIntervalMs;
|
|
16
|
+
flushing = false; // mutex for flush
|
|
17
|
+
finalized = false; // guard against double finalization
|
|
18
|
+
constructor(options) {
|
|
19
|
+
this.logPath = options.logPath;
|
|
20
|
+
this.startTime = Date.now();
|
|
21
|
+
this.flushIntervalMs = options.flushIntervalMs ?? 100;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Starts the auto-flush timer if not already running
|
|
25
|
+
*/
|
|
26
|
+
startFlushTimer() {
|
|
27
|
+
if (this.flushTimer)
|
|
28
|
+
return;
|
|
29
|
+
this.flushTimer = setInterval(() => {
|
|
30
|
+
void this.flush();
|
|
31
|
+
}, this.flushIntervalMs);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Stops the auto-flush timer
|
|
35
|
+
*/
|
|
36
|
+
stopFlushTimer() {
|
|
37
|
+
if (!this.flushTimer)
|
|
38
|
+
return;
|
|
39
|
+
clearInterval(this.flushTimer);
|
|
40
|
+
this.flushTimer = null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Ensures file handle is open and header is written
|
|
44
|
+
*/
|
|
45
|
+
async ensureFile() {
|
|
46
|
+
if (this.writeError)
|
|
47
|
+
return null;
|
|
48
|
+
if (!this.fileHandle) {
|
|
49
|
+
try {
|
|
50
|
+
// Ensure directory exists
|
|
51
|
+
await fs.mkdir(dirname(this.logPath), { recursive: true });
|
|
52
|
+
this.fileHandle = await fs.open(this.logPath, 'w');
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
this.writeError = err instanceof Error ? err : new Error(String(err));
|
|
56
|
+
console.error(`[StreamPersister] Failed to open file: ${this.writeError.message}`);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (!this.headerWritten) {
|
|
61
|
+
await this.writeHeader();
|
|
62
|
+
this.headerWritten = true;
|
|
63
|
+
}
|
|
64
|
+
return this.fileHandle;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Writes the log header with in_progress status
|
|
68
|
+
*/
|
|
69
|
+
async writeHeader() {
|
|
70
|
+
const header = [
|
|
71
|
+
`# Iteration Log`,
|
|
72
|
+
`Timestamp: ${new Date(this.startTime).toISOString()}`,
|
|
73
|
+
`Status: ${this.status}`,
|
|
74
|
+
'---',
|
|
75
|
+
'',
|
|
76
|
+
].join('\n');
|
|
77
|
+
await this.writeToFile(header);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Writes content to file atomically (complete string only)
|
|
81
|
+
*/
|
|
82
|
+
async writeToFile(content) {
|
|
83
|
+
if (!this.fileHandle || this.writeError)
|
|
84
|
+
return;
|
|
85
|
+
try {
|
|
86
|
+
await this.fileHandle.write(content, null, 'utf8');
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
this.writeError = err instanceof Error ? err : new Error(String(err));
|
|
90
|
+
console.error(`[StreamPersister] Write error: ${this.writeError.message}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async append(content, isEventBoundary = false) {
|
|
94
|
+
this.buffer += content;
|
|
95
|
+
this.startFlushTimer();
|
|
96
|
+
if (isEventBoundary) {
|
|
97
|
+
await this.flush();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async appendStderr(content) {
|
|
101
|
+
// Prefix each line with [stderr]
|
|
102
|
+
const prefixed = content
|
|
103
|
+
.split('\n')
|
|
104
|
+
.map((line) => (line ? `[stderr] ${line}` : line))
|
|
105
|
+
.join('\n');
|
|
106
|
+
this.buffer += prefixed;
|
|
107
|
+
this.startFlushTimer();
|
|
108
|
+
}
|
|
109
|
+
async flush() {
|
|
110
|
+
if (!this.buffer || this.flushing)
|
|
111
|
+
return;
|
|
112
|
+
this.flushing = true;
|
|
113
|
+
try {
|
|
114
|
+
const handle = await this.ensureFile();
|
|
115
|
+
if (!handle)
|
|
116
|
+
return;
|
|
117
|
+
const content = this.buffer;
|
|
118
|
+
this.buffer = '';
|
|
119
|
+
await this.writeToFile(content);
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
this.flushing = false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async complete(exitCode, duration) {
|
|
126
|
+
if (this.finalized)
|
|
127
|
+
return;
|
|
128
|
+
this.finalized = true;
|
|
129
|
+
this.stopFlushTimer();
|
|
130
|
+
this.status = 'completed';
|
|
131
|
+
await this.flush();
|
|
132
|
+
await this.writeMetadata({ exitCode, duration });
|
|
133
|
+
await this.close();
|
|
134
|
+
}
|
|
135
|
+
async abort(signal) {
|
|
136
|
+
if (this.finalized)
|
|
137
|
+
return;
|
|
138
|
+
this.finalized = true;
|
|
139
|
+
this.stopFlushTimer();
|
|
140
|
+
this.status = 'aborted';
|
|
141
|
+
await this.flush();
|
|
142
|
+
await this.writeMetadata({ signal });
|
|
143
|
+
await this.close();
|
|
144
|
+
}
|
|
145
|
+
async crash(error) {
|
|
146
|
+
if (this.finalized)
|
|
147
|
+
return;
|
|
148
|
+
this.finalized = true;
|
|
149
|
+
this.stopFlushTimer();
|
|
150
|
+
this.status = 'crashed';
|
|
151
|
+
await this.flush();
|
|
152
|
+
await this.writeMetadata({ error: error.message });
|
|
153
|
+
await this.close();
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Writes final metadata section
|
|
157
|
+
*/
|
|
158
|
+
async writeMetadata(info) {
|
|
159
|
+
const handle = await this.ensureFile();
|
|
160
|
+
if (!handle)
|
|
161
|
+
return;
|
|
162
|
+
const parts = ['\n---', `Status: ${this.status}`];
|
|
163
|
+
if (info.exitCode !== undefined) {
|
|
164
|
+
parts.push(`Exit Code: ${info.exitCode}`);
|
|
165
|
+
}
|
|
166
|
+
if (info.duration !== undefined) {
|
|
167
|
+
parts.push(`Duration: ${info.duration}ms`);
|
|
168
|
+
}
|
|
169
|
+
if (info.signal) {
|
|
170
|
+
parts.push(`Interrupted: ${info.signal}`);
|
|
171
|
+
}
|
|
172
|
+
if (info.error) {
|
|
173
|
+
parts.push(`Error: ${info.error}`);
|
|
174
|
+
}
|
|
175
|
+
await this.writeToFile(parts.join('\n') + '\n');
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Closes the file handle
|
|
179
|
+
*/
|
|
180
|
+
async close() {
|
|
181
|
+
if (!this.fileHandle)
|
|
182
|
+
return;
|
|
183
|
+
try {
|
|
184
|
+
await this.fileHandle.close();
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
// Ignore close errors
|
|
188
|
+
}
|
|
189
|
+
this.fileHandle = null;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Cleanup method for cases where persister is abandoned without complete/abort/crash
|
|
193
|
+
*/
|
|
194
|
+
async destroy() {
|
|
195
|
+
this.stopFlushTimer();
|
|
196
|
+
await this.close();
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Returns any write error that occurred
|
|
200
|
+
*/
|
|
201
|
+
getError() {
|
|
202
|
+
return this.writeError;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=persister.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persister.js","sourceRoot":"","sources":["../../src/stream/persister.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status of a stream persistence log
|
|
3
|
+
*/
|
|
4
|
+
export type StreamStatus = 'in_progress' | 'completed' | 'aborted' | 'crashed';
|
|
5
|
+
/**
|
|
6
|
+
* Options for creating a StreamPersister
|
|
7
|
+
*/
|
|
8
|
+
export interface StreamPersisterOptions {
|
|
9
|
+
/** Path to the log file */
|
|
10
|
+
logPath: string;
|
|
11
|
+
/** Interval in ms for auto-flush (default: 100) */
|
|
12
|
+
flushIntervalMs?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Interface for persisting streamed output incrementally
|
|
16
|
+
*/
|
|
17
|
+
export interface StreamPersister {
|
|
18
|
+
/**
|
|
19
|
+
* Append formatted content to buffer
|
|
20
|
+
* Called for each formatted event
|
|
21
|
+
* @param isEventBoundary If true, triggers immediate flush
|
|
22
|
+
*/
|
|
23
|
+
append(content: string, isEventBoundary?: boolean): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Append stderr content with [stderr] prefix
|
|
26
|
+
*/
|
|
27
|
+
appendStderr(content: string): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Force flush buffer to disk
|
|
30
|
+
*/
|
|
31
|
+
flush(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Called on normal completion
|
|
34
|
+
*/
|
|
35
|
+
complete(exitCode: number, duration: number): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Called on interruption (SIGINT, SIGTERM, SIGHUP)
|
|
38
|
+
*/
|
|
39
|
+
abort(signal: string): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Called on crash (uncaughtException)
|
|
42
|
+
*/
|
|
43
|
+
crash(error: Error): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Returns any write error that occurred during persistence
|
|
46
|
+
*/
|
|
47
|
+
getError(): Error | null;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/stream/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAA;AAE9E;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEjE;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE5C;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IAEtB;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE3D;;OAEG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEpC;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAElC;;OAEG;IACH,QAAQ,IAAI,KAAK,GAAG,IAAI,CAAA;CACzB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/stream/types.ts"],"names":[],"mappings":""}
|