@litmers/cursorflow-orchestrator 0.1.13 → 0.1.14
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/CHANGELOG.md +34 -0
- package/README.md +83 -2
- package/commands/cursorflow-clean.md +20 -6
- package/commands/cursorflow-prepare.md +1 -1
- package/commands/cursorflow-resume.md +127 -6
- package/commands/cursorflow-run.md +2 -2
- package/commands/cursorflow-signal.md +11 -4
- package/dist/cli/clean.js +164 -12
- package/dist/cli/clean.js.map +1 -1
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +6 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/logs.d.ts +8 -0
- package/dist/cli/logs.js +746 -0
- package/dist/cli/logs.js.map +1 -0
- package/dist/cli/monitor.js +113 -30
- package/dist/cli/monitor.js.map +1 -1
- package/dist/cli/prepare.js +1 -1
- package/dist/cli/resume.js +367 -18
- package/dist/cli/resume.js.map +1 -1
- package/dist/cli/run.js +2 -0
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/signal.js +34 -20
- package/dist/cli/signal.js.map +1 -1
- package/dist/core/orchestrator.d.ts +11 -1
- package/dist/core/orchestrator.js +257 -35
- package/dist/core/orchestrator.js.map +1 -1
- package/dist/core/reviewer.js +20 -0
- package/dist/core/reviewer.js.map +1 -1
- package/dist/core/runner.js +113 -13
- package/dist/core/runner.js.map +1 -1
- package/dist/utils/config.js +34 -0
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/enhanced-logger.d.ts +209 -0
- package/dist/utils/enhanced-logger.js +963 -0
- package/dist/utils/enhanced-logger.js.map +1 -0
- package/dist/utils/events.d.ts +59 -0
- package/dist/utils/events.js +37 -0
- package/dist/utils/events.js.map +1 -0
- package/dist/utils/git.d.ts +5 -0
- package/dist/utils/git.js +25 -0
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/types.d.ts +122 -1
- package/dist/utils/webhook.d.ts +5 -0
- package/dist/utils/webhook.js +109 -0
- package/dist/utils/webhook.js.map +1 -0
- package/examples/README.md +1 -1
- package/package.json +1 -1
- package/scripts/simple-logging-test.sh +97 -0
- package/scripts/test-real-logging.sh +289 -0
- package/scripts/test-streaming-multi-task.sh +247 -0
- package/src/cli/clean.ts +170 -13
- package/src/cli/index.ts +4 -1
- package/src/cli/logs.ts +848 -0
- package/src/cli/monitor.ts +123 -30
- package/src/cli/prepare.ts +1 -1
- package/src/cli/resume.ts +463 -22
- package/src/cli/run.ts +2 -0
- package/src/cli/signal.ts +43 -27
- package/src/core/orchestrator.ts +303 -37
- package/src/core/reviewer.ts +22 -0
- package/src/core/runner.ts +128 -12
- package/src/utils/config.ts +36 -0
- package/src/utils/enhanced-logger.ts +1097 -0
- package/src/utils/events.ts +117 -0
- package/src/utils/git.ts +25 -0
- package/src/utils/types.ts +150 -1
- package/src/utils/webhook.ts +85 -0
package/src/cli/monitor.ts
CHANGED
|
@@ -41,7 +41,8 @@ enum View {
|
|
|
41
41
|
MESSAGE_DETAIL,
|
|
42
42
|
FLOW,
|
|
43
43
|
TERMINAL,
|
|
44
|
-
INTERVENE
|
|
44
|
+
INTERVENE,
|
|
45
|
+
TIMEOUT
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
class InteractiveMonitor {
|
|
@@ -58,6 +59,7 @@ class InteractiveMonitor {
|
|
|
58
59
|
private terminalScrollOffset: number = 0;
|
|
59
60
|
private lastTerminalTotalLines: number = 0;
|
|
60
61
|
private interventionInput: string = '';
|
|
62
|
+
private timeoutInput: string = '';
|
|
61
63
|
private notification: { message: string; type: 'info' | 'error' | 'success'; time: number } | null = null;
|
|
62
64
|
|
|
63
65
|
constructor(runDir: string, interval: number) {
|
|
@@ -96,7 +98,9 @@ class InteractiveMonitor {
|
|
|
96
98
|
this.handleTerminalKey(keyName);
|
|
97
99
|
} else if (this.view === View.INTERVENE) {
|
|
98
100
|
this.handleInterveneKey(str, key);
|
|
99
|
-
} else {
|
|
101
|
+
} else if (this.view === View.TIMEOUT) {
|
|
102
|
+
this.handleTimeoutKey(str, key);
|
|
103
|
+
} else if (this.view === View.MESSAGE_DETAIL) {
|
|
100
104
|
this.handleMessageDetailKey(keyName);
|
|
101
105
|
}
|
|
102
106
|
});
|
|
@@ -182,9 +186,20 @@ class InteractiveMonitor {
|
|
|
182
186
|
this.interventionInput = '';
|
|
183
187
|
this.render();
|
|
184
188
|
} else {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
189
|
+
this.showNotification('Intervention only available for RUNNING lanes', 'error');
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
break;
|
|
193
|
+
case 'o':
|
|
194
|
+
const timeoutLane = this.lanes.find(l => l.name === this.selectedLaneName);
|
|
195
|
+
if (timeoutLane) {
|
|
196
|
+
const status = this.getLaneStatus(timeoutLane.path, timeoutLane.name);
|
|
197
|
+
if (status.status === 'running') {
|
|
198
|
+
this.view = View.TIMEOUT;
|
|
199
|
+
this.timeoutInput = '';
|
|
200
|
+
this.render();
|
|
201
|
+
} else {
|
|
202
|
+
this.showNotification('Timeout update only available for RUNNING lanes', 'error');
|
|
188
203
|
}
|
|
189
204
|
}
|
|
190
205
|
break;
|
|
@@ -244,44 +259,60 @@ class InteractiveMonitor {
|
|
|
244
259
|
}
|
|
245
260
|
|
|
246
261
|
private handleInterveneKey(str: string, key: any) {
|
|
247
|
-
if (key
|
|
262
|
+
if (key && key.name === 'escape') {
|
|
263
|
+
this.view = View.LANE_DETAIL;
|
|
264
|
+
this.render();
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (key && (key.name === 'return' || key.name === 'enter')) {
|
|
248
269
|
if (this.interventionInput.trim()) {
|
|
249
270
|
this.sendIntervention(this.interventionInput.trim());
|
|
250
271
|
}
|
|
251
272
|
this.view = View.LANE_DETAIL;
|
|
252
273
|
this.render();
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (key && key.name === 'backspace') {
|
|
257
278
|
this.interventionInput = this.interventionInput.slice(0, -1);
|
|
258
279
|
this.render();
|
|
259
|
-
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (str && str.length === 1 && !key.ctrl && !key.meta) {
|
|
260
284
|
this.interventionInput += str;
|
|
261
285
|
this.render();
|
|
262
286
|
}
|
|
263
287
|
}
|
|
264
288
|
|
|
265
|
-
private
|
|
266
|
-
if (
|
|
267
|
-
|
|
268
|
-
|
|
289
|
+
private handleTimeoutKey(str: string, key: any) {
|
|
290
|
+
if (key && key.name === 'escape') {
|
|
291
|
+
this.view = View.LANE_DETAIL;
|
|
292
|
+
this.render();
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
269
295
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
296
|
+
if (key && (key.name === 'return' || key.name === 'enter')) {
|
|
297
|
+
if (this.timeoutInput.trim()) {
|
|
298
|
+
this.sendTimeoutUpdate(this.timeoutInput.trim());
|
|
299
|
+
}
|
|
300
|
+
this.view = View.LANE_DETAIL;
|
|
301
|
+
this.render();
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
273
304
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
305
|
+
if (key && key.name === 'backspace') {
|
|
306
|
+
this.timeoutInput = this.timeoutInput.slice(0, -1);
|
|
307
|
+
this.render();
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Only allow numbers
|
|
312
|
+
if (str && /^\d$/.test(str)) {
|
|
313
|
+
this.timeoutInput += str;
|
|
314
|
+
this.render();
|
|
315
|
+
}
|
|
285
316
|
}
|
|
286
317
|
|
|
287
318
|
private handleFlowKey(key: string) {
|
|
@@ -302,6 +333,54 @@ class InteractiveMonitor {
|
|
|
302
333
|
}
|
|
303
334
|
}
|
|
304
335
|
|
|
336
|
+
private sendIntervention(message: string) {
|
|
337
|
+
if (!this.selectedLaneName) return;
|
|
338
|
+
const lane = this.lanes.find(l => l.name === this.selectedLaneName);
|
|
339
|
+
if (!lane) return;
|
|
340
|
+
|
|
341
|
+
try {
|
|
342
|
+
const interventionPath = path.join(lane.path, 'intervention.txt');
|
|
343
|
+
fs.writeFileSync(interventionPath, message, 'utf8');
|
|
344
|
+
|
|
345
|
+
// Also log it to the conversation
|
|
346
|
+
const convoPath = path.join(lane.path, 'conversation.jsonl');
|
|
347
|
+
const entry = {
|
|
348
|
+
timestamp: new Date().toISOString(),
|
|
349
|
+
role: 'user',
|
|
350
|
+
task: 'INTERVENTION',
|
|
351
|
+
fullText: `[HUMAN INTERVENTION]: ${message}`,
|
|
352
|
+
textLength: message.length + 20,
|
|
353
|
+
model: 'manual'
|
|
354
|
+
};
|
|
355
|
+
fs.appendFileSync(convoPath, JSON.stringify(entry) + '\n', 'utf8');
|
|
356
|
+
|
|
357
|
+
this.showNotification('Intervention message sent', 'success');
|
|
358
|
+
} catch (e) {
|
|
359
|
+
this.showNotification('Failed to send intervention', 'error');
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
private sendTimeoutUpdate(timeoutStr: string) {
|
|
364
|
+
if (!this.selectedLaneName) return;
|
|
365
|
+
const lane = this.lanes.find(l => l.name === this.selectedLaneName);
|
|
366
|
+
if (!lane) return;
|
|
367
|
+
|
|
368
|
+
try {
|
|
369
|
+
const timeoutMs = parseInt(timeoutStr);
|
|
370
|
+
if (isNaN(timeoutMs) || timeoutMs <= 0) {
|
|
371
|
+
this.showNotification('Invalid timeout value', 'error');
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const timeoutPath = path.join(lane.path, 'timeout.txt');
|
|
376
|
+
fs.writeFileSync(timeoutPath, String(timeoutMs), 'utf8');
|
|
377
|
+
|
|
378
|
+
this.showNotification(`Timeout updated to ${Math.round(timeoutMs/1000)}s`, 'success');
|
|
379
|
+
} catch (e) {
|
|
380
|
+
this.showNotification('Failed to update timeout', 'error');
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
305
384
|
private refreshLogs() {
|
|
306
385
|
if (!this.selectedLaneName) return;
|
|
307
386
|
const lane = this.lanes.find(l => l.name === this.selectedLaneName);
|
|
@@ -378,6 +457,9 @@ class InteractiveMonitor {
|
|
|
378
457
|
case View.INTERVENE:
|
|
379
458
|
this.renderIntervene();
|
|
380
459
|
break;
|
|
460
|
+
case View.TIMEOUT:
|
|
461
|
+
this.renderTimeout();
|
|
462
|
+
break;
|
|
381
463
|
}
|
|
382
464
|
}
|
|
383
465
|
|
|
@@ -460,7 +542,7 @@ class InteractiveMonitor {
|
|
|
460
542
|
|
|
461
543
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
462
544
|
console.log(`🔍 Lane: ${lane.name}`);
|
|
463
|
-
console.log(`🕒 Updated: ${new Date().toLocaleTimeString()} | [
|
|
545
|
+
console.log(`🕒 Updated: ${new Date().toLocaleTimeString()} | [↑/↓] Browse [T] Term [I] Intervene [O] Timeout [Esc] Back`);
|
|
464
546
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
|
|
465
547
|
|
|
466
548
|
process.stdout.write(` Status: ${this.getStatusIcon(status.status)} ${status.status}\n`);
|
|
@@ -659,6 +741,17 @@ class InteractiveMonitor {
|
|
|
659
741
|
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
660
742
|
}
|
|
661
743
|
|
|
744
|
+
private renderTimeout() {
|
|
745
|
+
console.clear();
|
|
746
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
747
|
+
console.log(`⏱ UPDATE TIMEOUT: ${this.selectedLaneName}`);
|
|
748
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
749
|
+
console.log('\n Enter new timeout in milliseconds (e.g., 600000 for 10 minutes).');
|
|
750
|
+
console.log(` Press \x1b[1mENTER\x1b[0m to apply, \x1b[1mESC\x1b[0m to cancel.\n`);
|
|
751
|
+
console.log(`\x1b[33m > \x1b[0m${this.timeoutInput}\x1b[37m█\x1b[0m`);
|
|
752
|
+
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
753
|
+
}
|
|
754
|
+
|
|
662
755
|
private listLanesWithDeps(runDir: string): LaneWithDeps[] {
|
|
663
756
|
const lanesDir = path.join(runDir, 'lanes');
|
|
664
757
|
if (!fs.existsSync(lanesDir)) return [];
|
package/src/cli/prepare.ts
CHANGED
|
@@ -515,7 +515,7 @@ function getDefaultConfig(laneNumber: number, featureName: string, tasks: Task[]
|
|
|
515
515
|
branchPrefix: `${featureName.toLowerCase()}/lane-${laneNumber}-`,
|
|
516
516
|
|
|
517
517
|
// Execution Settings
|
|
518
|
-
timeout:
|
|
518
|
+
timeout: 600000,
|
|
519
519
|
enableIntervention: false,
|
|
520
520
|
|
|
521
521
|
// Dependency Policy
|