@agent-link/agent 0.1.88 → 0.1.90

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,84 @@
1
+ /**
2
+ * Loop (Scheduled Tasks) scheduler module.
3
+ *
4
+ * Manages Loop CRUD, cron scheduling, execution lifecycle, and output capture.
5
+ * Each Loop is a scheduled prompt sent to Claude on a cron schedule.
6
+ * Executions are persisted as JSONL files for later replay.
7
+ */
8
+ import type { ClaudeMessage, HandleChatOptions } from './claude.js';
9
+ import type { HistoryMessage } from './history.js';
10
+ export interface Loop {
11
+ id: string;
12
+ name: string;
13
+ prompt: string;
14
+ schedule: string;
15
+ scheduleType: 'manual' | 'hourly' | 'daily' | 'weekly' | 'cron';
16
+ scheduleConfig: {
17
+ hour?: number;
18
+ minute?: number;
19
+ dayOfWeek?: number;
20
+ };
21
+ workDir: string;
22
+ enabled: boolean;
23
+ createdAt: string;
24
+ updatedAt: string;
25
+ lastExecution?: LoopExecutionSummary;
26
+ }
27
+ export interface LoopExecution {
28
+ id: string;
29
+ loopId: string;
30
+ status: 'running' | 'success' | 'error' | 'cancelled';
31
+ trigger: 'scheduled' | 'manual';
32
+ startedAt: string;
33
+ completedAt?: string;
34
+ durationMs?: number;
35
+ claudeSessionId?: string;
36
+ conversationId?: string;
37
+ summary?: string;
38
+ error?: string;
39
+ }
40
+ export type LoopExecutionSummary = Pick<LoopExecution, 'id' | 'status' | 'startedAt' | 'durationMs' | 'trigger'>;
41
+ type SendFn = (msg: Record<string, unknown>) => void;
42
+ type HandleChatFn = (conversationId: string | undefined, prompt: string, workDir: string, options?: HandleChatOptions) => void;
43
+ type CancelExecutionFn = (conversationId?: string) => void;
44
+ type AddOutputObserverFn = (fn: (conversationId: string, msg: ClaudeMessage) => boolean | void) => void;
45
+ type RemoveOutputObserverFn = (fn: (conversationId: string, msg: ClaudeMessage) => boolean | void) => void;
46
+ type AddCloseObserverFn = (fn: (conversationId: string, exitCode: number | null, resultReceived: boolean) => void) => void;
47
+ type RemoveCloseObserverFn = (fn: (conversationId: string, exitCode: number | null, resultReceived: boolean) => void) => void;
48
+ /**
49
+ * Initialize the scheduler. Loads loops from disk, reconciles orphaned
50
+ * executions, and starts cron jobs for all enabled loops.
51
+ */
52
+ export declare function initScheduler(deps: {
53
+ send: SendFn;
54
+ handleChat: HandleChatFn;
55
+ cancelExecution: CancelExecutionFn;
56
+ addOutputObserver: AddOutputObserverFn;
57
+ removeOutputObserver: RemoveOutputObserverFn;
58
+ addCloseObserver: AddCloseObserverFn;
59
+ removeCloseObserver: RemoveCloseObserverFn;
60
+ }): void;
61
+ /**
62
+ * Shutdown the scheduler. Stops all cron jobs.
63
+ * Running executions are NOT cancelled; they complete naturally.
64
+ */
65
+ export declare function shutdownScheduler(): void;
66
+ export declare function createLoop(config: {
67
+ name: string;
68
+ prompt: string;
69
+ schedule: string;
70
+ scheduleType: Loop['scheduleType'];
71
+ scheduleConfig: Loop['scheduleConfig'];
72
+ workDir: string;
73
+ }): Loop;
74
+ export declare function updateLoop(loopId: string, updates: Partial<Pick<Loop, 'name' | 'prompt' | 'schedule' | 'scheduleType' | 'scheduleConfig' | 'enabled'>>): Loop | null;
75
+ export declare function deleteLoop(loopId: string): boolean;
76
+ export declare function listLoops(workDir?: string): Loop[];
77
+ export declare function getLoop(loopId: string): Loop | null;
78
+ export declare function listLoopExecutions(loopId: string, limit?: number): LoopExecution[];
79
+ export declare function getLoopExecutionMessages(loopId: string, executionId: string): HistoryMessage[];
80
+ export declare function runLoopNow(loopId: string): void;
81
+ export declare function cancelLoopExecution(loopId: string): void;
82
+ /** Get currently running executions (for status queries). */
83
+ export declare function getRunningExecutions(): Map<string, LoopExecution>;
84
+ export {};
@@ -0,0 +1,559 @@
1
+ /**
2
+ * Loop (Scheduled Tasks) scheduler module.
3
+ *
4
+ * Manages Loop CRUD, cron scheduling, execution lifecycle, and output capture.
5
+ * Each Loop is a scheduled prompt sent to Claude on a cron schedule.
6
+ * Executions are persisted as JSONL files for later replay.
7
+ */
8
+ import { randomUUID } from 'crypto';
9
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, appendFileSync, renameSync, } from 'fs';
10
+ import { join } from 'path';
11
+ import cron from 'node-cron';
12
+ import { CONFIG_DIR } from './config.js';
13
+ // ── Constants ─────────────────────────────────────────────────────────────
14
+ const LOOPS_FILE = join(CONFIG_DIR, 'loops.json');
15
+ const EXECUTIONS_DIR = join(CONFIG_DIR, 'loop-executions');
16
+ const MAX_CONCURRENT_LOOPS = 3;
17
+ // ── Module state ──────────────────────────────────────────────────────────
18
+ let loops = [];
19
+ const cronJobs = new Map();
20
+ const runningExecutions = new Map();
21
+ let sendFn = null;
22
+ let handleChatFn = null;
23
+ let cancelExecutionFn = null;
24
+ let addOutputObserverFn = null;
25
+ let removeOutputObserverFn = null;
26
+ let addCloseObserverFn = null;
27
+ let removeCloseObserverFn = null;
28
+ // ── Public API ────────────────────────────────────────────────────────────
29
+ /**
30
+ * Initialize the scheduler. Loads loops from disk, reconciles orphaned
31
+ * executions, and starts cron jobs for all enabled loops.
32
+ */
33
+ export function initScheduler(deps) {
34
+ sendFn = deps.send;
35
+ handleChatFn = deps.handleChat;
36
+ cancelExecutionFn = deps.cancelExecution;
37
+ addOutputObserverFn = deps.addOutputObserver;
38
+ removeOutputObserverFn = deps.removeOutputObserver;
39
+ addCloseObserverFn = deps.addCloseObserver;
40
+ removeCloseObserverFn = deps.removeCloseObserver;
41
+ loops = loadLoopsFromDisk();
42
+ reconcileOrphanedExecutions();
43
+ // Register output and close observers
44
+ addOutputObserverFn(onLoopOutput);
45
+ addCloseObserverFn(onLoopClose);
46
+ for (const loop of loops) {
47
+ if (loop.enabled && loop.scheduleType !== 'manual') {
48
+ scheduleLoop(loop);
49
+ }
50
+ }
51
+ console.log(`[Scheduler] Initialized with ${loops.length} loops (${cronJobs.size} scheduled)`);
52
+ }
53
+ /**
54
+ * Shutdown the scheduler. Stops all cron jobs.
55
+ * Running executions are NOT cancelled; they complete naturally.
56
+ */
57
+ export function shutdownScheduler() {
58
+ for (const [, job] of cronJobs) {
59
+ job.stop();
60
+ }
61
+ cronJobs.clear();
62
+ // Remove observers
63
+ if (removeOutputObserverFn)
64
+ removeOutputObserverFn(onLoopOutput);
65
+ if (removeCloseObserverFn)
66
+ removeCloseObserverFn(onLoopClose);
67
+ console.log('[Scheduler] Shutdown complete');
68
+ }
69
+ // ── CRUD Operations ───────────────────────────────────────────────────────
70
+ export function createLoop(config) {
71
+ // Validate cron expression (skip for manual loops)
72
+ if (config.scheduleType !== 'manual' && !cron.validate(config.schedule)) {
73
+ throw new Error(`Invalid cron expression: ${config.schedule}`);
74
+ }
75
+ const loop = {
76
+ id: randomUUID(),
77
+ name: config.name,
78
+ prompt: config.prompt,
79
+ schedule: config.schedule,
80
+ scheduleType: config.scheduleType,
81
+ scheduleConfig: config.scheduleConfig,
82
+ workDir: config.workDir,
83
+ enabled: true,
84
+ createdAt: new Date().toISOString(),
85
+ updatedAt: new Date().toISOString(),
86
+ };
87
+ loops.push(loop);
88
+ saveLoopsToDisk();
89
+ if (config.scheduleType !== 'manual')
90
+ scheduleLoop(loop);
91
+ console.log(`[Scheduler] Created loop "${loop.name}" (${loop.id.slice(0, 8)}) schedule: ${loop.schedule}`);
92
+ return loop;
93
+ }
94
+ export function updateLoop(loopId, updates) {
95
+ const loop = loops.find(l => l.id === loopId);
96
+ if (!loop)
97
+ return null;
98
+ // Validate new cron expression if provided (skip for manual loops)
99
+ const effectiveType = updates.scheduleType ?? loop.scheduleType;
100
+ if (effectiveType !== 'manual' && updates.schedule && !cron.validate(updates.schedule)) {
101
+ throw new Error(`Invalid cron expression: ${updates.schedule}`);
102
+ }
103
+ const scheduleChanged = updates.schedule && updates.schedule !== loop.schedule;
104
+ const enabledChanged = updates.enabled !== undefined && updates.enabled !== loop.enabled;
105
+ const typeChanged = updates.scheduleType !== undefined && updates.scheduleType !== loop.scheduleType;
106
+ Object.assign(loop, updates, { updatedAt: new Date().toISOString() });
107
+ saveLoopsToDisk();
108
+ if (scheduleChanged || enabledChanged || typeChanged) {
109
+ unscheduleLoop(loopId);
110
+ if (loop.enabled && loop.scheduleType !== 'manual')
111
+ scheduleLoop(loop);
112
+ }
113
+ console.log(`[Scheduler] Updated loop "${loop.name}" (${loop.id.slice(0, 8)})`);
114
+ return loop;
115
+ }
116
+ export function deleteLoop(loopId) {
117
+ const idx = loops.findIndex(l => l.id === loopId);
118
+ if (idx < 0)
119
+ return false;
120
+ // Cancel if running
121
+ cancelLoopExecution(loopId);
122
+ unscheduleLoop(loopId);
123
+ loops.splice(idx, 1);
124
+ saveLoopsToDisk();
125
+ console.log(`[Scheduler] Deleted loop ${loopId.slice(0, 8)}`);
126
+ return true;
127
+ }
128
+ export function listLoops(workDir) {
129
+ const filtered = workDir ? loops.filter(l => l.workDir === workDir) : loops;
130
+ return filtered.map(l => ({ ...l }));
131
+ }
132
+ export function getLoop(loopId) {
133
+ const loop = loops.find(l => l.id === loopId);
134
+ return loop ? { ...loop } : null;
135
+ }
136
+ export function listLoopExecutions(loopId, limit = 50) {
137
+ return readExecutionIndex(loopId, limit);
138
+ }
139
+ export function getLoopExecutionMessages(loopId, executionId) {
140
+ return readExecutionLog(loopId, executionId);
141
+ }
142
+ export function runLoopNow(loopId) {
143
+ executeLoop(loopId, 'manual');
144
+ }
145
+ export function cancelLoopExecution(loopId) {
146
+ for (const [execId, exec] of runningExecutions) {
147
+ if (exec.loopId === loopId && exec.conversationId) {
148
+ if (cancelExecutionFn) {
149
+ cancelExecutionFn(exec.conversationId);
150
+ }
151
+ completeExecution(execId, 'cancelled');
152
+ break;
153
+ }
154
+ }
155
+ }
156
+ /** Get currently running executions (for status queries). */
157
+ export function getRunningExecutions() {
158
+ return runningExecutions;
159
+ }
160
+ // ── Scheduling ────────────────────────────────────────────────────────────
161
+ function scheduleLoop(loop) {
162
+ if (cronJobs.has(loop.id)) {
163
+ cronJobs.get(loop.id).stop();
164
+ }
165
+ const job = cron.schedule(loop.schedule, () => {
166
+ console.log(`[Scheduler] Cron fired for loop "${loop.name}" (${loop.id.slice(0, 8)})`);
167
+ executeLoop(loop.id, 'scheduled');
168
+ });
169
+ cronJobs.set(loop.id, job);
170
+ console.log(`[Scheduler] Scheduled loop "${loop.name}" with cron: ${loop.schedule}`);
171
+ }
172
+ function unscheduleLoop(loopId) {
173
+ const job = cronJobs.get(loopId);
174
+ if (job) {
175
+ job.stop();
176
+ cronJobs.delete(loopId);
177
+ }
178
+ }
179
+ // ── Execution ─────────────────────────────────────────────────────────────
180
+ function executeLoop(loopId, trigger) {
181
+ const loop = loops.find(l => l.id === loopId);
182
+ if (!loop) {
183
+ console.warn(`[Scheduler] Cannot execute: loop ${loopId.slice(0, 8)} not found`);
184
+ return;
185
+ }
186
+ // For scheduled triggers, the loop must be enabled
187
+ if (trigger === 'scheduled' && !loop.enabled) {
188
+ return;
189
+ }
190
+ // Check concurrent Loop quota
191
+ if (runningExecutions.size >= MAX_CONCURRENT_LOOPS) {
192
+ console.warn(`[Scheduler] Skipping execution for "${loop.name}": concurrent limit reached (${MAX_CONCURRENT_LOOPS})`);
193
+ return;
194
+ }
195
+ // Prevent overlap: skip if this specific Loop already has a running execution
196
+ for (const exec of runningExecutions.values()) {
197
+ if (exec.loopId === loopId) {
198
+ console.warn(`[Scheduler] Skipping execution for "${loop.name}": already running`);
199
+ return;
200
+ }
201
+ }
202
+ if (!handleChatFn) {
203
+ console.error('[Scheduler] Cannot execute: handleChat not initialized');
204
+ return;
205
+ }
206
+ const executionId = randomUUID();
207
+ const conversationId = `loop-${executionId.slice(0, 8)}`;
208
+ const execution = {
209
+ id: executionId,
210
+ loopId,
211
+ status: 'running',
212
+ trigger,
213
+ startedAt: new Date().toISOString(),
214
+ conversationId,
215
+ };
216
+ runningExecutions.set(executionId, execution);
217
+ // Ensure execution directory exists
218
+ ensureExecutionDir(loopId);
219
+ // Persist execution metadata
220
+ appendExecutionIndex(loopId, execution);
221
+ // Notify web UI
222
+ sendFn?.({
223
+ type: 'loop_execution_started',
224
+ loopId,
225
+ execution: { ...execution },
226
+ });
227
+ console.log(`[Scheduler] Starting execution ${executionId.slice(0, 8)} for "${loop.name}" (trigger: ${trigger})`);
228
+ // Execute via existing claude.ts handleChat
229
+ try {
230
+ handleChatFn(conversationId, loop.prompt, loop.workDir, {});
231
+ }
232
+ catch (err) {
233
+ console.error(`[Scheduler] Failed to start execution: ${err.message}`);
234
+ completeExecution(executionId, 'error', err.message);
235
+ }
236
+ }
237
+ // ── Output Observer ───────────────────────────────────────────────────────
238
+ /**
239
+ * Output observer callback registered with claude.ts.
240
+ * Captures messages from Loop conversations and persists them.
241
+ */
242
+ function onLoopOutput(conversationId, msg) {
243
+ // Only handle loop conversations
244
+ if (!conversationId.startsWith('loop-'))
245
+ return false;
246
+ const execution = findExecutionByConversationId(conversationId);
247
+ if (!execution)
248
+ return false;
249
+ // 1. Append raw message to execution JSONL file
250
+ appendToExecutionLog(execution.loopId, execution.id, msg);
251
+ // 2. Forward to web UI with loop context
252
+ sendFn?.({
253
+ type: 'loop_execution_output',
254
+ loopId: execution.loopId,
255
+ executionId: execution.id,
256
+ data: msg,
257
+ });
258
+ // 3. Capture session ID
259
+ if (msg.type === 'system' && msg.session_id) {
260
+ execution.claudeSessionId = msg.session_id;
261
+ }
262
+ // 4. Detect completion
263
+ if (msg.type === 'result') {
264
+ const summary = extractSummary(msg);
265
+ const isError = !!msg.is_error || msg.subtype === 'error_response';
266
+ completeExecution(execution.id, isError ? 'error' : 'success', undefined, summary);
267
+ }
268
+ // Don't suppress: let normal forwarding happen too so the web client
269
+ // gets the standard claude_output/turn_completed messages if needed.
270
+ return false;
271
+ }
272
+ /**
273
+ * Close observer callback. Detects Loop processes that exit without a result.
274
+ */
275
+ function onLoopClose(conversationId, _exitCode, resultReceived) {
276
+ if (!conversationId.startsWith('loop-'))
277
+ return;
278
+ if (resultReceived)
279
+ return;
280
+ const execution = findExecutionByConversationId(conversationId);
281
+ if (!execution)
282
+ return;
283
+ console.log(`[Scheduler] Loop process exited without result for execution ${execution.id.slice(0, 8)}`);
284
+ completeExecution(execution.id, 'error', 'Process exited without completing');
285
+ }
286
+ // ── Execution Completion ──────────────────────────────────────────────────
287
+ function completeExecution(executionId, status, error, summary) {
288
+ const execution = runningExecutions.get(executionId);
289
+ if (!execution)
290
+ return;
291
+ execution.status = status;
292
+ execution.completedAt = new Date().toISOString();
293
+ execution.durationMs = Date.now() - new Date(execution.startedAt).getTime();
294
+ if (summary)
295
+ execution.summary = summary;
296
+ if (error)
297
+ execution.error = error;
298
+ runningExecutions.delete(executionId);
299
+ // Update execution index on disk
300
+ updateExecutionIndex(execution.loopId, execution);
301
+ // Update Loop's lastExecution
302
+ const loop = loops.find(l => l.id === execution.loopId);
303
+ if (loop) {
304
+ loop.lastExecution = {
305
+ id: execution.id,
306
+ status: execution.status,
307
+ startedAt: execution.startedAt,
308
+ durationMs: execution.durationMs,
309
+ trigger: execution.trigger,
310
+ };
311
+ saveLoopsToDisk();
312
+ }
313
+ console.log(`[Scheduler] Execution ${executionId.slice(0, 8)} completed: ${status}${error ? ` (${error})` : ''}`);
314
+ // Notify web UI
315
+ sendFn?.({
316
+ type: 'loop_execution_completed',
317
+ loopId: execution.loopId,
318
+ execution: { ...execution },
319
+ });
320
+ }
321
+ // ── Helpers ───────────────────────────────────────────────────────────────
322
+ function findExecutionByConversationId(conversationId) {
323
+ for (const exec of runningExecutions.values()) {
324
+ if (exec.conversationId === conversationId)
325
+ return exec;
326
+ }
327
+ return null;
328
+ }
329
+ function extractSummary(msg) {
330
+ if (typeof msg.result === 'string' && msg.result.length > 0) {
331
+ // Truncate summary to first 500 chars
332
+ return msg.result.length > 500
333
+ ? msg.result.slice(0, 497) + '...'
334
+ : msg.result;
335
+ }
336
+ return undefined;
337
+ }
338
+ // ── Persistence: Loops ────────────────────────────────────────────────────
339
+ function loadLoopsFromDisk() {
340
+ try {
341
+ if (!existsSync(LOOPS_FILE))
342
+ return [];
343
+ const raw = readFileSync(LOOPS_FILE, 'utf-8');
344
+ const parsed = JSON.parse(raw);
345
+ if (!Array.isArray(parsed))
346
+ return [];
347
+ return parsed;
348
+ }
349
+ catch (err) {
350
+ console.error(`[Scheduler] Failed to load loops.json: ${err.message}`);
351
+ return [];
352
+ }
353
+ }
354
+ function saveLoopsToDisk() {
355
+ try {
356
+ if (!existsSync(CONFIG_DIR)) {
357
+ mkdirSync(CONFIG_DIR, { recursive: true });
358
+ }
359
+ const tmpFile = LOOPS_FILE + '.tmp';
360
+ writeFileSync(tmpFile, JSON.stringify(loops, null, 2) + '\n', 'utf-8');
361
+ renameSync(tmpFile, LOOPS_FILE);
362
+ }
363
+ catch (err) {
364
+ console.error(`[Scheduler] Failed to save loops.json: ${err.message}`);
365
+ }
366
+ }
367
+ // ── Persistence: Executions ───────────────────────────────────────────────
368
+ function ensureExecutionDir(loopId) {
369
+ const dir = join(EXECUTIONS_DIR, loopId);
370
+ if (!existsSync(dir)) {
371
+ mkdirSync(dir, { recursive: true });
372
+ }
373
+ }
374
+ function getExecutionIndexPath(loopId) {
375
+ return join(EXECUTIONS_DIR, loopId, 'index.jsonl');
376
+ }
377
+ function getExecutionLogPath(loopId, executionId) {
378
+ return join(EXECUTIONS_DIR, loopId, `${executionId}.jsonl`);
379
+ }
380
+ function appendExecutionIndex(loopId, execution) {
381
+ try {
382
+ ensureExecutionDir(loopId);
383
+ const line = JSON.stringify(execution) + '\n';
384
+ appendFileSync(getExecutionIndexPath(loopId), line, 'utf-8');
385
+ }
386
+ catch (err) {
387
+ console.error(`[Scheduler] Failed to append execution index: ${err.message}`);
388
+ }
389
+ }
390
+ function updateExecutionIndex(loopId, execution) {
391
+ try {
392
+ const indexPath = getExecutionIndexPath(loopId);
393
+ if (!existsSync(indexPath)) {
394
+ appendExecutionIndex(loopId, execution);
395
+ return;
396
+ }
397
+ const raw = readFileSync(indexPath, 'utf-8');
398
+ const lines = raw.trim().split('\n').filter(l => l.trim());
399
+ const updated = [];
400
+ let found = false;
401
+ for (const line of lines) {
402
+ try {
403
+ const entry = JSON.parse(line);
404
+ if (entry.id === execution.id) {
405
+ updated.push(JSON.stringify(execution));
406
+ found = true;
407
+ }
408
+ else {
409
+ updated.push(line);
410
+ }
411
+ }
412
+ catch {
413
+ updated.push(line); // preserve unparseable lines
414
+ }
415
+ }
416
+ if (!found) {
417
+ updated.push(JSON.stringify(execution));
418
+ }
419
+ writeFileSync(indexPath, updated.join('\n') + '\n', 'utf-8');
420
+ }
421
+ catch (err) {
422
+ console.error(`[Scheduler] Failed to update execution index: ${err.message}`);
423
+ }
424
+ }
425
+ function readExecutionIndex(loopId, limit) {
426
+ try {
427
+ const indexPath = getExecutionIndexPath(loopId);
428
+ if (!existsSync(indexPath))
429
+ return [];
430
+ const raw = readFileSync(indexPath, 'utf-8');
431
+ const lines = raw.trim().split('\n').filter(l => l.trim());
432
+ const executions = [];
433
+ for (const line of lines) {
434
+ try {
435
+ executions.push(JSON.parse(line));
436
+ }
437
+ catch {
438
+ // skip unparseable lines
439
+ }
440
+ }
441
+ // Sort by startedAt descending (most recent first) and limit
442
+ executions.sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime());
443
+ // Merge running status from in-memory state
444
+ for (const exec of executions) {
445
+ const running = runningExecutions.get(exec.id);
446
+ if (running) {
447
+ exec.status = running.status;
448
+ exec.claudeSessionId = running.claudeSessionId;
449
+ }
450
+ }
451
+ return executions.slice(0, limit);
452
+ }
453
+ catch (err) {
454
+ console.error(`[Scheduler] Failed to read execution index: ${err.message}`);
455
+ return [];
456
+ }
457
+ }
458
+ function appendToExecutionLog(loopId, executionId, msg) {
459
+ try {
460
+ ensureExecutionDir(loopId);
461
+ const line = JSON.stringify(msg) + '\n';
462
+ appendFileSync(getExecutionLogPath(loopId, executionId), line, 'utf-8');
463
+ }
464
+ catch (err) {
465
+ console.error(`[Scheduler] Failed to append execution log: ${err.message}`);
466
+ }
467
+ }
468
+ function readExecutionLog(loopId, executionId) {
469
+ try {
470
+ const logPath = getExecutionLogPath(loopId, executionId);
471
+ if (!existsSync(logPath))
472
+ return [];
473
+ const raw = readFileSync(logPath, 'utf-8');
474
+ const lines = raw.trim().split('\n').filter(l => l.trim());
475
+ const result = [];
476
+ for (const line of lines) {
477
+ try {
478
+ const data = JSON.parse(line);
479
+ const ts = data.timestamp || undefined;
480
+ if (data.type === 'user' && data.message?.content) {
481
+ // Extract tool results for tool_result content blocks
482
+ const content = data.message.content;
483
+ if (Array.isArray(content)) {
484
+ for (const block of content) {
485
+ if (block.type === 'tool_result' && block.content) {
486
+ const text = typeof block.content === 'string'
487
+ ? block.content
488
+ : JSON.stringify(block.content);
489
+ // Find the matching tool message and add output
490
+ for (let i = result.length - 1; i >= 0; i--) {
491
+ if (result[i].role === 'tool' && result[i].toolId === block.tool_use_id) {
492
+ result[i].toolOutput = text;
493
+ break;
494
+ }
495
+ }
496
+ }
497
+ }
498
+ }
499
+ else if (typeof content === 'string' && content.trim()) {
500
+ result.push({ role: 'user', content, timestamp: ts });
501
+ }
502
+ }
503
+ if (data.type === 'assistant' && data.message?.content && Array.isArray(data.message.content)) {
504
+ const textParts = [];
505
+ const toolBlocks = [];
506
+ for (const block of data.message.content) {
507
+ if (block.type === 'text' && block.text) {
508
+ textParts.push(block.text);
509
+ }
510
+ else if (block.type === 'tool_use') {
511
+ toolBlocks.push(block);
512
+ }
513
+ }
514
+ if (textParts.length > 0) {
515
+ result.push({ role: 'assistant', content: textParts.join('\n\n'), timestamp: ts });
516
+ }
517
+ for (const tool of toolBlocks) {
518
+ result.push({
519
+ role: 'tool',
520
+ content: '',
521
+ toolName: tool.name,
522
+ toolInput: JSON.stringify(tool.input || {}),
523
+ toolId: tool.id,
524
+ timestamp: ts,
525
+ });
526
+ }
527
+ }
528
+ }
529
+ catch {
530
+ // skip unparseable lines
531
+ }
532
+ }
533
+ return result;
534
+ }
535
+ catch (err) {
536
+ console.error(`[Scheduler] Failed to read execution log: ${err.message}`);
537
+ return [];
538
+ }
539
+ }
540
+ // ── Orphaned Execution Recovery ───────────────────────────────────────────
541
+ function reconcileOrphanedExecutions() {
542
+ let orphanCount = 0;
543
+ for (const loop of loops) {
544
+ const executions = readExecutionIndex(loop.id, 100);
545
+ for (const exec of executions) {
546
+ if (exec.status === 'running') {
547
+ exec.status = 'error';
548
+ exec.error = 'Agent restarted during execution';
549
+ exec.completedAt = new Date().toISOString();
550
+ updateExecutionIndex(loop.id, exec);
551
+ orphanCount++;
552
+ }
553
+ }
554
+ }
555
+ if (orphanCount > 0) {
556
+ console.log(`[Scheduler] Reconciled ${orphanCount} orphaned execution(s)`);
557
+ }
558
+ }
559
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"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"}