@exaudeus/workrail 1.7.4 → 1.8.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,36 @@
1
+ import type { Result } from 'neverthrow';
2
+ export type PromptPart = {
3
+ readonly kind: 'text';
4
+ readonly text: string;
5
+ } | {
6
+ readonly kind: 'ref';
7
+ readonly refId: string;
8
+ };
9
+ export type PromptValue = string | readonly PromptPart[];
10
+ export interface PromptBlocks {
11
+ readonly goal?: PromptValue;
12
+ readonly constraints?: readonly PromptValue[];
13
+ readonly procedure?: readonly PromptValue[];
14
+ readonly outputRequired?: Readonly<Record<string, string>>;
15
+ readonly verify?: readonly PromptValue[];
16
+ }
17
+ export type PromptBlocksRenderError = {
18
+ readonly code: 'EMPTY_BLOCKS';
19
+ readonly message: string;
20
+ } | {
21
+ readonly code: 'UNRESOLVED_REF';
22
+ readonly refId: string;
23
+ readonly message: string;
24
+ };
25
+ export declare function renderPromptBlocks(blocks: PromptBlocks): Result<string, PromptBlocksRenderError>;
26
+ import type { WorkflowStepDefinition, LoopStepDefinition } from '../../../types/workflow-definition.js';
27
+ export type PromptBlocksPassError = {
28
+ readonly code: 'PROMPT_BLOCKS_ERROR';
29
+ readonly stepId: string;
30
+ readonly cause: PromptBlocksRenderError;
31
+ } | {
32
+ readonly code: 'PROMPT_AND_BLOCKS_BOTH_SET';
33
+ readonly stepId: string;
34
+ readonly message: string;
35
+ };
36
+ export declare function resolvePromptBlocksPass(steps: readonly (WorkflowStepDefinition | LoopStepDefinition)[]): Result<readonly (WorkflowStepDefinition | LoopStepDefinition)[], PromptBlocksPassError>;
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderPromptBlocks = renderPromptBlocks;
4
+ exports.resolvePromptBlocksPass = resolvePromptBlocksPass;
5
+ const neverthrow_1 = require("neverthrow");
6
+ function resolvePromptValue(value) {
7
+ if (typeof value === 'string')
8
+ return (0, neverthrow_1.ok)(value);
9
+ const parts = [];
10
+ for (const part of value) {
11
+ switch (part.kind) {
12
+ case 'text':
13
+ parts.push(part.text);
14
+ break;
15
+ case 'ref':
16
+ return (0, neverthrow_1.err)({
17
+ code: 'UNRESOLVED_REF',
18
+ refId: part.refId,
19
+ message: `Unresolved ref '${part.refId}' in prompt blocks. Refs must be resolved before rendering.`,
20
+ });
21
+ }
22
+ }
23
+ return (0, neverthrow_1.ok)(parts.join(''));
24
+ }
25
+ function resolvePromptValues(values) {
26
+ const resolved = [];
27
+ for (const value of values) {
28
+ const res = resolvePromptValue(value);
29
+ if (res.isErr())
30
+ return (0, neverthrow_1.err)(res.error);
31
+ resolved.push(res.value);
32
+ }
33
+ return (0, neverthrow_1.ok)(resolved);
34
+ }
35
+ function renderPromptBlocks(blocks) {
36
+ const sections = [];
37
+ if (blocks.goal !== undefined) {
38
+ const res = resolvePromptValue(blocks.goal);
39
+ if (res.isErr())
40
+ return (0, neverthrow_1.err)(res.error);
41
+ sections.push(`## Goal\n${res.value}`);
42
+ }
43
+ if (blocks.constraints !== undefined && blocks.constraints.length > 0) {
44
+ const res = resolvePromptValues(blocks.constraints);
45
+ if (res.isErr())
46
+ return (0, neverthrow_1.err)(res.error);
47
+ sections.push(`## Constraints\n${res.value.map(c => `- ${c}`).join('\n')}`);
48
+ }
49
+ if (blocks.procedure !== undefined && blocks.procedure.length > 0) {
50
+ const res = resolvePromptValues(blocks.procedure);
51
+ if (res.isErr())
52
+ return (0, neverthrow_1.err)(res.error);
53
+ sections.push(`## Procedure\n${res.value.map((p, i) => `${i + 1}. ${p}`).join('\n')}`);
54
+ }
55
+ if (blocks.outputRequired !== undefined && Object.keys(blocks.outputRequired).length > 0) {
56
+ const entries = Object.entries(blocks.outputRequired)
57
+ .map(([key, value]) => `- **${key}**: ${value}`)
58
+ .join('\n');
59
+ sections.push(`## Output Required\n${entries}`);
60
+ }
61
+ if (blocks.verify !== undefined && blocks.verify.length > 0) {
62
+ const res = resolvePromptValues(blocks.verify);
63
+ if (res.isErr())
64
+ return (0, neverthrow_1.err)(res.error);
65
+ sections.push(`## Verify\n${res.value.map(v => `- ${v}`).join('\n')}`);
66
+ }
67
+ if (sections.length === 0) {
68
+ return (0, neverthrow_1.err)({
69
+ code: 'EMPTY_BLOCKS',
70
+ message: 'promptBlocks must contain at least one non-empty section.',
71
+ });
72
+ }
73
+ return (0, neverthrow_1.ok)(sections.join('\n\n'));
74
+ }
75
+ const workflow_definition_js_1 = require("../../../types/workflow-definition.js");
76
+ function resolveStepPromptBlocks(step) {
77
+ if (step.prompt && step.promptBlocks) {
78
+ return (0, neverthrow_1.err)({
79
+ code: 'PROMPT_AND_BLOCKS_BOTH_SET',
80
+ stepId: step.id,
81
+ message: `Step '${step.id}' declares both prompt and promptBlocks. Use exactly one.`,
82
+ });
83
+ }
84
+ if (!step.promptBlocks)
85
+ return (0, neverthrow_1.ok)(step);
86
+ const renderResult = renderPromptBlocks(step.promptBlocks);
87
+ if (renderResult.isErr()) {
88
+ return (0, neverthrow_1.err)({
89
+ code: 'PROMPT_BLOCKS_ERROR',
90
+ stepId: step.id,
91
+ cause: renderResult.error,
92
+ });
93
+ }
94
+ return (0, neverthrow_1.ok)({
95
+ ...step,
96
+ prompt: renderResult.value,
97
+ });
98
+ }
99
+ function resolvePromptBlocksPass(steps) {
100
+ const resolved = [];
101
+ for (const step of steps) {
102
+ if ((0, workflow_definition_js_1.isLoopStepDefinition)(step)) {
103
+ const loopRes = resolveStepPromptBlocks(step);
104
+ if (loopRes.isErr())
105
+ return (0, neverthrow_1.err)(loopRes.error);
106
+ if (Array.isArray(step.body)) {
107
+ const bodyResolved = [];
108
+ for (const bodyStep of step.body) {
109
+ const bodyRes = resolveStepPromptBlocks(bodyStep);
110
+ if (bodyRes.isErr())
111
+ return (0, neverthrow_1.err)(bodyRes.error);
112
+ bodyResolved.push(bodyRes.value);
113
+ }
114
+ const resolvedLoop = {
115
+ ...step,
116
+ ...(loopRes.value.prompt !== undefined ? { prompt: loopRes.value.prompt } : {}),
117
+ body: bodyResolved,
118
+ };
119
+ resolved.push(resolvedLoop);
120
+ }
121
+ else {
122
+ resolved.push({ ...step, ...(loopRes.value.prompt !== undefined ? { prompt: loopRes.value.prompt } : {}) });
123
+ }
124
+ }
125
+ else {
126
+ const res = resolveStepPromptBlocks(step);
127
+ if (res.isErr())
128
+ return (0, neverthrow_1.err)(res.error);
129
+ resolved.push(res.value);
130
+ }
131
+ }
132
+ return (0, neverthrow_1.ok)(resolved);
133
+ }
@@ -12,9 +12,18 @@ const workflow_1 = require("../../types/workflow");
12
12
  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
+ const prompt_blocks_1 = require("./compiler/prompt-blocks");
15
16
  let WorkflowCompiler = class WorkflowCompiler {
16
17
  compile(workflow) {
17
- const steps = workflow.definition.steps;
18
+ const blocksResult = (0, prompt_blocks_1.resolvePromptBlocksPass)(workflow.definition.steps);
19
+ if (blocksResult.isErr()) {
20
+ const e = blocksResult.error;
21
+ const message = e.code === 'PROMPT_AND_BLOCKS_BOTH_SET'
22
+ ? e.message
23
+ : `Step '${e.stepId}': promptBlocks error — ${e.cause.message}`;
24
+ return (0, neverthrow_1.err)(error_1.Err.invalidState(message));
25
+ }
26
+ const steps = blocksResult.value;
18
27
  const stepById = new Map();
19
28
  for (const step of steps) {
20
29
  if (stepById.has(step.id)) {
@@ -386,7 +386,7 @@ let WorkflowInterpreter = class WorkflowInterpreter {
386
386
  if (step.guidance && step.guidance.length > 0) {
387
387
  promptParts.push(`## Step Guidance\n${step.guidance.map((g) => `- ${g}`).join('\n')}\n`);
388
388
  }
389
- promptParts.push(step.prompt);
389
+ promptParts.push(step.prompt ?? '');
390
390
  if (instance.loopPath.length > 0) {
391
391
  const current = instance.loopPath[instance.loopPath.length - 1];
392
392
  promptParts.push(`\n\n## Loop Context\n- Loop: ${current.loopId}\n- Iteration: ${current.iteration + 1}`);
@@ -1,6 +1,14 @@
1
1
  {
2
2
  "distDir": "dist",
3
3
  "files": {
4
+ "application/services/compiler/prompt-blocks.d.ts": {
5
+ "sha256": "2f40fd7599bd351584505152e9916fdea60891833d22c774c8ac9955f01ccf66",
6
+ "bytes": 1416
7
+ },
8
+ "application/services/compiler/prompt-blocks.js": {
9
+ "sha256": "8ee0e8f7f23f0b298602b97af71a49eaf4fbdc8e7a2bb588c607c2f36e81ef1a",
10
+ "bytes": 5201
11
+ },
4
12
  "application/services/enhanced-error-service.d.ts": {
5
13
  "sha256": "b6fe8fad92717f0962f87aa9c0f88277bf28fe2b5e3cfd7875612ee57eb8c684",
6
14
  "bytes": 601
@@ -46,16 +54,16 @@
46
54
  "bytes": 990
47
55
  },
48
56
  "application/services/workflow-compiler.js": {
49
- "sha256": "f865278e4242867dfd9b679e489d8f2de89f46b578f586a80fc5490ab6c65cdb",
50
- "bytes": 5550
57
+ "sha256": "e4b8c0966ba04a87d753ca507fdc2ee5082a66e4fb6d539e4782c8ff8e93ef78",
58
+ "bytes": 6050
51
59
  },
52
60
  "application/services/workflow-interpreter.d.ts": {
53
61
  "sha256": "56b5b5ad06d42096deba9f0abe7642c18a355a1e598749aab1730df4e9847674",
54
62
  "bytes": 1507
55
63
  },
56
64
  "application/services/workflow-interpreter.js": {
57
- "sha256": "793833a14c6a55bbbe9df4473c301e54140e2c6c6064f24f9d781188b603b502",
58
- "bytes": 21396
65
+ "sha256": "0ea1861801d095d27e1e4c7c97978941b9d48613e28ce3a4c2efe64342814f5c",
66
+ "bytes": 21402
59
67
  },
60
68
  "application/services/workflow-service.d.ts": {
61
69
  "sha256": "b92da17c6d91c90758ec42b4ee3bc448e5d5b1dfe7351f2fe0f5e1d10a715ec6",
@@ -694,8 +702,8 @@
694
702
  "bytes": 471
695
703
  },
696
704
  "mcp/handlers/v2-resume.js": {
697
- "sha256": "74d66519764615780c556828c23ada5fa7df887c8263793de4323322aef14408",
698
- "bytes": 2826
705
+ "sha256": "851690a586328cb61a1aa0f9c2b8cac87b1a158430bab6e9601f63244a4dd69d",
706
+ "bytes": 3385
699
707
  },
700
708
  "mcp/handlers/v2-state-conversion.d.ts": {
701
709
  "sha256": "94bd06904ef58dd210ff17ffb75c2492beea8937eb06d99749e5d860c0e0d96b",
@@ -746,7 +754,7 @@
746
754
  "bytes": 7535
747
755
  },
748
756
  "mcp/output-schemas.d.ts": {
749
- "sha256": "5c8256c738cb2b3c193fa3fe955ca3aaf00ae9381e8ef162d1477824db18b137",
757
+ "sha256": "484a853815de731053618d7d710b6608392aef935239d899824f6a30a16ec3b7",
750
758
  "bytes": 51242
751
759
  },
752
760
  "mcp/output-schemas.js": {
@@ -1058,8 +1066,8 @@
1058
1066
  "bytes": 395
1059
1067
  },
1060
1068
  "types/workflow-definition.d.ts": {
1061
- "sha256": "350be64b9da13515fc717a3cd72ddf19b3544087a246c7b2e79da0ef5ed3ffef",
1062
- "bytes": 3614
1069
+ "sha256": "cb7d6be7e9aa0d4b7b17323cd167edad2f616b6a8c2149df6c40e4d965e7d9b8",
1070
+ "bytes": 3744
1063
1071
  },
1064
1072
  "types/workflow-definition.js": {
1065
1073
  "sha256": "e269d62f27b7f37f870183d6b77800b7aa1e22dabc894374bab8f34db049a55b",
@@ -1490,7 +1498,7 @@
1490
1498
  "bytes": 2099
1491
1499
  },
1492
1500
  "v2/durable-core/schemas/compiled-workflow/index.d.ts": {
1493
- "sha256": "5146bd86e5785117e260276775a3783871c141425a03f4643bf421a00e5b9bf2",
1501
+ "sha256": "d909c13d0d46bba1dcd411a0c53e767cf7e4c8bc5206581344ca1e7315552d95",
1494
1502
  "bytes": 3645
1495
1503
  },
1496
1504
  "v2/durable-core/schemas/compiled-workflow/index.js": {
@@ -1822,8 +1830,8 @@
1822
1830
  "bytes": 1004
1823
1831
  },
1824
1832
  "v2/infra/local/session-summary-provider/index.js": {
1825
- "sha256": "f6c0df4a3355241ee3eb83c0013f9a252479f27f4c9172e0607464339fba6920",
1826
- "bytes": 5655
1833
+ "sha256": "a38c877faddb8e14bf1c30e173e4299af5edb4a1f8fb4b036732c6ba6f11ca6f",
1834
+ "bytes": 5933
1827
1835
  },
1828
1836
  "v2/infra/local/sha256/index.d.ts": {
1829
1837
  "sha256": "8a727b7e54a38275ca6f9f1b8730f97cfc0a212df035df1bdc58e716e6824230",
@@ -2074,12 +2082,12 @@
2074
2082
  "bytes": 732
2075
2083
  },
2076
2084
  "v2/projections/resume-ranking.d.ts": {
2077
- "sha256": "50ef48d0b195f89f01c0051be453666e6a680e356ca9c328a754aced90ee8d7a",
2078
- "bytes": 2337
2085
+ "sha256": "ca5cb0701edded54f08395deebfe50161528d36edb74294c26481501391e64bc",
2086
+ "bytes": 2558
2079
2087
  },
2080
2088
  "v2/projections/resume-ranking.js": {
2081
- "sha256": "2cc54d484865507e65cc6202dfb7c42df4535e4cfd6faca6b0d9ce059852a8bc",
2082
- "bytes": 4281
2089
+ "sha256": "aa6ba4b5480caebba3107f86058b9a834cbd89962d0340c89342417f77956e47",
2090
+ "bytes": 4251
2083
2091
  },
2084
2092
  "v2/projections/run-context.d.ts": {
2085
2093
  "sha256": "a4d57470a435ac9860f60b3244d1b828853995027cd510d8da42762d21b2a687",
@@ -31,8 +31,28 @@ async function handleV2ResumeSession(input, ctx) {
31
31
  return (0, types_js_1.errNotRetryable)('INTERNAL_ERROR', `Resume failed: ${resumeResult.error.message}`);
32
32
  }
33
33
  const candidates = resumeResult.value;
34
+ const { outputCandidates, skipped } = mintCandidateTokens(candidates, v2.tokenCodecPorts);
35
+ if (skipped > 0) {
36
+ console.error(`[workrail:resume] ${skipped}/${candidates.length} candidate(s) skipped: token minting failed (workflowHashRef derivation or signing error)`);
37
+ }
38
+ const output = output_schemas_js_1.V2ResumeSessionOutputSchema.parse({
39
+ candidates: outputCandidates,
40
+ totalEligible: candidates.length,
41
+ });
42
+ return {
43
+ type: 'success',
44
+ data: output,
45
+ };
46
+ }
47
+ function mintCandidateTokens(candidates, ports) {
34
48
  const outputCandidates = [];
49
+ let skipped = 0;
35
50
  for (const candidate of candidates) {
51
+ const wfRefRes = (0, index_js_1.deriveWorkflowHashRef)(candidate.workflowHash);
52
+ if (wfRefRes.isErr()) {
53
+ skipped++;
54
+ continue;
55
+ }
36
56
  const stateTokenRes = (0, v2_token_ops_js_1.signTokenOrErr)({
37
57
  payload: {
38
58
  tokenVersion: 1,
@@ -40,11 +60,12 @@ async function handleV2ResumeSession(input, ctx) {
40
60
  sessionId: candidate.sessionId,
41
61
  runId: (0, index_js_1.asRunId)(candidate.runId),
42
62
  nodeId: (0, index_js_1.asNodeId)(candidate.preferredTipNodeId),
43
- workflowHashRef: (0, index_js_1.asWorkflowHashRef)(''),
63
+ workflowHashRef: wfRefRes.value,
44
64
  },
45
- ports: v2.tokenCodecPorts,
65
+ ports,
46
66
  });
47
67
  if (stateTokenRes.isErr()) {
68
+ skipped++;
48
69
  continue;
49
70
  }
50
71
  outputCandidates.push({
@@ -55,12 +76,5 @@ async function handleV2ResumeSession(input, ctx) {
55
76
  whyMatched: [...candidate.whyMatched],
56
77
  });
57
78
  }
58
- const output = output_schemas_js_1.V2ResumeSessionOutputSchema.parse({
59
- candidates: outputCandidates,
60
- totalEligible: candidates.length,
61
- });
62
- return {
63
- type: 'success',
64
- data: output,
65
- };
79
+ return { outputCandidates, skipped };
66
80
  }
@@ -237,13 +237,13 @@ export declare const V2PendingStepSchema: z.ZodObject<{
237
237
  title: z.ZodString;
238
238
  prompt: z.ZodString;
239
239
  }, "strip", z.ZodTypeAny, {
240
- title: string;
241
- prompt: string;
242
240
  stepId: string;
243
- }, {
244
- title: string;
245
241
  prompt: string;
242
+ title: string;
243
+ }, {
246
244
  stepId: string;
245
+ prompt: string;
246
+ title: string;
247
247
  }>;
248
248
  export declare const V2PreferencesSchema: z.ZodObject<{
249
249
  autonomy: z.ZodEnum<["guided", "full_auto_stop_on_user_deps", "full_auto_never_stop"]>;
@@ -484,13 +484,13 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
484
484
  title: z.ZodString;
485
485
  prompt: z.ZodString;
486
486
  }, "strip", z.ZodTypeAny, {
487
- title: string;
488
- prompt: string;
489
487
  stepId: string;
490
- }, {
491
- title: string;
492
488
  prompt: string;
489
+ title: string;
490
+ }, {
493
491
  stepId: string;
492
+ prompt: string;
493
+ title: string;
494
494
  }>>;
495
495
  preferences: z.ZodObject<{
496
496
  autonomy: z.ZodEnum<["guided", "full_auto_stop_on_user_deps", "full_auto_never_stop"]>;
@@ -551,9 +551,9 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
551
551
  }, "strip", z.ZodTypeAny, {
552
552
  kind: "ok";
553
553
  pending: {
554
- title: string;
555
- prompt: string;
556
554
  stepId: string;
555
+ prompt: string;
556
+ title: string;
557
557
  } | null;
558
558
  isComplete: boolean;
559
559
  stateToken: string;
@@ -578,9 +578,9 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
578
578
  }, {
579
579
  kind: "ok";
580
580
  pending: {
581
- title: string;
582
- prompt: string;
583
581
  stepId: string;
582
+ prompt: string;
583
+ title: string;
584
584
  } | null;
585
585
  isComplete: boolean;
586
586
  stateToken: string;
@@ -613,13 +613,13 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
613
613
  title: z.ZodString;
614
614
  prompt: z.ZodString;
615
615
  }, "strip", z.ZodTypeAny, {
616
- title: string;
617
- prompt: string;
618
616
  stepId: string;
619
- }, {
620
- title: string;
621
617
  prompt: string;
618
+ title: string;
619
+ }, {
622
620
  stepId: string;
621
+ prompt: string;
622
+ title: string;
623
623
  }>>;
624
624
  preferences: z.ZodObject<{
625
625
  autonomy: z.ZodEnum<["guided", "full_auto_stop_on_user_deps", "full_auto_never_stop"]>;
@@ -886,9 +886,9 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
886
886
  }[];
887
887
  };
888
888
  pending: {
889
- title: string;
890
- prompt: string;
891
889
  stepId: string;
890
+ prompt: string;
891
+ title: string;
892
892
  } | null;
893
893
  isComplete: boolean;
894
894
  stateToken: string;
@@ -941,9 +941,9 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
941
941
  }[];
942
942
  };
943
943
  pending: {
944
- title: string;
945
- prompt: string;
946
944
  stepId: string;
945
+ prompt: string;
946
+ title: string;
947
947
  } | null;
948
948
  isComplete: boolean;
949
949
  stateToken: string;
@@ -974,9 +974,9 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
974
974
  }>]>, {
975
975
  kind: "ok";
976
976
  pending: {
977
- title: string;
978
- prompt: string;
979
977
  stepId: string;
978
+ prompt: string;
979
+ title: string;
980
980
  } | null;
981
981
  isComplete: boolean;
982
982
  stateToken: string;
@@ -1023,9 +1023,9 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
1023
1023
  }[];
1024
1024
  };
1025
1025
  pending: {
1026
- title: string;
1027
- prompt: string;
1028
1026
  stepId: string;
1027
+ prompt: string;
1028
+ title: string;
1029
1029
  } | null;
1030
1030
  isComplete: boolean;
1031
1031
  stateToken: string;
@@ -1056,9 +1056,9 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
1056
1056
  }, {
1057
1057
  kind: "ok";
1058
1058
  pending: {
1059
- title: string;
1060
- prompt: string;
1061
1059
  stepId: string;
1060
+ prompt: string;
1061
+ title: string;
1062
1062
  } | null;
1063
1063
  isComplete: boolean;
1064
1064
  stateToken: string;
@@ -1105,9 +1105,9 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
1105
1105
  }[];
1106
1106
  };
1107
1107
  pending: {
1108
- title: string;
1109
- prompt: string;
1110
1108
  stepId: string;
1109
+ prompt: string;
1110
+ title: string;
1111
1111
  } | null;
1112
1112
  isComplete: boolean;
1113
1113
  stateToken: string;
@@ -1263,13 +1263,13 @@ export declare const V2StartWorkflowOutputSchema: z.ZodEffects<z.ZodObject<{
1263
1263
  title: z.ZodString;
1264
1264
  prompt: z.ZodString;
1265
1265
  }, "strip", z.ZodTypeAny, {
1266
- title: string;
1267
- prompt: string;
1268
1266
  stepId: string;
1269
- }, {
1270
- title: string;
1271
1267
  prompt: string;
1268
+ title: string;
1269
+ }, {
1272
1270
  stepId: string;
1271
+ prompt: string;
1272
+ title: string;
1273
1273
  }>>;
1274
1274
  preferences: z.ZodObject<{
1275
1275
  autonomy: z.ZodEnum<["guided", "full_auto_stop_on_user_deps", "full_auto_never_stop"]>;
@@ -1329,9 +1329,9 @@ export declare const V2StartWorkflowOutputSchema: z.ZodEffects<z.ZodObject<{
1329
1329
  }>>;
1330
1330
  }, "strip", z.ZodTypeAny, {
1331
1331
  pending: {
1332
- title: string;
1333
- prompt: string;
1334
1332
  stepId: string;
1333
+ prompt: string;
1334
+ title: string;
1335
1335
  } | null;
1336
1336
  isComplete: boolean;
1337
1337
  stateToken: string;
@@ -1355,9 +1355,9 @@ export declare const V2StartWorkflowOutputSchema: z.ZodEffects<z.ZodObject<{
1355
1355
  checkpointToken?: string | undefined;
1356
1356
  }, {
1357
1357
  pending: {
1358
- title: string;
1359
- prompt: string;
1360
1358
  stepId: string;
1359
+ prompt: string;
1360
+ title: string;
1361
1361
  } | null;
1362
1362
  isComplete: boolean;
1363
1363
  stateToken: string;
@@ -1381,9 +1381,9 @@ export declare const V2StartWorkflowOutputSchema: z.ZodEffects<z.ZodObject<{
1381
1381
  checkpointToken?: string | undefined;
1382
1382
  }>, {
1383
1383
  pending: {
1384
- title: string;
1385
- prompt: string;
1386
1384
  stepId: string;
1385
+ prompt: string;
1386
+ title: string;
1387
1387
  } | null;
1388
1388
  isComplete: boolean;
1389
1389
  stateToken: string;
@@ -1407,9 +1407,9 @@ export declare const V2StartWorkflowOutputSchema: z.ZodEffects<z.ZodObject<{
1407
1407
  checkpointToken?: string | undefined;
1408
1408
  }, {
1409
1409
  pending: {
1410
- title: string;
1411
- prompt: string;
1412
1410
  stepId: string;
1411
+ prompt: string;
1412
+ title: string;
1413
1413
  } | null;
1414
1414
  isComplete: boolean;
1415
1415
  stateToken: string;
@@ -1,5 +1,6 @@
1
1
  import { ValidationCriteria } from './validation';
2
2
  import type { ArtifactContractRef } from '../v2/durable-core/schemas/artifacts/index';
3
+ import type { PromptBlocks } from '../application/services/compiler/prompt-blocks.js';
3
4
  export interface OutputContract {
4
5
  readonly contractRef: ArtifactContractRef;
5
6
  readonly required?: boolean;
@@ -7,7 +8,8 @@ export interface OutputContract {
7
8
  export interface WorkflowStepDefinition {
8
9
  readonly id: string;
9
10
  readonly title: string;
10
- readonly prompt: string;
11
+ readonly prompt?: string;
12
+ readonly promptBlocks?: PromptBlocks;
11
13
  readonly agentRole?: string;
12
14
  readonly guidance?: readonly string[];
13
15
  readonly askForFiles?: boolean;
@@ -11,13 +11,13 @@ export declare const CompiledWorkflowSnapshotV1Schema: z.ZodDiscriminatedUnion<"
11
11
  title: z.ZodString;
12
12
  prompt: z.ZodString;
13
13
  }, "strip", z.ZodTypeAny, {
14
- title: string;
15
- prompt: string;
16
14
  stepId: string;
17
- }, {
18
- title: string;
19
15
  prompt: string;
16
+ title: string;
17
+ }, {
20
18
  stepId: string;
19
+ prompt: string;
20
+ title: string;
21
21
  }>;
22
22
  }, "strip", z.ZodTypeAny, {
23
23
  name: string;
@@ -27,9 +27,9 @@ export declare const CompiledWorkflowSnapshotV1Schema: z.ZodDiscriminatedUnion<"
27
27
  schemaVersion: 1;
28
28
  sourceKind: "v1_preview";
29
29
  preview: {
30
- title: string;
31
- prompt: string;
32
30
  stepId: string;
31
+ prompt: string;
32
+ title: string;
33
33
  };
34
34
  }, {
35
35
  name: string;
@@ -39,9 +39,9 @@ export declare const CompiledWorkflowSnapshotV1Schema: z.ZodDiscriminatedUnion<"
39
39
  schemaVersion: 1;
40
40
  sourceKind: "v1_preview";
41
41
  preview: {
42
- title: string;
43
- prompt: string;
44
42
  stepId: string;
43
+ prompt: string;
44
+ title: string;
45
45
  };
46
46
  }>, z.ZodObject<{
47
47
  schemaVersion: z.ZodLiteral<1>;
@@ -81,13 +81,13 @@ export declare const CompiledWorkflowSnapshotSchema: z.ZodDiscriminatedUnion<"so
81
81
  title: z.ZodString;
82
82
  prompt: z.ZodString;
83
83
  }, "strip", z.ZodTypeAny, {
84
- title: string;
85
- prompt: string;
86
84
  stepId: string;
87
- }, {
88
- title: string;
89
85
  prompt: string;
86
+ title: string;
87
+ }, {
90
88
  stepId: string;
89
+ prompt: string;
90
+ title: string;
91
91
  }>;
92
92
  }, "strip", z.ZodTypeAny, {
93
93
  name: string;
@@ -97,9 +97,9 @@ export declare const CompiledWorkflowSnapshotSchema: z.ZodDiscriminatedUnion<"so
97
97
  schemaVersion: 1;
98
98
  sourceKind: "v1_preview";
99
99
  preview: {
100
- title: string;
101
- prompt: string;
102
100
  stepId: string;
101
+ prompt: string;
102
+ title: string;
103
103
  };
104
104
  }, {
105
105
  name: string;
@@ -109,9 +109,9 @@ export declare const CompiledWorkflowSnapshotSchema: z.ZodDiscriminatedUnion<"so
109
109
  schemaVersion: 1;
110
110
  sourceKind: "v1_preview";
111
111
  preview: {
112
- title: string;
113
- prompt: string;
114
112
  stepId: string;
113
+ prompt: string;
114
+ title: string;
115
115
  };
116
116
  }>, z.ZodObject<{
117
117
  schemaVersion: z.ZodLiteral<1>;
@@ -7,6 +7,7 @@ const enumerate_sessions_js_1 = require("../../../usecases/enumerate-sessions.js
7
7
  const session_health_js_1 = require("../../../projections/session-health.js");
8
8
  const run_dag_js_1 = require("../../../projections/run-dag.js");
9
9
  const node_outputs_js_1 = require("../../../projections/node-outputs.js");
10
+ const index_js_1 = require("../../../durable-core/ids/index.js");
10
11
  const constants_js_1 = require("../../../durable-core/constants.js");
11
12
  const MAX_SESSIONS_TO_SCAN = 50;
12
13
  const MAX_RECAP_ANCESTOR_DEPTH = 100;
@@ -15,10 +16,6 @@ const EMPTY_OBSERVATIONS = {
15
16
  gitBranch: null,
16
17
  repoRootHash: null,
17
18
  };
18
- const UNKNOWN_WORKFLOW = {
19
- workflowId: null,
20
- workflowName: null,
21
- };
22
19
  class LocalSessionSummaryProviderV2 {
23
20
  constructor(ports) {
24
21
  this.ports = ports;
@@ -55,6 +52,9 @@ function projectSessionSummary(sessionId, truth) {
55
52
  const bestRun = selectBestRun(Object.values(dag.value.runsById));
56
53
  if (!bestRun)
57
54
  return null;
55
+ const workflow = extractWorkflowIdentity(truth.events, bestRun.run.runId);
56
+ if (!workflow)
57
+ return null;
58
58
  const outputsRes = (0, node_outputs_js_1.projectNodeOutputsV2)(truth.events);
59
59
  const recapSnippet = outputsRes.isOk()
60
60
  ? extractAggregateRecap(outputsRes.value, bestRun.run, bestRun.tipNodeId)
@@ -68,7 +68,7 @@ function projectSessionSummary(sessionId, truth) {
68
68
  },
69
69
  recapSnippet,
70
70
  observations: extractObservations(truth.events),
71
- workflow: extractWorkflowIdentity(truth.events, bestRun.run.runId),
71
+ workflow,
72
72
  };
73
73
  }
74
74
  function selectBestRun(runs) {
@@ -99,10 +99,13 @@ function extractWorkflowIdentity(events, runId) {
99
99
  .filter((e) => e.kind === constants_js_1.EVENT_KIND.RUN_STARTED)
100
100
  .find((e) => e.scope.runId === runId);
101
101
  if (!event)
102
- return UNKNOWN_WORKFLOW;
102
+ return null;
103
+ if (!constants_js_1.SHA256_DIGEST_PATTERN.test(event.data.workflowHash))
104
+ return null;
103
105
  return {
104
- workflowId: event.data.workflowId,
105
- workflowName: null,
106
+ kind: 'identified',
107
+ workflowId: (0, index_js_1.asWorkflowId)(event.data.workflowId),
108
+ workflowHash: (0, index_js_1.asWorkflowHash)((0, index_js_1.asSha256Digest)(event.data.workflowHash)),
106
109
  };
107
110
  }
108
111
  function collectAncestorNodeIds(nodesById, nodeId, remainingDepth) {
@@ -1,4 +1,4 @@
1
- import type { SessionId } from '../durable-core/ids/index.js';
1
+ import type { SessionId, WorkflowHash, WorkflowId } from '../durable-core/ids/index.js';
2
2
  export type RecapSnippet = string & {
3
3
  readonly __brand: 'RecapSnippet';
4
4
  };
@@ -8,10 +8,16 @@ export interface SessionObservations {
8
8
  readonly gitBranch: string | null;
9
9
  readonly repoRootHash: string | null;
10
10
  }
11
- export interface WorkflowIdentity {
12
- readonly workflowId: string | null;
13
- readonly workflowName: string | null;
14
- }
11
+ export type WorkflowIdentity = {
12
+ readonly kind: 'unknown';
13
+ } | {
14
+ readonly kind: 'identified';
15
+ readonly workflowId: WorkflowId;
16
+ readonly workflowHash: WorkflowHash;
17
+ };
18
+ export type IdentifiedWorkflow = Extract<WorkflowIdentity, {
19
+ kind: 'identified';
20
+ }>;
15
21
  export interface HealthySessionSummary {
16
22
  readonly sessionId: SessionId;
17
23
  readonly runId: string;
@@ -21,7 +27,7 @@ export interface HealthySessionSummary {
21
27
  };
22
28
  readonly recapSnippet: RecapSnippet | null;
23
29
  readonly observations: SessionObservations;
24
- readonly workflow: WorkflowIdentity;
30
+ readonly workflow: IdentifiedWorkflow;
25
31
  }
26
32
  export type WhyMatched = 'matched_head_sha' | 'matched_branch' | 'matched_notes' | 'matched_workflow_id' | 'recency_fallback';
27
33
  export type TierAssignment = {
@@ -57,6 +63,7 @@ export interface RankedResumeCandidate {
57
63
  readonly whyMatched: readonly WhyMatched[];
58
64
  readonly tierAssignment: TierAssignment;
59
65
  readonly lastActivityEventIndex: number;
66
+ readonly workflowHash: WorkflowHash;
60
67
  }
61
68
  export declare const MAX_RESUME_CANDIDATES = 5;
62
69
  export declare function rankResumeCandidates(summaries: readonly HealthySessionSummary[], query: ResumeQuery): readonly RankedResumeCandidate[];
@@ -56,13 +56,9 @@ function assignTier(summary, query) {
56
56
  return { tier: 3, kind: 'matched_notes' };
57
57
  }
58
58
  }
59
- if (query.freeTextQuery) {
59
+ if (query.freeTextQuery && summary.workflow.kind === 'identified') {
60
60
  const queryTokens = normalizeToTokens(query.freeTextQuery);
61
- const workflowText = [
62
- summary.workflow.workflowId ?? '',
63
- summary.workflow.workflowName ?? '',
64
- ].join(' ');
65
- const workflowTokens = normalizeToTokens(workflowText);
61
+ const workflowTokens = normalizeToTokens(String(summary.workflow.workflowId));
66
62
  if (allQueryTokensMatch(queryTokens, workflowTokens)) {
67
63
  return { tier: 4, kind: 'matched_workflow_id' };
68
64
  }
@@ -101,5 +97,6 @@ function rankResumeCandidates(summaries, query) {
101
97
  whyMatched: [tierToWhyMatched(tier)],
102
98
  tierAssignment: tier,
103
99
  lastActivityEventIndex: summary.preferredTip.lastActivityEventIndex,
100
+ workflowHash: summary.workflow.workflowHash,
104
101
  }));
105
102
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exaudeus/workrail",
3
- "version": "1.7.4",
3
+ "version": "1.8.0",
4
4
  "description": "Step-by-step workflow enforcement for AI agents via MCP",
5
5
  "license": "MIT",
6
6
  "repository": {