@portel/photon-core 1.3.0 → 1.4.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.
@@ -0,0 +1,469 @@
1
+ /**
2
+ * Stateful Workflow Execution with JSONL Persistence
3
+ *
4
+ * Enables photon workflows to be paused, resumed, and recovered across daemon restarts.
5
+ *
6
+ * ══════════════════════════════════════════════════════════════════════════════
7
+ * DESIGN PHILOSOPHY
8
+ * ══════════════════════════════════════════════════════════════════════════════
9
+ *
10
+ * Stateful workflows use an append-only JSONL log for persistence:
11
+ * - Each line is a self-contained JSON entry (start, emit, checkpoint, ask, answer, return, error)
12
+ * - Checkpoints mark safe resume points with accumulated state
13
+ * - Developer places checkpoint AFTER side effects to ensure idempotency
14
+ * - Resume loads log, reconstructs state from last checkpoint, continues
15
+ *
16
+ * ══════════════════════════════════════════════════════════════════════════════
17
+ * CHECKPOINT PATTERN (Idempotent Resume)
18
+ * ══════════════════════════════════════════════════════════════════════════════
19
+ *
20
+ * ```typescript
21
+ * async *workflow() {
22
+ * // Step 1: Side effect (e.g., posting to Slack)
23
+ * const posted = await this.slack.post_message({ channel: '#eng', text: 'Hello' });
24
+ * yield { checkpoint: true, state: { step: 1, messageTs: posted.ts } };
25
+ *
26
+ * // Step 2: Another side effect (e.g., creating GitHub issue)
27
+ * const issue = await this.github.create_issue({ ... });
28
+ * yield { checkpoint: true, state: { step: 2, messageTs: posted.ts, issueNumber: issue.number } };
29
+ *
30
+ * return { posted, issue };
31
+ * }
32
+ * ```
33
+ *
34
+ * On resume: Load state from last checkpoint, skip to that step, continue execution.
35
+ *
36
+ * ══════════════════════════════════════════════════════════════════════════════
37
+ * JSONL LOG FORMAT
38
+ * ══════════════════════════════════════════════════════════════════════════════
39
+ *
40
+ * ~/.photon/runs/{runId}.jsonl
41
+ *
42
+ * ```jsonl
43
+ * {"t":"start","tool":"generate","params":{"week":"52"},"ts":1704067200}
44
+ * {"t":"emit","emit":"status","message":"Collecting data...","ts":1704067201}
45
+ * {"t":"checkpoint","id":"cp_1","state":{"commits":["a1b2c3"],"step":1},"ts":1704067205}
46
+ * {"t":"ask","id":"approve","ask":"confirm","message":"Continue?","ts":1704067211}
47
+ * {"t":"answer","id":"approve","value":true,"ts":1704067215}
48
+ * {"t":"return","value":{"status":"done"},"ts":1704067220}
49
+ * ```
50
+ *
51
+ * @module stateful
52
+ */
53
+ import * as fs from 'fs/promises';
54
+ import * as path from 'path';
55
+ import * as os from 'os';
56
+ import { createReadStream } from 'fs';
57
+ import { createInterface } from 'readline';
58
+ import { isAskYield, isEmitYield, isAsyncGenerator, } from './generator.js';
59
+ // ══════════════════════════════════════════════════════════════════════════════
60
+ // CONSTANTS
61
+ // ══════════════════════════════════════════════════════════════════════════════
62
+ /**
63
+ * Default runs directory (~/.photon/runs)
64
+ */
65
+ export const RUNS_DIR = path.join(os.homedir(), '.photon', 'runs');
66
+ /**
67
+ * Type guard for checkpoint yields
68
+ */
69
+ export function isCheckpointYield(y) {
70
+ return 'checkpoint' in y && y.checkpoint === true;
71
+ }
72
+ // ══════════════════════════════════════════════════════════════════════════════
73
+ // STATE LOG - JSONL Persistence
74
+ // ══════════════════════════════════════════════════════════════════════════════
75
+ /**
76
+ * State log writer for a single workflow run
77
+ */
78
+ export class StateLog {
79
+ runId;
80
+ logPath;
81
+ constructor(runId, runsDir) {
82
+ this.runId = runId;
83
+ this.logPath = path.join(runsDir || RUNS_DIR, `${runId}.jsonl`);
84
+ }
85
+ /**
86
+ * Ensure runs directory exists
87
+ */
88
+ async init() {
89
+ await fs.mkdir(path.dirname(this.logPath), { recursive: true });
90
+ }
91
+ /**
92
+ * Append an entry to the log
93
+ */
94
+ async append(entry) {
95
+ const line = JSON.stringify({ ...entry, ts: Date.now() }) + '\n';
96
+ await fs.appendFile(this.logPath, line, 'utf-8');
97
+ }
98
+ /**
99
+ * Write start entry
100
+ */
101
+ async writeStart(tool, params) {
102
+ await this.append({ t: 'start', tool, params });
103
+ }
104
+ /**
105
+ * Write emit entry
106
+ */
107
+ async writeEmit(emit, message, data) {
108
+ await this.append({ t: 'emit', emit, message, data });
109
+ }
110
+ /**
111
+ * Write checkpoint entry
112
+ */
113
+ async writeCheckpoint(id, state) {
114
+ await this.append({ t: 'checkpoint', id, state });
115
+ }
116
+ /**
117
+ * Write ask entry
118
+ */
119
+ async writeAsk(id, ask, message) {
120
+ await this.append({ t: 'ask', id, ask, message });
121
+ }
122
+ /**
123
+ * Write answer entry
124
+ */
125
+ async writeAnswer(id, value) {
126
+ await this.append({ t: 'answer', id, value });
127
+ }
128
+ /**
129
+ * Write return entry
130
+ */
131
+ async writeReturn(value) {
132
+ await this.append({ t: 'return', value });
133
+ }
134
+ /**
135
+ * Write error entry
136
+ */
137
+ async writeError(message, stack) {
138
+ await this.append({ t: 'error', message, stack });
139
+ }
140
+ /**
141
+ * Read all entries from the log
142
+ */
143
+ async readAll() {
144
+ try {
145
+ const content = await fs.readFile(this.logPath, 'utf-8');
146
+ return content
147
+ .trim()
148
+ .split('\n')
149
+ .filter(line => line.length > 0)
150
+ .map(line => JSON.parse(line));
151
+ }
152
+ catch (error) {
153
+ if (error.code === 'ENOENT') {
154
+ return [];
155
+ }
156
+ throw error;
157
+ }
158
+ }
159
+ /**
160
+ * Stream entries from the log (memory efficient for large logs)
161
+ */
162
+ async *stream() {
163
+ const fileStream = createReadStream(this.logPath);
164
+ const rl = createInterface({ input: fileStream });
165
+ for await (const line of rl) {
166
+ if (line.trim()) {
167
+ yield JSON.parse(line);
168
+ }
169
+ }
170
+ }
171
+ /**
172
+ * Get the log file path
173
+ */
174
+ getPath() {
175
+ return this.logPath;
176
+ }
177
+ }
178
+ /**
179
+ * Parse a workflow log and reconstruct resume state
180
+ */
181
+ export async function parseResumeState(runId, runsDir) {
182
+ const log = new StateLog(runId, runsDir);
183
+ const entries = await log.readAll();
184
+ if (entries.length === 0) {
185
+ return null;
186
+ }
187
+ const state = {
188
+ tool: '',
189
+ params: {},
190
+ isComplete: false,
191
+ answers: {},
192
+ entries,
193
+ };
194
+ for (const entry of entries) {
195
+ switch (entry.t) {
196
+ case 'start':
197
+ state.tool = entry.tool;
198
+ state.params = entry.params;
199
+ break;
200
+ case 'checkpoint':
201
+ state.lastCheckpoint = {
202
+ id: entry.id,
203
+ state: entry.state,
204
+ ts: entry.ts,
205
+ };
206
+ break;
207
+ case 'answer':
208
+ state.answers[entry.id] = entry.value;
209
+ break;
210
+ case 'return':
211
+ state.isComplete = true;
212
+ state.result = entry.value;
213
+ break;
214
+ case 'error':
215
+ state.isComplete = true;
216
+ state.error = entry.message;
217
+ break;
218
+ }
219
+ }
220
+ return state;
221
+ }
222
+ /**
223
+ * Generate a unique run ID
224
+ */
225
+ export function generateRunId() {
226
+ const timestamp = Date.now().toString(36);
227
+ const random = Math.random().toString(36).substring(2, 8);
228
+ return `run_${timestamp}_${random}`;
229
+ }
230
+ /**
231
+ * Execute a stateful generator with checkpoint support
232
+ *
233
+ * @example
234
+ * const result = await executeStatefulGenerator(workflow(), {
235
+ * photon: 'weekly-report',
236
+ * tool: 'generate',
237
+ * params: { week: 52 },
238
+ * inputProvider: cliInputProvider,
239
+ * outputHandler: (emit) => console.log(emit.message)
240
+ * });
241
+ */
242
+ export async function executeStatefulGenerator(generatorFn, config) {
243
+ const runId = config.runId || generateRunId();
244
+ const log = new StateLog(runId, config.runsDir);
245
+ await log.init();
246
+ let resumed = false;
247
+ let resumeState = null;
248
+ let checkpointIndex = 0;
249
+ let askIndex = 0;
250
+ // Check if we should resume
251
+ if (config.resume) {
252
+ resumeState = await parseResumeState(runId, config.runsDir);
253
+ if (resumeState) {
254
+ resumed = true;
255
+ if (resumeState.isComplete) {
256
+ // Already complete, return cached result
257
+ return {
258
+ runId,
259
+ result: resumeState.result,
260
+ error: resumeState.error,
261
+ resumed: true,
262
+ status: resumeState.error ? 'failed' : 'completed',
263
+ };
264
+ }
265
+ }
266
+ }
267
+ // Write start entry (only if not resuming)
268
+ if (!resumed) {
269
+ await log.writeStart(config.tool, config.params);
270
+ }
271
+ try {
272
+ // Call the function and check if it returns a generator or a promise
273
+ const maybeGenerator = generatorFn();
274
+ // Handle non-generator functions (regular async methods)
275
+ if (!isAsyncGenerator(maybeGenerator)) {
276
+ // It's a promise, await it directly
277
+ const finalValue = await maybeGenerator;
278
+ await log.writeReturn(finalValue);
279
+ return {
280
+ runId,
281
+ result: finalValue,
282
+ resumed,
283
+ status: 'completed',
284
+ };
285
+ }
286
+ // It's a generator, proceed with generator execution
287
+ const generator = maybeGenerator;
288
+ let result = await generator.next();
289
+ // If resuming, fast-forward to last checkpoint
290
+ if (resumed && resumeState?.lastCheckpoint) {
291
+ const targetCheckpointId = resumeState.lastCheckpoint.id;
292
+ let foundCheckpoint = false;
293
+ // Fast-forward: run generator, skip until we hit the checkpoint
294
+ while (!result.done) {
295
+ const yielded = result.value;
296
+ if (isCheckpointYield(yielded)) {
297
+ const cpId = yielded.id || `cp_${checkpointIndex++}`;
298
+ if (cpId === targetCheckpointId) {
299
+ foundCheckpoint = true;
300
+ // Inject the saved state
301
+ result = await generator.next(resumeState.lastCheckpoint.state);
302
+ break;
303
+ }
304
+ // Not our checkpoint, continue
305
+ result = await generator.next(yielded.state);
306
+ }
307
+ else if (isAskYield(yielded)) {
308
+ // Use saved answer
309
+ const askId = yielded.id || `ask_${askIndex++}`;
310
+ if (askId in resumeState.answers) {
311
+ result = await generator.next(resumeState.answers[askId]);
312
+ }
313
+ else {
314
+ // No saved answer, this shouldn't happen if log is consistent
315
+ throw new Error(`Resume error: missing answer for ask '${askId}'`);
316
+ }
317
+ }
318
+ else if (isEmitYield(yielded)) {
319
+ // Skip emits during fast-forward
320
+ result = await generator.next();
321
+ }
322
+ else {
323
+ result = await generator.next();
324
+ }
325
+ }
326
+ if (!foundCheckpoint && !result.done) {
327
+ console.warn(`[stateful] Checkpoint '${targetCheckpointId}' not found during resume`);
328
+ }
329
+ }
330
+ // Normal execution loop
331
+ while (!result.done) {
332
+ const yielded = result.value;
333
+ if (isCheckpointYield(yielded)) {
334
+ const cpId = yielded.id || `cp_${checkpointIndex++}`;
335
+ await log.writeCheckpoint(cpId, yielded.state);
336
+ // Continue with the state (generator may use it)
337
+ result = await generator.next(yielded.state);
338
+ }
339
+ else if (isAskYield(yielded)) {
340
+ const askYield = yielded;
341
+ const askId = askYield.id || `ask_${askIndex++}`;
342
+ // Check for pre-answered (from resume state)
343
+ if (resumeState && askId in resumeState.answers) {
344
+ result = await generator.next(resumeState.answers[askId]);
345
+ continue;
346
+ }
347
+ // Log ask and get input
348
+ await log.writeAsk(askId, askYield.ask, askYield.message);
349
+ const input = await config.inputProvider(askYield);
350
+ await log.writeAnswer(askId, input);
351
+ result = await generator.next(input);
352
+ }
353
+ else if (isEmitYield(yielded)) {
354
+ const emitYield = yielded;
355
+ await log.writeEmit(emitYield.emit, emitYield.message, emitYield);
356
+ if (config.outputHandler) {
357
+ await config.outputHandler(emitYield);
358
+ }
359
+ result = await generator.next();
360
+ }
361
+ else {
362
+ // Unknown yield, skip
363
+ result = await generator.next();
364
+ }
365
+ }
366
+ // Write return entry
367
+ await log.writeReturn(result.value);
368
+ return {
369
+ runId,
370
+ result: result.value,
371
+ resumed,
372
+ status: 'completed',
373
+ };
374
+ }
375
+ catch (error) {
376
+ await log.writeError(error.message, error.stack);
377
+ return {
378
+ runId,
379
+ error: error.message,
380
+ resumed,
381
+ status: 'failed',
382
+ };
383
+ }
384
+ }
385
+ // ══════════════════════════════════════════════════════════════════════════════
386
+ // WORKFLOW RUN MANAGEMENT
387
+ // ══════════════════════════════════════════════════════════════════════════════
388
+ /**
389
+ * List all workflow runs
390
+ */
391
+ export async function listRuns(runsDir) {
392
+ const dir = runsDir || RUNS_DIR;
393
+ const runs = [];
394
+ try {
395
+ const files = await fs.readdir(dir);
396
+ const jsonlFiles = files.filter(f => f.endsWith('.jsonl'));
397
+ for (const file of jsonlFiles) {
398
+ const runId = file.replace('.jsonl', '');
399
+ const run = await getRunInfo(runId, dir);
400
+ if (run) {
401
+ runs.push(run);
402
+ }
403
+ }
404
+ // Sort by start time, most recent first
405
+ runs.sort((a, b) => b.startedAt - a.startedAt);
406
+ return runs;
407
+ }
408
+ catch (error) {
409
+ if (error.code === 'ENOENT') {
410
+ return [];
411
+ }
412
+ throw error;
413
+ }
414
+ }
415
+ /**
416
+ * Get info about a specific run
417
+ */
418
+ export async function getRunInfo(runId, runsDir) {
419
+ const state = await parseResumeState(runId, runsDir);
420
+ if (!state) {
421
+ return null;
422
+ }
423
+ const firstEntry = state.entries[0];
424
+ const lastEntry = state.entries[state.entries.length - 1];
425
+ // Determine status
426
+ let status = 'running';
427
+ if (state.isComplete) {
428
+ status = state.error ? 'failed' : 'completed';
429
+ }
430
+ else if (state.entries.some(e => e.t === 'ask' && !state.answers[e.id])) {
431
+ status = 'waiting';
432
+ }
433
+ return {
434
+ runId,
435
+ photon: '', // Would need to be stored in start entry
436
+ tool: state.tool,
437
+ params: state.params,
438
+ status,
439
+ startedAt: firstEntry.ts,
440
+ updatedAt: lastEntry.ts,
441
+ completedAt: state.isComplete ? lastEntry.ts : undefined,
442
+ result: state.result,
443
+ error: state.error,
444
+ lastCheckpoint: state.lastCheckpoint,
445
+ };
446
+ }
447
+ /**
448
+ * Delete a workflow run
449
+ */
450
+ export async function deleteRun(runId, runsDir) {
451
+ const logPath = path.join(runsDir || RUNS_DIR, `${runId}.jsonl`);
452
+ await fs.unlink(logPath);
453
+ }
454
+ /**
455
+ * Clean up completed/failed runs older than specified age
456
+ */
457
+ export async function cleanupRuns(maxAgeMs, runsDir) {
458
+ const runs = await listRuns(runsDir);
459
+ const cutoff = Date.now() - maxAgeMs;
460
+ let deleted = 0;
461
+ for (const run of runs) {
462
+ if ((run.status === 'completed' || run.status === 'failed') && run.updatedAt < cutoff) {
463
+ await deleteRun(run.runId, runsDir);
464
+ deleted++;
465
+ }
466
+ }
467
+ return deleted;
468
+ }
469
+ //# sourceMappingURL=stateful.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateful.js","sourceRoot":"","sources":["../src/stateful.ts"],"names":[],"mappings":"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"}