@exaudeus/workrail 3.26.2 → 3.28.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.js +22 -0
- package/dist/console/assets/{index-HhtarvD5.js → index-C146q2kN.js} +1 -1
- package/dist/console/index.html +1 -1
- package/dist/daemon/workflow-runner.d.ts +2 -0
- package/dist/daemon/workflow-runner.js +51 -4
- package/dist/infrastructure/session/HttpServer.js +66 -14
- package/dist/manifest.json +47 -31
- package/dist/mcp/server.js +34 -18
- package/dist/mcp/transports/bridge-entry.d.ts +33 -1
- package/dist/mcp/transports/bridge-entry.js +159 -10
- package/dist/mcp/transports/bridge-events.d.ts +17 -0
- package/dist/mcp/transports/fatal-exit.d.ts +1 -0
- package/dist/mcp/transports/fatal-exit.js +27 -1
- package/dist/mcp/transports/http-entry.js +10 -1
- package/dist/mcp/transports/primary-tombstone.d.ts +21 -0
- package/dist/mcp/transports/primary-tombstone.js +51 -0
- package/dist/mcp/transports/shutdown-hooks.js +20 -5
- package/dist/mcp/transports/stdio-entry.js +7 -0
- package/dist/mcp-server.js +5 -5
- package/dist/trigger/daemon-console.d.ts +24 -0
- package/dist/trigger/daemon-console.js +120 -0
- package/package.json +1 -1
- package/workflows/workflow-for-workflows.json +249 -90
- package/workflows/workflow-for-workflows.v2.json +185 -74
|
@@ -40,6 +40,7 @@ exports.DAEMON_SOUL_TEMPLATE = exports.DAEMON_SOUL_DEFAULT = exports.DAEMON_SESS
|
|
|
40
40
|
exports.readDaemonSessionState = readDaemonSessionState;
|
|
41
41
|
exports.readAllDaemonSessions = readAllDaemonSessions;
|
|
42
42
|
exports.runStartupRecovery = runStartupRecovery;
|
|
43
|
+
exports.makeContinueWorkflowTool = makeContinueWorkflowTool;
|
|
43
44
|
exports.makeBashTool = makeBashTool;
|
|
44
45
|
exports.buildSessionRecap = buildSessionRecap;
|
|
45
46
|
exports.buildSystemPrompt = buildSystemPrompt;
|
|
@@ -337,7 +338,7 @@ function getSchemas() {
|
|
|
337
338
|
};
|
|
338
339
|
return _schemas;
|
|
339
340
|
}
|
|
340
|
-
function makeContinueWorkflowTool(sessionId, ctx, onAdvance, onComplete, schemas) {
|
|
341
|
+
function makeContinueWorkflowTool(sessionId, ctx, onAdvance, onComplete, schemas, _executeContinueWorkflowFn = index_js_1.executeContinueWorkflow) {
|
|
341
342
|
return {
|
|
342
343
|
name: 'continue_workflow',
|
|
343
344
|
description: 'Advance the WorkRail workflow to the next step. Call this after completing all work ' +
|
|
@@ -345,7 +346,8 @@ function makeContinueWorkflowTool(sessionId, ctx, onAdvance, onComplete, schemas
|
|
|
345
346
|
inputSchema: schemas['ContinueWorkflowParams'],
|
|
346
347
|
label: 'Continue Workflow',
|
|
347
348
|
execute: async (_toolCallId, params) => {
|
|
348
|
-
|
|
349
|
+
console.log(`[WorkflowRunner] Tool: continue_workflow sessionId=${sessionId}`);
|
|
350
|
+
const result = await _executeContinueWorkflowFn({
|
|
349
351
|
continueToken: params.continueToken,
|
|
350
352
|
intent: (params.intent ?? 'advance'),
|
|
351
353
|
output: params.notesMarkdown
|
|
@@ -359,8 +361,50 @@ function makeContinueWorkflowTool(sessionId, ctx, onAdvance, onComplete, schemas
|
|
|
359
361
|
const out = result.value.response;
|
|
360
362
|
const continueToken = out.continueToken ?? '';
|
|
361
363
|
const checkpointToken = out.checkpointToken ?? null;
|
|
362
|
-
|
|
363
|
-
|
|
364
|
+
const persistToken = (out.kind === 'blocked' ? out.nextCall?.params.continueToken : undefined) ?? continueToken;
|
|
365
|
+
if (persistToken) {
|
|
366
|
+
await persistTokens(sessionId, persistToken, checkpointToken);
|
|
367
|
+
}
|
|
368
|
+
if (out.kind === 'blocked') {
|
|
369
|
+
const retryToken = out.nextCall?.params.continueToken ?? continueToken;
|
|
370
|
+
const lines = ['## Step blocked -- action required\n'];
|
|
371
|
+
for (const blocker of out.blockers.blockers) {
|
|
372
|
+
lines.push(blocker.message);
|
|
373
|
+
if (blocker.suggestedFix) {
|
|
374
|
+
lines.push(`\nWhat to do: ${blocker.suggestedFix}`);
|
|
375
|
+
}
|
|
376
|
+
lines.push('');
|
|
377
|
+
}
|
|
378
|
+
if (out.validation) {
|
|
379
|
+
if (out.validation.issues.length > 0) {
|
|
380
|
+
lines.push('**Issues:**');
|
|
381
|
+
for (const issue of out.validation.issues)
|
|
382
|
+
lines.push(`- ${issue}`);
|
|
383
|
+
lines.push('');
|
|
384
|
+
}
|
|
385
|
+
if (out.validation.suggestions.length > 0) {
|
|
386
|
+
lines.push('**Suggestions:**');
|
|
387
|
+
for (const s of out.validation.suggestions)
|
|
388
|
+
lines.push(`- ${s}`);
|
|
389
|
+
lines.push('');
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (out.assessmentFollowup) {
|
|
393
|
+
lines.push(`**Follow-up required:** ${out.assessmentFollowup.title}`);
|
|
394
|
+
lines.push(out.assessmentFollowup.guidance);
|
|
395
|
+
lines.push('');
|
|
396
|
+
}
|
|
397
|
+
if (out.retryable) {
|
|
398
|
+
lines.push(`Retry the same step with corrected output.\n\ncontinueToken: ${retryToken}`);
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
lines.push(`You cannot proceed without resolving this. Inform the user and wait for their response, then call continue_workflow.\n\ncontinueToken: ${retryToken}`);
|
|
402
|
+
}
|
|
403
|
+
const feedback = lines.join('\n');
|
|
404
|
+
return {
|
|
405
|
+
content: [{ type: 'text', text: feedback }],
|
|
406
|
+
details: out,
|
|
407
|
+
};
|
|
364
408
|
}
|
|
365
409
|
if (out.isComplete) {
|
|
366
410
|
onComplete(params.notesMarkdown);
|
|
@@ -391,6 +435,7 @@ function makeBashTool(workspacePath, schemas) {
|
|
|
391
435
|
inputSchema: schemas['BashParams'],
|
|
392
436
|
label: 'Bash',
|
|
393
437
|
execute: async (_toolCallId, params) => {
|
|
438
|
+
console.log(`[WorkflowRunner] Tool: bash "${String(params.command).slice(0, 80)}"`);
|
|
394
439
|
const cwd = params.cwd ?? workspacePath;
|
|
395
440
|
try {
|
|
396
441
|
const { stdout, stderr } = await execAsync(params.command, {
|
|
@@ -637,6 +682,7 @@ async function runWorkflow(trigger, ctx, apiKey, daemonRegistry) {
|
|
|
637
682
|
reject(new Error('Workflow timed out'));
|
|
638
683
|
}, sessionTimeoutMs);
|
|
639
684
|
});
|
|
685
|
+
console.log(`[WorkflowRunner] Agent loop started: sessionId=${sessionId} workflowId=${trigger.workflowId} modelId=${modelId}`);
|
|
640
686
|
await Promise.race([agent.prompt(buildUserMessage(initialPrompt)), timeoutPromise])
|
|
641
687
|
.catch((err) => {
|
|
642
688
|
agent.abort();
|
|
@@ -662,6 +708,7 @@ async function runWorkflow(trigger, ctx, apiKey, daemonRegistry) {
|
|
|
662
708
|
unsubscribe();
|
|
663
709
|
if (timeoutHandle !== undefined)
|
|
664
710
|
clearTimeout(timeoutHandle);
|
|
711
|
+
console.log(`[WorkflowRunner] Agent loop ended: sessionId=${sessionId} stopReason=${stopReason}${errorMessage ? ` error=${errorMessage.slice(0, 120)}` : ''}`);
|
|
665
712
|
}
|
|
666
713
|
if (timeoutReason !== null) {
|
|
667
714
|
daemonRegistry?.unregister(sessionId, 'failed');
|
|
@@ -425,11 +425,17 @@ let HttpServer = class HttpServer {
|
|
|
425
425
|
const lockData = JSON.parse(lockContent);
|
|
426
426
|
const { reclaim, reason } = this.shouldReclaimLock(lockData);
|
|
427
427
|
if (!reclaim) {
|
|
428
|
-
|
|
428
|
+
try {
|
|
429
|
+
process.stderr.write(`[Dashboard] Secondary mode: primary lock valid (PID ${lockData.pid}), yielding\n`);
|
|
430
|
+
}
|
|
431
|
+
catch { }
|
|
429
432
|
return false;
|
|
430
433
|
}
|
|
431
434
|
else {
|
|
432
|
-
|
|
435
|
+
try {
|
|
436
|
+
process.stderr.write(`[Dashboard] Lock reclaim needed: ${reason}\n`);
|
|
437
|
+
}
|
|
438
|
+
catch { }
|
|
433
439
|
}
|
|
434
440
|
const tempPath = `${this.lockFile}.${process.pid}.${Date.now()}`;
|
|
435
441
|
const newLockData = {
|
|
@@ -459,7 +465,24 @@ let HttpServer = class HttpServer {
|
|
|
459
465
|
throw err;
|
|
460
466
|
}
|
|
461
467
|
}
|
|
462
|
-
|
|
468
|
+
try {
|
|
469
|
+
const writtenContent = await promises_1.default.readFile(this.lockFile, 'utf-8');
|
|
470
|
+
const writtenData = JSON.parse(writtenContent);
|
|
471
|
+
if (writtenData.pid !== process.pid) {
|
|
472
|
+
try {
|
|
473
|
+
process.stderr.write(`[Dashboard] Lost lock election (winner PID ${writtenData.pid}), yielding\n`);
|
|
474
|
+
}
|
|
475
|
+
catch { }
|
|
476
|
+
return false;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
catch {
|
|
480
|
+
return await this.tryBecomePrimary();
|
|
481
|
+
}
|
|
482
|
+
try {
|
|
483
|
+
process.stderr.write('[Dashboard] Lock reclaimed successfully\n');
|
|
484
|
+
}
|
|
485
|
+
catch { }
|
|
463
486
|
this.isPrimary = true;
|
|
464
487
|
this.setupPrimaryCleanup();
|
|
465
488
|
this.heartbeat.start();
|
|
@@ -468,10 +491,16 @@ let HttpServer = class HttpServer {
|
|
|
468
491
|
catch (error) {
|
|
469
492
|
await promises_1.default.unlink(tempPath).catch(() => { });
|
|
470
493
|
if (error.code === 'ENOENT') {
|
|
471
|
-
|
|
494
|
+
try {
|
|
495
|
+
process.stderr.write('[Dashboard] Lock deleted during reclaim, trying fresh\n');
|
|
496
|
+
}
|
|
497
|
+
catch { }
|
|
472
498
|
return await this.tryBecomePrimary();
|
|
473
499
|
}
|
|
474
|
-
|
|
500
|
+
try {
|
|
501
|
+
process.stderr.write(`[Dashboard] Lock reclaim failed: ${error.message}\n`);
|
|
502
|
+
}
|
|
503
|
+
catch { }
|
|
475
504
|
return false;
|
|
476
505
|
}
|
|
477
506
|
}
|
|
@@ -479,7 +508,10 @@ let HttpServer = class HttpServer {
|
|
|
479
508
|
if (error.code === 'ENOENT') {
|
|
480
509
|
return await this.tryBecomePrimary();
|
|
481
510
|
}
|
|
482
|
-
|
|
511
|
+
try {
|
|
512
|
+
process.stderr.write('[Dashboard] Lock file corrupted, attempting fresh claim\n');
|
|
513
|
+
}
|
|
514
|
+
catch { }
|
|
483
515
|
await promises_1.default.unlink(this.lockFile).catch(() => { });
|
|
484
516
|
return await this.tryBecomePrimary();
|
|
485
517
|
}
|
|
@@ -574,14 +606,34 @@ let HttpServer = class HttpServer {
|
|
|
574
606
|
}
|
|
575
607
|
printBanner() {
|
|
576
608
|
const line = '═'.repeat(60);
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
609
|
+
try {
|
|
610
|
+
process.stderr.write(`\n${line}\n`);
|
|
611
|
+
}
|
|
612
|
+
catch { }
|
|
613
|
+
try {
|
|
614
|
+
process.stderr.write(`🔧 Workrail MCP Server Started\n`);
|
|
615
|
+
}
|
|
616
|
+
catch { }
|
|
617
|
+
try {
|
|
618
|
+
process.stderr.write(`${line}\n`);
|
|
619
|
+
}
|
|
620
|
+
catch { }
|
|
621
|
+
try {
|
|
622
|
+
process.stderr.write(`📊 Dashboard: ${this.baseUrl} ${this.isPrimary ? '(PRIMARY - All Projects)' : '(Legacy Mode)'}\n`);
|
|
623
|
+
}
|
|
624
|
+
catch { }
|
|
625
|
+
try {
|
|
626
|
+
process.stderr.write(`💾 Sessions: ${this.sessionManager.getSessionsRoot()}\n`);
|
|
627
|
+
}
|
|
628
|
+
catch { }
|
|
629
|
+
try {
|
|
630
|
+
process.stderr.write(`🏗️ Project: ${this.sessionManager.getProjectId()}\n`);
|
|
631
|
+
}
|
|
632
|
+
catch { }
|
|
633
|
+
try {
|
|
634
|
+
process.stderr.write(`${line}\n\n`);
|
|
635
|
+
}
|
|
636
|
+
catch { }
|
|
585
637
|
}
|
|
586
638
|
async openDashboard(sessionId) {
|
|
587
639
|
if (!this.baseUrl) {
|
package/dist/manifest.json
CHANGED
|
@@ -246,8 +246,8 @@
|
|
|
246
246
|
"bytes": 31
|
|
247
247
|
},
|
|
248
248
|
"cli.js": {
|
|
249
|
-
"sha256": "
|
|
250
|
-
"bytes":
|
|
249
|
+
"sha256": "d144366ebfb945c4947770899e2774516d594a085582ca3ee50a0cd46c081723",
|
|
250
|
+
"bytes": 13297
|
|
251
251
|
},
|
|
252
252
|
"cli/commands/cleanup.d.ts": {
|
|
253
253
|
"sha256": "efe1f9e2ecd58e92007ed38b9581a3852c2babe4b3f2a97237dccd878eebe7ec",
|
|
@@ -429,12 +429,12 @@
|
|
|
429
429
|
"sha256": "cf9d09641f1c31fffe6c7835b30bbbad52572befec1acab7fb9a0c188431af36",
|
|
430
430
|
"bytes": 60355
|
|
431
431
|
},
|
|
432
|
-
"console/assets/index-
|
|
433
|
-
"sha256": "
|
|
432
|
+
"console/assets/index-C146q2kN.js": {
|
|
433
|
+
"sha256": "ddd0903a3cc54437b6184a0ae3d13ab6810a4e36e3417e3f77a603e4f98ee85f",
|
|
434
434
|
"bytes": 754653
|
|
435
435
|
},
|
|
436
436
|
"console/index.html": {
|
|
437
|
-
"sha256": "
|
|
437
|
+
"sha256": "5d58c2a66cc94a9df4c520561efe94b5e3632d15392f602e2f1e510e8148b625",
|
|
438
438
|
"bytes": 417
|
|
439
439
|
},
|
|
440
440
|
"core/error-handler.d.ts": {
|
|
@@ -470,12 +470,12 @@
|
|
|
470
470
|
"bytes": 1009
|
|
471
471
|
},
|
|
472
472
|
"daemon/workflow-runner.d.ts": {
|
|
473
|
-
"sha256": "
|
|
474
|
-
"bytes":
|
|
473
|
+
"sha256": "049d32530519c1a9b82959df91e144a6324b0b9dfe7b6ed507624c450cc2fb77",
|
|
474
|
+
"bytes": 3178
|
|
475
475
|
},
|
|
476
476
|
"daemon/workflow-runner.js": {
|
|
477
|
-
"sha256": "
|
|
478
|
-
"bytes":
|
|
477
|
+
"sha256": "0243e7e779f08edf8258fd3946f815c0ff6cc4fd10eaa1511d358da31cbf1f68",
|
|
478
|
+
"bytes": 32730
|
|
479
479
|
},
|
|
480
480
|
"di/container.d.ts": {
|
|
481
481
|
"sha256": "003bb7fb7478d627524b9b1e76bd0a963a243794a687ff233b96dc0e33a06d9f",
|
|
@@ -634,8 +634,8 @@
|
|
|
634
634
|
"bytes": 2025
|
|
635
635
|
},
|
|
636
636
|
"infrastructure/session/HttpServer.js": {
|
|
637
|
-
"sha256": "
|
|
638
|
-
"bytes":
|
|
637
|
+
"sha256": "914e38d3f9ed1264075d226e24e60a32d8a2f1d425631404873a1be62f067386",
|
|
638
|
+
"bytes": 32736
|
|
639
639
|
},
|
|
640
640
|
"infrastructure/session/SessionDataNormalizer.d.ts": {
|
|
641
641
|
"sha256": "c89bb5e00d7d01fb4aa6d0095602541de53c425c6b99b67fa8367eb29cb63e9e",
|
|
@@ -762,8 +762,8 @@
|
|
|
762
762
|
"bytes": 409
|
|
763
763
|
},
|
|
764
764
|
"mcp-server.js": {
|
|
765
|
-
"sha256": "
|
|
766
|
-
"bytes":
|
|
765
|
+
"sha256": "3445ca2f12e70a07ce693ed6efde67826ebab00f85716954def4ee82f86da0cd",
|
|
766
|
+
"bytes": 3668
|
|
767
767
|
},
|
|
768
768
|
"mcp/assert-output.d.ts": {
|
|
769
769
|
"sha256": "f1b821c3652423b15a09d2d1c5a042ee565a503c3d7196bd8220fbe697e0dc75",
|
|
@@ -1122,8 +1122,8 @@
|
|
|
1122
1122
|
"bytes": 960
|
|
1123
1123
|
},
|
|
1124
1124
|
"mcp/server.js": {
|
|
1125
|
-
"sha256": "
|
|
1126
|
-
"bytes":
|
|
1125
|
+
"sha256": "655e05345310422de6487e9f045e04c53266eb0c71d4a6482a605c67761eb25e",
|
|
1126
|
+
"bytes": 16962
|
|
1127
1127
|
},
|
|
1128
1128
|
"mcp/step-content-envelope.d.ts": {
|
|
1129
1129
|
"sha256": "19bd63c4d4de1d5d93393d346625d28ffd1bebdc320d4ba4e694cb740ec97d3b",
|
|
@@ -1174,36 +1174,36 @@
|
|
|
1174
1174
|
"bytes": 8822
|
|
1175
1175
|
},
|
|
1176
1176
|
"mcp/transports/bridge-entry.d.ts": {
|
|
1177
|
-
"sha256": "
|
|
1178
|
-
"bytes":
|
|
1177
|
+
"sha256": "ba4c1df0691feeb79f4c7f9a8347807c86dbbb180cc4d5ba66740b6f8f216231",
|
|
1178
|
+
"bytes": 3556
|
|
1179
1179
|
},
|
|
1180
1180
|
"mcp/transports/bridge-entry.js": {
|
|
1181
|
-
"sha256": "
|
|
1182
|
-
"bytes":
|
|
1181
|
+
"sha256": "f48e2c8700fec74daa5a9a47ab59143a44eba85ea938a408e2970029d53e23b5",
|
|
1182
|
+
"bytes": 20196
|
|
1183
1183
|
},
|
|
1184
1184
|
"mcp/transports/bridge-events.d.ts": {
|
|
1185
|
-
"sha256": "
|
|
1186
|
-
"bytes":
|
|
1185
|
+
"sha256": "ba4034309d5a4d762166c058079a9b461d0c403c5b329d2f5ee3bf4bd4f446e1",
|
|
1186
|
+
"bytes": 1324
|
|
1187
1187
|
},
|
|
1188
1188
|
"mcp/transports/bridge-events.js": {
|
|
1189
1189
|
"sha256": "40e0eeb42aec6fb2906ac3da1d9f017cb9b9de56125736d4e90667239c5f019b",
|
|
1190
1190
|
"bytes": 955
|
|
1191
1191
|
},
|
|
1192
1192
|
"mcp/transports/fatal-exit.d.ts": {
|
|
1193
|
-
"sha256": "
|
|
1194
|
-
"bytes":
|
|
1193
|
+
"sha256": "e51b420a4f4b9d21cff8c79180618fb0ee43d17f4fb402b1fa05d05e9cd0b4bc",
|
|
1194
|
+
"bytes": 490
|
|
1195
1195
|
},
|
|
1196
1196
|
"mcp/transports/fatal-exit.js": {
|
|
1197
|
-
"sha256": "
|
|
1198
|
-
"bytes":
|
|
1197
|
+
"sha256": "3b9f7b93cbb672b8491fd6fd73e4c799cccf7e51567edf0b9fc0faccbc1f41c8",
|
|
1198
|
+
"bytes": 3593
|
|
1199
1199
|
},
|
|
1200
1200
|
"mcp/transports/http-entry.d.ts": {
|
|
1201
1201
|
"sha256": "35d313b120dcf38643de9462559163581b89943fe432706986252e8b698b9507",
|
|
1202
1202
|
"bytes": 70
|
|
1203
1203
|
},
|
|
1204
1204
|
"mcp/transports/http-entry.js": {
|
|
1205
|
-
"sha256": "
|
|
1206
|
-
"bytes":
|
|
1205
|
+
"sha256": "31ab4e9f518e1f9b6fd46a8b7e221639029abea51e0cbfe22e5008fecdc46e6b",
|
|
1206
|
+
"bytes": 3887
|
|
1207
1207
|
},
|
|
1208
1208
|
"mcp/transports/http-listener.d.ts": {
|
|
1209
1209
|
"sha256": "6c6cd6dcfe110ed8fa1dc2f9c96caba55959555f98048d3694ac104f42d6d51a",
|
|
@@ -1213,21 +1213,29 @@
|
|
|
1213
1213
|
"sha256": "d9b7deb9015e55b5b1e9b3e415b74a7fbbe8b6afb94bbd5a5f7957cd1a7f3f50",
|
|
1214
1214
|
"bytes": 3534
|
|
1215
1215
|
},
|
|
1216
|
+
"mcp/transports/primary-tombstone.d.ts": {
|
|
1217
|
+
"sha256": "b03c75684b5191752b9a0494a5a6c2b463e8dcf6d2d22d7e265cb6f94454513a",
|
|
1218
|
+
"bytes": 891
|
|
1219
|
+
},
|
|
1220
|
+
"mcp/transports/primary-tombstone.js": {
|
|
1221
|
+
"sha256": "faec43962d124e5a296ec1c4419693f33ea2c9fd25e26831bd9c486389001c74",
|
|
1222
|
+
"bytes": 1545
|
|
1223
|
+
},
|
|
1216
1224
|
"mcp/transports/shutdown-hooks.d.ts": {
|
|
1217
1225
|
"sha256": "abf3799e44183c8a7e3614e2f14c1d7c8c4bb4ce0b720d3005ee165e4dd6f211",
|
|
1218
1226
|
"bytes": 547
|
|
1219
1227
|
},
|
|
1220
1228
|
"mcp/transports/shutdown-hooks.js": {
|
|
1221
|
-
"sha256": "
|
|
1222
|
-
"bytes":
|
|
1229
|
+
"sha256": "e9b6261e223700d1d0d6253edff824c5ed6c42778afba2b18575b48923876e01",
|
|
1230
|
+
"bytes": 3082
|
|
1223
1231
|
},
|
|
1224
1232
|
"mcp/transports/stdio-entry.d.ts": {
|
|
1225
1233
|
"sha256": "4ced3c9e00ef67555781dea74315290eea8a9dbffd38155bc00c3fb07b0c1794",
|
|
1226
1234
|
"bytes": 59
|
|
1227
1235
|
},
|
|
1228
1236
|
"mcp/transports/stdio-entry.js": {
|
|
1229
|
-
"sha256": "
|
|
1230
|
-
"bytes":
|
|
1237
|
+
"sha256": "3acac4d05321d0bccb00aae61053b58327afc95bd4a05c1b2b4e853f774c036e",
|
|
1238
|
+
"bytes": 4299
|
|
1231
1239
|
},
|
|
1232
1240
|
"mcp/transports/transport-mode.d.ts": {
|
|
1233
1241
|
"sha256": "1c59128ab0174bd2a113fff17521e6339ca367f2b8980c2f2c164ec393c10518",
|
|
@@ -1493,6 +1501,14 @@
|
|
|
1493
1501
|
"sha256": "d43aa81f5bc89faa359e0f97c814ba25155591ff078fbb9bfd40f8c7c9683230",
|
|
1494
1502
|
"bytes": 77
|
|
1495
1503
|
},
|
|
1504
|
+
"trigger/daemon-console.d.ts": {
|
|
1505
|
+
"sha256": "8c1dca4a4683e4a96a8dc007df556309da0d2a2076ff0981c3b80f148cb5b3ad",
|
|
1506
|
+
"bytes": 937
|
|
1507
|
+
},
|
|
1508
|
+
"trigger/daemon-console.js": {
|
|
1509
|
+
"sha256": "51056eff122fea677803e8f17f800aa94c03cc796210f8d2ef40e767710444d0",
|
|
1510
|
+
"bytes": 5448
|
|
1511
|
+
},
|
|
1496
1512
|
"trigger/delivery-action.d.ts": {
|
|
1497
1513
|
"sha256": "58109eaa7124d2864e1d872ff0148548932d2fa4d7e672f5fd83d4bbe40afdda",
|
|
1498
1514
|
"bytes": 1188
|
package/dist/mcp/server.js
CHANGED
|
@@ -246,27 +246,43 @@ async function composeServer() {
|
|
|
246
246
|
console.error('[PerfTrace] WORKRAIL_DEV=1 -- tool call timing active');
|
|
247
247
|
}
|
|
248
248
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
249
|
+
try {
|
|
250
|
+
const { name, arguments: args } = request.params;
|
|
251
|
+
const handlerStartMs = Date.now();
|
|
252
|
+
const handlerStartHr = performance.now();
|
|
253
|
+
const handler = handlers[name];
|
|
254
|
+
if (!handler) {
|
|
255
|
+
const unknownResult = {
|
|
256
|
+
content: [{ type: 'text', text: `Unknown tool: ${name}` }],
|
|
257
|
+
isError: true,
|
|
258
|
+
};
|
|
259
|
+
const durationMs = Math.round((performance.now() - handlerStartHr) * 100) / 100;
|
|
260
|
+
try {
|
|
261
|
+
timingSink({ toolName: name ?? '(unknown)', startedAtMs: handlerStartMs, durationMs, outcome: 'unknown_tool' });
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
}
|
|
265
|
+
return unknownResult;
|
|
266
|
+
}
|
|
267
|
+
const requestCtx = ctx.v2
|
|
268
|
+
? { ...ctx, v2: { ...ctx.v2, resolvedRootUris: rootsManager.getCurrentRootUris() } }
|
|
269
|
+
: ctx;
|
|
270
|
+
return await (0, tool_call_timing_js_1.withToolCallTiming)(name, () => handler(args ?? {}, requestCtx), timingSink);
|
|
271
|
+
}
|
|
272
|
+
catch (err) {
|
|
273
|
+
process.stderr.write(`[WorkRail] Unhandled exception at CallTool boundary: ${err instanceof Error ? (err.stack ?? err.message) : String(err)}\n`);
|
|
274
|
+
return {
|
|
275
|
+
content: [{
|
|
276
|
+
type: 'text',
|
|
277
|
+
text: JSON.stringify({
|
|
278
|
+
code: 'INTERNAL_ERROR',
|
|
279
|
+
message: 'WorkRail encountered an unexpected error. This is not caused by your input.',
|
|
280
|
+
retry: { kind: 'retryable', suggestedDelayMs: 0 },
|
|
281
|
+
}),
|
|
282
|
+
}],
|
|
256
283
|
isError: true,
|
|
257
284
|
};
|
|
258
|
-
const durationMs = Math.round((performance.now() - handlerStartHr) * 100) / 100;
|
|
259
|
-
try {
|
|
260
|
-
timingSink({ toolName: name ?? '(unknown)', startedAtMs: handlerStartMs, durationMs, outcome: 'unknown_tool' });
|
|
261
|
-
}
|
|
262
|
-
catch {
|
|
263
|
-
}
|
|
264
|
-
return unknownResult;
|
|
265
285
|
}
|
|
266
|
-
const requestCtx = ctx.v2
|
|
267
|
-
? { ...ctx, v2: { ...ctx.v2, resolvedRootUris: rootsManager.getCurrentRootUris() } }
|
|
268
|
-
: ctx;
|
|
269
|
-
return (0, tool_call_timing_js_1.withToolCallTiming)(name, () => handler(args ?? {}, requestCtx), timingSink);
|
|
270
286
|
});
|
|
271
287
|
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
|
272
288
|
resources: [
|
|
@@ -4,6 +4,8 @@ export interface BridgeConfig {
|
|
|
4
4
|
readonly reconnectMaxAttempts: number;
|
|
5
5
|
readonly forwardTimeoutMs: number;
|
|
6
6
|
readonly maxRespawnAttempts: number;
|
|
7
|
+
readonly spawnLockStaleMs: number;
|
|
8
|
+
readonly waitForPrimaryPollMs: number;
|
|
7
9
|
}
|
|
8
10
|
export declare const DEFAULT_BRIDGE_CONFIG: BridgeConfig;
|
|
9
11
|
type HttpBridgeTransport = {
|
|
@@ -20,6 +22,8 @@ export type ConnectionState = {
|
|
|
20
22
|
readonly attempt: number;
|
|
21
23
|
readonly maxAttempts: number;
|
|
22
24
|
readonly respawnBudget: number;
|
|
25
|
+
} | {
|
|
26
|
+
readonly kind: 'waiting_for_primary';
|
|
23
27
|
} | {
|
|
24
28
|
readonly kind: 'closed';
|
|
25
29
|
};
|
|
@@ -30,6 +34,12 @@ export type ReconnectOutcome = {
|
|
|
30
34
|
} | {
|
|
31
35
|
readonly kind: 'aborted';
|
|
32
36
|
};
|
|
37
|
+
export type SpawnLockResult = {
|
|
38
|
+
readonly kind: 'acquired';
|
|
39
|
+
} | {
|
|
40
|
+
readonly kind: 'skipped';
|
|
41
|
+
readonly reason: string;
|
|
42
|
+
};
|
|
33
43
|
export type FetchLike = (url: string, init?: RequestInit) => Promise<Response>;
|
|
34
44
|
export type SpawnLike = (command: string, args: ReadonlyArray<string>, opts: {
|
|
35
45
|
readonly env: NodeJS.ProcessEnv;
|
|
@@ -38,11 +48,31 @@ export type SpawnLike = (command: string, args: ReadonlyArray<string>, opts: {
|
|
|
38
48
|
}) => {
|
|
39
49
|
unref: () => void;
|
|
40
50
|
};
|
|
51
|
+
export type WriteFileSyncLike = (path: string, content: string, opts: {
|
|
52
|
+
flag: 'wx';
|
|
53
|
+
}) => void;
|
|
54
|
+
export type StatSyncLike = (path: string) => {
|
|
55
|
+
mtimeMs: number;
|
|
56
|
+
};
|
|
57
|
+
export type UnlinkSyncLike = (path: string) => void;
|
|
58
|
+
export type HealthResponse = {
|
|
59
|
+
readonly port: number;
|
|
60
|
+
readonly pid: number;
|
|
61
|
+
};
|
|
41
62
|
export declare function detectHealthyPrimary(port: number, opts?: {
|
|
42
63
|
retries?: number;
|
|
43
64
|
baseDelayMs?: number;
|
|
44
65
|
fetch?: FetchLike;
|
|
45
|
-
}): Promise<
|
|
66
|
+
}): Promise<HealthResponse | null>;
|
|
67
|
+
export declare function spawnLockPath(port: number): string;
|
|
68
|
+
export declare function acquireSpawnLock(port: number, staleMs: number, deps?: {
|
|
69
|
+
readonly writeFileSync?: WriteFileSyncLike;
|
|
70
|
+
readonly statSync?: StatSyncLike;
|
|
71
|
+
readonly unlinkSync?: UnlinkSyncLike;
|
|
72
|
+
}): SpawnLockResult;
|
|
73
|
+
export declare function releaseSpawnLock(port: number, deps?: {
|
|
74
|
+
readonly unlinkSync?: UnlinkSyncLike;
|
|
75
|
+
}): void;
|
|
46
76
|
export declare function spawnPrimary(port: number, deps: {
|
|
47
77
|
spawn: SpawnLike;
|
|
48
78
|
fetch?: FetchLike;
|
|
@@ -57,6 +87,7 @@ type OutcomeHandlerDeps = {
|
|
|
57
87
|
readonly setConnectionState: (state: ConnectionState) => void;
|
|
58
88
|
readonly performShutdown: (reason: string) => void;
|
|
59
89
|
readonly startReconnectLoop: () => void;
|
|
90
|
+
readonly startWaitLoop: () => void;
|
|
60
91
|
readonly triggerSpawn: () => Promise<void>;
|
|
61
92
|
readonly config: Pick<BridgeConfig, 'reconnectMaxAttempts'>;
|
|
62
93
|
};
|
|
@@ -66,5 +97,6 @@ export declare function handleReconnectOutcome(outcome: ReconnectOutcome, reconn
|
|
|
66
97
|
export declare function startBridgeServer(primaryPort: number, config?: BridgeConfig, deps?: {
|
|
67
98
|
spawn?: SpawnLike;
|
|
68
99
|
fetch?: FetchLike;
|
|
100
|
+
originalPrimaryPid?: number;
|
|
69
101
|
}): Promise<void>;
|
|
70
102
|
export {};
|