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.
@@ -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;CACnC;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"}
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"}
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/agents/base.ts"],"names":[],"mappings":"AAiBA,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
+ {"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,KA0EpB,CAAA"}
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"}
@@ -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
- onOutput?.(chalk.yellow(`[warn] malformed JSON: ${line.slice(0, 100)}\n`));
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":"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"}
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":"AASA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wBAAsB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAsF1E"}
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"}
@@ -1,10 +1,92 @@
1
1
  import chalk from 'chalk';
2
- import { mkdir, writeFile } from 'node:fs/promises';
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
- for (let i = 0; i < iterations; i++) {
53
- actualIterations++;
54
- console.log(chalk.yellow(`[${i + 1}/${iterations}] Running ${agent.name}...`));
55
- console.log();
56
- const result = await agent.execute(prompt, process.cwd(), {
57
- onOutput: (chunk) => process.stdout.write(chunk),
58
- });
59
- console.log();
60
- await writeIterationLog(iterationsDir, i, result);
61
- if (result.exitCode !== 0) {
62
- console.log(chalk.red(` Exit code: ${result.exitCode}`));
63
- }
64
- else {
65
- console.log(chalk.green(` Done (${result.duration}ms)`));
66
- }
67
- // Check for completion marker
68
- if (result.output.includes(TASKS_COMPLETE_MARKER)) {
69
- console.log(chalk.cyan(` All tasks complete`));
70
- completed = true;
71
- break;
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
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/stream/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rlph-cli",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "Loop coding agent CLI - run agents headlessly in a loop",
5
5
  "type": "module",
6
6
  "bin": {