@exaudeus/workrail 3.3.0 → 3.5.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/application/services/compiler/binding-registry.d.ts +3 -0
- package/dist/application/services/compiler/binding-registry.js +71 -0
- package/dist/application/services/compiler/resolve-bindings.d.ts +18 -0
- package/dist/application/services/compiler/resolve-bindings.js +162 -0
- package/dist/application/services/compiler/sentinel-scan.d.ts +9 -0
- package/dist/application/services/compiler/sentinel-scan.js +37 -0
- package/dist/application/services/validation-engine.js +104 -0
- package/dist/application/services/workflow-compiler.d.ts +10 -2
- package/dist/application/services/workflow-compiler.js +25 -6
- package/dist/application/services/workflow-validation-pipeline.js +8 -1
- package/dist/cli.js +2 -2
- package/dist/engine/engine-factory.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -2
- package/dist/manifest.json +149 -101
- package/dist/mcp/handler-factory.d.ts +1 -1
- package/dist/mcp/handler-factory.js +2 -2
- package/dist/mcp/handlers/v2-checkpoint.js +5 -5
- package/dist/mcp/handlers/v2-error-mapping.js +4 -4
- package/dist/mcp/handlers/v2-execution/continue-advance.js +2 -2
- package/dist/mcp/handlers/v2-execution/continue-rehydrate.d.ts +1 -0
- package/dist/mcp/handlers/v2-execution/continue-rehydrate.js +76 -60
- package/dist/mcp/handlers/v2-execution/index.js +86 -44
- package/dist/mcp/handlers/v2-execution-helpers.js +1 -1
- package/dist/mcp/handlers/v2-resume.js +10 -5
- package/dist/mcp/handlers/v2-token-ops.d.ts +1 -1
- package/dist/mcp/handlers/v2-token-ops.js +5 -5
- package/dist/mcp/handlers/v2-workspace-resolution.d.ts +1 -0
- package/dist/mcp/handlers/v2-workspace-resolution.js +12 -0
- package/dist/mcp/index.d.ts +4 -1
- package/dist/mcp/index.js +6 -2
- package/dist/mcp/output-schemas.d.ts +148 -8
- package/dist/mcp/output-schemas.js +22 -4
- package/dist/mcp/server.d.ts +6 -4
- package/dist/mcp/server.js +2 -57
- package/dist/mcp/tool-descriptions.js +9 -158
- package/dist/mcp/transports/http-entry.js +6 -25
- package/dist/mcp/transports/shutdown-hooks.d.ts +5 -0
- package/dist/mcp/transports/shutdown-hooks.js +38 -0
- package/dist/mcp/transports/stdio-entry.js +6 -28
- package/dist/mcp/v2/tool-registry.js +2 -1
- package/dist/mcp/v2/tools.d.ts +28 -11
- package/dist/mcp/v2/tools.js +28 -4
- package/dist/mcp/v2-response-formatter.js +28 -1
- package/dist/mcp/validation/suggestion-generator.d.ts +1 -1
- package/dist/mcp/validation/suggestion-generator.js +13 -3
- package/dist/mcp/workflow-protocol-contracts.d.ts +31 -0
- package/dist/mcp/workflow-protocol-contracts.js +207 -0
- package/dist/mcp-server.d.ts +3 -1
- package/dist/mcp-server.js +6 -2
- package/dist/types/workflow-definition.d.ts +7 -0
- package/dist/types/workflow-definition.js +1 -0
- package/dist/v2/durable-core/domain/binding-drift.d.ts +8 -0
- package/dist/v2/durable-core/domain/binding-drift.js +29 -0
- package/dist/v2/durable-core/domain/reason-model.js +2 -2
- package/dist/v2/durable-core/schemas/compiled-workflow/index.d.ts +12 -0
- package/dist/v2/durable-core/schemas/compiled-workflow/index.js +2 -0
- package/dist/v2/durable-core/schemas/export-bundle/index.d.ts +56 -56
- package/dist/v2/durable-core/schemas/session/events.d.ts +16 -16
- package/dist/v2/durable-core/schemas/session/gaps.d.ts +6 -6
- package/dist/v2/projections/resume-ranking.d.ts +1 -0
- package/dist/v2/projections/resume-ranking.js +1 -0
- package/dist/v2/read-only/v1-to-v2-shim.js +27 -10
- package/dist/v2/usecases/resume-session.d.ts +5 -1
- package/dist/v2/usecases/resume-session.js +4 -1
- package/package.json +1 -1
- package/spec/authoring-spec.json +1373 -0
- package/spec/workflow.schema.json +132 -2
- package/workflows/coding-task-workflow-agentic.json +15 -15
- package/workflows/coding-task-workflow-agentic.lean.v2.json +10 -10
- package/workflows/coding-task-workflow-agentic.v2.json +12 -12
- package/workflows/coding-task-workflow-with-loops.json +2 -2
- package/workflows/cross-platform-code-conversion.v2.json +199 -0
- package/workflows/document-creation-workflow.json +1 -1
- package/workflows/exploration-workflow.json +3 -3
- package/workflows/mr-review-workflow.agentic.v2.json +11 -11
- package/workflows/routines/parallel-work-partitioning.json +43 -0
- package/workflows/workflow-for-workflows.v2.json +186 -0
|
@@ -21,4 +21,5 @@ export declare function handleRehydrateIntent(args: {
|
|
|
21
21
|
};
|
|
22
22
|
readonly aliasStore: import('../../../v2/ports/token-alias-store.port.js').TokenAliasStorePortV2;
|
|
23
23
|
readonly entropy: import('../../../v2/ports/random-entropy.port.js').RandomEntropyPortV2;
|
|
24
|
+
readonly resolvedRootUris?: readonly string[];
|
|
24
25
|
}): RA<z.infer<typeof V2ContinueWorkflowOutputSchema>, ContinueWorkflowError>;
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.handleRehydrateIntent = handleRehydrateIntent;
|
|
4
4
|
const output_schemas_js_1 = require("../../output-schemas.js");
|
|
5
|
+
const binding_drift_js_1 = require("../../../v2/durable-core/domain/binding-drift.js");
|
|
6
|
+
const binding_registry_js_1 = require("../../../application/services/compiler/binding-registry.js");
|
|
7
|
+
const v2_workspace_resolution_js_1 = require("../v2-workspace-resolution.js");
|
|
5
8
|
const snapshot_state_js_1 = require("../../../v2/durable-core/projections/snapshot-state.js");
|
|
6
9
|
const workflow_js_1 = require("../../../types/workflow.js");
|
|
7
10
|
const index_js_1 = require("../../../v2/durable-core/ids/index.js");
|
|
@@ -16,14 +19,14 @@ const v2_state_conversion_js_1 = require("../v2-state-conversion.js");
|
|
|
16
19
|
const constants_js_1 = require("../../../v2/durable-core/constants.js");
|
|
17
20
|
const index_js_2 = require("./index.js");
|
|
18
21
|
function handleRehydrateIntent(args) {
|
|
19
|
-
const { input, sessionId, runId, nodeId, workflowHashRef, truth, tokenCodecPorts, pinnedStore, snapshotStore, idFactory, aliasStore, entropy } = args;
|
|
22
|
+
const { input, sessionId, runId, nodeId, workflowHashRef, truth, tokenCodecPorts, pinnedStore, snapshotStore, idFactory, aliasStore, entropy, resolvedRootUris } = args;
|
|
20
23
|
const runStarted = truth.events.find((e) => e.kind === constants_js_1.EVENT_KIND.RUN_STARTED && e.scope.runId === String(runId));
|
|
21
24
|
const workflowId = runStarted?.data.workflowId;
|
|
22
25
|
if (!runStarted || typeof workflowId !== 'string' || workflowId.trim() === '') {
|
|
23
26
|
return (0, neverthrow_1.errAsync)({
|
|
24
27
|
kind: 'token_unknown_node',
|
|
25
|
-
message: 'No durable run state was found for this
|
|
26
|
-
suggestion: 'Use start_workflow to mint a new run, or use a
|
|
28
|
+
message: 'No durable run state was found for this continueToken (missing run_started).',
|
|
29
|
+
suggestion: 'Use start_workflow to mint a new run, or use a continueToken returned by WorkRail for an existing run.',
|
|
27
30
|
});
|
|
28
31
|
}
|
|
29
32
|
const workflowHash = runStarted.data.workflowHash;
|
|
@@ -36,14 +39,14 @@ function handleRehydrateIntent(args) {
|
|
|
36
39
|
});
|
|
37
40
|
}
|
|
38
41
|
if (String(expectedRefRes.value) !== String(workflowHashRef)) {
|
|
39
|
-
return (0, neverthrow_1.errAsync)({ kind: 'precondition_failed', message: 'workflowHash mismatch for this run.', suggestion: 'Use the
|
|
42
|
+
return (0, neverthrow_1.errAsync)({ kind: 'precondition_failed', message: 'workflowHash mismatch for this run.', suggestion: 'Use the continueToken returned by WorkRail for this run.' });
|
|
40
43
|
}
|
|
41
44
|
const nodeCreated = truth.events.find((e) => e.kind === constants_js_1.EVENT_KIND.NODE_CREATED && e.scope.nodeId === String(nodeId) && e.scope.runId === String(runId));
|
|
42
45
|
if (!nodeCreated) {
|
|
43
46
|
return (0, neverthrow_1.errAsync)({
|
|
44
47
|
kind: 'token_unknown_node',
|
|
45
|
-
message: 'No durable node state was found for this
|
|
46
|
-
suggestion: 'Use a
|
|
48
|
+
message: 'No durable node state was found for this continueToken (missing node_created).',
|
|
49
|
+
suggestion: 'Use a continueToken returned by WorkRail for an existing node.',
|
|
47
50
|
});
|
|
48
51
|
}
|
|
49
52
|
const expectedNodeRefRes = (0, workflow_hash_ref_js_1.deriveWorkflowHashRef)(nodeCreated.data.workflowHash);
|
|
@@ -55,7 +58,7 @@ function handleRehydrateIntent(args) {
|
|
|
55
58
|
});
|
|
56
59
|
}
|
|
57
60
|
if (String(expectedNodeRefRes.value) !== String(workflowHashRef)) {
|
|
58
|
-
return (0, neverthrow_1.errAsync)({ kind: 'precondition_failed', message: 'workflowHash mismatch for this node.', suggestion: 'Use the
|
|
61
|
+
return (0, neverthrow_1.errAsync)({ kind: 'precondition_failed', message: 'workflowHash mismatch for this node.', suggestion: 'Use the continueToken returned by WorkRail for this node.' });
|
|
59
62
|
}
|
|
60
63
|
return snapshotStore.getExecutionSnapshotV1(nodeCreated.data.snapshotRef)
|
|
61
64
|
.mapErr((cause) => ({ kind: 'snapshot_load_failed', cause }))
|
|
@@ -64,35 +67,13 @@ function handleRehydrateIntent(args) {
|
|
|
64
67
|
return (0, neverthrow_1.errAsync)({
|
|
65
68
|
kind: 'token_unknown_node',
|
|
66
69
|
message: 'No execution snapshot was found for this node.',
|
|
67
|
-
suggestion: 'Use a
|
|
70
|
+
suggestion: 'Use a continueToken returned by WorkRail for an existing node.',
|
|
68
71
|
});
|
|
69
72
|
}
|
|
70
73
|
const engineState = snapshot.enginePayload.engineState;
|
|
71
74
|
const pending = (0, snapshot_state_js_1.derivePendingStep)(engineState);
|
|
72
75
|
const isComplete = (0, snapshot_state_js_1.deriveIsComplete)(engineState);
|
|
73
|
-
|
|
74
|
-
const preferences = (0, v2_execution_helpers_js_1.derivePreferencesOrDefault)({ truth, runId, nodeId });
|
|
75
|
-
const nextIntent = (0, v2_state_conversion_js_1.deriveNextIntent)({ rehydrateOnly: true, isComplete, pending: null });
|
|
76
|
-
return (0, neverthrow_1.okAsync)(output_schemas_js_1.V2ContinueWorkflowOutputSchema.parse({
|
|
77
|
-
kind: 'ok',
|
|
78
|
-
isComplete,
|
|
79
|
-
pending: null,
|
|
80
|
-
preferences,
|
|
81
|
-
nextIntent,
|
|
82
|
-
nextCall: null,
|
|
83
|
-
}));
|
|
84
|
-
}
|
|
85
|
-
const attemptId = (0, v2_token_ops_js_1.newAttemptId)(idFactory);
|
|
86
|
-
const entryBase = {
|
|
87
|
-
sessionId: String(sessionId),
|
|
88
|
-
runId: String(runId),
|
|
89
|
-
nodeId: String(nodeId),
|
|
90
|
-
attemptId: String(attemptId),
|
|
91
|
-
workflowHashRef: String(workflowHashRef),
|
|
92
|
-
};
|
|
93
|
-
return (0, v2_token_ops_js_1.mintContinueAndCheckpointTokens)({ entry: entryBase, ports: tokenCodecPorts, aliasStore, entropy })
|
|
94
|
-
.mapErr((failure) => ({ kind: 'token_signing_failed', cause: failure }))
|
|
95
|
-
.andThen(({ continueToken: continueTokenValue, checkpointToken: checkpointTokenValue }) => pinnedStore.get(workflowHash)
|
|
76
|
+
return pinnedStore.get(workflowHash)
|
|
96
77
|
.mapErr((cause) => ({ kind: 'pinned_workflow_store_failed', cause }))
|
|
97
78
|
.andThen((pinned) => {
|
|
98
79
|
if (!pinned)
|
|
@@ -106,35 +87,70 @@ function handleRehydrateIntent(args) {
|
|
|
106
87
|
suggestion: 'Re-pin the workflow via start_workflow.',
|
|
107
88
|
});
|
|
108
89
|
}
|
|
109
|
-
const
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
});
|
|
90
|
+
const bindingBaseDir = (0, v2_workspace_resolution_js_1.resolveBindingBaseDir)(input.workspacePath, resolvedRootUris ?? []);
|
|
91
|
+
const driftWarnings = detectBindingDriftForSnapshot(pinned, workflowId, bindingBaseDir);
|
|
92
|
+
if (!pending) {
|
|
93
|
+
const preferences = (0, v2_execution_helpers_js_1.derivePreferencesOrDefault)({ truth, runId, nodeId });
|
|
94
|
+
const nextIntent = (0, v2_state_conversion_js_1.deriveNextIntent)({ rehydrateOnly: true, isComplete, pending: null });
|
|
95
|
+
return (0, neverthrow_1.okAsync)(output_schemas_js_1.V2ContinueWorkflowOutputSchema.parse({
|
|
96
|
+
kind: 'ok',
|
|
97
|
+
isComplete,
|
|
98
|
+
pending: null,
|
|
99
|
+
preferences,
|
|
100
|
+
nextIntent,
|
|
101
|
+
nextCall: null,
|
|
102
|
+
...(driftWarnings.length > 0 ? { warnings: driftWarnings } : {}),
|
|
103
|
+
}));
|
|
124
104
|
}
|
|
125
|
-
const
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
105
|
+
const attemptId = (0, v2_token_ops_js_1.newAttemptId)(idFactory);
|
|
106
|
+
const entryBase = {
|
|
107
|
+
sessionId: String(sessionId),
|
|
108
|
+
runId: String(runId),
|
|
109
|
+
nodeId: String(nodeId),
|
|
110
|
+
attemptId: String(attemptId),
|
|
111
|
+
workflowHashRef: String(workflowHashRef),
|
|
112
|
+
};
|
|
113
|
+
return (0, v2_token_ops_js_1.mintContinueAndCheckpointTokens)({ entry: entryBase, ports: tokenCodecPorts, aliasStore, entropy })
|
|
114
|
+
.mapErr((failure) => ({ kind: 'token_signing_failed', cause: failure }))
|
|
115
|
+
.andThen(({ continueToken: continueTokenValue, checkpointToken: checkpointTokenValue }) => {
|
|
116
|
+
const wf = (0, workflow_js_1.createWorkflow)(pinned.definition, (0, workflow_source_js_1.createBundledSource)());
|
|
117
|
+
const metaRes = (0, prompt_renderer_js_1.renderPendingPrompt)({
|
|
118
|
+
workflow: wf,
|
|
119
|
+
stepId: String(pending.stepId),
|
|
120
|
+
loopPath: pending.loopPath,
|
|
121
|
+
truth,
|
|
122
|
+
runId: (0, index_js_1.asRunId)(String(runId)),
|
|
123
|
+
nodeId: (0, index_js_1.asNodeId)(String(nodeId)),
|
|
124
|
+
rehydrateOnly: true,
|
|
125
|
+
});
|
|
126
|
+
if (metaRes.isErr()) {
|
|
127
|
+
return (0, neverthrow_1.errAsync)({
|
|
128
|
+
kind: 'invariant_violation',
|
|
129
|
+
message: `Prompt rendering failed: ${metaRes.error.message}`,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
const meta = metaRes.value;
|
|
133
|
+
const preferences = (0, v2_execution_helpers_js_1.derivePreferencesOrDefault)({ truth, runId, nodeId });
|
|
134
|
+
const nextIntent = (0, v2_state_conversion_js_1.deriveNextIntent)({ rehydrateOnly: true, isComplete, pending: meta });
|
|
135
|
+
return (0, neverthrow_1.okAsync)(output_schemas_js_1.V2ContinueWorkflowOutputSchema.parse({
|
|
136
|
+
kind: 'ok',
|
|
137
|
+
continueToken: continueTokenValue,
|
|
138
|
+
checkpointToken: checkpointTokenValue,
|
|
139
|
+
isComplete,
|
|
140
|
+
pending: (0, output_schemas_js_1.toPendingStep)(meta),
|
|
141
|
+
preferences,
|
|
142
|
+
nextIntent,
|
|
143
|
+
nextCall: (0, index_js_2.buildNextCall)({ continueToken: continueTokenValue, isComplete, pending: meta }),
|
|
144
|
+
...(driftWarnings.length > 0 ? { warnings: driftWarnings } : {}),
|
|
145
|
+
}));
|
|
146
|
+
});
|
|
147
|
+
});
|
|
139
148
|
});
|
|
140
149
|
}
|
|
150
|
+
function detectBindingDriftForSnapshot(pinned, workflowId, baseDir) {
|
|
151
|
+
const pinnedOverrides = pinned.pinnedOverrides ?? pinned.resolvedBindings;
|
|
152
|
+
if (!pinnedOverrides || Object.keys(pinnedOverrides).length === 0)
|
|
153
|
+
return [];
|
|
154
|
+
const currentBindings = (0, binding_registry_js_1.loadProjectBindings)(workflowId, baseDir);
|
|
155
|
+
return (0, binding_drift_js_1.detectBindingDrift)(pinnedOverrides, currentBindings);
|
|
156
|
+
}
|
|
@@ -10,6 +10,7 @@ const index_js_2 = require("../../../v2/durable-core/ids/index.js");
|
|
|
10
10
|
const neverthrow_1 = require("neverthrow");
|
|
11
11
|
const v2_execution_helpers_js_1 = require("../v2-execution-helpers.js");
|
|
12
12
|
const v2_token_ops_js_1 = require("../v2-token-ops.js");
|
|
13
|
+
const types_js_2 = require("../../types.js");
|
|
13
14
|
const v2_context_budget_js_1 = require("../v2-context-budget.js");
|
|
14
15
|
const start_js_1 = require("./start.js");
|
|
15
16
|
const continue_rehydrate_js_1 = require("./continue-rehydrate.js");
|
|
@@ -37,56 +38,97 @@ async function handleV2ContinueWorkflow(input, ctx) {
|
|
|
37
38
|
return guard.error;
|
|
38
39
|
return executeContinueWorkflow(input, guard.ctx).match((payload) => (0, types_js_1.success)(payload), (e) => (0, v2_execution_helpers_js_1.mapContinueWorkflowErrorToToolError)(e));
|
|
39
40
|
}
|
|
41
|
+
function classifyToken(raw) {
|
|
42
|
+
if (raw.startsWith('st_') || raw.startsWith('st1'))
|
|
43
|
+
return { kind: 'state', raw };
|
|
44
|
+
return { kind: 'continue', raw };
|
|
45
|
+
}
|
|
46
|
+
function loadAndRehydrate(args) {
|
|
47
|
+
const { sessionId, runId, nodeId, workflowHashRef, input } = args;
|
|
48
|
+
const { sessionStore, tokenCodecPorts, pinnedStore, snapshotStore, idFactory, tokenAliasStore, entropy } = args.ctx.v2;
|
|
49
|
+
return sessionStore.load(sessionId)
|
|
50
|
+
.mapErr((cause) => ({ kind: 'session_load_failed', cause }))
|
|
51
|
+
.andThen((truth) => (0, continue_rehydrate_js_1.handleRehydrateIntent)({
|
|
52
|
+
input,
|
|
53
|
+
sessionId,
|
|
54
|
+
runId,
|
|
55
|
+
nodeId,
|
|
56
|
+
workflowHashRef,
|
|
57
|
+
truth,
|
|
58
|
+
tokenCodecPorts,
|
|
59
|
+
pinnedStore,
|
|
60
|
+
snapshotStore,
|
|
61
|
+
idFactory,
|
|
62
|
+
aliasStore: tokenAliasStore,
|
|
63
|
+
entropy,
|
|
64
|
+
resolvedRootUris: args.ctx.v2.resolvedRootUris,
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
40
67
|
function executeContinueWorkflow(input, ctx) {
|
|
41
68
|
const { gate, sessionStore, snapshotStore, pinnedStore, sha256, tokenCodecPorts, idFactory, tokenAliasStore, entropy } = ctx.v2;
|
|
42
69
|
const ctxCheck = (0, v2_context_budget_js_1.checkContextBudget)({ tool: 'continue_workflow', context: input.context });
|
|
43
70
|
if (!ctxCheck.ok)
|
|
44
71
|
return (0, neverthrow_1.errAsync)({ kind: 'validation_failed', failure: ctxCheck.error });
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
const routing = classifyToken(input.continueToken);
|
|
73
|
+
switch (routing.kind) {
|
|
74
|
+
case 'state': {
|
|
75
|
+
if (input.intent === 'advance') {
|
|
76
|
+
const hasOutput = input.output != null;
|
|
77
|
+
const message = hasOutput
|
|
78
|
+
? 'A resumeToken cannot carry output — resumeTokens are read-only. Remove the output field and call continue_workflow with just the resumeToken to rehydrate session context.'
|
|
79
|
+
: 'A resumeToken (st_... / st1...) carries no advance authority. Use intent: "rehydrate" to restore session context.';
|
|
80
|
+
const suggestion = hasOutput
|
|
81
|
+
? 'Remove the output field. Pass just { continueToken: "<resumeToken>", intent: "rehydrate" } to rehydrate, then use the returned continueToken to advance.'
|
|
82
|
+
: 'Pass intent: "rehydrate" when using the resumeToken from resume_session or checkpoint_workflow.';
|
|
83
|
+
return (0, neverthrow_1.errAsync)({
|
|
84
|
+
kind: 'validation_failed',
|
|
85
|
+
failure: (0, types_js_2.errNotRetryable)('TOKEN_SCOPE_MISMATCH', message, { suggestion }),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return (0, v2_token_ops_js_1.parseStateTokenOrFail)(routing.raw, tokenCodecPorts, tokenAliasStore)
|
|
89
|
+
.mapErr((failure) => ({ kind: 'validation_failed', failure }))
|
|
90
|
+
.andThen((resolved) => loadAndRehydrate({
|
|
91
|
+
sessionId: (0, index_js_2.asSessionId)(resolved.payload.sessionId),
|
|
92
|
+
runId: (0, index_js_2.asRunId)(resolved.payload.runId),
|
|
93
|
+
nodeId: (0, index_js_2.asNodeId)(resolved.payload.nodeId),
|
|
94
|
+
workflowHashRef: resolved.payload.workflowHashRef,
|
|
56
95
|
input,
|
|
57
|
-
|
|
58
|
-
runId,
|
|
59
|
-
nodeId,
|
|
60
|
-
workflowHashRef,
|
|
61
|
-
truth,
|
|
62
|
-
tokenCodecPorts,
|
|
63
|
-
pinnedStore,
|
|
64
|
-
snapshotStore,
|
|
65
|
-
idFactory,
|
|
66
|
-
aliasStore: tokenAliasStore,
|
|
67
|
-
entropy,
|
|
96
|
+
ctx,
|
|
68
97
|
}));
|
|
69
98
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
99
|
+
case 'continue': {
|
|
100
|
+
return (0, v2_token_ops_js_1.parseContinueTokenOrFail)(routing.raw, tokenCodecPorts, tokenAliasStore)
|
|
101
|
+
.mapErr((failure) => ({ kind: 'validation_failed', failure }))
|
|
102
|
+
.andThen((resolved) => {
|
|
103
|
+
const sessionId = (0, index_js_2.asSessionId)(resolved.sessionId);
|
|
104
|
+
const runId = (0, index_js_2.asRunId)(resolved.runId);
|
|
105
|
+
const nodeId = (0, index_js_2.asNodeId)(resolved.nodeId);
|
|
106
|
+
const workflowHashRef = resolved.workflowHashRef;
|
|
107
|
+
if (input.intent === 'rehydrate') {
|
|
108
|
+
return loadAndRehydrate({ sessionId, runId, nodeId, workflowHashRef, input, ctx });
|
|
109
|
+
}
|
|
110
|
+
const attemptId = (0, index_js_1.asAttemptId)(resolved.attemptId);
|
|
111
|
+
return sessionStore.load(sessionId)
|
|
112
|
+
.mapErr((cause) => ({ kind: 'session_load_failed', cause }))
|
|
113
|
+
.andThen((truth) => (0, continue_advance_js_1.handleAdvanceIntent)({
|
|
114
|
+
input,
|
|
115
|
+
sessionId,
|
|
116
|
+
runId,
|
|
117
|
+
nodeId,
|
|
118
|
+
attemptId,
|
|
119
|
+
workflowHashRef,
|
|
120
|
+
truth,
|
|
121
|
+
gate,
|
|
122
|
+
sessionStore,
|
|
123
|
+
snapshotStore,
|
|
124
|
+
pinnedStore,
|
|
125
|
+
tokenCodecPorts,
|
|
126
|
+
idFactory,
|
|
127
|
+
sha256,
|
|
128
|
+
aliasStore: tokenAliasStore,
|
|
129
|
+
entropy,
|
|
130
|
+
}));
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
92
134
|
}
|
|
@@ -107,7 +107,7 @@ function mapTokenDecodeErrorToToolError(e) {
|
|
|
107
107
|
}
|
|
108
108
|
if (bech32mErr.code === 'BECH32M_HRP_MISMATCH') {
|
|
109
109
|
return (0, types_js_1.errNotRetryable)('TOKEN_INVALID_FORMAT', `Wrong token type. ${e.message}`, {
|
|
110
|
-
suggestion: 'Ensure you are using the correct token
|
|
110
|
+
suggestion: 'Ensure you are using the correct token type for this operation (continueToken, checkpointToken, or resumeToken).',
|
|
111
111
|
details: {
|
|
112
112
|
errorType: 'hrp_mismatch',
|
|
113
113
|
},
|
|
@@ -30,14 +30,14 @@ async function handleV2ResumeSession(input, ctx) {
|
|
|
30
30
|
if (resumeResult.isErr()) {
|
|
31
31
|
return (0, types_js_1.errNotRetryable)('INTERNAL_ERROR', `Resume failed: ${resumeResult.error.message}`);
|
|
32
32
|
}
|
|
33
|
-
const candidates = resumeResult.value;
|
|
33
|
+
const { candidates, totalFound } = resumeResult.value;
|
|
34
34
|
const { outputCandidates, skipped } = mintCandidateTokens(candidates, v2.tokenCodecPorts);
|
|
35
35
|
if (skipped > 0) {
|
|
36
36
|
console.error(`[workrail:resume] ${skipped}/${candidates.length} candidate(s) skipped: token minting failed (workflowHashRef derivation or signing error)`);
|
|
37
37
|
}
|
|
38
38
|
const output = output_schemas_js_1.V2ResumeSessionOutputSchema.parse({
|
|
39
39
|
candidates: outputCandidates,
|
|
40
|
-
totalEligible:
|
|
40
|
+
totalEligible: totalFound,
|
|
41
41
|
});
|
|
42
42
|
return {
|
|
43
43
|
type: 'success',
|
|
@@ -53,7 +53,7 @@ function mintCandidateTokens(candidates, ports) {
|
|
|
53
53
|
skipped++;
|
|
54
54
|
continue;
|
|
55
55
|
}
|
|
56
|
-
const
|
|
56
|
+
const resumeTokenRes = (0, v2_token_ops_js_1.signTokenOrErr)({
|
|
57
57
|
payload: {
|
|
58
58
|
tokenVersion: 1,
|
|
59
59
|
tokenKind: 'state',
|
|
@@ -64,16 +64,21 @@ function mintCandidateTokens(candidates, ports) {
|
|
|
64
64
|
},
|
|
65
65
|
ports,
|
|
66
66
|
});
|
|
67
|
-
if (
|
|
67
|
+
if (resumeTokenRes.isErr()) {
|
|
68
68
|
skipped++;
|
|
69
69
|
continue;
|
|
70
70
|
}
|
|
71
71
|
outputCandidates.push({
|
|
72
72
|
sessionId: candidate.sessionId,
|
|
73
73
|
runId: candidate.runId,
|
|
74
|
-
|
|
74
|
+
workflowId: candidate.workflowId,
|
|
75
|
+
resumeToken: resumeTokenRes.value,
|
|
75
76
|
snippet: candidate.snippet,
|
|
76
77
|
whyMatched: [...candidate.whyMatched],
|
|
78
|
+
nextCall: {
|
|
79
|
+
tool: 'continue_workflow',
|
|
80
|
+
params: { continueToken: resumeTokenRes.value, intent: 'rehydrate' },
|
|
81
|
+
},
|
|
77
82
|
});
|
|
78
83
|
}
|
|
79
84
|
return { outputCandidates, skipped };
|
|
@@ -35,7 +35,7 @@ export declare function mintContinueAndCheckpointTokens(args: Omit<MintShortToke
|
|
|
35
35
|
readonly entry: Omit<TokenAliasEntryV2, 'nonceHex' | 'tokenKind'>;
|
|
36
36
|
}): ResultAsync<ContinueAndCheckpointTokens, ToolFailure>;
|
|
37
37
|
export interface ShortTokenTriple {
|
|
38
|
-
readonly
|
|
38
|
+
readonly resumeToken: string;
|
|
39
39
|
readonly ackToken: string;
|
|
40
40
|
readonly checkpointToken: string;
|
|
41
41
|
}
|
|
@@ -94,7 +94,7 @@ function parseStateTokenOrFail(raw, ports, aliasStore) {
|
|
|
94
94
|
return resolveShortToken(raw, ports, aliasStore).andThen((resolved) => {
|
|
95
95
|
if (resolved.payload.tokenKind !== 'state') {
|
|
96
96
|
return (0, neverthrow_1.errAsync)((0, types_js_1.errNotRetryable)('TOKEN_INVALID_FORMAT', 'Expected a state token (st_... or st1...).', {
|
|
97
|
-
suggestion: 'Use the
|
|
97
|
+
suggestion: 'Use the resumeToken returned by WorkRail.',
|
|
98
98
|
}));
|
|
99
99
|
}
|
|
100
100
|
return (0, neverthrow_1.okAsync)(resolved);
|
|
@@ -110,7 +110,7 @@ function parseStateTokenOrFail(raw, ports, aliasStore) {
|
|
|
110
110
|
}
|
|
111
111
|
if (parsedRes.value.payload.tokenKind !== 'state') {
|
|
112
112
|
return (0, neverthrow_1.errAsync)((0, types_js_1.errNotRetryable)('TOKEN_INVALID_FORMAT', 'Expected a state token (st1...).', {
|
|
113
|
-
suggestion: 'Use the
|
|
113
|
+
suggestion: 'Use the resumeToken returned by WorkRail.',
|
|
114
114
|
}));
|
|
115
115
|
}
|
|
116
116
|
return (0, neverthrow_1.okAsync)(parsedRes.value);
|
|
@@ -288,7 +288,7 @@ function mintShortTokenTriple(args) {
|
|
|
288
288
|
const replayCk = reTokenFromNonceHex('checkpoint', existingCk.nonceHex, ports);
|
|
289
289
|
if (replayState.isOk() && replayAck.isOk() && replayCk.isOk()) {
|
|
290
290
|
return (0, neverthrow_1.okAsync)({
|
|
291
|
-
|
|
291
|
+
resumeToken: replayState.value,
|
|
292
292
|
ackToken: replayAck.value,
|
|
293
293
|
checkpointToken: replayCk.value,
|
|
294
294
|
});
|
|
@@ -310,7 +310,7 @@ function mintShortTokenTriple(args) {
|
|
|
310
310
|
: 'UNKNOWN';
|
|
311
311
|
return (0, neverthrow_1.errAsync)((0, types_js_1.errNotRetryable)('INTERNAL_ERROR', `Short token minting failed: ${msg}`));
|
|
312
312
|
}
|
|
313
|
-
const
|
|
313
|
+
const resumeTokenStr = stateMinted.value;
|
|
314
314
|
const ackTokenStr = ackMinted.value;
|
|
315
315
|
const ckTokenStr = ckMinted.value;
|
|
316
316
|
const stateNonceHex = bufToHex(stateNonce);
|
|
@@ -347,7 +347,7 @@ function mintShortTokenTriple(args) {
|
|
|
347
347
|
.andThen(() => aliasStore.register(ackEntry))
|
|
348
348
|
.andThen(() => aliasStore.register(ckEntry))
|
|
349
349
|
.map(() => ({
|
|
350
|
-
|
|
350
|
+
resumeToken: resumeTokenStr,
|
|
351
351
|
ackToken: ackTokenStr,
|
|
352
352
|
checkpointToken: ckTokenStr,
|
|
353
353
|
}))
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ResultAsync } from 'neverthrow';
|
|
2
2
|
import type { WorkspaceAnchor, WorkspaceSource } from '../../v2/ports/workspace-anchor.port.js';
|
|
3
3
|
import type { V2Dependencies } from '../types.js';
|
|
4
|
+
export declare function resolveBindingBaseDir(workspacePath: string | undefined, resolvedRootUris: readonly string[]): string;
|
|
4
5
|
export declare function selectWorkspaceSource(workspacePath: string | undefined, resolvedRootUris: readonly string[]): WorkspaceSource;
|
|
5
6
|
export declare function resolveWorkspaceAnchors(v2: V2Dependencies, workspacePath: string | undefined): ResultAsync<readonly WorkspaceAnchor[], never>;
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveBindingBaseDir = resolveBindingBaseDir;
|
|
3
4
|
exports.selectWorkspaceSource = selectWorkspaceSource;
|
|
4
5
|
exports.resolveWorkspaceAnchors = resolveWorkspaceAnchors;
|
|
5
6
|
const neverthrow_1 = require("neverthrow");
|
|
7
|
+
function resolveBindingBaseDir(workspacePath, resolvedRootUris) {
|
|
8
|
+
if (workspacePath !== undefined)
|
|
9
|
+
return workspacePath;
|
|
10
|
+
const primaryUri = resolvedRootUris[0];
|
|
11
|
+
if (primaryUri !== undefined) {
|
|
12
|
+
if (primaryUri.startsWith('file://')) {
|
|
13
|
+
return decodeURIComponent(primaryUri.replace(/^file:\/\//, ''));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return process.cwd();
|
|
17
|
+
}
|
|
6
18
|
function selectWorkspaceSource(workspacePath, resolvedRootUris) {
|
|
7
19
|
if (workspacePath !== undefined) {
|
|
8
20
|
return { kind: 'explicit_path', path: workspacePath };
|
package/dist/mcp/index.d.ts
CHANGED
|
@@ -12,5 +12,8 @@ export { handleWorkflowList, handleWorkflowGet, handleWorkflowNext, handleWorkfl
|
|
|
12
12
|
export type { WorkflowSummary, WorkflowListOutput, WorkflowGetOutput, WorkflowNextOutput, WorkflowValidateJsonOutput, WorkflowGetSchemaOutput, } from './handlers/workflow.js';
|
|
13
13
|
export { handleCreateSession, handleUpdateSession, handleReadSession, handleOpenDashboard, } from './handlers/session.js';
|
|
14
14
|
export type { CreateSessionOutput, UpdateSessionOutput, ReadSessionOutput, ReadSessionSchemaOutput, SchemaOverview, OpenDashboardOutput, } from './handlers/session.js';
|
|
15
|
-
export { createToolContext,
|
|
15
|
+
export { createToolContext, composeServer, } from './server.js';
|
|
16
|
+
export type { ComposedServer } from './server.js';
|
|
17
|
+
export { startStdioServer } from './transports/stdio-entry.js';
|
|
18
|
+
export { startHttpServer } from './transports/http-entry.js';
|
|
16
19
|
export { zodToJsonSchema } from './zod-to-json-schema.js';
|
package/dist/mcp/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.zodToJsonSchema = exports.
|
|
3
|
+
exports.zodToJsonSchema = exports.startHttpServer = exports.startStdioServer = exports.composeServer = exports.createToolContext = exports.handleOpenDashboard = exports.handleReadSession = exports.handleUpdateSession = exports.handleCreateSession = exports.handleWorkflowGetSchema = exports.handleWorkflowValidateJson = exports.handleWorkflowNext = exports.handleWorkflowGet = exports.handleWorkflowList = exports.sessionTools = exports.openDashboardTool = exports.readSessionTool = exports.updateSessionTool = exports.createSessionTool = exports.OpenDashboardInput = exports.ReadSessionInput = exports.UpdateSessionInput = exports.CreateSessionInput = exports.WORKFLOW_TOOL_TITLES = exports.WORKFLOW_TOOL_ANNOTATIONS = exports.WorkflowGetSchemaInput = exports.WorkflowValidateJsonInput = exports.WorkflowNextInput = exports.WorkflowGetInput = exports.WorkflowListInput = exports.DESCRIPTIONS = exports.StaticToolDescriptionProvider = exports.ToolDescriptionProvider = exports.isWorkflowToolName = exports.isDescriptionMode = exports.WORKFLOW_TOOL_NAMES = exports.DESCRIPTION_MODES = exports.createToolFactory = exports.errRetryImmediate = exports.errRetryAfterMs = exports.errNotRetryable = exports.error = exports.success = void 0;
|
|
4
4
|
var types_js_1 = require("./types.js");
|
|
5
5
|
Object.defineProperty(exports, "success", { enumerable: true, get: function () { return types_js_1.success; } });
|
|
6
6
|
Object.defineProperty(exports, "error", { enumerable: true, get: function () { return types_js_1.error; } });
|
|
@@ -49,6 +49,10 @@ Object.defineProperty(exports, "handleReadSession", { enumerable: true, get: fun
|
|
|
49
49
|
Object.defineProperty(exports, "handleOpenDashboard", { enumerable: true, get: function () { return session_js_1.handleOpenDashboard; } });
|
|
50
50
|
var server_js_1 = require("./server.js");
|
|
51
51
|
Object.defineProperty(exports, "createToolContext", { enumerable: true, get: function () { return server_js_1.createToolContext; } });
|
|
52
|
-
Object.defineProperty(exports, "
|
|
52
|
+
Object.defineProperty(exports, "composeServer", { enumerable: true, get: function () { return server_js_1.composeServer; } });
|
|
53
|
+
var stdio_entry_js_1 = require("./transports/stdio-entry.js");
|
|
54
|
+
Object.defineProperty(exports, "startStdioServer", { enumerable: true, get: function () { return stdio_entry_js_1.startStdioServer; } });
|
|
55
|
+
var http_entry_js_1 = require("./transports/http-entry.js");
|
|
56
|
+
Object.defineProperty(exports, "startHttpServer", { enumerable: true, get: function () { return http_entry_js_1.startHttpServer; } });
|
|
53
57
|
var zod_to_json_schema_js_1 = require("./zod-to-json-schema.js");
|
|
54
58
|
Object.defineProperty(exports, "zodToJsonSchema", { enumerable: true, get: function () { return zod_to_json_schema_js_1.zodToJsonSchema; } });
|