@exaudeus/workrail 3.7.1 → 3.7.3
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/engine/engine-factory.js +4 -1
- package/dist/manifest.json +41 -41
- package/dist/mcp/handler-factory.js +1 -1
- package/dist/mcp/handlers/v2-execution/start.js +16 -7
- package/dist/mcp/handlers/v2-resume.js +11 -0
- package/dist/mcp/output-schemas.d.ts +44 -9
- package/dist/mcp/output-schemas.js +16 -3
- package/dist/mcp/server.js +1 -0
- package/dist/mcp/v2/tools.d.ts +15 -6
- package/dist/mcp/v2/tools.js +28 -10
- package/dist/mcp/v2-response-formatter.d.ts +1 -0
- package/dist/mcp/v2-response-formatter.js +168 -0
- package/dist/mcp/workflow-protocol-contracts.js +27 -24
- package/dist/v2/durable-core/schemas/export-bundle/index.d.ts +10 -10
- package/dist/v2/durable-core/schemas/session/manifest.d.ts +2 -2
- package/dist/v2/durable-core/tokens/payloads.d.ts +24 -24
- package/dist/v2/infra/local/session-summary-provider/index.d.ts +2 -0
- package/dist/v2/infra/local/session-summary-provider/index.js +131 -17
- package/dist/v2/infra/local/workspace-anchor/index.js +23 -0
- package/dist/v2/projections/resume-ranking.d.ts +33 -6
- package/dist/v2/projections/resume-ranking.js +261 -30
- package/dist/v2/usecases/enumerate-sessions.d.ts +5 -1
- package/dist/v2/usecases/enumerate-sessions.js +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.formatV2ExecutionResponse = formatV2ExecutionResponse;
|
|
4
|
+
exports.formatV2ResumeResponse = formatV2ResumeResponse;
|
|
4
5
|
const render_envelope_js_1 = require("./render-envelope.js");
|
|
5
6
|
const response_supplements_js_1 = require("./response-supplements.js");
|
|
6
7
|
function isV2ExecutionResponse(data) {
|
|
@@ -388,3 +389,170 @@ function formatV2Clean(data) {
|
|
|
388
389
|
primary: formatCleanSuccess(data),
|
|
389
390
|
};
|
|
390
391
|
}
|
|
392
|
+
function isResumeSessionResponse(data) {
|
|
393
|
+
if (typeof data !== 'object' || data === null)
|
|
394
|
+
return false;
|
|
395
|
+
const d = data;
|
|
396
|
+
return (Array.isArray(d.candidates) &&
|
|
397
|
+
typeof d.totalEligible === 'number' &&
|
|
398
|
+
!('pending' in d) &&
|
|
399
|
+
!('nextIntent' in d));
|
|
400
|
+
}
|
|
401
|
+
const WHY_MATCHED_LABELS = {
|
|
402
|
+
matched_exact_id: 'Exact ID match',
|
|
403
|
+
matched_notes: 'Query matched session notes',
|
|
404
|
+
matched_notes_partial: 'Query partially matched session notes',
|
|
405
|
+
matched_workflow_id: 'Query matched workflow type',
|
|
406
|
+
matched_head_sha: 'Same git commit (HEAD SHA)',
|
|
407
|
+
matched_branch: 'Same git branch',
|
|
408
|
+
matched_repo_root: 'Same workspace/repository',
|
|
409
|
+
recency_fallback: 'No strong match signal (recent session)',
|
|
410
|
+
};
|
|
411
|
+
function formatRelativeTime(epochMs) {
|
|
412
|
+
const diffMs = Date.now() - epochMs;
|
|
413
|
+
if (diffMs < 0)
|
|
414
|
+
return 'just now';
|
|
415
|
+
const minutes = Math.floor(diffMs / 60000);
|
|
416
|
+
if (minutes < 1)
|
|
417
|
+
return 'just now';
|
|
418
|
+
if (minutes < 60)
|
|
419
|
+
return `${minutes} minute${minutes === 1 ? '' : 's'} ago`;
|
|
420
|
+
const hours = Math.floor(minutes / 60);
|
|
421
|
+
if (hours < 24)
|
|
422
|
+
return `${hours} hour${hours === 1 ? '' : 's'} ago`;
|
|
423
|
+
const days = Math.floor(hours / 24);
|
|
424
|
+
if (days < 7)
|
|
425
|
+
return `${days} day${days === 1 ? '' : 's'} ago`;
|
|
426
|
+
const weeks = Math.floor(days / 7);
|
|
427
|
+
if (weeks < 5)
|
|
428
|
+
return `${weeks} week${weeks === 1 ? '' : 's'} ago`;
|
|
429
|
+
const months = Math.floor(days / 30);
|
|
430
|
+
return `${months} month${months === 1 ? '' : 's'} ago`;
|
|
431
|
+
}
|
|
432
|
+
function formatResumeCandidate(c, index) {
|
|
433
|
+
const lines = [];
|
|
434
|
+
const matchLabel = c.whyMatched.map(w => WHY_MATCHED_LABELS[w] ?? w).join(', ');
|
|
435
|
+
const isWeak = c.whyMatched.every(w => w === 'recency_fallback');
|
|
436
|
+
const statusTag = c.isComplete ? ' (completed)' : '';
|
|
437
|
+
const heading = c.sessionTitle?.trim() || c.workflowId;
|
|
438
|
+
lines.push(`### Candidate ${index + 1}: \`${heading}\`${statusTag}${isWeak ? ' (weak match)' : ''}`);
|
|
439
|
+
lines.push(`- **Session**: \`${c.sessionId}\``);
|
|
440
|
+
lines.push(`- **Run**: \`${c.runId}\``);
|
|
441
|
+
lines.push(`- **Workflow**: \`${c.workflowId}\``);
|
|
442
|
+
lines.push(`- **Match reason**: ${matchLabel}`);
|
|
443
|
+
if (c.confidence) {
|
|
444
|
+
lines.push(`- **Confidence**: ${c.confidence}`);
|
|
445
|
+
}
|
|
446
|
+
if (c.matchExplanation) {
|
|
447
|
+
lines.push(`- **Why this ranked here**: ${c.matchExplanation}`);
|
|
448
|
+
}
|
|
449
|
+
if (c.gitBranch) {
|
|
450
|
+
lines.push(`- **Branch**: \`${c.gitBranch}\``);
|
|
451
|
+
}
|
|
452
|
+
if (c.pendingStepId) {
|
|
453
|
+
lines.push(`- **Current step**: \`${c.pendingStepId}\``);
|
|
454
|
+
}
|
|
455
|
+
else if (c.isComplete) {
|
|
456
|
+
lines.push('- **Status**: Workflow completed');
|
|
457
|
+
}
|
|
458
|
+
if (c.lastModifiedMs != null) {
|
|
459
|
+
lines.push(`- **Last active**: ${formatRelativeTime(c.lastModifiedMs)}`);
|
|
460
|
+
}
|
|
461
|
+
if (c.snippet) {
|
|
462
|
+
const preview = c.snippet.length > 200 ? c.snippet.slice(0, 200) + '...' : c.snippet;
|
|
463
|
+
lines.push(`- **Preview**: ${preview.replace(/\n/g, ' ')}`);
|
|
464
|
+
}
|
|
465
|
+
else {
|
|
466
|
+
lines.push('- **Preview**: (no recap notes available)');
|
|
467
|
+
}
|
|
468
|
+
if (c.isComplete) {
|
|
469
|
+
lines.push('');
|
|
470
|
+
lines.push('> This workflow has already completed. Resuming it will show the final state.');
|
|
471
|
+
}
|
|
472
|
+
lines.push('');
|
|
473
|
+
lines.push('To inspect or resume this candidate, call `continue_workflow` with:');
|
|
474
|
+
lines.push('```json');
|
|
475
|
+
lines.push(JSON.stringify(c.nextCall.params, null, 2));
|
|
476
|
+
lines.push('```');
|
|
477
|
+
lines.push('This `rehydrate` call restores the exact workflow state and shows the current step/context.');
|
|
478
|
+
return lines.join('\n');
|
|
479
|
+
}
|
|
480
|
+
const SEARCH_PARAMS_HELP = [
|
|
481
|
+
'**To narrow results, call `resume_session` again with any of these parameters:**',
|
|
482
|
+
'- `query`: Free text keywords from the session (e.g. "mr ownership", "ACEI-1234", "login feature")',
|
|
483
|
+
'- `runId`: Exact run ID if the user has one (e.g. "run_abc123def456")',
|
|
484
|
+
'- `sessionId`: Exact session ID if the user has one (e.g. "sess_abc123")',
|
|
485
|
+
'- `workspacePath`: Absolute path to the workspace (helps match by git branch/commit)',
|
|
486
|
+
'- `sameWorkspaceOnly`: Restrict results to the current repo/workspace when that is clearly what the user means',
|
|
487
|
+
].join('\n');
|
|
488
|
+
function formatV2ResumeResponse(data) {
|
|
489
|
+
if (!isResumeSessionResponse(data))
|
|
490
|
+
return null;
|
|
491
|
+
const { candidates, totalEligible } = data;
|
|
492
|
+
const lines = [];
|
|
493
|
+
if (candidates.length === 0) {
|
|
494
|
+
lines.push('## No Resumable Sessions Found');
|
|
495
|
+
lines.push('');
|
|
496
|
+
lines.push(`Searched ${totalEligible} session(s) but none matched your query or workspace context.`);
|
|
497
|
+
lines.push('');
|
|
498
|
+
lines.push('**What to do**: Ask the user for more details about which session they want to resume. They might know:');
|
|
499
|
+
lines.push('- A description of what they were working on (pass as `query`)');
|
|
500
|
+
lines.push('- A run ID or session ID (pass as `runId` or `sessionId`)');
|
|
501
|
+
lines.push('- Or start a fresh workflow with `start_workflow`.');
|
|
502
|
+
lines.push('');
|
|
503
|
+
lines.push(SEARCH_PARAMS_HELP);
|
|
504
|
+
return { primary: lines.join('\n') };
|
|
505
|
+
}
|
|
506
|
+
const hasStrongMatch = candidates.some(c => !c.whyMatched.every(w => w === 'recency_fallback'));
|
|
507
|
+
const allRecencyFallback = !hasStrongMatch;
|
|
508
|
+
if (allRecencyFallback) {
|
|
509
|
+
lines.push('## Recent Workflow Sessions');
|
|
510
|
+
lines.push('');
|
|
511
|
+
lines.push(`No specific search criteria matched, so here are the **${candidates.length} most recent** sessions (out of ${totalEligible} total).`);
|
|
512
|
+
lines.push('');
|
|
513
|
+
lines.push('**Action required**: Present these to the user and ask which one they want to resume. If none of these are right, ask the user to describe what they were working on so you can search more specifically.');
|
|
514
|
+
lines.push('');
|
|
515
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
516
|
+
lines.push(formatResumeCandidate(candidates[i], i));
|
|
517
|
+
lines.push('');
|
|
518
|
+
}
|
|
519
|
+
if (totalEligible > candidates.length) {
|
|
520
|
+
lines.push('---');
|
|
521
|
+
lines.push(`${totalEligible - candidates.length} more session(s) not shown.`);
|
|
522
|
+
lines.push('');
|
|
523
|
+
}
|
|
524
|
+
lines.push(SEARCH_PARAMS_HELP);
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
lines.push('## Resumable Workflow Sessions');
|
|
528
|
+
lines.push('');
|
|
529
|
+
lines.push(`Found **${totalEligible}** session(s) total. Showing the top ${candidates.length} ranked by match strength.`);
|
|
530
|
+
lines.push('');
|
|
531
|
+
const allWorkspaceDriven = candidates.every((c) => c.whyMatched.every((w) => w === 'matched_head_sha' || w === 'matched_branch'));
|
|
532
|
+
if (allWorkspaceDriven) {
|
|
533
|
+
lines.push('**Note**: These candidates are ranked primarily from current workspace git context (branch/commit), not from a strong text match on your query.');
|
|
534
|
+
lines.push('If the previews do not clearly match the user\'s request, inspect a candidate with `continue_workflow(..., intent: "rehydrate")` or ask for a more specific phrase / session ID.');
|
|
535
|
+
lines.push('');
|
|
536
|
+
}
|
|
537
|
+
const best = candidates[0];
|
|
538
|
+
const bestIsExact = best.whyMatched.includes('matched_exact_id');
|
|
539
|
+
if (bestIsExact) {
|
|
540
|
+
lines.push(`**Recommendation**: Candidate 1 is an exact ID match. Resume it directly.`);
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
lines.push(`**Recommendation**: Candidate 1 has the strongest match signal. Present the top candidates to the user and let them confirm which one to resume.`);
|
|
544
|
+
}
|
|
545
|
+
lines.push('');
|
|
546
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
547
|
+
lines.push(formatResumeCandidate(candidates[i], i));
|
|
548
|
+
lines.push('');
|
|
549
|
+
}
|
|
550
|
+
if (totalEligible > candidates.length) {
|
|
551
|
+
lines.push('---');
|
|
552
|
+
lines.push(`${totalEligible - candidates.length} more session(s) not shown.`);
|
|
553
|
+
lines.push('');
|
|
554
|
+
lines.push(SEARCH_PARAMS_HELP);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return { primary: lines.join('\n') };
|
|
558
|
+
}
|
|
@@ -46,8 +46,8 @@ function findAliasFieldConflicts(value, aliasMap) {
|
|
|
46
46
|
}
|
|
47
47
|
exports.START_WORKFLOW_PROTOCOL = {
|
|
48
48
|
canonicalParams: {
|
|
49
|
-
required: ['workflowId'],
|
|
50
|
-
optional: [
|
|
49
|
+
required: ['workflowId', 'workspacePath'],
|
|
50
|
+
optional: [],
|
|
51
51
|
},
|
|
52
52
|
descriptions: {
|
|
53
53
|
standard: {
|
|
@@ -56,6 +56,7 @@ exports.START_WORKFLOW_PROTOCOL = {
|
|
|
56
56
|
rules: [
|
|
57
57
|
'Follow the returned step exactly; treat it as the user\'s current instruction.',
|
|
58
58
|
'When the step is done, call continue_workflow with the returned continueToken.',
|
|
59
|
+
'Always pass workspacePath. Shared MCP servers cannot safely infer which repo/workspace you mean.',
|
|
59
60
|
'Only pass context on later continue_workflow calls if facts changed.',
|
|
60
61
|
],
|
|
61
62
|
examplePayload: {
|
|
@@ -70,7 +71,7 @@ exports.START_WORKFLOW_PROTOCOL = {
|
|
|
70
71
|
rules: [
|
|
71
72
|
'Execute the returned step exactly as written.',
|
|
72
73
|
'When the step is complete, call continue_workflow with the returned continueToken.',
|
|
73
|
-
'Pass workspacePath
|
|
74
|
+
'Pass workspacePath on every call. Shared MCP servers cannot safely infer the correct workspace.',
|
|
74
75
|
],
|
|
75
76
|
examplePayload: {
|
|
76
77
|
workflowId: 'coding-task-workflow-agentic',
|
|
@@ -83,7 +84,7 @@ exports.START_WORKFLOW_PROTOCOL = {
|
|
|
83
84
|
exports.CONTINUE_WORKFLOW_PROTOCOL = {
|
|
84
85
|
canonicalParams: {
|
|
85
86
|
required: ['continueToken'],
|
|
86
|
-
optional: ['intent', 'context', 'output'],
|
|
87
|
+
optional: ['intent', 'context', 'output', 'workspacePath'],
|
|
87
88
|
},
|
|
88
89
|
aliasMap: {
|
|
89
90
|
contextVariables: 'context',
|
|
@@ -95,6 +96,7 @@ exports.CONTINUE_WORKFLOW_PROTOCOL = {
|
|
|
95
96
|
rules: [
|
|
96
97
|
'Advance by sending output (and intent: "advance" if you want to be explicit).',
|
|
97
98
|
'Rehydrate by omitting output (and intent: "rehydrate" if you want to be explicit).',
|
|
99
|
+
'When rehydrating, always pass workspacePath so WorkRail can restore the correct repo/workspace context on shared servers.',
|
|
98
100
|
'Put changed facts under context only.',
|
|
99
101
|
'Round-trip continueToken exactly as returned by WorkRail; use the single-token API only.',
|
|
100
102
|
'Notes (output.notesMarkdown): write for a human reader. Include what you did and key decisions, what you produced (files, tests, numbers), and anything notable (risks, open questions, deliberate omissions). Use markdown headings, bullets, bold, code refs. Be specific. Scope: THIS step only (WorkRail concatenates automatically). 10-30 lines ideal. Omitting notes blocks the step.',
|
|
@@ -114,6 +116,7 @@ exports.CONTINUE_WORKFLOW_PROTOCOL = {
|
|
|
114
116
|
'Use continueToken exactly as returned by WorkRail.',
|
|
115
117
|
'Use the single-token API only.',
|
|
116
118
|
'Advance by sending output; rehydrate by omitting output.',
|
|
119
|
+
'For rehydrate calls, pass workspacePath so WorkRail can restore the correct workspace context.',
|
|
117
120
|
'Put updated facts in context only.',
|
|
118
121
|
'Notes (output.notesMarkdown): write for a human reader. Include what you did and key decisions, what you produced (files, tests, numbers), and anything notable (risks, open questions, deliberate omissions). Use markdown headings, bullets, bold, code refs. Be specific. Scope: THIS step only (WorkRail concatenates automatically). 10-30 lines ideal. Omitting notes blocks the step.',
|
|
119
122
|
],
|
|
@@ -164,43 +167,43 @@ exports.CHECKPOINT_WORKFLOW_PROTOCOL = {
|
|
|
164
167
|
};
|
|
165
168
|
exports.RESUME_SESSION_PROTOCOL = {
|
|
166
169
|
canonicalParams: {
|
|
167
|
-
required: [],
|
|
168
|
-
optional: ['query', '
|
|
170
|
+
required: ['workspacePath'],
|
|
171
|
+
optional: ['query', 'runId', 'sessionId', 'gitBranch', 'gitHeadSha'],
|
|
169
172
|
},
|
|
170
173
|
descriptions: {
|
|
171
174
|
standard: {
|
|
172
|
-
purpose: 'Find and reconnect to an existing WorkRail
|
|
173
|
-
whenToUse: 'Use this when
|
|
175
|
+
purpose: 'Find and reconnect to an existing WorkRail workflow session. WorkRail is a workflow engine that persists session state across chat conversations. When a user says "resume my workflow", this is the tool to call.',
|
|
176
|
+
whenToUse: 'Use this when the user wants to resume, continue, or reconnect to a previously started workflow. The user may provide a session ID, run ID, a description of what they were working on, or nothing at all. This tool searches stored sessions and returns the best matches.',
|
|
174
177
|
rules: [
|
|
175
|
-
'
|
|
176
|
-
'
|
|
177
|
-
'
|
|
178
|
-
'
|
|
179
|
-
'
|
|
180
|
-
'If
|
|
178
|
+
'If the user provides a run ID (run_...) or session ID (sess_...), pass it as runId or sessionId for an exact match. This is the most reliable way to find a specific session.',
|
|
179
|
+
'If the user describes what they were working on (e.g. "the mr ownership task"), pass their words as query. This searches session recap notes and workflow IDs for matching keywords.',
|
|
180
|
+
'Always pass workspacePath (from your system parameters). Shared MCP servers cannot safely infer the current workspace, and resume quality depends on the current repo identity.',
|
|
181
|
+
'The response includes ranked candidates with match explanations and ready-to-use continuation templates. Present the top candidates to the user if there is ambiguity.',
|
|
182
|
+
'To inspect or resume a candidate: call continue_workflow with the candidate\'s nextCall.params (continueToken and intent: "rehydrate"). This is the correct inspection path for v2 sessions and restores the full session context.',
|
|
183
|
+
'If no candidates match, ask the user for more details or suggest starting a fresh workflow with start_workflow.',
|
|
181
184
|
],
|
|
182
185
|
examplePayload: {
|
|
183
186
|
workspacePath: '/Users/you/git/my-project',
|
|
184
187
|
query: 'resume the coding task workflow for protocol drift',
|
|
185
188
|
},
|
|
186
|
-
returns: 'Up to 5 ranked candidates,
|
|
189
|
+
returns: 'Up to 5 ranked candidates with match signals, session previews, and ready-to-use continuation templates. The response explains which candidate to pick and exactly how to resume it.',
|
|
187
190
|
},
|
|
188
191
|
authoritative: {
|
|
189
|
-
purpose: 'Find an existing WorkRail
|
|
190
|
-
whenToUse: 'Call this when resuming a workflow
|
|
192
|
+
purpose: 'Find an existing WorkRail workflow session and reconnect to it. WorkRail persists workflow state across chat conversations. When a user says "resume my workflow", call this tool.',
|
|
193
|
+
whenToUse: 'Call this when resuming a workflow. The user may provide a run ID, session ID, a description, or nothing.',
|
|
191
194
|
rules: [
|
|
192
|
-
'
|
|
193
|
-
'
|
|
194
|
-
'
|
|
195
|
-
'
|
|
196
|
-
'
|
|
197
|
-
'
|
|
195
|
+
'If the user provides a run ID (run_...) or session ID (sess_...), pass it as runId or sessionId for exact lookup.',
|
|
196
|
+
'If the user describes their task, pass their words as query to search session notes.',
|
|
197
|
+
'Always pass workspacePath from your system parameters. Shared MCP servers cannot safely infer the current workspace.',
|
|
198
|
+
'Present candidates to the user when there is ambiguity. The response explains match strength.',
|
|
199
|
+
'To inspect or resume: call continue_workflow with the chosen candidate\'s nextCall.params (continueToken + intent: "rehydrate"). Do NOT use legacy session tools to inspect a v2 workflow resume candidate.',
|
|
200
|
+
'If no candidates match, ask for more details or start a fresh workflow.',
|
|
198
201
|
],
|
|
199
202
|
examplePayload: {
|
|
200
203
|
workspacePath: '/Users/you/git/my-project',
|
|
201
204
|
query: 'resume the coding task workflow for protocol drift',
|
|
202
205
|
},
|
|
203
|
-
returns: 'Up to 5 ranked candidates
|
|
206
|
+
returns: 'Up to 5 ranked candidates with match signals, previews, and ready-to-use continuation templates.',
|
|
204
207
|
},
|
|
205
208
|
},
|
|
206
209
|
};
|
|
@@ -2183,8 +2183,8 @@ export declare const SessionContentsV1Schema: z.ZodObject<{
|
|
|
2183
2183
|
bytes: z.ZodNumber;
|
|
2184
2184
|
}, "strip", z.ZodTypeAny, {
|
|
2185
2185
|
kind: "segment_closed";
|
|
2186
|
-
sha256: string;
|
|
2187
2186
|
sessionId: string;
|
|
2187
|
+
sha256: string;
|
|
2188
2188
|
v: 1;
|
|
2189
2189
|
manifestIndex: number;
|
|
2190
2190
|
firstEventIndex: number;
|
|
@@ -2193,8 +2193,8 @@ export declare const SessionContentsV1Schema: z.ZodObject<{
|
|
|
2193
2193
|
bytes: number;
|
|
2194
2194
|
}, {
|
|
2195
2195
|
kind: "segment_closed";
|
|
2196
|
-
sha256: string;
|
|
2197
2196
|
sessionId: string;
|
|
2197
|
+
sha256: string;
|
|
2198
2198
|
v: 1;
|
|
2199
2199
|
manifestIndex: number;
|
|
2200
2200
|
firstEventIndex: number;
|
|
@@ -4601,8 +4601,8 @@ export declare const SessionContentsV1Schema: z.ZodObject<{
|
|
|
4601
4601
|
})[];
|
|
4602
4602
|
manifest: ({
|
|
4603
4603
|
kind: "segment_closed";
|
|
4604
|
-
sha256: string;
|
|
4605
4604
|
sessionId: string;
|
|
4605
|
+
sha256: string;
|
|
4606
4606
|
v: 1;
|
|
4607
4607
|
manifestIndex: number;
|
|
4608
4608
|
firstEventIndex: number;
|
|
@@ -5113,8 +5113,8 @@ export declare const SessionContentsV1Schema: z.ZodObject<{
|
|
|
5113
5113
|
})[];
|
|
5114
5114
|
manifest: ({
|
|
5115
5115
|
kind: "segment_closed";
|
|
5116
|
-
sha256: string;
|
|
5117
5116
|
sessionId: string;
|
|
5117
|
+
sha256: string;
|
|
5118
5118
|
v: 1;
|
|
5119
5119
|
manifestIndex: number;
|
|
5120
5120
|
firstEventIndex: number;
|
|
@@ -7305,8 +7305,8 @@ export declare const ExportBundleV1Schema: z.ZodObject<{
|
|
|
7305
7305
|
bytes: z.ZodNumber;
|
|
7306
7306
|
}, "strip", z.ZodTypeAny, {
|
|
7307
7307
|
kind: "segment_closed";
|
|
7308
|
-
sha256: string;
|
|
7309
7308
|
sessionId: string;
|
|
7309
|
+
sha256: string;
|
|
7310
7310
|
v: 1;
|
|
7311
7311
|
manifestIndex: number;
|
|
7312
7312
|
firstEventIndex: number;
|
|
@@ -7315,8 +7315,8 @@ export declare const ExportBundleV1Schema: z.ZodObject<{
|
|
|
7315
7315
|
bytes: number;
|
|
7316
7316
|
}, {
|
|
7317
7317
|
kind: "segment_closed";
|
|
7318
|
-
sha256: string;
|
|
7319
7318
|
sessionId: string;
|
|
7319
|
+
sha256: string;
|
|
7320
7320
|
v: 1;
|
|
7321
7321
|
manifestIndex: number;
|
|
7322
7322
|
firstEventIndex: number;
|
|
@@ -9723,8 +9723,8 @@ export declare const ExportBundleV1Schema: z.ZodObject<{
|
|
|
9723
9723
|
})[];
|
|
9724
9724
|
manifest: ({
|
|
9725
9725
|
kind: "segment_closed";
|
|
9726
|
-
sha256: string;
|
|
9727
9726
|
sessionId: string;
|
|
9727
|
+
sha256: string;
|
|
9728
9728
|
v: 1;
|
|
9729
9729
|
manifestIndex: number;
|
|
9730
9730
|
firstEventIndex: number;
|
|
@@ -10235,8 +10235,8 @@ export declare const ExportBundleV1Schema: z.ZodObject<{
|
|
|
10235
10235
|
})[];
|
|
10236
10236
|
manifest: ({
|
|
10237
10237
|
kind: "segment_closed";
|
|
10238
|
-
sha256: string;
|
|
10239
10238
|
sessionId: string;
|
|
10239
|
+
sha256: string;
|
|
10240
10240
|
v: 1;
|
|
10241
10241
|
manifestIndex: number;
|
|
10242
10242
|
firstEventIndex: number;
|
|
@@ -10776,8 +10776,8 @@ export declare const ExportBundleV1Schema: z.ZodObject<{
|
|
|
10776
10776
|
})[];
|
|
10777
10777
|
manifest: ({
|
|
10778
10778
|
kind: "segment_closed";
|
|
10779
|
-
sha256: string;
|
|
10780
10779
|
sessionId: string;
|
|
10780
|
+
sha256: string;
|
|
10781
10781
|
v: 1;
|
|
10782
10782
|
manifestIndex: number;
|
|
10783
10783
|
firstEventIndex: number;
|
|
@@ -11305,8 +11305,8 @@ export declare const ExportBundleV1Schema: z.ZodObject<{
|
|
|
11305
11305
|
})[];
|
|
11306
11306
|
manifest: ({
|
|
11307
11307
|
kind: "segment_closed";
|
|
11308
|
-
sha256: string;
|
|
11309
11308
|
sessionId: string;
|
|
11309
|
+
sha256: string;
|
|
11310
11310
|
v: 1;
|
|
11311
11311
|
manifestIndex: number;
|
|
11312
11312
|
firstEventIndex: number;
|
|
@@ -11,8 +11,8 @@ export declare const ManifestRecordV1Schema: z.ZodDiscriminatedUnion<"kind", [z.
|
|
|
11
11
|
bytes: z.ZodNumber;
|
|
12
12
|
}, "strip", z.ZodTypeAny, {
|
|
13
13
|
kind: "segment_closed";
|
|
14
|
-
sha256: string;
|
|
15
14
|
sessionId: string;
|
|
15
|
+
sha256: string;
|
|
16
16
|
v: 1;
|
|
17
17
|
manifestIndex: number;
|
|
18
18
|
firstEventIndex: number;
|
|
@@ -21,8 +21,8 @@ export declare const ManifestRecordV1Schema: z.ZodDiscriminatedUnion<"kind", [z.
|
|
|
21
21
|
bytes: number;
|
|
22
22
|
}, {
|
|
23
23
|
kind: "segment_closed";
|
|
24
|
-
sha256: string;
|
|
25
24
|
sessionId: string;
|
|
25
|
+
sha256: string;
|
|
26
26
|
v: 1;
|
|
27
27
|
manifestIndex: number;
|
|
28
28
|
firstEventIndex: number;
|
|
@@ -14,13 +14,13 @@ export declare const StateTokenPayloadV1Schema: z.ZodObject<{
|
|
|
14
14
|
nodeId: z.ZodEffects<z.ZodString, NodeId, string>;
|
|
15
15
|
workflowHashRef: z.ZodEffects<z.ZodString, WorkflowHashRef, string>;
|
|
16
16
|
}, "strip", z.ZodTypeAny, {
|
|
17
|
+
runId: string & {
|
|
18
|
+
readonly __brand: "v2.RunId";
|
|
19
|
+
};
|
|
17
20
|
sessionId: string & {
|
|
18
21
|
readonly __brand: "v2.SessionId";
|
|
19
22
|
};
|
|
20
23
|
tokenKind: "state";
|
|
21
|
-
runId: string & {
|
|
22
|
-
readonly __brand: "v2.RunId";
|
|
23
|
-
};
|
|
24
24
|
nodeId: string & {
|
|
25
25
|
readonly __brand: "v2.NodeId";
|
|
26
26
|
};
|
|
@@ -29,9 +29,9 @@ export declare const StateTokenPayloadV1Schema: z.ZodObject<{
|
|
|
29
29
|
};
|
|
30
30
|
tokenVersion: 1;
|
|
31
31
|
}, {
|
|
32
|
+
runId: string;
|
|
32
33
|
sessionId: string;
|
|
33
34
|
tokenKind: "state";
|
|
34
|
-
runId: string;
|
|
35
35
|
nodeId: string;
|
|
36
36
|
workflowHashRef: string;
|
|
37
37
|
tokenVersion: 1;
|
|
@@ -52,13 +52,13 @@ export declare const AckTokenPayloadV1Schema: z.ZodObject<{
|
|
|
52
52
|
nodeId: z.ZodEffects<z.ZodString, NodeId, string>;
|
|
53
53
|
attemptId: z.ZodEffects<z.ZodString, AttemptId, string>;
|
|
54
54
|
}, "strip", z.ZodTypeAny, {
|
|
55
|
+
runId: string & {
|
|
56
|
+
readonly __brand: "v2.RunId";
|
|
57
|
+
};
|
|
55
58
|
sessionId: string & {
|
|
56
59
|
readonly __brand: "v2.SessionId";
|
|
57
60
|
};
|
|
58
61
|
tokenKind: "ack";
|
|
59
|
-
runId: string & {
|
|
60
|
-
readonly __brand: "v2.RunId";
|
|
61
|
-
};
|
|
62
62
|
nodeId: string & {
|
|
63
63
|
readonly __brand: "v2.NodeId";
|
|
64
64
|
};
|
|
@@ -67,9 +67,9 @@ export declare const AckTokenPayloadV1Schema: z.ZodObject<{
|
|
|
67
67
|
};
|
|
68
68
|
tokenVersion: 1;
|
|
69
69
|
}, {
|
|
70
|
+
runId: string;
|
|
70
71
|
sessionId: string;
|
|
71
72
|
tokenKind: "ack";
|
|
72
|
-
runId: string;
|
|
73
73
|
nodeId: string;
|
|
74
74
|
attemptId: string;
|
|
75
75
|
tokenVersion: 1;
|
|
@@ -90,13 +90,13 @@ export declare const CheckpointTokenPayloadV1Schema: z.ZodObject<{
|
|
|
90
90
|
nodeId: z.ZodEffects<z.ZodString, NodeId, string>;
|
|
91
91
|
attemptId: z.ZodEffects<z.ZodString, AttemptId, string>;
|
|
92
92
|
}, "strip", z.ZodTypeAny, {
|
|
93
|
+
runId: string & {
|
|
94
|
+
readonly __brand: "v2.RunId";
|
|
95
|
+
};
|
|
93
96
|
sessionId: string & {
|
|
94
97
|
readonly __brand: "v2.SessionId";
|
|
95
98
|
};
|
|
96
99
|
tokenKind: "checkpoint";
|
|
97
|
-
runId: string & {
|
|
98
|
-
readonly __brand: "v2.RunId";
|
|
99
|
-
};
|
|
100
100
|
nodeId: string & {
|
|
101
101
|
readonly __brand: "v2.NodeId";
|
|
102
102
|
};
|
|
@@ -105,9 +105,9 @@ export declare const CheckpointTokenPayloadV1Schema: z.ZodObject<{
|
|
|
105
105
|
};
|
|
106
106
|
tokenVersion: 1;
|
|
107
107
|
}, {
|
|
108
|
+
runId: string;
|
|
108
109
|
sessionId: string;
|
|
109
110
|
tokenKind: "checkpoint";
|
|
110
|
-
runId: string;
|
|
111
111
|
nodeId: string;
|
|
112
112
|
attemptId: string;
|
|
113
113
|
tokenVersion: 1;
|
|
@@ -128,13 +128,13 @@ export declare const TokenPayloadV1Schema: z.ZodDiscriminatedUnion<"tokenKind",
|
|
|
128
128
|
nodeId: z.ZodEffects<z.ZodString, NodeId, string>;
|
|
129
129
|
workflowHashRef: z.ZodEffects<z.ZodString, WorkflowHashRef, string>;
|
|
130
130
|
}, "strip", z.ZodTypeAny, {
|
|
131
|
+
runId: string & {
|
|
132
|
+
readonly __brand: "v2.RunId";
|
|
133
|
+
};
|
|
131
134
|
sessionId: string & {
|
|
132
135
|
readonly __brand: "v2.SessionId";
|
|
133
136
|
};
|
|
134
137
|
tokenKind: "state";
|
|
135
|
-
runId: string & {
|
|
136
|
-
readonly __brand: "v2.RunId";
|
|
137
|
-
};
|
|
138
138
|
nodeId: string & {
|
|
139
139
|
readonly __brand: "v2.NodeId";
|
|
140
140
|
};
|
|
@@ -143,9 +143,9 @@ export declare const TokenPayloadV1Schema: z.ZodDiscriminatedUnion<"tokenKind",
|
|
|
143
143
|
};
|
|
144
144
|
tokenVersion: 1;
|
|
145
145
|
}, {
|
|
146
|
+
runId: string;
|
|
146
147
|
sessionId: string;
|
|
147
148
|
tokenKind: "state";
|
|
148
|
-
runId: string;
|
|
149
149
|
nodeId: string;
|
|
150
150
|
workflowHashRef: string;
|
|
151
151
|
tokenVersion: 1;
|
|
@@ -157,13 +157,13 @@ export declare const TokenPayloadV1Schema: z.ZodDiscriminatedUnion<"tokenKind",
|
|
|
157
157
|
nodeId: z.ZodEffects<z.ZodString, NodeId, string>;
|
|
158
158
|
attemptId: z.ZodEffects<z.ZodString, AttemptId, string>;
|
|
159
159
|
}, "strip", z.ZodTypeAny, {
|
|
160
|
+
runId: string & {
|
|
161
|
+
readonly __brand: "v2.RunId";
|
|
162
|
+
};
|
|
160
163
|
sessionId: string & {
|
|
161
164
|
readonly __brand: "v2.SessionId";
|
|
162
165
|
};
|
|
163
166
|
tokenKind: "ack";
|
|
164
|
-
runId: string & {
|
|
165
|
-
readonly __brand: "v2.RunId";
|
|
166
|
-
};
|
|
167
167
|
nodeId: string & {
|
|
168
168
|
readonly __brand: "v2.NodeId";
|
|
169
169
|
};
|
|
@@ -172,9 +172,9 @@ export declare const TokenPayloadV1Schema: z.ZodDiscriminatedUnion<"tokenKind",
|
|
|
172
172
|
};
|
|
173
173
|
tokenVersion: 1;
|
|
174
174
|
}, {
|
|
175
|
+
runId: string;
|
|
175
176
|
sessionId: string;
|
|
176
177
|
tokenKind: "ack";
|
|
177
|
-
runId: string;
|
|
178
178
|
nodeId: string;
|
|
179
179
|
attemptId: string;
|
|
180
180
|
tokenVersion: 1;
|
|
@@ -186,13 +186,13 @@ export declare const TokenPayloadV1Schema: z.ZodDiscriminatedUnion<"tokenKind",
|
|
|
186
186
|
nodeId: z.ZodEffects<z.ZodString, NodeId, string>;
|
|
187
187
|
attemptId: z.ZodEffects<z.ZodString, AttemptId, string>;
|
|
188
188
|
}, "strip", z.ZodTypeAny, {
|
|
189
|
+
runId: string & {
|
|
190
|
+
readonly __brand: "v2.RunId";
|
|
191
|
+
};
|
|
189
192
|
sessionId: string & {
|
|
190
193
|
readonly __brand: "v2.SessionId";
|
|
191
194
|
};
|
|
192
195
|
tokenKind: "checkpoint";
|
|
193
|
-
runId: string & {
|
|
194
|
-
readonly __brand: "v2.RunId";
|
|
195
|
-
};
|
|
196
196
|
nodeId: string & {
|
|
197
197
|
readonly __brand: "v2.NodeId";
|
|
198
198
|
};
|
|
@@ -201,9 +201,9 @@ export declare const TokenPayloadV1Schema: z.ZodDiscriminatedUnion<"tokenKind",
|
|
|
201
201
|
};
|
|
202
202
|
tokenVersion: 1;
|
|
203
203
|
}, {
|
|
204
|
+
runId: string;
|
|
204
205
|
sessionId: string;
|
|
205
206
|
tokenKind: "checkpoint";
|
|
206
|
-
runId: string;
|
|
207
207
|
nodeId: string;
|
|
208
208
|
attemptId: string;
|
|
209
209
|
tokenVersion: 1;
|
|
@@ -2,12 +2,14 @@ import type { ResultAsync } from 'neverthrow';
|
|
|
2
2
|
import type { DirectoryListingPortV2 } from '../../../ports/directory-listing.port.js';
|
|
3
3
|
import type { DataDirPortV2 } from '../../../ports/data-dir.port.js';
|
|
4
4
|
import type { SessionEventLogReadonlyStorePortV2 } from '../../../ports/session-event-log-store.port.js';
|
|
5
|
+
import type { SnapshotStorePortV2 } from '../../../ports/snapshot-store.port.js';
|
|
5
6
|
import type { SessionSummaryProviderPortV2, SessionSummaryError } from '../../../ports/session-summary-provider.port.js';
|
|
6
7
|
import type { HealthySessionSummary } from '../../../projections/resume-ranking.js';
|
|
7
8
|
export interface LocalSessionSummaryProviderPorts {
|
|
8
9
|
readonly directoryListing: DirectoryListingPortV2;
|
|
9
10
|
readonly dataDir: DataDirPortV2;
|
|
10
11
|
readonly sessionStore: SessionEventLogReadonlyStorePortV2;
|
|
12
|
+
readonly snapshotStore?: SnapshotStorePortV2;
|
|
11
13
|
}
|
|
12
14
|
export declare class LocalSessionSummaryProviderV2 implements SessionSummaryProviderPortV2 {
|
|
13
15
|
private readonly ports;
|