@exaudeus/workrail 2.0.0 → 3.0.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/template-registry.d.ts +4 -2
- package/dist/application/services/compiler/template-registry.js +97 -5
- package/dist/application/services/workflow-compiler.d.ts +5 -1
- package/dist/application/services/workflow-compiler.js +20 -7
- package/dist/application/use-cases/raw-workflow-file-scanner.d.ts +1 -1
- package/dist/application/use-cases/raw-workflow-file-scanner.js +2 -0
- package/dist/application/use-cases/validate-workflow-registry.js +2 -1
- package/dist/config/feature-flags.js +8 -0
- package/dist/di/container.js +10 -1
- package/dist/di/tokens.d.ts +1 -0
- package/dist/di/tokens.js +1 -0
- package/dist/engine/engine-factory.d.ts +3 -0
- package/dist/engine/engine-factory.js +295 -0
- package/dist/engine/index.d.ts +3 -0
- package/dist/engine/index.js +12 -0
- package/dist/engine/types.d.ts +130 -0
- package/dist/engine/types.js +18 -0
- package/dist/infrastructure/storage/file-workflow-storage.d.ts +1 -0
- package/dist/infrastructure/storage/file-workflow-storage.js +18 -3
- package/dist/infrastructure/storage/workflow-resolution.d.ts +9 -6
- package/dist/infrastructure/storage/workflow-resolution.js +14 -1
- package/dist/manifest.json +166 -94
- package/dist/mcp/handlers/shared/request-workflow-reader.d.ts +19 -0
- package/dist/mcp/handlers/shared/request-workflow-reader.js +50 -0
- package/dist/mcp/handlers/v2-checkpoint.d.ts +31 -1
- package/dist/mcp/handlers/v2-checkpoint.js +76 -64
- package/dist/mcp/handlers/v2-execution/continue-advance.d.ts +2 -0
- package/dist/mcp/handlers/v2-execution/continue-advance.js +5 -5
- package/dist/mcp/handlers/v2-execution/continue-rehydrate.d.ts +2 -0
- package/dist/mcp/handlers/v2-execution/continue-rehydrate.js +17 -22
- package/dist/mcp/handlers/v2-execution/index.d.ts +10 -17
- package/dist/mcp/handlers/v2-execution/index.js +44 -54
- package/dist/mcp/handlers/v2-execution/replay.d.ts +4 -15
- package/dist/mcp/handlers/v2-execution/replay.js +52 -128
- package/dist/mcp/handlers/v2-execution/start.d.ts +4 -3
- package/dist/mcp/handlers/v2-execution/start.js +32 -49
- package/dist/mcp/handlers/v2-token-ops.d.ts +45 -24
- package/dist/mcp/handlers/v2-token-ops.js +372 -32
- package/dist/mcp/handlers/v2-workflow.d.ts +1 -1
- package/dist/mcp/handlers/v2-workflow.js +25 -4
- package/dist/mcp/output-schemas.d.ts +104 -283
- package/dist/mcp/output-schemas.js +24 -22
- package/dist/mcp/server.js +8 -0
- package/dist/mcp/tool-descriptions.js +9 -2
- package/dist/mcp/types.d.ts +4 -0
- package/dist/mcp/v2/tools.d.ts +32 -53
- package/dist/mcp/v2/tools.js +27 -37
- package/dist/mcp/v2-response-formatter.js +12 -16
- package/dist/runtime/runtime-mode.d.ts +2 -0
- package/dist/v2/durable-core/domain/prompt-renderer.d.ts +1 -0
- package/dist/v2/durable-core/domain/prompt-renderer.js +5 -3
- package/dist/v2/durable-core/schemas/export-bundle/index.d.ts +14 -14
- package/dist/v2/durable-core/schemas/session/events.d.ts +4 -4
- package/dist/v2/durable-core/schemas/session/validation-event.d.ts +2 -2
- package/dist/v2/durable-core/tokens/payloads.d.ts +32 -32
- package/dist/v2/durable-core/tokens/short-token.d.ts +38 -0
- package/dist/v2/durable-core/tokens/short-token.js +126 -0
- package/dist/v2/durable-core/tokens/token-patterns.d.ts +4 -0
- package/dist/v2/durable-core/tokens/token-patterns.js +9 -0
- package/dist/v2/infra/in-memory/token-alias-store/index.d.ts +11 -0
- package/dist/v2/infra/in-memory/token-alias-store/index.js +38 -0
- package/dist/v2/infra/local/data-dir/index.d.ts +1 -0
- package/dist/v2/infra/local/data-dir/index.js +3 -0
- package/dist/v2/infra/local/token-alias-store/index.d.ts +16 -0
- package/dist/v2/infra/local/token-alias-store/index.js +117 -0
- package/dist/v2/ports/data-dir.port.d.ts +1 -0
- package/dist/v2/ports/token-alias-store.port.d.ts +33 -0
- package/dist/v2/ports/token-alias-store.port.js +2 -0
- package/package.json +8 -1
- package/workflows/coding-task-workflow-agentic.lean.v2.json +224 -0
- package/workflows/routines/philosophy-alignment.json +12 -12
- package/workflows/routines/tension-driven-design.json +63 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Result } from 'neverthrow';
|
|
2
|
-
import type { WorkflowStepDefinition } from '../../../types/workflow-definition.js';
|
|
2
|
+
import type { WorkflowStepDefinition, WorkflowDefinition } from '../../../types/workflow-definition.js';
|
|
3
3
|
export type TemplateExpander = (callerId: string, args: Readonly<Record<string, unknown>>) => Result<readonly WorkflowStepDefinition[], TemplateExpandError>;
|
|
4
4
|
export type TemplateExpandError = {
|
|
5
5
|
readonly code: 'TEMPLATE_EXPAND_FAILED';
|
|
@@ -16,4 +16,6 @@ export interface TemplateRegistry {
|
|
|
16
16
|
readonly has: (templateId: string) => boolean;
|
|
17
17
|
readonly knownIds: () => readonly string[];
|
|
18
18
|
}
|
|
19
|
-
export declare function
|
|
19
|
+
export declare function createRoutineExpander(routineId: string, definition: WorkflowDefinition): Result<TemplateExpander, TemplateExpandError>;
|
|
20
|
+
export declare function routineIdToTemplateId(routineId: string): string;
|
|
21
|
+
export declare function createTemplateRegistry(routineDefinitions?: ReadonlyMap<string, WorkflowDefinition>): TemplateRegistry;
|
|
@@ -1,13 +1,105 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRoutineExpander = createRoutineExpander;
|
|
4
|
+
exports.routineIdToTemplateId = routineIdToTemplateId;
|
|
3
5
|
exports.createTemplateRegistry = createTemplateRegistry;
|
|
4
6
|
const neverthrow_1 = require("neverthrow");
|
|
5
|
-
const
|
|
6
|
-
function
|
|
7
|
-
const
|
|
7
|
+
const SINGLE_BRACE_ARG = /(?<!\{)\{([^{}]+)\}(?!\})/g;
|
|
8
|
+
function substituteArgs(text, args, routineId, stepId) {
|
|
9
|
+
const missing = [];
|
|
10
|
+
const substituted = text.replace(SINGLE_BRACE_ARG, (match, argName) => {
|
|
11
|
+
if (argName in args) {
|
|
12
|
+
return String(args[argName]);
|
|
13
|
+
}
|
|
14
|
+
missing.push(argName);
|
|
15
|
+
return match;
|
|
16
|
+
});
|
|
17
|
+
if (missing.length > 0) {
|
|
18
|
+
return (0, neverthrow_1.err)({
|
|
19
|
+
code: 'TEMPLATE_EXPAND_FAILED',
|
|
20
|
+
templateId: `wr.templates.routine.${routineId}`,
|
|
21
|
+
message: `MISSING_TEMPLATE_ARG: routine '${routineId}' step '${stepId}' references arg(s) '${missing.join("', '")}' but they were not provided in templateCall.args`,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return (0, neverthrow_1.ok)(substituted);
|
|
25
|
+
}
|
|
26
|
+
function validateNoRecursiveTemplateCall(routineId, steps) {
|
|
27
|
+
for (const step of steps) {
|
|
28
|
+
if (step.templateCall) {
|
|
29
|
+
return (0, neverthrow_1.err)({
|
|
30
|
+
code: 'TEMPLATE_EXPAND_FAILED',
|
|
31
|
+
templateId: `wr.templates.routine.${routineId}`,
|
|
32
|
+
message: `Routine '${routineId}' step '${step.id}' contains a templateCall. Recursive routine injection is not supported.`,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return (0, neverthrow_1.ok)(undefined);
|
|
37
|
+
}
|
|
38
|
+
function createRoutineExpander(routineId, definition) {
|
|
39
|
+
const routineSteps = definition.steps;
|
|
40
|
+
const recursiveCheck = validateNoRecursiveTemplateCall(routineId, routineSteps);
|
|
41
|
+
if (recursiveCheck.isErr())
|
|
42
|
+
return (0, neverthrow_1.err)(recursiveCheck.error);
|
|
43
|
+
for (const step of routineSteps) {
|
|
44
|
+
if (!step.id || !step.title) {
|
|
45
|
+
return (0, neverthrow_1.err)({
|
|
46
|
+
code: 'TEMPLATE_EXPAND_FAILED',
|
|
47
|
+
templateId: `wr.templates.routine.${routineId}`,
|
|
48
|
+
message: `Routine '${routineId}' step '${step.id ?? '(missing id)'}' is missing required field '${!step.id ? 'id' : 'title'}'.`,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (!step.prompt) {
|
|
52
|
+
return (0, neverthrow_1.err)({
|
|
53
|
+
code: 'TEMPLATE_EXPAND_FAILED',
|
|
54
|
+
templateId: `wr.templates.routine.${routineId}`,
|
|
55
|
+
message: `Routine '${routineId}' step '${step.id}' is missing required field 'prompt'.`,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const routineGuidance = definition.metaGuidance ?? [];
|
|
60
|
+
const expander = (callerId, args) => {
|
|
61
|
+
const expandedSteps = [];
|
|
62
|
+
for (const step of routineSteps) {
|
|
63
|
+
const promptResult = substituteArgs(step.prompt, args, routineId, step.id);
|
|
64
|
+
if (promptResult.isErr())
|
|
65
|
+
return (0, neverthrow_1.err)(promptResult.error);
|
|
66
|
+
const mergedGuidance = routineGuidance.length > 0
|
|
67
|
+
? [...(step.guidance ?? []), ...routineGuidance]
|
|
68
|
+
: (step.guidance ?? []);
|
|
69
|
+
const expandedStep = {
|
|
70
|
+
id: `${callerId}.${step.id}`,
|
|
71
|
+
title: step.title,
|
|
72
|
+
prompt: promptResult.value,
|
|
73
|
+
...(step.agentRole !== undefined && { agentRole: step.agentRole }),
|
|
74
|
+
...(mergedGuidance.length > 0 && { guidance: mergedGuidance }),
|
|
75
|
+
...(step.requireConfirmation !== undefined && { requireConfirmation: step.requireConfirmation }),
|
|
76
|
+
};
|
|
77
|
+
expandedSteps.push(expandedStep);
|
|
78
|
+
}
|
|
79
|
+
return (0, neverthrow_1.ok)(expandedSteps);
|
|
80
|
+
};
|
|
81
|
+
return (0, neverthrow_1.ok)(expander);
|
|
82
|
+
}
|
|
83
|
+
function routineIdToTemplateId(routineId) {
|
|
84
|
+
const name = routineId.startsWith('routine-') ? routineId.slice('routine-'.length) : routineId;
|
|
85
|
+
return `wr.templates.routine.${name}`;
|
|
86
|
+
}
|
|
87
|
+
const STATIC_TEMPLATE_DEFINITIONS = new Map();
|
|
88
|
+
function createTemplateRegistry(routineDefinitions) {
|
|
89
|
+
const allTemplates = new Map(STATIC_TEMPLATE_DEFINITIONS);
|
|
90
|
+
if (routineDefinitions) {
|
|
91
|
+
for (const [routineId, definition] of routineDefinitions) {
|
|
92
|
+
const templateId = routineIdToTemplateId(routineId);
|
|
93
|
+
const expanderResult = createRoutineExpander(routineId, definition);
|
|
94
|
+
if (expanderResult.isOk()) {
|
|
95
|
+
allTemplates.set(templateId, expanderResult.value);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const knownIds = [...allTemplates.keys()];
|
|
8
100
|
return {
|
|
9
101
|
resolve(templateId) {
|
|
10
|
-
const expander =
|
|
102
|
+
const expander = allTemplates.get(templateId);
|
|
11
103
|
if (!expander) {
|
|
12
104
|
return (0, neverthrow_1.err)({
|
|
13
105
|
code: 'UNKNOWN_TEMPLATE',
|
|
@@ -18,7 +110,7 @@ function createTemplateRegistry() {
|
|
|
18
110
|
return (0, neverthrow_1.ok)(expander);
|
|
19
111
|
},
|
|
20
112
|
has(templateId) {
|
|
21
|
-
return
|
|
113
|
+
return allTemplates.has(templateId);
|
|
22
114
|
},
|
|
23
115
|
knownIds() {
|
|
24
116
|
return knownIds;
|
|
@@ -2,6 +2,7 @@ import { Workflow, WorkflowStepDefinition, LoopStepDefinition } from '../../type
|
|
|
2
2
|
import type { LoopConditionSource } from '../../types/workflow-definition';
|
|
3
3
|
import type { Result } from 'neverthrow';
|
|
4
4
|
import { type DomainError } from '../../domain/execution/error';
|
|
5
|
+
import { type TemplateRegistry } from './compiler/template-registry';
|
|
5
6
|
export interface CompiledLoop {
|
|
6
7
|
readonly loop: LoopStepDefinition;
|
|
7
8
|
readonly bodySteps: readonly WorkflowStepDefinition[];
|
|
@@ -14,8 +15,11 @@ export interface CompiledWorkflow {
|
|
|
14
15
|
readonly compiledLoops: ReadonlyMap<string, CompiledLoop>;
|
|
15
16
|
readonly loopBodyStepIds: ReadonlySet<string>;
|
|
16
17
|
}
|
|
17
|
-
export declare function resolveDefinitionSteps(steps: readonly (WorkflowStepDefinition | LoopStepDefinition)[], features: readonly string[]): Result<readonly (WorkflowStepDefinition | LoopStepDefinition)[], DomainError>;
|
|
18
|
+
export declare function resolveDefinitionSteps(steps: readonly (WorkflowStepDefinition | LoopStepDefinition)[], features: readonly string[], templateRegistry?: TemplateRegistry): Result<readonly (WorkflowStepDefinition | LoopStepDefinition)[], DomainError>;
|
|
18
19
|
export declare class WorkflowCompiler {
|
|
20
|
+
private readonly templateRegistry;
|
|
21
|
+
constructor();
|
|
22
|
+
static withTemplateRegistry(registry: TemplateRegistry): WorkflowCompiler;
|
|
19
23
|
compile(workflow: Workflow): Result<CompiledWorkflow, DomainError>;
|
|
20
24
|
private deriveConditionSource;
|
|
21
25
|
private resolveLoopBody;
|
|
@@ -5,6 +5,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
6
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
7
|
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var WorkflowCompiler_1;
|
|
8
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
13
|
exports.WorkflowCompiler = void 0;
|
|
10
14
|
exports.resolveDefinitionSteps = resolveDefinitionSteps;
|
|
@@ -22,9 +26,9 @@ const resolve_templates_1 = require("./compiler/resolve-templates");
|
|
|
22
26
|
const template_registry_1 = require("./compiler/template-registry");
|
|
23
27
|
const _refRegistry = (0, ref_registry_1.createRefRegistry)();
|
|
24
28
|
const _featureRegistry = (0, feature_registry_1.createFeatureRegistry)();
|
|
25
|
-
const
|
|
26
|
-
function resolveDefinitionSteps(steps, features) {
|
|
27
|
-
const templatesResult = (0, resolve_templates_1.resolveTemplatesPass)(steps,
|
|
29
|
+
const _defaultTemplateRegistry = (0, template_registry_1.createTemplateRegistry)();
|
|
30
|
+
function resolveDefinitionSteps(steps, features, templateRegistry = _defaultTemplateRegistry) {
|
|
31
|
+
const templatesResult = (0, resolve_templates_1.resolveTemplatesPass)(steps, templateRegistry);
|
|
28
32
|
if (templatesResult.isErr()) {
|
|
29
33
|
const e = templatesResult.error;
|
|
30
34
|
const message = e.code === 'TEMPLATE_RESOLVE_ERROR'
|
|
@@ -55,9 +59,17 @@ function resolveDefinitionSteps(steps, features) {
|
|
|
55
59
|
}
|
|
56
60
|
return (0, neverthrow_1.ok)(blocksResult.value);
|
|
57
61
|
}
|
|
58
|
-
let WorkflowCompiler = class WorkflowCompiler {
|
|
62
|
+
let WorkflowCompiler = WorkflowCompiler_1 = class WorkflowCompiler {
|
|
63
|
+
constructor() {
|
|
64
|
+
this.templateRegistry = _defaultTemplateRegistry;
|
|
65
|
+
}
|
|
66
|
+
static withTemplateRegistry(registry) {
|
|
67
|
+
const compiler = new WorkflowCompiler_1();
|
|
68
|
+
compiler.templateRegistry = registry;
|
|
69
|
+
return compiler;
|
|
70
|
+
}
|
|
59
71
|
compile(workflow) {
|
|
60
|
-
const resolvedResult = resolveDefinitionSteps(workflow.definition.steps, workflow.definition.features ?? []);
|
|
72
|
+
const resolvedResult = resolveDefinitionSteps(workflow.definition.steps, workflow.definition.features ?? [], this.templateRegistry);
|
|
61
73
|
if (resolvedResult.isErr())
|
|
62
74
|
return (0, neverthrow_1.err)(resolvedResult.error);
|
|
63
75
|
const steps = resolvedResult.value;
|
|
@@ -158,6 +170,7 @@ let WorkflowCompiler = class WorkflowCompiler {
|
|
|
158
170
|
}
|
|
159
171
|
};
|
|
160
172
|
exports.WorkflowCompiler = WorkflowCompiler;
|
|
161
|
-
exports.WorkflowCompiler = WorkflowCompiler = __decorate([
|
|
162
|
-
(0, tsyringe_1.singleton)()
|
|
173
|
+
exports.WorkflowCompiler = WorkflowCompiler = WorkflowCompiler_1 = __decorate([
|
|
174
|
+
(0, tsyringe_1.singleton)(),
|
|
175
|
+
__metadata("design:paramtypes", [])
|
|
163
176
|
], WorkflowCompiler);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { WorkflowDefinition } from '../../types/workflow-definition.js';
|
|
2
2
|
export declare function findWorkflowJsonFiles(baseDirReal: string): Promise<string[]>;
|
|
3
|
-
export type VariantKind = 'v2' | 'agentic' | 'standard';
|
|
3
|
+
export type VariantKind = 'lean' | 'v2' | 'agentic' | 'standard';
|
|
4
4
|
export interface ParsedRawWorkflowFile {
|
|
5
5
|
readonly kind: 'parsed';
|
|
6
6
|
readonly filePath: string;
|
|
@@ -77,6 +77,8 @@ async function scanRawWorkflowFiles(baseDirReal) {
|
|
|
77
77
|
}
|
|
78
78
|
function detectVariantKind(relativeFilePath) {
|
|
79
79
|
const normalized = relativeFilePath.replace(/\\/g, '/');
|
|
80
|
+
if (normalized.includes('.lean.'))
|
|
81
|
+
return 'lean';
|
|
80
82
|
if (normalized.includes('.v2.'))
|
|
81
83
|
return 'v2';
|
|
82
84
|
if (normalized.includes('.agentic.'))
|
|
@@ -191,7 +191,7 @@ function deriveVariantResolutions(loadedWorkflows, allRawFiles, source) {
|
|
|
191
191
|
const availableVariants = rawFilesForId.map(f => f.variantKind);
|
|
192
192
|
const selectedRaw = rawFilesForId.find(f => f.definition.id === id);
|
|
193
193
|
const selectedVariant = selectedRaw?.variantKind ?? 'standard';
|
|
194
|
-
if (selectedVariant === 'v2' || selectedVariant === 'agentic') {
|
|
194
|
+
if (selectedVariant === 'lean' || selectedVariant === 'v2' || selectedVariant === 'agentic') {
|
|
195
195
|
result.set(id, {
|
|
196
196
|
kind: 'feature_flag_selected',
|
|
197
197
|
selectedVariant,
|
|
@@ -199,6 +199,7 @@ function deriveVariantResolutions(loadedWorkflows, allRawFiles, source) {
|
|
|
199
199
|
enabledFlags: {
|
|
200
200
|
v2Tools: selectedVariant === 'v2',
|
|
201
201
|
agenticRoutines: selectedVariant === 'agentic',
|
|
202
|
+
leanWorkflows: selectedVariant === 'lean',
|
|
202
203
|
},
|
|
203
204
|
});
|
|
204
205
|
}
|
|
@@ -45,6 +45,14 @@ exports.FEATURE_FLAG_DEFINITIONS = [
|
|
|
45
45
|
since: '0.8.3',
|
|
46
46
|
stable: false,
|
|
47
47
|
},
|
|
48
|
+
{
|
|
49
|
+
key: 'leanWorkflows',
|
|
50
|
+
envVar: 'WORKRAIL_ENABLE_LEAN_WORKFLOWS',
|
|
51
|
+
defaultValue: false,
|
|
52
|
+
description: 'Enable lean workflow variants (.lean.) that merge phases and reduce token usage while preserving quality',
|
|
53
|
+
since: '0.10.0',
|
|
54
|
+
stable: false,
|
|
55
|
+
},
|
|
48
56
|
{
|
|
49
57
|
key: 'authoritativeDescriptions',
|
|
50
58
|
envVar: 'WORKRAIL_AUTHORITATIVE_DESCRIPTIONS',
|
package/dist/di/container.js
CHANGED
|
@@ -86,6 +86,7 @@ function detectRuntimeMode() {
|
|
|
86
86
|
function toProcessLifecyclePolicy(mode) {
|
|
87
87
|
switch (mode.kind) {
|
|
88
88
|
case 'test':
|
|
89
|
+
case 'library':
|
|
89
90
|
return { kind: 'no_signal_handlers' };
|
|
90
91
|
case 'cli':
|
|
91
92
|
case 'rpc':
|
|
@@ -103,7 +104,7 @@ function registerRuntime(options = {}) {
|
|
|
103
104
|
const signals = policy.kind === 'no_signal_handlers' ? new noop_process_signals_js_1.NoopProcessSignals() : new node_process_signals_js_1.NodeProcessSignals();
|
|
104
105
|
tsyringe_1.container.register(tokens_js_1.DI.Runtime.ProcessSignals, { useValue: signals });
|
|
105
106
|
tsyringe_1.container.register(tokens_js_1.DI.Runtime.ShutdownEvents, { useValue: new in_memory_shutdown_events_js_1.InMemoryShutdownEvents() });
|
|
106
|
-
const terminator = mode.kind === 'test' ? new throwing_process_terminator_js_1.ThrowingProcessTerminator() : new node_process_terminator_js_1.NodeProcessTerminator();
|
|
107
|
+
const terminator = (mode.kind === 'test' || mode.kind === 'library') ? new throwing_process_terminator_js_1.ThrowingProcessTerminator() : new node_process_terminator_js_1.NodeProcessTerminator();
|
|
107
108
|
tsyringe_1.container.register(tokens_js_1.DI.Runtime.ProcessTerminator, { useValue: terminator });
|
|
108
109
|
}
|
|
109
110
|
async function registerStorageChain() {
|
|
@@ -221,6 +222,7 @@ async function registerV2Services() {
|
|
|
221
222
|
}),
|
|
222
223
|
});
|
|
223
224
|
const { LocalKeyringV2 } = await Promise.resolve().then(() => __importStar(require('../v2/infra/local/keyring/index.js')));
|
|
225
|
+
const { LocalTokenAliasStoreV2 } = await Promise.resolve().then(() => __importStar(require('../v2/infra/local/token-alias-store/index.js')));
|
|
224
226
|
const { LocalSessionEventLogStoreV2 } = await Promise.resolve().then(() => __importStar(require('../v2/infra/local/session-store/index.js')));
|
|
225
227
|
const { LocalSnapshotStoreV2 } = await Promise.resolve().then(() => __importStar(require('../v2/infra/local/snapshot-store/index.js')));
|
|
226
228
|
const { LocalPinnedWorkflowStoreV2 } = await Promise.resolve().then(() => __importStar(require('../v2/infra/local/pinned-workflow-store/index.js')));
|
|
@@ -234,6 +236,13 @@ async function registerV2Services() {
|
|
|
234
236
|
return new LocalKeyringV2(dataDir, fs, base64url, entropy);
|
|
235
237
|
}),
|
|
236
238
|
});
|
|
239
|
+
tsyringe_1.container.register(tokens_js_1.DI.V2.TokenAliasStore, {
|
|
240
|
+
useFactory: (0, tsyringe_1.instanceCachingFactory)((c) => {
|
|
241
|
+
const dataDir = c.resolve(tokens_js_1.DI.V2.DataDir);
|
|
242
|
+
const fs = c.resolve(tokens_js_1.DI.V2.FileSystem);
|
|
243
|
+
return new LocalTokenAliasStoreV2(dataDir, fs);
|
|
244
|
+
}),
|
|
245
|
+
});
|
|
237
246
|
tsyringe_1.container.register(tokens_js_1.DI.V2.SessionStore, {
|
|
238
247
|
useFactory: (0, tsyringe_1.instanceCachingFactory)((c) => {
|
|
239
248
|
const dataDir = c.resolve(tokens_js_1.DI.V2.DataDir);
|
package/dist/di/tokens.d.ts
CHANGED
package/dist/di/tokens.js
CHANGED
|
@@ -41,6 +41,7 @@ exports.DI = {
|
|
|
41
41
|
SnapshotStore: Symbol('V2.SnapshotStore'),
|
|
42
42
|
PinnedWorkflowStore: Symbol('V2.PinnedWorkflowStore'),
|
|
43
43
|
SessionLock: Symbol('V2.SessionLock'),
|
|
44
|
+
TokenAliasStore: Symbol('V2.TokenAliasStore'),
|
|
44
45
|
ExecutionGate: Symbol('V2.ExecutionGate'),
|
|
45
46
|
},
|
|
46
47
|
Runtime: {
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createWorkRailEngine = createWorkRailEngine;
|
|
4
|
+
require("reflect-metadata");
|
|
5
|
+
const container_js_1 = require("../di/container.js");
|
|
6
|
+
const tokens_js_1 = require("../di/tokens.js");
|
|
7
|
+
const token_codec_ports_js_1 = require("../v2/durable-core/tokens/token-codec-ports.js");
|
|
8
|
+
const validation_js_1 = require("../application/validation.js");
|
|
9
|
+
const v1_to_v2_shim_js_1 = require("../v2/read-only/v1-to-v2-shim.js");
|
|
10
|
+
const feature_flags_js_1 = require("../config/feature-flags.js");
|
|
11
|
+
const index_js_1 = require("../v2/infra/local/data-dir/index.js");
|
|
12
|
+
const start_js_1 = require("../mcp/handlers/v2-execution/start.js");
|
|
13
|
+
const index_js_2 = require("../mcp/handlers/v2-execution/index.js");
|
|
14
|
+
const v2_checkpoint_js_1 = require("../mcp/handlers/v2-checkpoint.js");
|
|
15
|
+
const types_js_1 = require("./types.js");
|
|
16
|
+
async function safeAsync(fn) {
|
|
17
|
+
try {
|
|
18
|
+
return (0, types_js_1.engineOk)(await fn());
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
return (0, types_js_1.engineErr)({
|
|
22
|
+
kind: 'storage_error',
|
|
23
|
+
message: e instanceof Error ? e.message : String(e),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function mapStartError(e) {
|
|
28
|
+
switch (e.kind) {
|
|
29
|
+
case 'workflow_not_found':
|
|
30
|
+
return { kind: 'workflow_not_found', workflowId: e.workflowId };
|
|
31
|
+
case 'workflow_has_no_steps':
|
|
32
|
+
return { kind: 'workflow_has_no_steps', workflowId: e.workflowId };
|
|
33
|
+
case 'workflow_compile_failed':
|
|
34
|
+
return { kind: 'workflow_compile_failed', message: e.message };
|
|
35
|
+
case 'token_signing_failed':
|
|
36
|
+
return { kind: 'token_signing_failed', message: String(e.cause) };
|
|
37
|
+
case 'prompt_render_failed':
|
|
38
|
+
return { kind: 'prompt_render_failed', message: e.message };
|
|
39
|
+
case 'precondition_failed':
|
|
40
|
+
return { kind: 'precondition_failed', message: e.message };
|
|
41
|
+
case 'invariant_violation':
|
|
42
|
+
return { kind: 'internal_error', message: e.message };
|
|
43
|
+
case 'validation_failed':
|
|
44
|
+
return { kind: 'validation_failed', message: e.failure.message };
|
|
45
|
+
case 'keyring_load_failed':
|
|
46
|
+
return { kind: 'internal_error', message: e.cause.message, code: e.cause.code };
|
|
47
|
+
case 'hash_computation_failed':
|
|
48
|
+
return { kind: 'internal_error', message: e.message };
|
|
49
|
+
case 'pinned_workflow_store_failed':
|
|
50
|
+
return { kind: 'storage_error', message: e.cause.message, code: e.cause.code };
|
|
51
|
+
case 'snapshot_creation_failed':
|
|
52
|
+
return { kind: 'storage_error', message: e.cause.message, code: e.cause.code };
|
|
53
|
+
case 'session_append_failed':
|
|
54
|
+
return { kind: 'session_error', message: e.cause.message, code: e.cause.code };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function mapContinueError(e) {
|
|
58
|
+
switch (e.kind) {
|
|
59
|
+
case 'precondition_failed':
|
|
60
|
+
return { kind: 'precondition_failed', message: e.message };
|
|
61
|
+
case 'token_unknown_node':
|
|
62
|
+
return { kind: 'token_invalid', message: e.message };
|
|
63
|
+
case 'invariant_violation':
|
|
64
|
+
return { kind: 'internal_error', message: e.message };
|
|
65
|
+
case 'validation_failed':
|
|
66
|
+
return { kind: 'validation_failed', message: e.failure.message };
|
|
67
|
+
case 'token_decode_failed':
|
|
68
|
+
return { kind: 'token_invalid', message: e.cause.message, code: e.cause.code };
|
|
69
|
+
case 'token_verify_failed':
|
|
70
|
+
return { kind: 'token_invalid', message: e.cause.message, code: e.cause.code };
|
|
71
|
+
case 'keyring_load_failed':
|
|
72
|
+
return { kind: 'internal_error', message: e.cause.message, code: e.cause.code };
|
|
73
|
+
case 'session_load_failed':
|
|
74
|
+
return { kind: 'session_error', message: e.cause.message, code: e.cause.code };
|
|
75
|
+
case 'snapshot_load_failed':
|
|
76
|
+
return { kind: 'storage_error', message: e.cause.message, code: e.cause.code };
|
|
77
|
+
case 'pinned_workflow_store_failed':
|
|
78
|
+
return { kind: 'storage_error', message: e.cause.message, code: e.cause.code };
|
|
79
|
+
case 'pinned_workflow_missing':
|
|
80
|
+
return { kind: 'storage_error', message: `Pinned workflow missing: ${e.workflowHash}` };
|
|
81
|
+
case 'token_signing_failed':
|
|
82
|
+
return { kind: 'token_signing_failed', message: String(e.cause) };
|
|
83
|
+
case 'advance_execution_failed':
|
|
84
|
+
return { kind: 'session_error', message: e.cause.message, code: e.cause.code };
|
|
85
|
+
case 'prompt_render_failed':
|
|
86
|
+
return { kind: 'prompt_render_failed', message: e.message };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function mapCheckpointError(e) {
|
|
90
|
+
switch (e.kind) {
|
|
91
|
+
case 'precondition_failed':
|
|
92
|
+
return { kind: 'precondition_failed', message: e.message };
|
|
93
|
+
case 'token_signing_failed':
|
|
94
|
+
return { kind: 'token_signing_failed', message: String(e.cause) };
|
|
95
|
+
case 'validation_failed':
|
|
96
|
+
return { kind: 'validation_failed', message: e.failure.message };
|
|
97
|
+
case 'missing_node_or_run':
|
|
98
|
+
return { kind: 'session_error', message: 'Node or run not found in session events' };
|
|
99
|
+
case 'event_schema_invalid':
|
|
100
|
+
return { kind: 'internal_error', message: `Event schema invalid: ${e.issues}` };
|
|
101
|
+
case 'gate_failed':
|
|
102
|
+
return { kind: 'session_error', message: e.cause.message, code: e.cause.code };
|
|
103
|
+
case 'store_failed':
|
|
104
|
+
return { kind: 'storage_error', message: e.cause.message, code: e.cause.code };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function mapPending(raw) {
|
|
108
|
+
if (!raw)
|
|
109
|
+
return null;
|
|
110
|
+
return {
|
|
111
|
+
stepId: raw.stepId,
|
|
112
|
+
title: raw.title,
|
|
113
|
+
prompt: raw.prompt,
|
|
114
|
+
...(raw.agentRole ? { agentRole: raw.agentRole } : {}),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function mapStartOutput(out) {
|
|
118
|
+
const ct = out.continueToken ?? '';
|
|
119
|
+
return {
|
|
120
|
+
kind: 'ok',
|
|
121
|
+
stateToken: (0, types_js_1.asStateToken)(ct),
|
|
122
|
+
ackToken: (0, types_js_1.asAckToken)(ct),
|
|
123
|
+
checkpointToken: out.checkpointToken ? (0, types_js_1.asCheckpointToken)(out.checkpointToken) : null,
|
|
124
|
+
isComplete: out.isComplete,
|
|
125
|
+
pending: mapPending(out.pending),
|
|
126
|
+
preferences: out.preferences,
|
|
127
|
+
nextIntent: out.nextIntent,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function mapContinueOutput(out) {
|
|
131
|
+
const ct = out.continueToken ?? '';
|
|
132
|
+
const base = {
|
|
133
|
+
stateToken: (0, types_js_1.asStateToken)(ct),
|
|
134
|
+
ackToken: (0, types_js_1.asAckToken)(ct),
|
|
135
|
+
checkpointToken: out.checkpointToken ? (0, types_js_1.asCheckpointToken)(out.checkpointToken) : null,
|
|
136
|
+
isComplete: out.isComplete,
|
|
137
|
+
pending: mapPending(out.pending),
|
|
138
|
+
preferences: out.preferences,
|
|
139
|
+
nextIntent: out.nextIntent,
|
|
140
|
+
};
|
|
141
|
+
if (out.kind === 'blocked') {
|
|
142
|
+
const blocked = {
|
|
143
|
+
kind: 'blocked',
|
|
144
|
+
...base,
|
|
145
|
+
blockers: out.blockers.blockers.map(b => ({
|
|
146
|
+
code: b.code,
|
|
147
|
+
message: b.message,
|
|
148
|
+
...(b.suggestedFix ? { suggestedFix: b.suggestedFix } : {}),
|
|
149
|
+
})),
|
|
150
|
+
retryable: out.retryable ?? false,
|
|
151
|
+
retryAckToken: out.retryContinueToken ? (0, types_js_1.asAckToken)(out.retryContinueToken) : null,
|
|
152
|
+
};
|
|
153
|
+
return blocked;
|
|
154
|
+
}
|
|
155
|
+
return { kind: 'ok', ...base };
|
|
156
|
+
}
|
|
157
|
+
let engineActive = false;
|
|
158
|
+
async function createWorkRailEngine(config = {}) {
|
|
159
|
+
if (engineActive) {
|
|
160
|
+
return (0, types_js_1.engineErr)({
|
|
161
|
+
kind: 'precondition_failed',
|
|
162
|
+
message: 'An engine is already active. Call engine.close() before creating another instance.',
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
await (0, container_js_1.initializeContainer)({ runtimeMode: { kind: 'library' } });
|
|
166
|
+
if (config.dataDir) {
|
|
167
|
+
const customEnv = { ...process.env, WORKRAIL_DATA_DIR: config.dataDir };
|
|
168
|
+
container_js_1.container.register(tokens_js_1.DI.V2.DataDir, { useValue: new index_js_1.LocalDataDirV2(customEnv) });
|
|
169
|
+
}
|
|
170
|
+
const workflowService = container_js_1.container.resolve(tokens_js_1.DI.Services.Workflow);
|
|
171
|
+
const gate = container_js_1.container.resolve(tokens_js_1.DI.V2.ExecutionGate);
|
|
172
|
+
const sessionStore = container_js_1.container.resolve(tokens_js_1.DI.V2.SessionStore);
|
|
173
|
+
const snapshotStore = container_js_1.container.resolve(tokens_js_1.DI.V2.SnapshotStore);
|
|
174
|
+
const pinnedStore = container_js_1.container.resolve(tokens_js_1.DI.V2.PinnedWorkflowStore);
|
|
175
|
+
const keyringPort = container_js_1.container.resolve(tokens_js_1.DI.V2.Keyring);
|
|
176
|
+
const keyringResult = await keyringPort.loadOrCreate();
|
|
177
|
+
if (keyringResult.isErr()) {
|
|
178
|
+
(0, container_js_1.resetContainer)();
|
|
179
|
+
return (0, types_js_1.engineErr)({
|
|
180
|
+
kind: 'internal_error',
|
|
181
|
+
message: keyringResult.error.message,
|
|
182
|
+
code: keyringResult.error.code,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
const sha256 = container_js_1.container.resolve(tokens_js_1.DI.V2.Sha256);
|
|
186
|
+
const crypto = container_js_1.container.resolve(tokens_js_1.DI.V2.Crypto);
|
|
187
|
+
const entropy = container_js_1.container.resolve(tokens_js_1.DI.V2.RandomEntropy);
|
|
188
|
+
const hmac = container_js_1.container.resolve(tokens_js_1.DI.V2.HmacSha256);
|
|
189
|
+
const base64url = container_js_1.container.resolve(tokens_js_1.DI.V2.Base64Url);
|
|
190
|
+
const base32 = container_js_1.container.resolve(tokens_js_1.DI.V2.Base32);
|
|
191
|
+
const bech32m = container_js_1.container.resolve(tokens_js_1.DI.V2.Bech32m);
|
|
192
|
+
const idFactory = container_js_1.container.resolve(tokens_js_1.DI.V2.IdFactory);
|
|
193
|
+
const tokenCodecPorts = (0, token_codec_ports_js_1.unsafeTokenCodecPorts)({
|
|
194
|
+
keyring: keyringResult.value,
|
|
195
|
+
hmac,
|
|
196
|
+
base64url,
|
|
197
|
+
base32,
|
|
198
|
+
bech32m,
|
|
199
|
+
});
|
|
200
|
+
const validationEngine = container_js_1.container.resolve(tokens_js_1.DI.Infra.ValidationEngine);
|
|
201
|
+
const compiler = container_js_1.container.resolve(tokens_js_1.DI.Services.WorkflowCompiler);
|
|
202
|
+
const validationPipelineDeps = {
|
|
203
|
+
schemaValidate: validation_js_1.validateWorkflowSchema,
|
|
204
|
+
structuralValidate: validationEngine.validateWorkflowStructureOnly.bind(validationEngine),
|
|
205
|
+
compiler,
|
|
206
|
+
normalizeToExecutable: v1_to_v2_shim_js_1.normalizeV1WorkflowToPinnedSnapshot,
|
|
207
|
+
};
|
|
208
|
+
const dataDir = container_js_1.container.resolve(tokens_js_1.DI.V2.DataDir);
|
|
209
|
+
const tokenAliasStore = container_js_1.container.resolve(tokens_js_1.DI.V2.TokenAliasStore);
|
|
210
|
+
const aliasLoadResult = await tokenAliasStore.loadIndex();
|
|
211
|
+
if (aliasLoadResult.isErr()) {
|
|
212
|
+
console.error(`[engine-factory] Token alias index load warning: ${aliasLoadResult.error.message}`);
|
|
213
|
+
}
|
|
214
|
+
const v2 = {
|
|
215
|
+
gate,
|
|
216
|
+
sessionStore,
|
|
217
|
+
snapshotStore,
|
|
218
|
+
pinnedStore,
|
|
219
|
+
sha256,
|
|
220
|
+
crypto,
|
|
221
|
+
entropy,
|
|
222
|
+
idFactory,
|
|
223
|
+
tokenCodecPorts,
|
|
224
|
+
tokenAliasStore,
|
|
225
|
+
validationPipelineDeps,
|
|
226
|
+
resolvedRootUris: [],
|
|
227
|
+
dataDir,
|
|
228
|
+
};
|
|
229
|
+
const featureFlags = new feature_flags_js_1.StaticFeatureFlagProvider({ v2Tools: true });
|
|
230
|
+
const ctx = {
|
|
231
|
+
workflowService,
|
|
232
|
+
featureFlags,
|
|
233
|
+
sessionManager: null,
|
|
234
|
+
httpServer: null,
|
|
235
|
+
v2,
|
|
236
|
+
};
|
|
237
|
+
const v2Ctx = ctx;
|
|
238
|
+
engineActive = true;
|
|
239
|
+
const engine = {
|
|
240
|
+
async startWorkflow(workflowId) {
|
|
241
|
+
const result = await (0, start_js_1.executeStartWorkflow)({ workflowId }, v2Ctx);
|
|
242
|
+
if (result.isErr()) {
|
|
243
|
+
return (0, types_js_1.engineErr)(mapStartError(result.error));
|
|
244
|
+
}
|
|
245
|
+
return (0, types_js_1.engineOk)(mapStartOutput(result.value));
|
|
246
|
+
},
|
|
247
|
+
async continueWorkflow(stateToken, ackToken, output, context) {
|
|
248
|
+
const intent = ackToken ? 'advance' : 'rehydrate';
|
|
249
|
+
const input = {
|
|
250
|
+
continueToken: (0, types_js_1.unwrapToken)(stateToken),
|
|
251
|
+
intent: intent,
|
|
252
|
+
...(output ? {
|
|
253
|
+
output: {
|
|
254
|
+
notesMarkdown: output.notesMarkdown,
|
|
255
|
+
...(output.artifacts?.length ? { artifacts: [...output.artifacts] } : {}),
|
|
256
|
+
},
|
|
257
|
+
} : {}),
|
|
258
|
+
...(context ? { context } : {}),
|
|
259
|
+
};
|
|
260
|
+
const result = await (0, index_js_2.executeContinueWorkflow)(input, v2Ctx);
|
|
261
|
+
if (result.isErr()) {
|
|
262
|
+
return (0, types_js_1.engineErr)(mapContinueError(result.error));
|
|
263
|
+
}
|
|
264
|
+
return (0, types_js_1.engineOk)(mapContinueOutput(result.value));
|
|
265
|
+
},
|
|
266
|
+
async checkpointWorkflow(checkpointToken) {
|
|
267
|
+
const result = await (0, v2_checkpoint_js_1.executeCheckpoint)({ checkpointToken: (0, types_js_1.unwrapToken)(checkpointToken) }, v2Ctx);
|
|
268
|
+
if (result.isErr()) {
|
|
269
|
+
return (0, types_js_1.engineErr)(mapCheckpointError(result.error));
|
|
270
|
+
}
|
|
271
|
+
return (0, types_js_1.engineOk)({
|
|
272
|
+
checkpointNodeId: result.value.checkpointNodeId,
|
|
273
|
+
stateToken: (0, types_js_1.asStateToken)(result.value.stateToken),
|
|
274
|
+
});
|
|
275
|
+
},
|
|
276
|
+
async listWorkflows() {
|
|
277
|
+
const result = await safeAsync(() => workflowService.listWorkflowSummaries());
|
|
278
|
+
if (!result.ok)
|
|
279
|
+
return result;
|
|
280
|
+
return (0, types_js_1.engineOk)({
|
|
281
|
+
workflows: result.value.map((s) => ({
|
|
282
|
+
workflowId: s.id,
|
|
283
|
+
name: s.name,
|
|
284
|
+
description: s.description,
|
|
285
|
+
version: s.version,
|
|
286
|
+
})),
|
|
287
|
+
});
|
|
288
|
+
},
|
|
289
|
+
async close() {
|
|
290
|
+
(0, container_js_1.resetContainer)();
|
|
291
|
+
engineActive = false;
|
|
292
|
+
},
|
|
293
|
+
};
|
|
294
|
+
return (0, types_js_1.engineOk)(engine);
|
|
295
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { createWorkRailEngine } from './engine-factory.js';
|
|
2
|
+
export type { WorkRailEngine, EngineConfig, EngineResult, EngineError, InfraErrorCode, StepResponse, StepResponseOk, StepResponseBlocked, CheckpointResponse, WorkflowListResponse, WorkflowListItem, PendingStep, StepPreferences, Autonomy, RiskPolicy, NextIntent, Blocker, BlockerCode, StateToken, AckToken, CheckpointToken, } from './types.js';
|
|
3
|
+
export { engineOk, engineErr, asStateToken, asAckToken, asCheckpointToken, unwrapToken } from './types.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.unwrapToken = exports.asCheckpointToken = exports.asAckToken = exports.asStateToken = exports.engineErr = exports.engineOk = exports.createWorkRailEngine = void 0;
|
|
4
|
+
var engine_factory_js_1 = require("./engine-factory.js");
|
|
5
|
+
Object.defineProperty(exports, "createWorkRailEngine", { enumerable: true, get: function () { return engine_factory_js_1.createWorkRailEngine; } });
|
|
6
|
+
var types_js_1 = require("./types.js");
|
|
7
|
+
Object.defineProperty(exports, "engineOk", { enumerable: true, get: function () { return types_js_1.engineOk; } });
|
|
8
|
+
Object.defineProperty(exports, "engineErr", { enumerable: true, get: function () { return types_js_1.engineErr; } });
|
|
9
|
+
Object.defineProperty(exports, "asStateToken", { enumerable: true, get: function () { return types_js_1.asStateToken; } });
|
|
10
|
+
Object.defineProperty(exports, "asAckToken", { enumerable: true, get: function () { return types_js_1.asAckToken; } });
|
|
11
|
+
Object.defineProperty(exports, "asCheckpointToken", { enumerable: true, get: function () { return types_js_1.asCheckpointToken; } });
|
|
12
|
+
Object.defineProperty(exports, "unwrapToken", { enumerable: true, get: function () { return types_js_1.unwrapToken; } });
|