@exaudeus/workrail 1.8.0 → 1.10.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.
@@ -0,0 +1,19 @@
1
+ import type { Result } from 'neverthrow';
2
+ import type { PromptValue } from './prompt-blocks.js';
3
+ export interface FeatureDefinition {
4
+ readonly id: string;
5
+ readonly constraints?: readonly PromptValue[];
6
+ readonly procedure?: readonly PromptValue[];
7
+ readonly verify?: readonly PromptValue[];
8
+ }
9
+ export type FeatureResolveError = {
10
+ readonly code: 'UNKNOWN_FEATURE';
11
+ readonly featureId: string;
12
+ readonly message: string;
13
+ };
14
+ export interface FeatureRegistry {
15
+ readonly resolve: (featureId: string) => Result<FeatureDefinition, FeatureResolveError>;
16
+ readonly has: (featureId: string) => boolean;
17
+ readonly knownIds: () => readonly string[];
18
+ }
19
+ export declare function createFeatureRegistry(): FeatureRegistry;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createFeatureRegistry = createFeatureRegistry;
4
+ const neverthrow_1 = require("neverthrow");
5
+ const FEATURE_DEFINITIONS = [
6
+ {
7
+ id: 'wr.features.memory_context',
8
+ constraints: [
9
+ [
10
+ { kind: 'ref', refId: 'wr.refs.memory_usage' },
11
+ ],
12
+ ],
13
+ },
14
+ ];
15
+ function createFeatureRegistry() {
16
+ const byId = new Map(FEATURE_DEFINITIONS.map(f => [f.id, f]));
17
+ const knownIds = FEATURE_DEFINITIONS.map(f => f.id);
18
+ return {
19
+ resolve(featureId) {
20
+ const def = byId.get(featureId);
21
+ if (!def) {
22
+ return (0, neverthrow_1.err)({
23
+ code: 'UNKNOWN_FEATURE',
24
+ featureId,
25
+ message: `Unknown feature '${featureId}'. Known features: ${knownIds.join(', ')}`,
26
+ });
27
+ }
28
+ return (0, neverthrow_1.ok)(def);
29
+ },
30
+ has(featureId) {
31
+ return byId.has(featureId);
32
+ },
33
+ knownIds() {
34
+ return knownIds;
35
+ },
36
+ };
37
+ }
@@ -0,0 +1,12 @@
1
+ import type { Result } from 'neverthrow';
2
+ export type RefResolveError = {
3
+ readonly code: 'UNKNOWN_REF';
4
+ readonly refId: string;
5
+ readonly message: string;
6
+ };
7
+ export interface RefRegistry {
8
+ readonly resolve: (refId: string) => Result<string, RefResolveError>;
9
+ readonly has: (refId: string) => boolean;
10
+ readonly knownIds: () => readonly string[];
11
+ }
12
+ export declare function createRefRegistry(): RefRegistry;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createRefRegistry = createRefRegistry;
4
+ const neverthrow_1 = require("neverthrow");
5
+ const REF_CONTENT = {
6
+ 'wr.refs.memory_usage': [
7
+ 'If Memory MCP tools are available (memory_briefing, memory_store, memory_query):',
8
+ '- Query Memory for relevant prior knowledge about this workspace before beginning work',
9
+ '- After completing significant work, store key discoveries and decisions',
10
+ '- Use descriptive topics and titles so future sessions can find them',
11
+ '- Do not block on Memory failures — it is advisory, not load-bearing',
12
+ ].join('\n'),
13
+ 'wr.refs.memory_store': [
14
+ 'If Memory MCP tools are available (memory_store):',
15
+ '- Store the key findings from this phase with a descriptive topic and title',
16
+ '- Include file paths, decisions made, and rationale',
17
+ '- Do not block on Memory failures — continue regardless',
18
+ ].join('\n'),
19
+ 'wr.refs.memory_query': [
20
+ 'If Memory MCP tools are available (memory_briefing, memory_query):',
21
+ '- Check Memory for prior context relevant to this task',
22
+ '- Use workspace-scoped queries to find related past work',
23
+ '- Do not block on Memory failures — proceed without prior context if unavailable',
24
+ ].join('\n'),
25
+ };
26
+ function createRefRegistry() {
27
+ const knownIds = Object.keys(REF_CONTENT);
28
+ return {
29
+ resolve(refId) {
30
+ const content = REF_CONTENT[refId];
31
+ if (content === undefined) {
32
+ return (0, neverthrow_1.err)({
33
+ code: 'UNKNOWN_REF',
34
+ refId,
35
+ message: `Unknown ref '${refId}'. Known refs: ${knownIds.join(', ')}`,
36
+ });
37
+ }
38
+ return (0, neverthrow_1.ok)(content);
39
+ },
40
+ has(refId) {
41
+ return refId in REF_CONTENT;
42
+ },
43
+ knownIds() {
44
+ return knownIds;
45
+ },
46
+ };
47
+ }
@@ -0,0 +1,12 @@
1
+ import type { Result } from 'neverthrow';
2
+ import type { FeatureRegistry, FeatureResolveError } from './feature-registry.js';
3
+ import type { WorkflowStepDefinition, LoopStepDefinition } from '../../../types/workflow-definition.js';
4
+ export type ResolveFeaturesPassError = {
5
+ readonly code: 'FEATURE_RESOLVE_ERROR';
6
+ readonly cause: FeatureResolveError;
7
+ } | {
8
+ readonly code: 'FEATURE_ON_RAW_PROMPT_STEP';
9
+ readonly stepId: string;
10
+ readonly message: string;
11
+ };
12
+ export declare function resolveFeaturesPass(steps: readonly (WorkflowStepDefinition | LoopStepDefinition)[], featureIds: readonly string[], registry: FeatureRegistry): Result<readonly (WorkflowStepDefinition | LoopStepDefinition)[], ResolveFeaturesPassError>;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveFeaturesPass = resolveFeaturesPass;
4
+ const neverthrow_1 = require("neverthrow");
5
+ const workflow_definition_js_1 = require("../../../types/workflow-definition.js");
6
+ function appendValues(existing, injected) {
7
+ if (!injected || injected.length === 0)
8
+ return existing;
9
+ if (!existing || existing.length === 0)
10
+ return injected;
11
+ return [...existing, ...injected];
12
+ }
13
+ function applyFeatureToBlocks(blocks, feature) {
14
+ return {
15
+ ...blocks,
16
+ constraints: appendValues(blocks.constraints, feature.constraints),
17
+ procedure: appendValues(blocks.procedure, feature.procedure),
18
+ verify: appendValues(blocks.verify, feature.verify),
19
+ };
20
+ }
21
+ function applyFeaturesToStep(step, features) {
22
+ if (!step.promptBlocks || features.length === 0)
23
+ return step;
24
+ let blocks = step.promptBlocks;
25
+ for (const feature of features) {
26
+ blocks = applyFeatureToBlocks(blocks, feature);
27
+ }
28
+ return { ...step, promptBlocks: blocks };
29
+ }
30
+ function resolveFeaturesPass(steps, featureIds, registry) {
31
+ if (featureIds.length === 0)
32
+ return (0, neverthrow_1.ok)(steps);
33
+ const features = [];
34
+ for (const id of featureIds) {
35
+ const res = registry.resolve(id);
36
+ if (res.isErr()) {
37
+ return (0, neverthrow_1.err)({ code: 'FEATURE_RESOLVE_ERROR', cause: res.error });
38
+ }
39
+ features.push(res.value);
40
+ }
41
+ const resolved = [];
42
+ for (const step of steps) {
43
+ if ((0, workflow_definition_js_1.isLoopStepDefinition)(step)) {
44
+ const resolvedLoop = applyFeaturesToStep(step, features);
45
+ if (Array.isArray(step.body)) {
46
+ const bodyResolved = step.body.map(bodyStep => applyFeaturesToStep(bodyStep, features));
47
+ resolved.push({
48
+ ...step,
49
+ ...(resolvedLoop.promptBlocks ? { promptBlocks: resolvedLoop.promptBlocks } : {}),
50
+ body: bodyResolved,
51
+ });
52
+ }
53
+ else {
54
+ resolved.push({
55
+ ...step,
56
+ ...(resolvedLoop.promptBlocks ? { promptBlocks: resolvedLoop.promptBlocks } : {}),
57
+ });
58
+ }
59
+ }
60
+ else {
61
+ resolved.push(applyFeaturesToStep(step, features));
62
+ }
63
+ }
64
+ return (0, neverthrow_1.ok)(resolved);
65
+ }
@@ -0,0 +1,9 @@
1
+ import type { Result } from 'neverthrow';
2
+ import type { RefRegistry, RefResolveError } from './ref-registry.js';
3
+ import type { WorkflowStepDefinition, LoopStepDefinition } from '../../../types/workflow-definition.js';
4
+ export type ResolveRefsPassError = {
5
+ readonly code: 'REF_RESOLVE_ERROR';
6
+ readonly stepId: string;
7
+ readonly cause: RefResolveError;
8
+ };
9
+ export declare function resolveRefsPass(steps: readonly (WorkflowStepDefinition | LoopStepDefinition)[], registry: RefRegistry): Result<readonly (WorkflowStepDefinition | LoopStepDefinition)[], ResolveRefsPassError>;
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveRefsPass = resolveRefsPass;
4
+ const neverthrow_1 = require("neverthrow");
5
+ const workflow_definition_js_1 = require("../../../types/workflow-definition.js");
6
+ function resolvePromptValueRefs(value, registry) {
7
+ if (typeof value === 'string')
8
+ return (0, neverthrow_1.ok)(value);
9
+ const resolved = [];
10
+ for (const part of value) {
11
+ switch (part.kind) {
12
+ case 'text':
13
+ resolved.push(part);
14
+ break;
15
+ case 'ref': {
16
+ const res = registry.resolve(part.refId);
17
+ if (res.isErr())
18
+ return (0, neverthrow_1.err)(res.error);
19
+ resolved.push({ kind: 'text', text: res.value });
20
+ break;
21
+ }
22
+ }
23
+ }
24
+ return (0, neverthrow_1.ok)(resolved);
25
+ }
26
+ function resolvePromptValuesRefs(values, registry) {
27
+ const resolved = [];
28
+ for (const value of values) {
29
+ const res = resolvePromptValueRefs(value, registry);
30
+ if (res.isErr())
31
+ return (0, neverthrow_1.err)(res.error);
32
+ resolved.push(res.value);
33
+ }
34
+ return (0, neverthrow_1.ok)(resolved);
35
+ }
36
+ function resolveBlockRefs(blocks, registry) {
37
+ let result = { ...blocks };
38
+ if (blocks.goal !== undefined) {
39
+ const res = resolvePromptValueRefs(blocks.goal, registry);
40
+ if (res.isErr())
41
+ return (0, neverthrow_1.err)(res.error);
42
+ result = { ...result, goal: res.value };
43
+ }
44
+ if (blocks.constraints !== undefined) {
45
+ const res = resolvePromptValuesRefs(blocks.constraints, registry);
46
+ if (res.isErr())
47
+ return (0, neverthrow_1.err)(res.error);
48
+ result = { ...result, constraints: res.value };
49
+ }
50
+ if (blocks.procedure !== undefined) {
51
+ const res = resolvePromptValuesRefs(blocks.procedure, registry);
52
+ if (res.isErr())
53
+ return (0, neverthrow_1.err)(res.error);
54
+ result = { ...result, procedure: res.value };
55
+ }
56
+ if (blocks.verify !== undefined) {
57
+ const res = resolvePromptValuesRefs(blocks.verify, registry);
58
+ if (res.isErr())
59
+ return (0, neverthrow_1.err)(res.error);
60
+ result = { ...result, verify: res.value };
61
+ }
62
+ return (0, neverthrow_1.ok)(result);
63
+ }
64
+ function resolveStepRefs(step, registry) {
65
+ if (!step.promptBlocks)
66
+ return (0, neverthrow_1.ok)(step);
67
+ const res = resolveBlockRefs(step.promptBlocks, registry);
68
+ if (res.isErr()) {
69
+ return (0, neverthrow_1.err)({
70
+ code: 'REF_RESOLVE_ERROR',
71
+ stepId: step.id,
72
+ cause: res.error,
73
+ });
74
+ }
75
+ return (0, neverthrow_1.ok)({ ...step, promptBlocks: res.value });
76
+ }
77
+ function resolveRefsPass(steps, registry) {
78
+ const resolved = [];
79
+ for (const step of steps) {
80
+ if ((0, workflow_definition_js_1.isLoopStepDefinition)(step)) {
81
+ const loopRes = resolveStepRefs(step, registry);
82
+ if (loopRes.isErr())
83
+ return (0, neverthrow_1.err)(loopRes.error);
84
+ if (Array.isArray(step.body)) {
85
+ const bodyResolved = [];
86
+ for (const bodyStep of step.body) {
87
+ const bodyRes = resolveStepRefs(bodyStep, registry);
88
+ if (bodyRes.isErr())
89
+ return (0, neverthrow_1.err)(bodyRes.error);
90
+ bodyResolved.push(bodyRes.value);
91
+ }
92
+ resolved.push({
93
+ ...step,
94
+ ...(loopRes.value.promptBlocks ? { promptBlocks: loopRes.value.promptBlocks } : {}),
95
+ body: bodyResolved,
96
+ });
97
+ }
98
+ else {
99
+ resolved.push({
100
+ ...step,
101
+ ...(loopRes.value.promptBlocks ? { promptBlocks: loopRes.value.promptBlocks } : {}),
102
+ });
103
+ }
104
+ }
105
+ else {
106
+ const res = resolveStepRefs(step, registry);
107
+ if (res.isErr())
108
+ return (0, neverthrow_1.err)(res.error);
109
+ resolved.push(res.value);
110
+ }
111
+ }
112
+ return (0, neverthrow_1.ok)(resolved);
113
+ }
@@ -15,6 +15,8 @@ export interface CompiledWorkflow {
15
15
  readonly loopBodyStepIds: ReadonlySet<string>;
16
16
  }
17
17
  export declare class WorkflowCompiler {
18
+ private readonly refRegistry;
19
+ private readonly featureRegistry;
18
20
  compile(workflow: Workflow): Result<CompiledWorkflow, DomainError>;
19
21
  private deriveConditionSource;
20
22
  private resolveLoopBody;
@@ -13,9 +13,30 @@ const index_1 = require("../../v2/durable-core/schemas/artifacts/index");
13
13
  const neverthrow_1 = require("neverthrow");
14
14
  const error_1 = require("../../domain/execution/error");
15
15
  const prompt_blocks_1 = require("./compiler/prompt-blocks");
16
+ const resolve_refs_1 = require("./compiler/resolve-refs");
17
+ const ref_registry_1 = require("./compiler/ref-registry");
18
+ const resolve_features_1 = require("./compiler/resolve-features");
19
+ const feature_registry_1 = require("./compiler/feature-registry");
16
20
  let WorkflowCompiler = class WorkflowCompiler {
21
+ constructor() {
22
+ this.refRegistry = (0, ref_registry_1.createRefRegistry)();
23
+ this.featureRegistry = (0, feature_registry_1.createFeatureRegistry)();
24
+ }
17
25
  compile(workflow) {
18
- const blocksResult = (0, prompt_blocks_1.resolvePromptBlocksPass)(workflow.definition.steps);
26
+ const featuresResult = (0, resolve_features_1.resolveFeaturesPass)(workflow.definition.steps, workflow.definition.features ?? [], this.featureRegistry);
27
+ if (featuresResult.isErr()) {
28
+ const e = featuresResult.error;
29
+ const message = e.code === 'FEATURE_RESOLVE_ERROR'
30
+ ? `Feature error — ${e.cause.message}`
31
+ : e.message;
32
+ return (0, neverthrow_1.err)(error_1.Err.invalidState(message));
33
+ }
34
+ const refsResult = (0, resolve_refs_1.resolveRefsPass)(featuresResult.value, this.refRegistry);
35
+ if (refsResult.isErr()) {
36
+ const e = refsResult.error;
37
+ return (0, neverthrow_1.err)(error_1.Err.invalidState(`Step '${e.stepId}': ref resolution error — ${e.cause.message}`));
38
+ }
39
+ const blocksResult = (0, prompt_blocks_1.resolvePromptBlocksPass)(refsResult.value);
19
40
  if (blocksResult.isErr()) {
20
41
  const e = blocksResult.error;
21
42
  const message = e.code === 'PROMPT_AND_BLOCKS_BOTH_SET'
@@ -1,6 +1,14 @@
1
1
  {
2
2
  "distDir": "dist",
3
3
  "files": {
4
+ "application/services/compiler/feature-registry.d.ts": {
5
+ "sha256": "0df999218ba4dac5cf3fad34f3291e2b217b662badef01ee20f1258c4d03d13f",
6
+ "bytes": 740
7
+ },
8
+ "application/services/compiler/feature-registry.js": {
9
+ "sha256": "0350c0bd6ab92b1f38f58d12e2d2064af4275b34dfabf7e1677df9eb284d8ba4",
10
+ "bytes": 1124
11
+ },
4
12
  "application/services/compiler/prompt-blocks.d.ts": {
5
13
  "sha256": "2f40fd7599bd351584505152e9916fdea60891833d22c774c8ac9955f01ccf66",
6
14
  "bytes": 1416
@@ -9,6 +17,30 @@
9
17
  "sha256": "8ee0e8f7f23f0b298602b97af71a49eaf4fbdc8e7a2bb588c607c2f36e81ef1a",
10
18
  "bytes": 5201
11
19
  },
20
+ "application/services/compiler/ref-registry.d.ts": {
21
+ "sha256": "b93074634a3a26097b9ed35d72351272c567dff184401a95e9f80ea7ae8724a5",
22
+ "bytes": 428
23
+ },
24
+ "application/services/compiler/ref-registry.js": {
25
+ "sha256": "075b14ab0efd34df85eb9b564362d2415eacffc13f44f1ba54bdc5e8229a7d2e",
26
+ "bytes": 2008
27
+ },
28
+ "application/services/compiler/resolve-features.d.ts": {
29
+ "sha256": "bb5d0719f1156fe5fc92464bc828407b7be1b1149e79e70e71669cf54dce4ddc",
30
+ "bytes": 733
31
+ },
32
+ "application/services/compiler/resolve-features.js": {
33
+ "sha256": "04637806407d1888b8b0d78ee05a92eb08c9bb33f695a3db4ad6373e5666831a",
34
+ "bytes": 2444
35
+ },
36
+ "application/services/compiler/resolve-refs.d.ts": {
37
+ "sha256": "64ed63007495f8b95baeb5f867a6b6ac39f097ad5976803b2642defa80ed31bf",
38
+ "bytes": 581
39
+ },
40
+ "application/services/compiler/resolve-refs.js": {
41
+ "sha256": "9f9e2a44cec6dfd6d870a645b38e4faf52e17c9ef3654fd600ebcd9943f532c5",
42
+ "bytes": 4214
43
+ },
12
44
  "application/services/enhanced-error-service.d.ts": {
13
45
  "sha256": "b6fe8fad92717f0962f87aa9c0f88277bf28fe2b5e3cfd7875612ee57eb8c684",
14
46
  "bytes": 601
@@ -50,12 +82,12 @@
50
82
  "bytes": 31038
51
83
  },
52
84
  "application/services/workflow-compiler.d.ts": {
53
- "sha256": "dc7b1ed75ee4e90f90c35088d5c336a94d782012e5926fd7c939613e483b23fc",
54
- "bytes": 990
85
+ "sha256": "d175afb550035f44e6e86dde5a1cf2a1ba68eeb61d39590e02b355a9f0e19bf3",
86
+ "bytes": 1062
55
87
  },
56
88
  "application/services/workflow-compiler.js": {
57
- "sha256": "e4b8c0966ba04a87d753ca507fdc2ee5082a66e4fb6d539e4782c8ff8e93ef78",
58
- "bytes": 6050
89
+ "sha256": "7517fe0d70974f770dad82ede863477e0f367a63bb1fde84636eb96596c52dca",
90
+ "bytes": 7269
59
91
  },
60
92
  "application/services/workflow-interpreter.d.ts": {
61
93
  "sha256": "56b5b5ad06d42096deba9f0abe7642c18a355a1e598749aab1730df4e9847674",
@@ -1066,8 +1098,8 @@
1066
1098
  "bytes": 395
1067
1099
  },
1068
1100
  "types/workflow-definition.d.ts": {
1069
- "sha256": "cb7d6be7e9aa0d4b7b17323cd167edad2f616b6a8c2149df6c40e4d965e7d9b8",
1070
- "bytes": 3744
1101
+ "sha256": "d8fa099c4f2939f27a7fef55b4c6e40161a9bd0a82e2c6137de0eb8210982e9c",
1102
+ "bytes": 3787
1071
1103
  },
1072
1104
  "types/workflow-definition.js": {
1073
1105
  "sha256": "e269d62f27b7f37f870183d6b77800b7aa1e22dabc894374bab8f34db049a55b",
@@ -79,6 +79,7 @@ export interface WorkflowDefinition {
79
79
  readonly metaGuidance?: readonly string[];
80
80
  readonly functionDefinitions?: readonly FunctionDefinition[];
81
81
  readonly recommendedPreferences?: WorkflowRecommendedPreferences;
82
+ readonly features?: readonly string[];
82
83
  }
83
84
  export declare function isLoopStepDefinition(step: WorkflowStepDefinition | LoopStepDefinition): step is LoopStepDefinition;
84
85
  export declare function isWorkflowStepDefinition(step: WorkflowStepDefinition | LoopStepDefinition): step is WorkflowStepDefinition;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exaudeus/workrail",
3
- "version": "1.8.0",
3
+ "version": "1.10.0",
4
4
  "description": "Step-by-step workflow enforcement for AI agents via MCP",
5
5
  "license": "MIT",
6
6
  "repository": {