@exaudeus/workrail 2.1.0 → 3.1.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.
Files changed (61) hide show
  1. package/dist/application/services/compiler/resolve-templates.d.ts +5 -0
  2. package/dist/application/services/compiler/resolve-templates.js +35 -0
  3. package/dist/application/services/compiler/routine-loader.d.ts +11 -0
  4. package/dist/application/services/compiler/routine-loader.js +45 -0
  5. package/dist/application/services/compiler/template-registry.d.ts +4 -2
  6. package/dist/application/services/compiler/template-registry.js +105 -4
  7. package/dist/application/services/workflow-compiler.js +34 -3
  8. package/dist/di/container.js +10 -1
  9. package/dist/di/tokens.d.ts +1 -0
  10. package/dist/di/tokens.js +1 -0
  11. package/dist/engine/engine-factory.d.ts +3 -0
  12. package/dist/engine/engine-factory.js +295 -0
  13. package/dist/engine/index.d.ts +3 -0
  14. package/dist/engine/index.js +12 -0
  15. package/dist/engine/types.d.ts +130 -0
  16. package/dist/engine/types.js +18 -0
  17. package/dist/manifest.json +146 -74
  18. package/dist/mcp/handlers/v2-checkpoint.d.ts +31 -1
  19. package/dist/mcp/handlers/v2-checkpoint.js +76 -64
  20. package/dist/mcp/handlers/v2-execution/continue-advance.d.ts +2 -0
  21. package/dist/mcp/handlers/v2-execution/continue-advance.js +5 -5
  22. package/dist/mcp/handlers/v2-execution/continue-rehydrate.d.ts +2 -0
  23. package/dist/mcp/handlers/v2-execution/continue-rehydrate.js +17 -22
  24. package/dist/mcp/handlers/v2-execution/index.d.ts +10 -17
  25. package/dist/mcp/handlers/v2-execution/index.js +44 -54
  26. package/dist/mcp/handlers/v2-execution/replay.d.ts +4 -15
  27. package/dist/mcp/handlers/v2-execution/replay.js +52 -128
  28. package/dist/mcp/handlers/v2-execution/start.d.ts +3 -2
  29. package/dist/mcp/handlers/v2-execution/start.js +18 -46
  30. package/dist/mcp/handlers/v2-token-ops.d.ts +45 -24
  31. package/dist/mcp/handlers/v2-token-ops.js +372 -32
  32. package/dist/mcp/output-schemas.d.ts +104 -283
  33. package/dist/mcp/output-schemas.js +24 -22
  34. package/dist/mcp/server.js +8 -0
  35. package/dist/mcp/types.d.ts +4 -0
  36. package/dist/mcp/v2/tools.d.ts +22 -52
  37. package/dist/mcp/v2/tools.js +18 -32
  38. package/dist/mcp/v2-response-formatter.js +12 -16
  39. package/dist/runtime/runtime-mode.d.ts +2 -0
  40. package/dist/v2/durable-core/domain/prompt-renderer.d.ts +1 -0
  41. package/dist/v2/durable-core/domain/prompt-renderer.js +5 -3
  42. package/dist/v2/durable-core/schemas/export-bundle/index.d.ts +14 -14
  43. package/dist/v2/durable-core/schemas/session/events.d.ts +4 -4
  44. package/dist/v2/durable-core/schemas/session/validation-event.d.ts +2 -2
  45. package/dist/v2/durable-core/tokens/payloads.d.ts +32 -32
  46. package/dist/v2/durable-core/tokens/short-token.d.ts +38 -0
  47. package/dist/v2/durable-core/tokens/short-token.js +126 -0
  48. package/dist/v2/durable-core/tokens/token-patterns.d.ts +4 -0
  49. package/dist/v2/durable-core/tokens/token-patterns.js +9 -0
  50. package/dist/v2/infra/in-memory/token-alias-store/index.d.ts +11 -0
  51. package/dist/v2/infra/in-memory/token-alias-store/index.js +38 -0
  52. package/dist/v2/infra/local/data-dir/index.d.ts +1 -0
  53. package/dist/v2/infra/local/data-dir/index.js +3 -0
  54. package/dist/v2/infra/local/token-alias-store/index.d.ts +16 -0
  55. package/dist/v2/infra/local/token-alias-store/index.js +117 -0
  56. package/dist/v2/ports/data-dir.port.d.ts +1 -0
  57. package/dist/v2/ports/token-alias-store.port.d.ts +33 -0
  58. package/dist/v2/ports/token-alias-store.port.js +2 -0
  59. package/package.json +8 -1
  60. package/workflows/coding-task-workflow-agentic.lean.v2.json +41 -3
  61. package/workflows/examples/routine-injection-example.json +28 -0
@@ -874,8 +874,8 @@ export declare const DomainEventV1Schema: z.ZodDiscriminatedUnion<"kind", [z.Zod
874
874
  }>;
875
875
  }, "strict", z.ZodTypeAny, {
876
876
  contractRef: string;
877
- validationId: string;
878
877
  attemptId: string;
878
+ validationId: string;
879
879
  result: {
880
880
  issues: readonly string[];
881
881
  valid: boolean;
@@ -883,8 +883,8 @@ export declare const DomainEventV1Schema: z.ZodDiscriminatedUnion<"kind", [z.Zod
883
883
  };
884
884
  }, {
885
885
  contractRef: string;
886
- validationId: string;
887
886
  attemptId: string;
887
+ validationId: string;
888
888
  result: {
889
889
  issues: readonly string[];
890
890
  valid: boolean;
@@ -896,8 +896,8 @@ export declare const DomainEventV1Schema: z.ZodDiscriminatedUnion<"kind", [z.Zod
896
896
  sessionId: string;
897
897
  data: {
898
898
  contractRef: string;
899
- validationId: string;
900
899
  attemptId: string;
900
+ validationId: string;
901
901
  result: {
902
902
  issues: readonly string[];
903
903
  valid: boolean;
@@ -917,8 +917,8 @@ export declare const DomainEventV1Schema: z.ZodDiscriminatedUnion<"kind", [z.Zod
917
917
  sessionId: string;
918
918
  data: {
919
919
  contractRef: string;
920
- validationId: string;
921
920
  attemptId: string;
921
+ validationId: string;
922
922
  result: {
923
923
  issues: readonly string[];
924
924
  valid: boolean;
@@ -47,8 +47,8 @@ export declare const ValidationPerformedDataV1Schema: z.ZodObject<{
47
47
  }>;
48
48
  }, "strict", z.ZodTypeAny, {
49
49
  contractRef: string;
50
- validationId: string;
51
50
  attemptId: string;
51
+ validationId: string;
52
52
  result: {
53
53
  issues: readonly string[];
54
54
  valid: boolean;
@@ -56,8 +56,8 @@ export declare const ValidationPerformedDataV1Schema: z.ZodObject<{
56
56
  };
57
57
  }, {
58
58
  contractRef: string;
59
- validationId: string;
60
59
  attemptId: string;
60
+ validationId: string;
61
61
  result: {
62
62
  issues: readonly string[];
63
63
  valid: boolean;
@@ -17,24 +17,24 @@ export declare const StateTokenPayloadV1Schema: z.ZodObject<{
17
17
  sessionId: string & {
18
18
  readonly __brand: "v2.SessionId";
19
19
  };
20
+ tokenKind: "state";
20
21
  runId: string & {
21
22
  readonly __brand: "v2.RunId";
22
23
  };
23
24
  nodeId: string & {
24
25
  readonly __brand: "v2.NodeId";
25
26
  };
26
- tokenVersion: 1;
27
- tokenKind: "state";
28
27
  workflowHashRef: string & {
29
28
  readonly __brand: "v2.WorkflowHashRef";
30
29
  };
30
+ tokenVersion: 1;
31
31
  }, {
32
32
  sessionId: string;
33
+ tokenKind: "state";
33
34
  runId: string;
34
35
  nodeId: string;
35
- tokenVersion: 1;
36
- tokenKind: "state";
37
36
  workflowHashRef: string;
37
+ tokenVersion: 1;
38
38
  }>;
39
39
  export type StateTokenPayloadV1 = z.infer<typeof StateTokenPayloadV1Schema> & {
40
40
  readonly tokenVersion: TokenVersionV1;
@@ -55,24 +55,24 @@ export declare const AckTokenPayloadV1Schema: z.ZodObject<{
55
55
  sessionId: string & {
56
56
  readonly __brand: "v2.SessionId";
57
57
  };
58
- attemptId: string & {
59
- readonly __brand: "v2.AttemptId";
60
- };
58
+ tokenKind: "ack";
61
59
  runId: string & {
62
60
  readonly __brand: "v2.RunId";
63
61
  };
64
62
  nodeId: string & {
65
63
  readonly __brand: "v2.NodeId";
66
64
  };
65
+ attemptId: string & {
66
+ readonly __brand: "v2.AttemptId";
67
+ };
67
68
  tokenVersion: 1;
68
- tokenKind: "ack";
69
69
  }, {
70
70
  sessionId: string;
71
- attemptId: string;
71
+ tokenKind: "ack";
72
72
  runId: string;
73
73
  nodeId: string;
74
+ attemptId: string;
74
75
  tokenVersion: 1;
75
- tokenKind: "ack";
76
76
  }>;
77
77
  export type AckTokenPayloadV1 = z.infer<typeof AckTokenPayloadV1Schema> & {
78
78
  readonly tokenVersion: TokenVersionV1;
@@ -93,24 +93,24 @@ export declare const CheckpointTokenPayloadV1Schema: z.ZodObject<{
93
93
  sessionId: string & {
94
94
  readonly __brand: "v2.SessionId";
95
95
  };
96
- attemptId: string & {
97
- readonly __brand: "v2.AttemptId";
98
- };
96
+ tokenKind: "checkpoint";
99
97
  runId: string & {
100
98
  readonly __brand: "v2.RunId";
101
99
  };
102
100
  nodeId: string & {
103
101
  readonly __brand: "v2.NodeId";
104
102
  };
103
+ attemptId: string & {
104
+ readonly __brand: "v2.AttemptId";
105
+ };
105
106
  tokenVersion: 1;
106
- tokenKind: "checkpoint";
107
107
  }, {
108
108
  sessionId: string;
109
- attemptId: string;
109
+ tokenKind: "checkpoint";
110
110
  runId: string;
111
111
  nodeId: string;
112
+ attemptId: string;
112
113
  tokenVersion: 1;
113
- tokenKind: "checkpoint";
114
114
  }>;
115
115
  export type CheckpointTokenPayloadV1 = z.infer<typeof CheckpointTokenPayloadV1Schema> & {
116
116
  readonly tokenVersion: TokenVersionV1;
@@ -131,24 +131,24 @@ export declare const TokenPayloadV1Schema: z.ZodDiscriminatedUnion<"tokenKind",
131
131
  sessionId: string & {
132
132
  readonly __brand: "v2.SessionId";
133
133
  };
134
+ tokenKind: "state";
134
135
  runId: string & {
135
136
  readonly __brand: "v2.RunId";
136
137
  };
137
138
  nodeId: string & {
138
139
  readonly __brand: "v2.NodeId";
139
140
  };
140
- tokenVersion: 1;
141
- tokenKind: "state";
142
141
  workflowHashRef: string & {
143
142
  readonly __brand: "v2.WorkflowHashRef";
144
143
  };
144
+ tokenVersion: 1;
145
145
  }, {
146
146
  sessionId: string;
147
+ tokenKind: "state";
147
148
  runId: string;
148
149
  nodeId: string;
149
- tokenVersion: 1;
150
- tokenKind: "state";
151
150
  workflowHashRef: string;
151
+ tokenVersion: 1;
152
152
  }>, z.ZodObject<{
153
153
  tokenVersion: z.ZodLiteral<1>;
154
154
  tokenKind: z.ZodLiteral<"ack">;
@@ -160,24 +160,24 @@ export declare const TokenPayloadV1Schema: z.ZodDiscriminatedUnion<"tokenKind",
160
160
  sessionId: string & {
161
161
  readonly __brand: "v2.SessionId";
162
162
  };
163
- attemptId: string & {
164
- readonly __brand: "v2.AttemptId";
165
- };
163
+ tokenKind: "ack";
166
164
  runId: string & {
167
165
  readonly __brand: "v2.RunId";
168
166
  };
169
167
  nodeId: string & {
170
168
  readonly __brand: "v2.NodeId";
171
169
  };
170
+ attemptId: string & {
171
+ readonly __brand: "v2.AttemptId";
172
+ };
172
173
  tokenVersion: 1;
173
- tokenKind: "ack";
174
174
  }, {
175
175
  sessionId: string;
176
- attemptId: string;
176
+ tokenKind: "ack";
177
177
  runId: string;
178
178
  nodeId: string;
179
+ attemptId: string;
179
180
  tokenVersion: 1;
180
- tokenKind: "ack";
181
181
  }>, z.ZodObject<{
182
182
  tokenVersion: z.ZodLiteral<1>;
183
183
  tokenKind: z.ZodLiteral<"checkpoint">;
@@ -189,24 +189,24 @@ export declare const TokenPayloadV1Schema: z.ZodDiscriminatedUnion<"tokenKind",
189
189
  sessionId: string & {
190
190
  readonly __brand: "v2.SessionId";
191
191
  };
192
- attemptId: string & {
193
- readonly __brand: "v2.AttemptId";
194
- };
192
+ tokenKind: "checkpoint";
195
193
  runId: string & {
196
194
  readonly __brand: "v2.RunId";
197
195
  };
198
196
  nodeId: string & {
199
197
  readonly __brand: "v2.NodeId";
200
198
  };
199
+ attemptId: string & {
200
+ readonly __brand: "v2.AttemptId";
201
+ };
201
202
  tokenVersion: 1;
202
- tokenKind: "checkpoint";
203
203
  }, {
204
204
  sessionId: string;
205
- attemptId: string;
205
+ tokenKind: "checkpoint";
206
206
  runId: string;
207
207
  nodeId: string;
208
+ attemptId: string;
208
209
  tokenVersion: 1;
209
- tokenKind: "checkpoint";
210
210
  }>]>;
211
211
  export type TokenPayloadV1 = StateTokenPayloadV1 | AckTokenPayloadV1 | CheckpointTokenPayloadV1;
212
212
  export type TokenPrefixV1 = 'st' | 'ack' | 'chk';
@@ -0,0 +1,38 @@
1
+ import type { Result } from 'neverthrow';
2
+ import type { HmacSha256PortV2 } from '../../ports/hmac-sha256.port.js';
3
+ import type { Base64UrlPortV2 } from '../../ports/base64url.port.js';
4
+ import type { KeyringV1 } from '../../ports/keyring.port.js';
5
+ export type ShortTokenKind = 'state' | 'ack' | 'checkpoint' | 'continue';
6
+ export declare const SHORT_TOKEN_NONCE_BYTES = 12;
7
+ export declare const SHORT_TOKEN_HMAC_BYTES = 6;
8
+ export declare const SHORT_TOKEN_PAYLOAD_BYTES: number;
9
+ export type ShortTokenError = {
10
+ readonly code: 'SHORT_TOKEN_UNKNOWN_PREFIX';
11
+ readonly raw: string;
12
+ } | {
13
+ readonly code: 'SHORT_TOKEN_INVALID_LENGTH';
14
+ readonly expected: number;
15
+ readonly actual: number;
16
+ } | {
17
+ readonly code: 'SHORT_TOKEN_INVALID_ENCODING';
18
+ readonly message: string;
19
+ } | {
20
+ readonly code: 'SHORT_TOKEN_BAD_SIGNATURE';
21
+ } | {
22
+ readonly code: 'SHORT_TOKEN_SIGNING_FAILED';
23
+ readonly message: string;
24
+ };
25
+ export interface ParsedShortToken {
26
+ readonly kind: ShortTokenKind;
27
+ readonly nonce: Uint8Array;
28
+ readonly hmac6: Uint8Array;
29
+ readonly nonceHex: string;
30
+ }
31
+ export declare function mintShortToken(kind: ShortTokenKind, nonce: Uint8Array, keyring: KeyringV1, hmac: HmacSha256PortV2, base64url: Base64UrlPortV2): Result<string, ShortTokenError>;
32
+ export declare function parseShortToken(raw: string, base64url: Base64UrlPortV2): Result<ParsedShortToken, ShortTokenError>;
33
+ export declare function verifyShortTokenHmac(parsed: ParsedShortToken, keyring: KeyringV1, hmac: HmacSha256PortV2, base64url: Base64UrlPortV2): Result<void, ShortTokenError>;
34
+ export interface NativeParsedShortToken {
35
+ readonly kind: ShortTokenKind;
36
+ readonly nonceHex: string;
37
+ }
38
+ export declare function parseShortTokenNative(raw: string): NativeParsedShortToken | null;
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SHORT_TOKEN_PAYLOAD_BYTES = exports.SHORT_TOKEN_HMAC_BYTES = exports.SHORT_TOKEN_NONCE_BYTES = void 0;
4
+ exports.mintShortToken = mintShortToken;
5
+ exports.parseShortToken = parseShortToken;
6
+ exports.verifyShortTokenHmac = verifyShortTokenHmac;
7
+ exports.parseShortTokenNative = parseShortTokenNative;
8
+ const neverthrow_1 = require("neverthrow");
9
+ const KIND_PREFIXES = {
10
+ state: 'st_',
11
+ ack: 'ak_',
12
+ checkpoint: 'ck_',
13
+ continue: 'ct_',
14
+ };
15
+ const PREFIX_TO_KIND = {
16
+ 'st_': 'state',
17
+ 'ak_': 'ack',
18
+ 'ck_': 'checkpoint',
19
+ 'ct_': 'continue',
20
+ };
21
+ const KIND_BYTES = {
22
+ state: 0x01,
23
+ ack: 0x02,
24
+ checkpoint: 0x03,
25
+ continue: 0x04,
26
+ };
27
+ exports.SHORT_TOKEN_NONCE_BYTES = 12;
28
+ exports.SHORT_TOKEN_HMAC_BYTES = 6;
29
+ exports.SHORT_TOKEN_PAYLOAD_BYTES = exports.SHORT_TOKEN_NONCE_BYTES + exports.SHORT_TOKEN_HMAC_BYTES;
30
+ function mintShortToken(kind, nonce, keyring, hmac, base64url) {
31
+ if (nonce.length !== exports.SHORT_TOKEN_NONCE_BYTES) {
32
+ return (0, neverthrow_1.err)({
33
+ code: 'SHORT_TOKEN_INVALID_LENGTH',
34
+ expected: exports.SHORT_TOKEN_NONCE_BYTES,
35
+ actual: nonce.length,
36
+ });
37
+ }
38
+ const keyResult = decodeKey(keyring.current.keyBase64Url, base64url);
39
+ if (keyResult.isErr())
40
+ return (0, neverthrow_1.err)(keyResult.error);
41
+ const key = keyResult.value;
42
+ const hmacInput = buildHmacInput(nonce, kind);
43
+ const hmacFull = hmac.hmacSha256(key, hmacInput);
44
+ const hmac6 = hmacFull.slice(0, exports.SHORT_TOKEN_HMAC_BYTES);
45
+ const payload = new Uint8Array(exports.SHORT_TOKEN_PAYLOAD_BYTES);
46
+ payload.set(nonce, 0);
47
+ payload.set(hmac6, exports.SHORT_TOKEN_NONCE_BYTES);
48
+ const encoded = base64url.encodeBase64Url(payload);
49
+ return (0, neverthrow_1.ok)(`${KIND_PREFIXES[kind]}${encoded}`);
50
+ }
51
+ function parseShortToken(raw, base64url) {
52
+ const prefix = raw.slice(0, 3);
53
+ const kind = PREFIX_TO_KIND[prefix];
54
+ if (!kind) {
55
+ return (0, neverthrow_1.err)({ code: 'SHORT_TOKEN_UNKNOWN_PREFIX', raw });
56
+ }
57
+ const encoded = raw.slice(3);
58
+ const decoded = base64url.decodeBase64Url(encoded);
59
+ if (decoded.isErr()) {
60
+ return (0, neverthrow_1.err)({ code: 'SHORT_TOKEN_INVALID_ENCODING', message: decoded.error.message });
61
+ }
62
+ const bytes = decoded.value;
63
+ if (bytes.length !== exports.SHORT_TOKEN_PAYLOAD_BYTES) {
64
+ return (0, neverthrow_1.err)({
65
+ code: 'SHORT_TOKEN_INVALID_LENGTH',
66
+ expected: exports.SHORT_TOKEN_PAYLOAD_BYTES,
67
+ actual: bytes.length,
68
+ });
69
+ }
70
+ const nonce = bytes.slice(0, exports.SHORT_TOKEN_NONCE_BYTES);
71
+ const hmac6 = bytes.slice(exports.SHORT_TOKEN_NONCE_BYTES);
72
+ const nonceHex = bufToHex(nonce);
73
+ return (0, neverthrow_1.ok)({ kind, nonce, hmac6, nonceHex });
74
+ }
75
+ function verifyShortTokenHmac(parsed, keyring, hmac, base64url) {
76
+ const hmacInput = buildHmacInput(parsed.nonce, parsed.kind);
77
+ if (checkHmac(parsed.hmac6, hmacInput, keyring.current.keyBase64Url, hmac, base64url)) {
78
+ return (0, neverthrow_1.ok)(undefined);
79
+ }
80
+ if (keyring.previous) {
81
+ if (checkHmac(parsed.hmac6, hmacInput, keyring.previous.keyBase64Url, hmac, base64url)) {
82
+ return (0, neverthrow_1.ok)(undefined);
83
+ }
84
+ }
85
+ return (0, neverthrow_1.err)({ code: 'SHORT_TOKEN_BAD_SIGNATURE' });
86
+ }
87
+ function buildHmacInput(nonce, kind) {
88
+ const input = new Uint8Array(exports.SHORT_TOKEN_NONCE_BYTES + 1);
89
+ input.set(nonce, 0);
90
+ input[exports.SHORT_TOKEN_NONCE_BYTES] = KIND_BYTES[kind];
91
+ return input;
92
+ }
93
+ function checkHmac(expected6, hmacInput, keyBase64Url, hmac, base64url) {
94
+ const keyResult = decodeKey(keyBase64Url, base64url);
95
+ if (keyResult.isErr())
96
+ return false;
97
+ const full = hmac.hmacSha256(keyResult.value, hmacInput);
98
+ const truncated = full.slice(0, exports.SHORT_TOKEN_HMAC_BYTES);
99
+ return hmac.timingSafeEqual(truncated, expected6);
100
+ }
101
+ function decodeKey(keyBase64Url, base64url) {
102
+ const r = base64url.decodeBase64Url(keyBase64Url);
103
+ if (r.isErr())
104
+ return (0, neverthrow_1.err)({ code: 'SHORT_TOKEN_SIGNING_FAILED', message: r.error.message });
105
+ return (0, neverthrow_1.ok)(r.value);
106
+ }
107
+ function bufToHex(bytes) {
108
+ return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
109
+ }
110
+ function parseShortTokenNative(raw) {
111
+ const prefix = raw.slice(0, 3);
112
+ const kind = PREFIX_TO_KIND[prefix];
113
+ if (!kind)
114
+ return null;
115
+ const encoded = raw.slice(3);
116
+ try {
117
+ const bytes = Buffer.from(encoded, 'base64url');
118
+ if (bytes.length !== exports.SHORT_TOKEN_PAYLOAD_BYTES)
119
+ return null;
120
+ const nonceHex = Buffer.from(bytes.slice(0, exports.SHORT_TOKEN_NONCE_BYTES)).toString('hex');
121
+ return { kind, nonceHex };
122
+ }
123
+ catch {
124
+ return null;
125
+ }
126
+ }
@@ -0,0 +1,4 @@
1
+ export declare const STATE_TOKEN_PATTERN: RegExp;
2
+ export declare const ACK_TOKEN_PATTERN: RegExp;
3
+ export declare const CHECKPOINT_TOKEN_PATTERN: RegExp;
4
+ export declare const CONTINUE_TOKEN_PATTERN: RegExp;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CONTINUE_TOKEN_PATTERN = exports.CHECKPOINT_TOKEN_PATTERN = exports.ACK_TOKEN_PATTERN = exports.STATE_TOKEN_PATTERN = void 0;
4
+ const BECH32_CHARS = '[023456789acdefghjklmnpqrstuvwxyz]+';
5
+ const BASE64URL_24 = '[A-Za-z0-9_-]{24}';
6
+ exports.STATE_TOKEN_PATTERN = new RegExp(`^(st1${BECH32_CHARS}|st_${BASE64URL_24})$`);
7
+ exports.ACK_TOKEN_PATTERN = new RegExp(`^(ack1${BECH32_CHARS}|ak_${BASE64URL_24})$`);
8
+ exports.CHECKPOINT_TOKEN_PATTERN = new RegExp(`^(chk1${BECH32_CHARS}|ck_${BASE64URL_24})$`);
9
+ exports.CONTINUE_TOKEN_PATTERN = new RegExp(`^ct_${BASE64URL_24}$`);
@@ -0,0 +1,11 @@
1
+ import type { ResultAsync } from 'neverthrow';
2
+ import type { TokenAliasStorePortV2, TokenAliasEntryV2, TokenAliasRegistrationError, TokenAliasLoadError } from '../../../ports/token-alias-store.port.js';
3
+ import type { ShortTokenKind } from '../../../durable-core/tokens/short-token.js';
4
+ export declare class InMemoryTokenAliasStoreV2 implements TokenAliasStorePortV2 {
5
+ private readonly index;
6
+ private readonly positionIndex;
7
+ register(entry: TokenAliasEntryV2): ResultAsync<void, TokenAliasRegistrationError>;
8
+ lookup(nonceHex: string): TokenAliasEntryV2 | null;
9
+ lookupByPosition(tokenKind: ShortTokenKind, sessionId: string, nodeId: string, attemptId?: string, aliasSlot?: 'retry'): TokenAliasEntryV2 | null;
10
+ loadIndex(): ResultAsync<void, TokenAliasLoadError>;
11
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InMemoryTokenAliasStoreV2 = void 0;
4
+ const neverthrow_1 = require("neverthrow");
5
+ function positionKey(tokenKind, sessionId, nodeId, attemptId, aliasSlot) {
6
+ return `${tokenKind}:${aliasSlot ?? ''}:${sessionId}:${nodeId}:${attemptId ?? ''}`;
7
+ }
8
+ class InMemoryTokenAliasStoreV2 {
9
+ constructor() {
10
+ this.index = new Map();
11
+ this.positionIndex = new Map();
12
+ }
13
+ register(entry) {
14
+ if (this.index.has(entry.nonceHex)) {
15
+ return (0, neverthrow_1.errAsync)({
16
+ code: 'ALIAS_DUPLICATE_NONCE',
17
+ nonceHex: entry.nonceHex,
18
+ });
19
+ }
20
+ this.index.set(entry.nonceHex, entry);
21
+ this.positionIndex.set(positionKey(entry.tokenKind, entry.sessionId, entry.nodeId, entry.attemptId, entry.aliasSlot), entry.nonceHex);
22
+ return (0, neverthrow_1.okAsync)(undefined);
23
+ }
24
+ lookup(nonceHex) {
25
+ return this.index.get(nonceHex) ?? null;
26
+ }
27
+ lookupByPosition(tokenKind, sessionId, nodeId, attemptId, aliasSlot) {
28
+ const key = positionKey(tokenKind, sessionId, nodeId, attemptId, aliasSlot);
29
+ const nonceHex = this.positionIndex.get(key);
30
+ if (!nonceHex)
31
+ return null;
32
+ return this.index.get(nonceHex) ?? null;
33
+ }
34
+ loadIndex() {
35
+ return (0, neverthrow_1.okAsync)(undefined);
36
+ }
37
+ }
38
+ exports.InMemoryTokenAliasStoreV2 = InMemoryTokenAliasStoreV2;
@@ -16,4 +16,5 @@ export declare class LocalDataDirV2 implements DataDirPortV2 {
16
16
  sessionEventsDir(sessionId: SessionId): string;
17
17
  sessionManifestPath(sessionId: SessionId): string;
18
18
  sessionLockPath(sessionId: SessionId): string;
19
+ tokenIndexPath(): string;
19
20
  }
@@ -80,5 +80,8 @@ class LocalDataDirV2 {
80
80
  sessionLockPath(sessionId) {
81
81
  return path.join(this.sessionDir(sessionId), '.lock');
82
82
  }
83
+ tokenIndexPath() {
84
+ return path.join(this.keysDir(), 'token-index.jsonl');
85
+ }
83
86
  }
84
87
  exports.LocalDataDirV2 = LocalDataDirV2;
@@ -0,0 +1,16 @@
1
+ import type { ResultAsync } from 'neverthrow';
2
+ import type { DataDirPortV2 } from '../../../ports/data-dir.port.js';
3
+ import type { FileSystemPortV2 } from '../../../ports/fs.port.js';
4
+ import type { TokenAliasStorePortV2, TokenAliasEntryV2, TokenAliasRegistrationError, TokenAliasLoadError } from '../../../ports/token-alias-store.port.js';
5
+ import type { ShortTokenKind } from '../../../durable-core/tokens/short-token.js';
6
+ export declare class LocalTokenAliasStoreV2 implements TokenAliasStorePortV2 {
7
+ private readonly dataDir;
8
+ private readonly fs;
9
+ private readonly index;
10
+ private readonly positionIndex;
11
+ constructor(dataDir: DataDirPortV2, fs: FileSystemPortV2);
12
+ register(entry: TokenAliasEntryV2): ResultAsync<void, TokenAliasRegistrationError>;
13
+ lookup(nonceHex: string): TokenAliasEntryV2 | null;
14
+ lookupByPosition(tokenKind: ShortTokenKind, sessionId: string, nodeId: string, attemptId?: string, aliasSlot?: 'retry'): TokenAliasEntryV2 | null;
15
+ loadIndex(): ResultAsync<void, TokenAliasLoadError>;
16
+ }
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LocalTokenAliasStoreV2 = void 0;
4
+ const neverthrow_1 = require("neverthrow");
5
+ const ALIAS_FILE_VERSION = 1;
6
+ function positionKey(tokenKind, sessionId, nodeId, attemptId, aliasSlot) {
7
+ return `${tokenKind}:${aliasSlot ?? ''}:${sessionId}:${nodeId}:${attemptId ?? ''}`;
8
+ }
9
+ class LocalTokenAliasStoreV2 {
10
+ constructor(dataDir, fs) {
11
+ this.dataDir = dataDir;
12
+ this.fs = fs;
13
+ this.index = new Map();
14
+ this.positionIndex = new Map();
15
+ }
16
+ register(entry) {
17
+ if (this.index.has(entry.nonceHex)) {
18
+ return (0, neverthrow_1.errAsync)({
19
+ code: 'ALIAS_DUPLICATE_NONCE',
20
+ nonceHex: entry.nonceHex,
21
+ });
22
+ }
23
+ const line = { v: ALIAS_FILE_VERSION, ...entry };
24
+ const lineBytes = encodeJsonlLine(line);
25
+ const filePath = this.dataDir.tokenIndexPath();
26
+ const dir = this.dataDir.keysDir();
27
+ return this.fs.mkdirp(dir)
28
+ .andThen(() => this.fs.openAppend(filePath))
29
+ .andThen((handle) => this.fs.writeAll(handle.fd, lineBytes)
30
+ .andThen(() => this.fs.fsyncFile(handle.fd))
31
+ .andThen(() => this.fs.closeFile(handle.fd))
32
+ .orElse((e) => this.fs.closeFile(handle.fd)
33
+ .mapErr(() => e)
34
+ .andThen(() => (0, neverthrow_1.errAsync)(e))))
35
+ .map(() => {
36
+ this.index.set(entry.nonceHex, entry);
37
+ this.positionIndex.set(positionKey(entry.tokenKind, entry.sessionId, entry.nodeId, entry.attemptId, entry.aliasSlot), entry.nonceHex);
38
+ })
39
+ .mapErr((e) => ({
40
+ code: 'ALIAS_IO_ERROR',
41
+ message: e.message ?? String(e),
42
+ }));
43
+ }
44
+ lookup(nonceHex) {
45
+ return this.index.get(nonceHex) ?? null;
46
+ }
47
+ lookupByPosition(tokenKind, sessionId, nodeId, attemptId, aliasSlot) {
48
+ const key = positionKey(tokenKind, sessionId, nodeId, attemptId, aliasSlot);
49
+ const nonceHex = this.positionIndex.get(key);
50
+ if (!nonceHex)
51
+ return null;
52
+ return this.index.get(nonceHex) ?? null;
53
+ }
54
+ loadIndex() {
55
+ const filePath = this.dataDir.tokenIndexPath();
56
+ return this.fs.readFileUtf8(filePath)
57
+ .map((content) => {
58
+ let loaded = 0;
59
+ let skipped = 0;
60
+ for (const line of content.split('\n')) {
61
+ const trimmed = line.trim();
62
+ if (!trimmed)
63
+ continue;
64
+ try {
65
+ const parsed = JSON.parse(trimmed);
66
+ const entry = parseAliasLine(parsed);
67
+ if (entry) {
68
+ this.index.set(entry.nonceHex, entry);
69
+ this.positionIndex.set(positionKey(entry.tokenKind, entry.sessionId, entry.nodeId, entry.attemptId, entry.aliasSlot), entry.nonceHex);
70
+ loaded++;
71
+ }
72
+ else {
73
+ skipped++;
74
+ }
75
+ }
76
+ catch {
77
+ skipped++;
78
+ }
79
+ }
80
+ if (skipped > 0) {
81
+ process.stderr.write(`[TokenAliasStore] loadIndex: loaded=${loaded} skipped=${skipped} (malformed lines)\n`);
82
+ }
83
+ })
84
+ .orElse((e) => {
85
+ if (e.code === 'FS_NOT_FOUND')
86
+ return (0, neverthrow_1.okAsync)(undefined);
87
+ return (0, neverthrow_1.errAsync)({ code: 'ALIAS_IO_ERROR', message: e.message });
88
+ });
89
+ }
90
+ }
91
+ exports.LocalTokenAliasStoreV2 = LocalTokenAliasStoreV2;
92
+ function encodeJsonlLine(line) {
93
+ return new TextEncoder().encode(JSON.stringify(line) + '\n');
94
+ }
95
+ function parseAliasLine(parsed) {
96
+ if (typeof parsed !== 'object' || parsed === null)
97
+ return null;
98
+ const r = parsed;
99
+ if (r['v'] !== ALIAS_FILE_VERSION ||
100
+ typeof r['nonceHex'] !== 'string' ||
101
+ (r['tokenKind'] !== 'state' && r['tokenKind'] !== 'ack' && r['tokenKind'] !== 'checkpoint' && r['tokenKind'] !== 'continue') ||
102
+ typeof r['sessionId'] !== 'string' ||
103
+ typeof r['runId'] !== 'string' ||
104
+ typeof r['nodeId'] !== 'string') {
105
+ return null;
106
+ }
107
+ return {
108
+ nonceHex: r['nonceHex'],
109
+ tokenKind: r['tokenKind'],
110
+ sessionId: r['sessionId'],
111
+ runId: r['runId'],
112
+ nodeId: r['nodeId'],
113
+ ...(typeof r['attemptId'] === 'string' ? { attemptId: r['attemptId'] } : {}),
114
+ ...(r['aliasSlot'] === 'retry' ? { aliasSlot: 'retry' } : {}),
115
+ ...(typeof r['workflowHashRef'] === 'string' ? { workflowHashRef: r['workflowHashRef'] } : {}),
116
+ };
117
+ }
@@ -11,4 +11,5 @@ export interface DataDirPortV2 {
11
11
  sessionEventsDir(sessionId: SessionId): string;
12
12
  sessionManifestPath(sessionId: SessionId): string;
13
13
  sessionLockPath(sessionId: SessionId): string;
14
+ tokenIndexPath(): string;
14
15
  }
@@ -0,0 +1,33 @@
1
+ import type { ResultAsync } from 'neverthrow';
2
+ import type { ShortTokenKind } from '../durable-core/tokens/short-token.js';
3
+ export interface TokenAliasEntryV2 {
4
+ readonly nonceHex: string;
5
+ readonly tokenKind: ShortTokenKind;
6
+ readonly aliasSlot?: 'retry';
7
+ readonly sessionId: string;
8
+ readonly runId: string;
9
+ readonly nodeId: string;
10
+ readonly attemptId?: string;
11
+ readonly workflowHashRef?: string;
12
+ }
13
+ export type TokenAliasRegistrationError = {
14
+ readonly code: 'ALIAS_IO_ERROR';
15
+ readonly message: string;
16
+ } | {
17
+ readonly code: 'ALIAS_DUPLICATE_NONCE';
18
+ readonly nonceHex: string;
19
+ };
20
+ export type TokenAliasLookupError = {
21
+ readonly code: 'ALIAS_IO_ERROR';
22
+ readonly message: string;
23
+ };
24
+ export type TokenAliasLoadError = {
25
+ readonly code: 'ALIAS_IO_ERROR';
26
+ readonly message: string;
27
+ };
28
+ export interface TokenAliasStorePortV2 {
29
+ register(entry: TokenAliasEntryV2): ResultAsync<void, TokenAliasRegistrationError>;
30
+ lookup(nonceHex: string): TokenAliasEntryV2 | null;
31
+ lookupByPosition(tokenKind: ShortTokenKind, sessionId: string, nodeId: string, attemptId?: string, aliasSlot?: 'retry'): TokenAliasEntryV2 | null;
32
+ loadIndex(): ResultAsync<void, TokenAliasLoadError>;
33
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });