@exaudeus/workrail 3.31.1 → 3.33.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/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.js +3 -1
- package/dist/cli/commands/worktrain-await.js +11 -9
- package/dist/cli/commands/worktrain-daemon-install.d.ts +35 -0
- package/dist/cli/commands/worktrain-daemon-install.js +291 -0
- package/dist/cli/commands/worktrain-daemon.d.ts +31 -0
- package/dist/cli/commands/worktrain-daemon.js +272 -0
- package/dist/cli/commands/worktrain-spawn.js +11 -9
- package/dist/cli-worktrain.js +329 -0
- package/dist/cli.js +4 -22
- package/dist/console/standalone-console.d.ts +28 -0
- package/dist/console/standalone-console.js +142 -0
- package/dist/{console/assets/index-6H9DeFxj.js → console-ui/assets/index-BuJFLLfY.js} +1 -1
- package/dist/{console → console-ui}/index.html +1 -1
- package/dist/daemon/agent-loop.d.ts +26 -0
- package/dist/daemon/agent-loop.js +53 -2
- package/dist/daemon/daemon-events.d.ts +103 -0
- package/dist/daemon/daemon-events.js +56 -0
- package/dist/daemon/workflow-runner.d.ts +6 -3
- package/dist/daemon/workflow-runner.js +229 -33
- package/dist/infrastructure/session/HttpServer.js +133 -34
- package/dist/manifest.json +134 -70
- package/dist/mcp/output-schemas.d.ts +30 -30
- package/dist/mcp/transports/bridge-events.d.ts +4 -0
- package/dist/mcp/transports/fatal-exit.js +4 -0
- package/dist/mcp/transports/http-entry.js +2 -0
- package/dist/mcp/transports/stdio-entry.js +26 -6
- package/dist/mcp/v2/tools.d.ts +4 -4
- package/dist/trigger/adapters/github-poller.d.ts +44 -0
- package/dist/trigger/adapters/github-poller.js +190 -0
- package/dist/trigger/adapters/gitlab-poller.d.ts +27 -0
- package/dist/trigger/adapters/gitlab-poller.js +81 -0
- package/dist/trigger/delivery-client.d.ts +2 -1
- package/dist/trigger/delivery-client.js +4 -1
- package/dist/trigger/index.d.ts +4 -1
- package/dist/trigger/index.js +5 -1
- package/dist/trigger/polled-event-store.d.ts +22 -0
- package/dist/trigger/polled-event-store.js +173 -0
- package/dist/trigger/polling-scheduler.d.ts +20 -0
- package/dist/trigger/polling-scheduler.js +249 -0
- package/dist/trigger/trigger-listener.d.ts +5 -0
- package/dist/trigger/trigger-listener.js +53 -4
- package/dist/trigger/trigger-router.d.ts +4 -2
- package/dist/trigger/trigger-router.js +7 -4
- package/dist/trigger/trigger-store.js +114 -33
- package/dist/trigger/types.d.ts +17 -1
- package/dist/v2/durable-core/schemas/export-bundle/index.d.ts +224 -224
- package/dist/v2/durable-core/schemas/session/events.d.ts +42 -42
- package/dist/v2/durable-core/schemas/session/manifest.d.ts +6 -6
- package/dist/v2/durable-core/schemas/session/validation-event.d.ts +2 -2
- package/dist/v2/durable-core/tokens/payloads.d.ts +52 -52
- package/dist/v2/usecases/console-routes.js +3 -3
- package/dist/v2/usecases/console-service.js +133 -9
- package/dist/v2/usecases/console-types.d.ts +7 -0
- package/docs/design/daemon-conversation-logging-plan.md +98 -0
- package/docs/design/daemon-conversation-logging-review.md +55 -0
- package/docs/design/daemon-conversation-logging.md +129 -0
- package/docs/design/github-polling-adapter-design-candidates.md +226 -0
- package/docs/design/github-polling-adapter-design-review-findings.md +131 -0
- package/docs/design/github-polling-adapter-implementation-plan.md +284 -0
- package/docs/design/implementation_plan.md +192 -0
- package/docs/design/workflow-id-validation-at-startup.md +146 -0
- package/docs/design/workflow-id-validation-design-review.md +87 -0
- package/docs/design/workflow-id-validation-implementation-plan.md +185 -0
- package/docs/design/worktrain-system-prompt-report-issue-candidates.md +135 -0
- package/docs/design/worktrain-system-prompt-report-issue-design-review.md +73 -0
- package/docs/ideas/backlog.md +465 -0
- package/package.json +1 -1
- package/workflows/architecture-scalability-audit.json +1 -1
- package/workflows/bug-investigation.agentic.v2.json +3 -3
- package/workflows/coding-task-workflow-agentic.json +32 -32
- package/workflows/coding-task-workflow-agentic.lean.v2.json +1 -1
- package/workflows/coding-task-workflow-agentic.v2.json +7 -7
- package/workflows/mr-review-workflow.agentic.v2.json +21 -12
- package/workflows/personal-learning-materials-creation-branched.json +2 -2
- package/workflows/production-readiness-audit.json +1 -1
- package/workflows/relocation-workflow-us.json +2 -2
- package/workflows/ui-ux-design-workflow.json +14 -14
- package/workflows/workflow-for-workflows.json +3 -3
- package/workflows/workflow-for-workflows.v2.json +2 -2
- package/workflows/wr.discovery.json +1 -1
- /package/dist/{console → console-ui}/assets/index-8dh0Psu-.css +0 -0
|
@@ -75,7 +75,10 @@ let HttpServer = class HttpServer {
|
|
|
75
75
|
const start = Date.now();
|
|
76
76
|
res.on('finish', () => {
|
|
77
77
|
const duration = Date.now() - start;
|
|
78
|
-
|
|
78
|
+
try {
|
|
79
|
+
process.stderr.write(`[HTTP] ${req.method} ${req.path} ${res.statusCode} (${duration}ms)\n`);
|
|
80
|
+
}
|
|
81
|
+
catch { }
|
|
79
82
|
});
|
|
80
83
|
next();
|
|
81
84
|
});
|
|
@@ -217,7 +220,10 @@ let HttpServer = class HttpServer {
|
|
|
217
220
|
res.write(`data: ${JSON.stringify({ type: 'update', session: event.session })}\n\n`);
|
|
218
221
|
}
|
|
219
222
|
catch (error) {
|
|
220
|
-
|
|
223
|
+
try {
|
|
224
|
+
process.stderr.write(`[SSE] Write error for ${workflow}/${id}: ${error?.message ?? String(error)}\n`);
|
|
225
|
+
}
|
|
226
|
+
catch { }
|
|
221
227
|
cleanup();
|
|
222
228
|
}
|
|
223
229
|
};
|
|
@@ -231,7 +237,10 @@ let HttpServer = class HttpServer {
|
|
|
231
237
|
return true;
|
|
232
238
|
}
|
|
233
239
|
catch (error) {
|
|
234
|
-
|
|
240
|
+
try {
|
|
241
|
+
process.stderr.write(`[SSE] Write error for ${workflow}/${id}: ${error?.message ?? String(error)}\n`);
|
|
242
|
+
}
|
|
243
|
+
catch { }
|
|
235
244
|
cleanup();
|
|
236
245
|
return false;
|
|
237
246
|
}
|
|
@@ -241,7 +250,10 @@ let HttpServer = class HttpServer {
|
|
|
241
250
|
res.setHeader('Connection', 'keep-alive');
|
|
242
251
|
res.setHeader('X-Accel-Buffering', 'no');
|
|
243
252
|
maxConnectionTimeout = setTimeout(() => {
|
|
244
|
-
|
|
253
|
+
try {
|
|
254
|
+
process.stderr.write(`[SSE] Max connection time reached for ${workflow}/${id}, closing\n`);
|
|
255
|
+
}
|
|
256
|
+
catch { }
|
|
245
257
|
cleanup();
|
|
246
258
|
}, 30 * 60 * 1000);
|
|
247
259
|
if (!safeWrite(`data: ${JSON.stringify({ type: 'connected', workflowId: workflow, sessionId: id })}\n\n`)) {
|
|
@@ -263,11 +275,17 @@ let HttpServer = class HttpServer {
|
|
|
263
275
|
}, 30000);
|
|
264
276
|
req.on('close', cleanup);
|
|
265
277
|
req.on('error', (error) => {
|
|
266
|
-
|
|
278
|
+
try {
|
|
279
|
+
process.stderr.write(`[SSE] Request error for ${workflow}/${id}: ${error?.message ?? String(error)}\n`);
|
|
280
|
+
}
|
|
281
|
+
catch { }
|
|
267
282
|
cleanup();
|
|
268
283
|
});
|
|
269
284
|
res.on('error', (error) => {
|
|
270
|
-
|
|
285
|
+
try {
|
|
286
|
+
process.stderr.write(`[SSE] Response error for ${workflow}/${id}: ${error?.message ?? String(error)}\n`);
|
|
287
|
+
}
|
|
288
|
+
catch { }
|
|
271
289
|
cleanup();
|
|
272
290
|
});
|
|
273
291
|
res.on('finish', cleanup);
|
|
@@ -287,7 +305,10 @@ let HttpServer = class HttpServer {
|
|
|
287
305
|
});
|
|
288
306
|
}
|
|
289
307
|
catch (error) {
|
|
290
|
-
|
|
308
|
+
try {
|
|
309
|
+
process.stderr.write(`[HttpServer] Delete session error: ${error?.message ?? String(error)}\n`);
|
|
310
|
+
}
|
|
311
|
+
catch { }
|
|
291
312
|
res.status(500).json({
|
|
292
313
|
success: false,
|
|
293
314
|
error: error.message || 'Failed to delete session'
|
|
@@ -311,7 +332,10 @@ let HttpServer = class HttpServer {
|
|
|
311
332
|
});
|
|
312
333
|
}
|
|
313
334
|
catch (error) {
|
|
314
|
-
|
|
335
|
+
try {
|
|
336
|
+
process.stderr.write(`[HttpServer] Bulk delete error: ${error?.message ?? String(error)}\n`);
|
|
337
|
+
}
|
|
338
|
+
catch { }
|
|
315
339
|
res.status(500).json({
|
|
316
340
|
success: false,
|
|
317
341
|
error: error.message || 'Failed to delete sessions'
|
|
@@ -335,7 +359,10 @@ let HttpServer = class HttpServer {
|
|
|
335
359
|
this._stopPromise = null;
|
|
336
360
|
const mode = this.config.dashboardMode ?? this.dashboardMode;
|
|
337
361
|
if (mode.kind === 'legacy') {
|
|
338
|
-
|
|
362
|
+
try {
|
|
363
|
+
process.stderr.write('[Dashboard] Unified dashboard disabled, using legacy mode\n');
|
|
364
|
+
}
|
|
365
|
+
catch { }
|
|
339
366
|
return await this.startLegacyMode();
|
|
340
367
|
}
|
|
341
368
|
if (await this.tryBecomePrimary()) {
|
|
@@ -345,8 +372,11 @@ let HttpServer = class HttpServer {
|
|
|
345
372
|
}
|
|
346
373
|
catch (error) {
|
|
347
374
|
if (error.code === 'EADDRINUSE') {
|
|
348
|
-
|
|
349
|
-
`
|
|
375
|
+
try {
|
|
376
|
+
process.stderr.write(`[Dashboard] Port ${this.port} still held by previous instance -- ` +
|
|
377
|
+
`running on next available port. Restart the old instance to move to ${this.port}.\n`);
|
|
378
|
+
}
|
|
379
|
+
catch { }
|
|
350
380
|
await promises_1.default.unlink(this.lockFile).catch(() => { });
|
|
351
381
|
return await this.startLegacyMode();
|
|
352
382
|
}
|
|
@@ -354,7 +384,10 @@ let HttpServer = class HttpServer {
|
|
|
354
384
|
}
|
|
355
385
|
}
|
|
356
386
|
else {
|
|
357
|
-
|
|
387
|
+
try {
|
|
388
|
+
process.stderr.write(`[Dashboard] Unified dashboard at http://localhost:${this.port}\n`);
|
|
389
|
+
}
|
|
390
|
+
catch { }
|
|
358
391
|
return null;
|
|
359
392
|
}
|
|
360
393
|
}
|
|
@@ -371,7 +404,10 @@ let HttpServer = class HttpServer {
|
|
|
371
404
|
version: CURRENT_VERSION
|
|
372
405
|
};
|
|
373
406
|
await promises_1.default.writeFile(this.lockFile, JSON.stringify(lockData, null, 2), { flag: 'wx' });
|
|
374
|
-
|
|
407
|
+
try {
|
|
408
|
+
process.stderr.write('[Dashboard] Primary elected\n');
|
|
409
|
+
}
|
|
410
|
+
catch { }
|
|
375
411
|
this.isPrimary = true;
|
|
376
412
|
this.setupPrimaryCleanup();
|
|
377
413
|
this.heartbeat.start();
|
|
@@ -382,7 +418,10 @@ let HttpServer = class HttpServer {
|
|
|
382
418
|
return await this.reclaimStaleLock();
|
|
383
419
|
}
|
|
384
420
|
else if (error.code === 'EACCES' || error.code === 'EPERM') {
|
|
385
|
-
|
|
421
|
+
try {
|
|
422
|
+
process.stderr.write('[Dashboard] Cannot write lock file (permission denied)\n');
|
|
423
|
+
}
|
|
424
|
+
catch { }
|
|
386
425
|
return false;
|
|
387
426
|
}
|
|
388
427
|
throw error;
|
|
@@ -525,15 +564,24 @@ let HttpServer = class HttpServer {
|
|
|
525
564
|
if (isCleaningUp || !this.isPrimary)
|
|
526
565
|
return;
|
|
527
566
|
isCleaningUp = true;
|
|
528
|
-
|
|
567
|
+
try {
|
|
568
|
+
process.stderr.write('[Dashboard] Primary shutting down (sync cleanup)\n');
|
|
569
|
+
}
|
|
570
|
+
catch { }
|
|
529
571
|
this.heartbeat.stop();
|
|
530
572
|
try {
|
|
531
573
|
(0, DashboardLockRelease_js_1.releaseLockFileSync)(this.lockFile);
|
|
532
|
-
|
|
574
|
+
try {
|
|
575
|
+
process.stderr.write('[Dashboard] Lock file released\n');
|
|
576
|
+
}
|
|
577
|
+
catch { }
|
|
533
578
|
}
|
|
534
579
|
catch (error) {
|
|
535
580
|
if (error.code !== 'ENOENT') {
|
|
536
|
-
|
|
581
|
+
try {
|
|
582
|
+
process.stderr.write(`[Dashboard] Failed to release lock file: ${error.message}\n`);
|
|
583
|
+
}
|
|
584
|
+
catch { }
|
|
537
585
|
}
|
|
538
586
|
}
|
|
539
587
|
this.isPrimary = false;
|
|
@@ -542,9 +590,15 @@ let HttpServer = class HttpServer {
|
|
|
542
590
|
if (isCleaningUp)
|
|
543
591
|
return;
|
|
544
592
|
isCleaningUp = true;
|
|
545
|
-
|
|
593
|
+
try {
|
|
594
|
+
process.stderr.write(`[Dashboard] Received ${signal}\n`);
|
|
595
|
+
}
|
|
596
|
+
catch { }
|
|
546
597
|
this.stop()
|
|
547
|
-
.catch(err =>
|
|
598
|
+
.catch(err => { try {
|
|
599
|
+
process.stderr.write(`[Dashboard] Cleanup error: ${err.message}\n`);
|
|
600
|
+
}
|
|
601
|
+
catch { } })
|
|
548
602
|
.finally(() => {
|
|
549
603
|
if (signal !== 'exit') {
|
|
550
604
|
this.shutdownEvents.emit({ kind: 'shutdown_requested', signal });
|
|
@@ -589,7 +643,10 @@ let HttpServer = class HttpServer {
|
|
|
589
643
|
});
|
|
590
644
|
});
|
|
591
645
|
this.baseUrl = `http://localhost:${this.port}`;
|
|
592
|
-
|
|
646
|
+
try {
|
|
647
|
+
process.stderr.write(`[Dashboard] Started in legacy mode on port ${this.port}\n`);
|
|
648
|
+
}
|
|
649
|
+
catch { }
|
|
593
650
|
this.printBanner();
|
|
594
651
|
return this.baseUrl;
|
|
595
652
|
}
|
|
@@ -648,10 +705,16 @@ let HttpServer = class HttpServer {
|
|
|
648
705
|
if (behavior.kind === 'auto_open') {
|
|
649
706
|
try {
|
|
650
707
|
await (0, open_1.default)(url);
|
|
651
|
-
|
|
708
|
+
try {
|
|
709
|
+
process.stderr.write(`Opened dashboard: ${url}\n`);
|
|
710
|
+
}
|
|
711
|
+
catch { }
|
|
652
712
|
}
|
|
653
713
|
catch (error) {
|
|
654
|
-
|
|
714
|
+
try {
|
|
715
|
+
process.stderr.write(`Dashboard URL: ${url} (auto-open failed, please open manually)\n`);
|
|
716
|
+
}
|
|
717
|
+
catch { }
|
|
655
718
|
}
|
|
656
719
|
}
|
|
657
720
|
return url;
|
|
@@ -678,12 +741,18 @@ let HttpServer = class HttpServer {
|
|
|
678
741
|
if (!this.server)
|
|
679
742
|
return resolve();
|
|
680
743
|
const closeTimeout = setTimeout(() => {
|
|
681
|
-
|
|
744
|
+
try {
|
|
745
|
+
process.stderr.write('[Dashboard] Server close timeout after 5s, forcing shutdown\n');
|
|
746
|
+
}
|
|
747
|
+
catch { }
|
|
682
748
|
resolve();
|
|
683
749
|
}, 5000);
|
|
684
750
|
this.server.close(() => {
|
|
685
751
|
clearTimeout(closeTimeout);
|
|
686
|
-
|
|
752
|
+
try {
|
|
753
|
+
process.stderr.write('HTTP server stopped\n');
|
|
754
|
+
}
|
|
755
|
+
catch { }
|
|
687
756
|
resolve();
|
|
688
757
|
});
|
|
689
758
|
});
|
|
@@ -717,45 +786,75 @@ let HttpServer = class HttpServer {
|
|
|
717
786
|
try {
|
|
718
787
|
const busyPorts = await this.getWorkrailPorts();
|
|
719
788
|
if (busyPorts.length === 0) {
|
|
720
|
-
|
|
789
|
+
try {
|
|
790
|
+
process.stderr.write('[Cleanup] No workrail processes found\n');
|
|
791
|
+
}
|
|
792
|
+
catch { }
|
|
721
793
|
return 0;
|
|
722
794
|
}
|
|
723
|
-
|
|
795
|
+
try {
|
|
796
|
+
process.stderr.write(`[Cleanup] Found ${busyPorts.length} workrail process(es), removing all...\n`);
|
|
797
|
+
}
|
|
798
|
+
catch { }
|
|
724
799
|
let cleanedCount = 0;
|
|
725
800
|
for (const { port, pid } of busyPorts) {
|
|
726
801
|
if (pid === process.pid) {
|
|
727
|
-
|
|
802
|
+
try {
|
|
803
|
+
process.stderr.write(`[Cleanup] Skipping current process ${pid}\n`);
|
|
804
|
+
}
|
|
805
|
+
catch { }
|
|
728
806
|
continue;
|
|
729
807
|
}
|
|
730
|
-
|
|
808
|
+
try {
|
|
809
|
+
process.stderr.write(`[Cleanup] Killing process ${pid} on port ${port}\n`);
|
|
810
|
+
}
|
|
811
|
+
catch { }
|
|
731
812
|
try {
|
|
732
813
|
process.kill(pid, 'SIGTERM');
|
|
733
814
|
await new Promise(r => setTimeout(r, 1000));
|
|
734
815
|
try {
|
|
735
816
|
process.kill(pid, 0);
|
|
736
817
|
process.kill(pid, 'SIGKILL');
|
|
737
|
-
|
|
818
|
+
try {
|
|
819
|
+
process.stderr.write(`[Cleanup] Force killed process ${pid}\n`);
|
|
820
|
+
}
|
|
821
|
+
catch { }
|
|
738
822
|
}
|
|
739
823
|
catch {
|
|
740
|
-
|
|
824
|
+
try {
|
|
825
|
+
process.stderr.write(`[Cleanup] Process ${pid} terminated gracefully\n`);
|
|
826
|
+
}
|
|
827
|
+
catch { }
|
|
741
828
|
}
|
|
742
829
|
cleanedCount++;
|
|
743
830
|
}
|
|
744
831
|
catch (error) {
|
|
745
|
-
|
|
832
|
+
try {
|
|
833
|
+
process.stderr.write(`[Cleanup] Failed to kill process ${pid}: ${error?.message ?? String(error)}\n`);
|
|
834
|
+
}
|
|
835
|
+
catch { }
|
|
746
836
|
}
|
|
747
837
|
}
|
|
748
|
-
|
|
838
|
+
try {
|
|
839
|
+
process.stderr.write(`[Cleanup] Cleaned up ${cleanedCount} process(es)\n`);
|
|
840
|
+
}
|
|
841
|
+
catch { }
|
|
749
842
|
try {
|
|
750
843
|
await promises_1.default.unlink(this.lockFile);
|
|
751
|
-
|
|
844
|
+
try {
|
|
845
|
+
process.stderr.write('[Cleanup] Removed lock file\n');
|
|
846
|
+
}
|
|
847
|
+
catch { }
|
|
752
848
|
}
|
|
753
849
|
catch {
|
|
754
850
|
}
|
|
755
851
|
return cleanedCount;
|
|
756
852
|
}
|
|
757
853
|
catch (error) {
|
|
758
|
-
|
|
854
|
+
try {
|
|
855
|
+
process.stderr.write(`[Cleanup] Full cleanup failed: ${error?.message ?? String(error)}\n`);
|
|
856
|
+
}
|
|
857
|
+
catch { }
|
|
759
858
|
throw error;
|
|
760
859
|
}
|
|
761
860
|
}
|