@exaudeus/workrail 0.15.0 → 0.17.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 (32) hide show
  1. package/dist/di/container.js +7 -0
  2. package/dist/di/tokens.d.ts +1 -0
  3. package/dist/di/tokens.js +1 -0
  4. package/dist/manifest.json +96 -24
  5. package/dist/mcp/handlers/v2-execution.js +40 -23
  6. package/dist/mcp/handlers/workflow.js +1 -1
  7. package/dist/mcp/server.js +8 -0
  8. package/dist/mcp/tool-descriptions.js +8 -2
  9. package/dist/mcp/tools.d.ts +3 -3
  10. package/dist/mcp/tools.js +5 -4
  11. package/dist/mcp/types.d.ts +4 -0
  12. package/dist/mcp/v2/tools.js +2 -2
  13. package/dist/mcp/validation/index.d.ts +7 -0
  14. package/dist/mcp/validation/index.js +30 -0
  15. package/dist/mcp/validation/schema-introspection.d.ts +8 -0
  16. package/dist/mcp/validation/schema-introspection.js +163 -0
  17. package/dist/mcp/validation/string-similarity.d.ts +10 -0
  18. package/dist/mcp/validation/string-similarity.js +76 -0
  19. package/dist/mcp/validation/suggestion-config.d.ts +9 -0
  20. package/dist/mcp/validation/suggestion-config.js +16 -0
  21. package/dist/mcp/validation/suggestion-generator.d.ts +6 -0
  22. package/dist/mcp/validation/suggestion-generator.js +101 -0
  23. package/dist/mcp/validation/suggestion-types.d.ts +31 -0
  24. package/dist/mcp/validation/suggestion-types.js +23 -0
  25. package/dist/v2/durable-core/encoding/base32-lower.d.ts +4 -0
  26. package/dist/v2/durable-core/encoding/base32-lower.js +30 -0
  27. package/dist/v2/durable-core/ids/attempt-id-derivation.d.ts +3 -0
  28. package/dist/v2/durable-core/ids/attempt-id-derivation.js +32 -0
  29. package/dist/v2/durable-core/tokens/payloads.js +5 -4
  30. package/dist/v2/infra/local/id-factory/index.d.ts +11 -0
  31. package/dist/v2/infra/local/id-factory/index.js +32 -0
  32. package/package.json +1 -1
@@ -181,6 +181,7 @@ async function registerV2Services() {
181
181
  const { NodeBase64UrlV2 } = await Promise.resolve().then(() => __importStar(require('../v2/infra/local/base64url/index.js')));
182
182
  const { NodeRandomEntropyV2 } = await Promise.resolve().then(() => __importStar(require('../v2/infra/local/random-entropy/index.js')));
183
183
  const { NodeTimeClockV2 } = await Promise.resolve().then(() => __importStar(require('../v2/infra/local/time-clock/index.js')));
184
+ const { IdFactoryV2 } = await Promise.resolve().then(() => __importStar(require('../v2/infra/local/id-factory/index.js')));
184
185
  tsyringe_1.container.register(tokens_js_1.DI.V2.DataDir, {
185
186
  useFactory: (0, tsyringe_1.instanceCachingFactory)(() => new LocalDataDirV2(process.env)),
186
187
  });
@@ -205,6 +206,12 @@ async function registerV2Services() {
205
206
  tsyringe_1.container.register(tokens_js_1.DI.V2.TimeClock, {
206
207
  useFactory: (0, tsyringe_1.instanceCachingFactory)(() => new NodeTimeClockV2()),
207
208
  });
209
+ tsyringe_1.container.register(tokens_js_1.DI.V2.IdFactory, {
210
+ useFactory: (0, tsyringe_1.instanceCachingFactory)((c) => {
211
+ const entropy = c.resolve(tokens_js_1.DI.V2.RandomEntropy);
212
+ return new IdFactoryV2(entropy);
213
+ }),
214
+ });
208
215
  const { LocalKeyringV2 } = await Promise.resolve().then(() => __importStar(require('../v2/infra/local/keyring/index.js')));
209
216
  const { LocalSessionEventLogStoreV2 } = await Promise.resolve().then(() => __importStar(require('../v2/infra/local/session-store/index.js')));
210
217
  const { LocalSnapshotStoreV2 } = await Promise.resolve().then(() => __importStar(require('../v2/infra/local/snapshot-store/index.js')));
@@ -30,6 +30,7 @@ export declare const DI: {
30
30
  readonly Base64Url: symbol;
31
31
  readonly RandomEntropy: symbol;
32
32
  readonly TimeClock: symbol;
33
+ readonly IdFactory: symbol;
33
34
  readonly Keyring: symbol;
34
35
  readonly SessionStore: symbol;
35
36
  readonly SnapshotStore: symbol;
package/dist/di/tokens.js CHANGED
@@ -33,6 +33,7 @@ exports.DI = {
33
33
  Base64Url: Symbol('V2.Base64Url'),
34
34
  RandomEntropy: Symbol('V2.RandomEntropy'),
35
35
  TimeClock: Symbol('V2.TimeClock'),
36
+ IdFactory: Symbol('V2.IdFactory'),
36
37
  Keyring: Symbol('V2.Keyring'),
37
38
  SessionStore: Symbol('V2.SessionStore'),
38
39
  SnapshotStore: Symbol('V2.SnapshotStore'),
@@ -254,16 +254,16 @@
254
254
  "bytes": 565
255
255
  },
256
256
  "di/container.js": {
257
- "sha256": "ab2e782ae89f52655598140677903c37257ee14d15dab77fcaa2ca43afb9a260",
258
- "bytes": 18492
257
+ "sha256": "200c41528c64e4e8cf0e04046bfd254cdbe0900c157be2dfd8c302a4a096d193",
258
+ "bytes": 18890
259
259
  },
260
260
  "di/tokens.d.ts": {
261
- "sha256": "2be51a547ab9bfdd2026e7e9cfdc79ee693ad5454fa3dd773e72659a49837fde",
262
- "bytes": 1846
261
+ "sha256": "3b9e46e178107ad65575350da5d99c238e7a4389d3537e67ff516a04df1191fe",
262
+ "bytes": 1882
263
263
  },
264
264
  "di/tokens.js": {
265
- "sha256": "a8774e7c93f07a829d4770b33f6aef663cc68a055ed88236a085f553bf161297",
266
- "bytes": 2284
265
+ "sha256": "aa90a1af7eba9941663beeeb13a25e2f3ba877ba37cb786bac46b468cc840f1b",
266
+ "bytes": 2327
267
267
  },
268
268
  "domain/execution/error.d.ts": {
269
269
  "sha256": "2eac85c42ec399a23724f868641eeadd0d196b4d324ee4caaff82a6b46155bd9",
@@ -534,8 +534,8 @@
534
534
  "bytes": 399
535
535
  },
536
536
  "mcp/handlers/v2-execution.js": {
537
- "sha256": "58502dd04d88634578de5e32af45fc1671e2decc90b8eb9d8a6819a37b9d1bce",
538
- "bytes": 52776
537
+ "sha256": "4f3f7d9009007a6795e2dfe998165722f660354323f7e856b26f1a7f62a136be",
538
+ "bytes": 53400
539
539
  },
540
540
  "mcp/handlers/v2-workflow.d.ts": {
541
541
  "sha256": "9fbd4d44854e2060c54982b21e72c608970bb2bd107bb15a8388b26c6b492e55",
@@ -550,8 +550,8 @@
550
550
  "bytes": 1748
551
551
  },
552
552
  "mcp/handlers/workflow.js": {
553
- "sha256": "99ff7aac9705ef540cc5681515cf2aa9650d886761f7ae69f829ff87ac772756",
554
- "bytes": 8246
553
+ "sha256": "7ebd383922c6f238c35c376c8a0aa87b0969a80bb4e7c48e704a8480fd974bb4",
554
+ "bytes": 8254
555
555
  },
556
556
  "mcp/index.d.ts": {
557
557
  "sha256": "525b4247cf90ba3af66769462bcfaab5dbf38ee8c49d2a9ceec1e4b38e33511b",
@@ -574,8 +574,8 @@
574
574
  "bytes": 168
575
575
  },
576
576
  "mcp/server.js": {
577
- "sha256": "41c61033d821f9794cada0bb40058fa220fa11175897326ae597df422a1fcd0b",
578
- "bytes": 13552
577
+ "sha256": "f6bc4b1f3416d03add7b715a5bdae7955a877eae8008c0d2f8b8490dd8ae5708",
578
+ "bytes": 14097
579
579
  },
580
580
  "mcp/tool-description-provider.d.ts": {
581
581
  "sha256": "1d46abc3112e11b68e57197e846f5708293ec9b2281fa71a9124ee2aad71e41b",
@@ -590,8 +590,8 @@
590
590
  "bytes": 132
591
591
  },
592
592
  "mcp/tool-descriptions.js": {
593
- "sha256": "06a6eff077301d66a90b6240fbebae166ddfdcd3aa9177d5cfb48d6e0a31698c",
594
- "bytes": 7792
593
+ "sha256": "c8150119782dadd286e8430e9377b0b727891c414be2396e314423713939d6eb",
594
+ "bytes": 7980
595
595
  },
596
596
  "mcp/tool-factory.d.ts": {
597
597
  "sha256": "0fe3c6b863b2d7aef0c3d659ff54f3a9ee8a0a3c2005b6565d2f8ad517bc7211",
@@ -602,16 +602,16 @@
602
602
  "bytes": 479
603
603
  },
604
604
  "mcp/tools.d.ts": {
605
- "sha256": "f11991cdc3cdbd2912c38252541818adaca8a99c08cc7c1aaa37636ae112cfd6",
606
- "bytes": 5952
605
+ "sha256": "8474e810cae37197d5968be4c3dfb9751ba2b09fe8a7f39e0e7dcc414af4bdb5",
606
+ "bytes": 5976
607
607
  },
608
608
  "mcp/tools.js": {
609
- "sha256": "34522d0b078477627fe068130d3b0a5d4d8cc9fc90599a583d979080d632f544",
610
- "bytes": 7688
609
+ "sha256": "0af59932b32bad5ebc9cbc925279d325350c91b43085561d0d218035250b641a",
610
+ "bytes": 8020
611
611
  },
612
612
  "mcp/types.d.ts": {
613
- "sha256": "4ab4a4af1eeedf9ba9bcdc70476a5adcc24ce05b3d7d715d70979052b1eb7246",
614
- "bytes": 3473
613
+ "sha256": "3b7d7d7d30d65cd22b47bc9d559820b3f51984476fce11d4f3b6d820e2ce1eb8",
614
+ "bytes": 3683
615
615
  },
616
616
  "mcp/types.js": {
617
617
  "sha256": "0c12576fd0053115ff096fe26b38f77f1e830b7ec4781aaf94564827c4c9e81a",
@@ -638,8 +638,8 @@
638
638
  "bytes": 2579
639
639
  },
640
640
  "mcp/v2/tools.js": {
641
- "sha256": "9e934ea8a5f83bffc68d343970292267b207f67d72a5aa824348967e53777820",
642
- "bytes": 2333
641
+ "sha256": "4b0d5d1c019d3f747b0f4211a606d1aba4944f9e570ae9fecc6831987a6cc16f",
642
+ "bytes": 2537
643
643
  },
644
644
  "mcp/validation/bounded-json.d.ts": {
645
645
  "sha256": "82203ac6123d5c6989606c3b5405aaea99ab829c8958835f9ae3ba45b8bc8fd5",
@@ -649,6 +649,54 @@
649
649
  "sha256": "0134fd92e1b160f1b57230d9f8a471044858af43484206f911619cf7159e3f0d",
650
650
  "bytes": 834
651
651
  },
652
+ "mcp/validation/index.d.ts": {
653
+ "sha256": "3e3f12357fd8214470d111454e4002338e5eb93329b5a3758664db51e44c12ec",
654
+ "bytes": 944
655
+ },
656
+ "mcp/validation/index.js": {
657
+ "sha256": "dccd3a2dc7e486afd27ee44f77303486f60cc840563821b97ac341f9cad6650c",
658
+ "bytes": 4445
659
+ },
660
+ "mcp/validation/schema-introspection.d.ts": {
661
+ "sha256": "7e0262e76234dd37079156027e95a30987b8949351f3e9ec0fd7b2be093a159d",
662
+ "bytes": 713
663
+ },
664
+ "mcp/validation/schema-introspection.js": {
665
+ "sha256": "850c09a3c01a5f22440ebc34236c393f3b428748210f5277258a9905cb847d71",
666
+ "bytes": 5293
667
+ },
668
+ "mcp/validation/string-similarity.d.ts": {
669
+ "sha256": "4326210a768a526336b54d4ea20a128a939d92f53e8b2a5a33da06b5372d196a",
670
+ "bytes": 671
671
+ },
672
+ "mcp/validation/string-similarity.js": {
673
+ "sha256": "fafdb80673ad56336009e562cd5dccd93486dd94fa78acbb923cdc47ba63becf",
674
+ "bytes": 2627
675
+ },
676
+ "mcp/validation/suggestion-config.d.ts": {
677
+ "sha256": "70b8395db74ec18bb1ef2309dd16516345b75839d2793bf9c5bfbd1e1d1baa0e",
678
+ "bytes": 388
679
+ },
680
+ "mcp/validation/suggestion-config.js": {
681
+ "sha256": "efda43e48812979d0ddae2abe23809b6b5a3e5b955e74ca5a67716933e468db4",
682
+ "bytes": 592
683
+ },
684
+ "mcp/validation/suggestion-generator.d.ts": {
685
+ "sha256": "491d983f4a03516fc0ba09ff40da2c859ec600f29a41093b0359ba549c7882cc",
686
+ "bytes": 450
687
+ },
688
+ "mcp/validation/suggestion-generator.js": {
689
+ "sha256": "e952a4d3cb569222cde1bd01dd9d5be887ee394ba007478bbb446fa177172859",
690
+ "bytes": 4075
691
+ },
692
+ "mcp/validation/suggestion-types.d.ts": {
693
+ "sha256": "b93ae2e42f4b24789dcbe19db31a41af9534ad0dca85635339c2a10db42e298b",
694
+ "bytes": 1333
695
+ },
696
+ "mcp/validation/suggestion-types.js": {
697
+ "sha256": "c7753960a199508a8a59f8030c4240a076857a3e5926efadc01e808f08d7ff3a",
698
+ "bytes": 729
699
+ },
652
700
  "mcp/validation/workflow-next-prevalidate.d.ts": {
653
701
  "sha256": "179058225dfb17f4be02d6105bbacdaa99f1441cfc25062b38d8283f0bf35b5a",
654
702
  "bytes": 254
@@ -945,6 +993,22 @@
945
993
  "sha256": "ae16a0df03c3dec30e9ffca0066b6148568966f6660a3c660f82853e077a0cbd",
946
994
  "bytes": 817
947
995
  },
996
+ "v2/durable-core/encoding/base32-lower.d.ts": {
997
+ "sha256": "849ef1984db20984f1fce7f40b15d3680c888e01411932d30af6fae4d2132a67",
998
+ "bytes": 175
999
+ },
1000
+ "v2/durable-core/encoding/base32-lower.js": {
1001
+ "sha256": "9065da38936496a34c2808388b5fb68d8aaac6bd3f0f05de184abc101e07c419",
1002
+ "bytes": 934
1003
+ },
1004
+ "v2/durable-core/ids/attempt-id-derivation.d.ts": {
1005
+ "sha256": "baee295f114d8d4a74e9fa529e7c72d458a7c7244f50fad9ebbaea06c57dfe92",
1006
+ "bytes": 207
1007
+ },
1008
+ "v2/durable-core/ids/attempt-id-derivation.js": {
1009
+ "sha256": "c13da44f23890d85edfb64a471f4f4817e973a63b41287d79144a3c9c6a5dcea",
1010
+ "bytes": 1309
1011
+ },
948
1012
  "v2/durable-core/ids/index.d.ts": {
949
1013
  "sha256": "5525efc423ad30635996907f7560f53559e49e33a64411a684370ebd1ae56410",
950
1014
  "bytes": 1792
@@ -1086,8 +1150,8 @@
1086
1150
  "bytes": 6756
1087
1151
  },
1088
1152
  "v2/durable-core/tokens/payloads.js": {
1089
- "sha256": "f1026ba47d9b2e0ab3bbec47aa9e8afd5695805f6f4a83ecddd4610616ea4def",
1090
- "bytes": 2343
1153
+ "sha256": "24978999201e0413cb193e1fee2b9977335ecaa9e2170b901358c9119fac6c3a",
1154
+ "bytes": 2479
1091
1155
  },
1092
1156
  "v2/durable-core/tokens/token-codec.d.ts": {
1093
1157
  "sha256": "44bd65c6102b3aa5fcd82d2854f5466263a20c0b9cbd31aa25f169dfeed8e045",
@@ -1145,6 +1209,14 @@
1145
1209
  "sha256": "11917c1d29f34efcd7139f5573067ad20a4093a1c5190e6069ccdc25acf53f24",
1146
1210
  "bytes": 578
1147
1211
  },
1212
+ "v2/infra/local/id-factory/index.d.ts": {
1213
+ "sha256": "ffcbdcce6a9c6a93c2703e0d844f84fef59e6ef8a3f657d50750e885b88e879b",
1214
+ "bytes": 432
1215
+ },
1216
+ "v2/infra/local/id-factory/index.js": {
1217
+ "sha256": "bd7d8cde4fb63b299f11ff51721c9b468c887856d581e95867bbbee6547642e4",
1218
+ "bytes": 1044
1219
+ },
1148
1220
  "v2/infra/local/keyring/index.d.ts": {
1149
1221
  "sha256": "e8698dab64327f994bf78e1a6c30131062d8418847417610e6b071ce7e873763",
1150
1222
  "bytes": 932
@@ -36,7 +36,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.handleV2StartWorkflow = handleV2StartWorkflow;
37
37
  exports.handleV2ContinueWorkflow = handleV2ContinueWorkflow;
38
38
  const os = __importStar(require("os"));
39
- const crypto_1 = require("crypto");
40
39
  const types_js_1 = require("../types.js");
41
40
  const output_schemas_js_1 = require("../output-schemas.js");
42
41
  const snapshot_state_js_1 = require("../../v2/durable-core/projections/snapshot-state.js");
@@ -45,6 +44,7 @@ const index_js_1 = require("../../v2/durable-core/tokens/index.js");
45
44
  const index_js_2 = require("../../v2/durable-core/tokens/index.js");
46
45
  const workflow_js_1 = require("../../types/workflow.js");
47
46
  const index_js_3 = require("../../v2/durable-core/ids/index.js");
47
+ const attempt_id_derivation_js_1 = require("../../v2/durable-core/ids/attempt-id-derivation.js");
48
48
  const neverthrow_1 = require("neverthrow");
49
49
  const v1_to_v2_shim_js_1 = require("../../v2/read-only/v1-to-v2-shim.js");
50
50
  const hashing_js_1 = require("../../v2/durable-core/canonical/hashing.js");
@@ -238,7 +238,7 @@ function mapInternalErrorToToolError(e) {
238
238
  }
239
239
  }
240
240
  function replayFromRecordedAdvance(args) {
241
- const { recordedEvent, truth, sessionId, runId, nodeId, workflowHash, attemptId, inputStateToken, inputAckToken, pinnedWorkflow, snapshotStore, keyring, hmac, base64url, } = args;
241
+ const { recordedEvent, truth, sessionId, runId, nodeId, workflowHash, attemptId, inputStateToken, inputAckToken, pinnedWorkflow, snapshotStore, keyring, sha256, hmac, base64url, } = args;
242
242
  const checkpointTokenRes = signTokenOrErr({
243
243
  unsignedPrefix: 'chk.v1.',
244
244
  payload: { tokenVersion: 1, tokenKind: 'checkpoint', sessionId, runId, nodeId, attemptId },
@@ -295,7 +295,7 @@ function replayFromRecordedAdvance(args) {
295
295
  }
296
296
  const pending = (0, snapshot_state_js_1.derivePendingStep)(snap.enginePayload.engineState);
297
297
  const isComplete = (0, snapshot_state_js_1.deriveIsComplete)(snap.enginePayload.engineState);
298
- const nextAttemptId = attemptIdForNextNode(attemptId);
298
+ const nextAttemptId = attemptIdForNextNode(attemptId, sha256);
299
299
  const nextAckTokenRes = signTokenOrErr({
300
300
  unsignedPrefix: 'ack.v1.',
301
301
  payload: { tokenVersion: 1, tokenKind: 'ack', sessionId, runId, nodeId: toNodeIdBranded, attemptId: nextAttemptId },
@@ -338,7 +338,7 @@ function replayFromRecordedAdvance(args) {
338
338
  });
339
339
  }
340
340
  function advanceAndRecord(args) {
341
- const { truth, sessionId, runId, nodeId, attemptId, workflowHash, dedupeKey, inputContext, inputOutput, lock, pinnedWorkflow, snapshotStore, sessionStore } = args;
341
+ const { truth, sessionId, runId, nodeId, attemptId, workflowHash, dedupeKey, inputContext, inputOutput, lock, pinnedWorkflow, snapshotStore, sessionStore, idFactory } = args;
342
342
  const hasRun = truth.events.some((e) => e.kind === 'run_started' && e.scope?.runId === String(runId));
343
343
  const hasNode = truth.events.some((e) => e.kind === 'node_created' && e.scope?.runId === String(runId) && e.scope?.nodeId === String(nodeId));
344
344
  if (!hasRun || !hasNode) {
@@ -385,11 +385,11 @@ function advanceAndRecord(args) {
385
385
  enginePayload: { v: 1, engineState: newEngineState },
386
386
  };
387
387
  return snapshotStore.putExecutionSnapshotV1(snapshotFile).andThen((newSnapshotRef) => {
388
- const toNodeId = `node_${(0, crypto_1.randomUUID)()}`;
388
+ const toNodeId = String(idFactory.mintNodeId());
389
389
  const nextEventIndex = truth.events.length === 0 ? 0 : truth.events[truth.events.length - 1].eventIndex + 1;
390
- const evtAdvanceRecorded = `evt_${(0, crypto_1.randomUUID)()}`;
391
- const evtNodeCreated = `evt_${(0, crypto_1.randomUUID)()}`;
392
- const evtEdgeCreated = `evt_${(0, crypto_1.randomUUID)()}`;
390
+ const evtAdvanceRecorded = idFactory.mintEventId();
391
+ const evtNodeCreated = idFactory.mintEventId();
392
+ const evtEdgeCreated = idFactory.mintEventId();
393
393
  const hasChildren = truth.events.some((e) => e.kind === 'edge_created' && e.data.fromNodeId === String(nodeId));
394
394
  const causeKind = hasChildren ? 'non_tip_advance' : 'intentional_fork';
395
395
  const outputId = (0, index_js_1.asOutputId)(`out_recap_${String(attemptId)}`);
@@ -406,7 +406,7 @@ function advanceAndRecord(args) {
406
406
  ]
407
407
  : [];
408
408
  const normalizedOutputs = (0, outputs_js_1.normalizeOutputsForAppend)(outputsToAppend);
409
- const outputEventIds = normalizedOutputs.map(() => `evt_${(0, crypto_1.randomUUID)()}`);
409
+ const outputEventIds = normalizedOutputs.map(() => idFactory.mintEventId());
410
410
  const planRes = (0, ack_advance_append_plan_js_1.buildAckAdvanceAppendPlanV1)({
411
411
  sessionId: String(sessionId),
412
412
  runId: String(runId),
@@ -534,11 +534,11 @@ function parseAckTokenOrFail(raw, keyring, hmac, base64url) {
534
534
  }
535
535
  return { ok: true, token: parsedRes.value };
536
536
  }
537
- function newAttemptId() {
538
- return (0, index_js_1.asAttemptId)(`attempt_${(0, crypto_1.randomUUID)()}`);
537
+ function newAttemptId(idFactory) {
538
+ return idFactory.mintAttemptId();
539
539
  }
540
- function attemptIdForNextNode(parentAttemptId) {
541
- return (0, index_js_1.asAttemptId)(`next_${parentAttemptId}`);
540
+ function attemptIdForNextNode(parentAttemptId, sha256) {
541
+ return (0, attempt_id_derivation_js_1.deriveChildAttemptId)(parentAttemptId, sha256);
542
542
  }
543
543
  function signTokenOrErr(args) {
544
544
  const bytes = (0, index_js_2.encodeTokenPayloadV1)(args.payload);
@@ -630,7 +630,14 @@ function executeStartWorkflow(input, ctx) {
630
630
  if (!ctx.v2) {
631
631
  return (0, neverthrow_1.errAsync)({ kind: 'precondition_failed', message: 'v2 tools disabled', suggestion: 'Enable v2Tools flag' });
632
632
  }
633
- const { gate, sessionStore, snapshotStore, pinnedStore, keyring, crypto, hmac, base64url } = ctx.v2;
633
+ const { gate, sessionStore, snapshotStore, pinnedStore, keyring, crypto, hmac, base64url, idFactory } = ctx.v2;
634
+ if (!idFactory) {
635
+ return (0, neverthrow_1.errAsync)({
636
+ kind: 'precondition_failed',
637
+ message: 'v2 context missing idFactory',
638
+ suggestion: 'Reinitialize v2 tool context (idFactory must be provided when v2Tools are enabled).',
639
+ });
640
+ }
634
641
  const ctxCheck = checkContextBudget({ tool: 'start_workflow', context: input.context });
635
642
  if (!ctxCheck.ok)
636
643
  return (0, neverthrow_1.errAsync)({ kind: 'validation_failed', failure: ctxCheck.error });
@@ -678,9 +685,9 @@ function executeStartWorkflow(input, ctx) {
678
685
  });
679
686
  })
680
687
  .andThen(({ workflow, firstStep, workflowHash, pinnedWorkflow }) => {
681
- const sessionId = (0, index_js_3.asSessionId)(`sess_${(0, crypto_1.randomUUID)()}`);
682
- const runId = (0, index_js_3.asRunId)(`run_${(0, crypto_1.randomUUID)()}`);
683
- const nodeId = (0, index_js_3.asNodeId)(`node_${(0, crypto_1.randomUUID)()}`);
688
+ const sessionId = idFactory.mintSessionId();
689
+ const runId = idFactory.mintRunId();
690
+ const nodeId = idFactory.mintNodeId();
684
691
  const snapshot = {
685
692
  v: 1,
686
693
  kind: 'execution_snapshot',
@@ -697,9 +704,9 @@ function executeStartWorkflow(input, ctx) {
697
704
  return snapshotStore.putExecutionSnapshotV1(snapshot)
698
705
  .mapErr((cause) => ({ kind: 'snapshot_creation_failed', cause }))
699
706
  .andThen((snapshotRef) => {
700
- const evtSessionCreated = `evt_${(0, crypto_1.randomUUID)()}`;
701
- const evtRunStarted = `evt_${(0, crypto_1.randomUUID)()}`;
702
- const evtNodeCreated = `evt_${(0, crypto_1.randomUUID)()}`;
707
+ const evtSessionCreated = idFactory.mintEventId();
708
+ const evtRunStarted = idFactory.mintEventId();
709
+ const evtNodeCreated = idFactory.mintEventId();
703
710
  return gate.withHealthySessionLock(sessionId, (lock) => {
704
711
  const eventsArray = [
705
712
  {
@@ -768,7 +775,7 @@ function executeStartWorkflow(input, ctx) {
768
775
  nodeId,
769
776
  workflowHash,
770
777
  };
771
- const attemptId = newAttemptId();
778
+ const attemptId = newAttemptId(idFactory);
772
779
  const ackPayload = {
773
780
  tokenVersion: 1,
774
781
  tokenKind: 'ack',
@@ -812,7 +819,14 @@ function executeContinueWorkflow(input, ctx) {
812
819
  if (!ctx.v2) {
813
820
  return (0, neverthrow_1.errAsync)({ kind: 'precondition_failed', message: 'v2 tools disabled', suggestion: 'Enable v2Tools flag' });
814
821
  }
815
- const { gate, sessionStore, snapshotStore, pinnedStore, keyring, crypto, hmac, base64url } = ctx.v2;
822
+ const { gate, sessionStore, snapshotStore, pinnedStore, keyring, sha256, crypto, hmac, base64url, idFactory } = ctx.v2;
823
+ if (!sha256 || !idFactory) {
824
+ return (0, neverthrow_1.errAsync)({
825
+ kind: 'precondition_failed',
826
+ message: 'v2 context missing required dependencies',
827
+ suggestion: 'Reinitialize v2 tool context (sha256 and idFactory must be provided when v2Tools are enabled).',
828
+ });
829
+ }
816
830
  const stateRes = parseStateTokenOrFail(input.stateToken, keyring, hmac, base64url);
817
831
  if (!stateRes.ok)
818
832
  return (0, neverthrow_1.errAsync)({ kind: 'validation_failed', failure: stateRes.failure });
@@ -864,7 +878,7 @@ function executeContinueWorkflow(input, ctx) {
864
878
  const engineState = snapshot.enginePayload.engineState;
865
879
  const pending = (0, snapshot_state_js_1.derivePendingStep)(engineState);
866
880
  const isComplete = (0, snapshot_state_js_1.deriveIsComplete)(engineState);
867
- const attemptId = newAttemptId();
881
+ const attemptId = newAttemptId(idFactory);
868
882
  const ackTokenRes = signTokenOrErr({
869
883
  unsignedPrefix: 'ack.v1.',
870
884
  payload: { tokenVersion: 1, tokenKind: 'ack', sessionId, runId, nodeId, attemptId },
@@ -963,6 +977,7 @@ function executeContinueWorkflow(input, ctx) {
963
977
  pinnedWorkflow,
964
978
  snapshotStore,
965
979
  keyring,
980
+ sha256,
966
981
  hmac,
967
982
  base64url,
968
983
  });
@@ -986,6 +1001,7 @@ function executeContinueWorkflow(input, ctx) {
986
1001
  pinnedWorkflow,
987
1002
  snapshotStore,
988
1003
  sessionStore,
1004
+ idFactory,
989
1005
  }).andThen(() => sessionStore
990
1006
  .load(sessionId)
991
1007
  .map((truthAfter) => ({ kind: 'replay', truth: truthAfter, recordedEvent: null })));
@@ -1035,6 +1051,7 @@ function executeContinueWorkflow(input, ctx) {
1035
1051
  pinnedWorkflow,
1036
1052
  snapshotStore,
1037
1053
  keyring,
1054
+ sha256,
1038
1055
  hmac,
1039
1056
  base64url,
1040
1057
  });
@@ -65,7 +65,7 @@ async function handleWorkflowGet(input, ctx) {
65
65
  try {
66
66
  const { createGetWorkflow } = await Promise.resolve().then(() => __importStar(require('../../application/use-cases/get-workflow.js')));
67
67
  const getWorkflowUseCase = createGetWorkflow(ctx.workflowService);
68
- const result = await withTimeout(getWorkflowUseCase(input.id, input.mode), TIMEOUT_MS, 'workflow_get');
68
+ const result = await withTimeout(getWorkflowUseCase(input.workflowId, input.mode), TIMEOUT_MS, 'workflow_get');
69
69
  if (result.isErr()) {
70
70
  const mapped = (0, error_mapper_js_1.mapDomainErrorToToolError)(result.error);
71
71
  return mapped;
@@ -42,6 +42,7 @@ const types_js_1 = require("./types.js");
42
42
  const tool_factory_js_1 = require("./tool-factory.js");
43
43
  const workflow_next_prevalidate_js_1 = require("./validation/workflow-next-prevalidate.js");
44
44
  const bounded_json_js_1 = require("./validation/bounded-json.js");
45
+ const index_js_1 = require("./validation/index.js");
45
46
  const tools_js_1 = require("./tools.js");
46
47
  const tool_registry_js_1 = require("./v2/tool-registry.js");
47
48
  const workflow_js_1 = require("./handlers/workflow.js");
@@ -94,18 +95,22 @@ async function createToolContext() {
94
95
  console.error('[FeatureFlags] v2 tools disabled due to keyring initialization failure');
95
96
  }
96
97
  else {
98
+ const sha256 = container_js_1.container.resolve(tokens_js_1.DI.V2.Sha256);
97
99
  const crypto = container_js_1.container.resolve(tokens_js_1.DI.V2.Crypto);
98
100
  const hmac = container_js_1.container.resolve(tokens_js_1.DI.V2.HmacSha256);
99
101
  const base64url = container_js_1.container.resolve(tokens_js_1.DI.V2.Base64Url);
102
+ const idFactory = container_js_1.container.resolve(tokens_js_1.DI.V2.IdFactory);
100
103
  v2 = {
101
104
  gate,
102
105
  sessionStore,
103
106
  snapshotStore,
104
107
  pinnedStore,
105
108
  keyring: keyringResult.value,
109
+ sha256,
106
110
  crypto,
107
111
  hmac,
108
112
  base64url,
113
+ idFactory,
109
114
  };
110
115
  console.error('[FeatureFlags] v2 tools enabled');
111
116
  }
@@ -133,11 +138,14 @@ function createHandler(schema, handler) {
133
138
  return async (args, ctx) => {
134
139
  const parseResult = schema.safeParse(args);
135
140
  if (!parseResult.success) {
141
+ const suggestionResult = (0, index_js_1.generateSuggestions)(args, schema, index_js_1.DEFAULT_SUGGESTION_CONFIG);
142
+ const suggestionDetails = (0, index_js_1.formatSuggestionDetails)(suggestionResult);
136
143
  return toMcpResult((0, types_js_1.errNotRetryable)('VALIDATION_ERROR', 'Invalid input', {
137
144
  validationErrors: parseResult.error.errors.map(e => ({
138
145
  path: e.path.join('.'),
139
146
  message: e.message,
140
147
  })),
148
+ ...suggestionDetails,
141
149
  }));
142
150
  }
143
151
  return toMcpResult(await handler(parseResult.data, ctx));
@@ -10,7 +10,11 @@ Your process:
10
10
  2. Analyze the returned descriptions to find a match for the user's goal.
11
11
  3. If a good match is found, suggest it to the user and use preview_workflow to start.
12
12
  4. If NO match is found, inform the user and then attempt to solve the task using your general abilities.`,
13
- preview_workflow: `Retrieves workflow information with configurable detail level. Supports progressive disclosure to prevent "workflow spoiling" while providing necessary context for workflow selection and initiation.`,
13
+ preview_workflow: `Retrieves workflow information with configurable detail level. Supports progressive disclosure to prevent "workflow spoiling" while providing necessary context for workflow selection and initiation.
14
+
15
+ Parameters:
16
+ - workflowId: The unique identifier of the workflow to retrieve
17
+ - mode (optional): 'metadata' for overview only, 'preview' (default) for first step`,
14
18
  advance_workflow: `Executes one workflow step at a time by returning the next eligible step and an updated execution state.
15
19
 
16
20
  Inputs:
@@ -75,7 +79,9 @@ By retrieving a workflow, you agree to:
75
79
 
76
80
  The workflow content is the user's will expressed as structured steps. Treat each step as a direct instruction from the user.
77
81
 
78
- Returns: Workflow metadata and first step. Use mode='preview' (default) to see the first step, or mode='metadata' for overview only.`,
82
+ Parameters:
83
+ - workflowId: The unique identifier of the workflow to retrieve
84
+ - mode (optional): 'metadata' for overview only, 'preview' (default) for first step`,
79
85
  advance_workflow: `Get your next MANDATORY INSTRUCTION from the active workflow.
80
86
 
81
87
  The step returned is a DIRECT INSTRUCTION from the user. You MUST:
@@ -3,13 +3,13 @@ export type { ToolAnnotations, ToolDefinition } from './tool-factory.js';
3
3
  export declare const WorkflowListInput: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
4
4
  export type WorkflowListInput = z.infer<typeof WorkflowListInput>;
5
5
  export declare const WorkflowGetInput: z.ZodObject<{
6
- id: z.ZodString;
6
+ workflowId: z.ZodString;
7
7
  mode: z.ZodDefault<z.ZodEnum<["metadata", "preview"]>>;
8
8
  }, "strip", z.ZodTypeAny, {
9
- id: string;
9
+ workflowId: string;
10
10
  mode: "metadata" | "preview";
11
11
  }, {
12
- id: string;
12
+ workflowId: string;
13
13
  mode?: "metadata" | "preview" | undefined;
14
14
  }>;
15
15
  export type WorkflowGetInput = z.infer<typeof WorkflowGetInput>;
package/dist/mcp/tools.js CHANGED
@@ -6,9 +6,9 @@ const state_js_1 = require("../domain/execution/state.js");
6
6
  const event_js_1 = require("../domain/execution/event.js");
7
7
  exports.WorkflowListInput = zod_1.z.object({});
8
8
  exports.WorkflowGetInput = zod_1.z.object({
9
- id: zod_1.z
9
+ workflowId: zod_1.z
10
10
  .string()
11
- .regex(/^[A-Za-z0-9_-]+$/, 'ID must contain only letters, numbers, hyphens, and underscores')
11
+ .regex(/^[A-Za-z0-9_-]+$/, 'Workflow ID must contain only letters, numbers, hyphens, and underscores')
12
12
  .describe('The unique identifier of the workflow to retrieve'),
13
13
  mode: zod_1.z
14
14
  .enum(['metadata', 'preview'])
@@ -97,6 +97,7 @@ exports.WORKFLOW_TOOL_TITLES = {
97
97
  exports.CreateSessionInput = zod_1.z.object({
98
98
  workflowId: zod_1.z
99
99
  .string()
100
+ .regex(/^[A-Za-z0-9_-]+$/, 'Workflow ID must contain only letters, numbers, hyphens, and underscores')
100
101
  .describe('Workflow identifier (e.g., "bug-investigation", "mr-review")'),
101
102
  sessionId: zod_1.z
102
103
  .string()
@@ -107,14 +108,14 @@ exports.CreateSessionInput = zod_1.z.object({
107
108
  .describe('Initial session data. Can include dashboard, phases, etc.'),
108
109
  });
109
110
  exports.UpdateSessionInput = zod_1.z.object({
110
- workflowId: zod_1.z.string().describe('Workflow identifier'),
111
+ workflowId: zod_1.z.string().regex(/^[A-Za-z0-9_-]+$/, 'Workflow ID must contain only letters, numbers, hyphens, and underscores').describe('Workflow identifier'),
111
112
  sessionId: zod_1.z.string().describe('Session identifier'),
112
113
  updates: zod_1.z
113
114
  .record(zod_1.z.unknown())
114
115
  .describe('Data to merge into session. Supports nested updates via dot notation.'),
115
116
  });
116
117
  exports.ReadSessionInput = zod_1.z.object({
117
- workflowId: zod_1.z.string().describe('Workflow identifier'),
118
+ workflowId: zod_1.z.string().regex(/^[A-Za-z0-9_-]+$/, 'Workflow ID must contain only letters, numbers, hyphens, and underscores').describe('Workflow identifier'),
118
119
  sessionId: zod_1.z.string().describe('Session identifier'),
119
120
  path: zod_1.z
120
121
  .string()
@@ -8,9 +8,11 @@ import type { SessionEventLogAppendStorePortV2, SessionEventLogReadonlyStorePort
8
8
  import type { SnapshotStorePortV2 } from '../v2/ports/snapshot-store.port.js';
9
9
  import type { PinnedWorkflowStorePortV2 } from '../v2/ports/pinned-workflow-store.port.js';
10
10
  import type { KeyringV1 } from '../v2/ports/keyring.port.js';
11
+ import type { Sha256PortV2 } from '../v2/ports/sha256.port.js';
11
12
  import type { CryptoPortV2 } from '../v2/durable-core/canonical/hashing.js';
12
13
  import type { HmacSha256PortV2 } from '../v2/ports/hmac-sha256.port.js';
13
14
  import type { Base64UrlPortV2 } from '../v2/ports/base64url.port.js';
15
+ import type { IdFactoryV2 } from '../v2/infra/local/id-factory/index.js';
14
16
  import type { JsonValue } from './output-schemas.js';
15
17
  export interface SessionHealthDetails {
16
18
  readonly health: SessionHealthV2;
@@ -48,9 +50,11 @@ export interface V2Dependencies {
48
50
  readonly snapshotStore: SnapshotStorePortV2;
49
51
  readonly pinnedStore: PinnedWorkflowStorePortV2;
50
52
  readonly keyring: KeyringV1;
53
+ readonly sha256: Sha256PortV2;
51
54
  readonly crypto: CryptoPortV2;
52
55
  readonly hmac: HmacSha256PortV2;
53
56
  readonly base64url: Base64UrlPortV2;
57
+ readonly idFactory: IdFactoryV2;
54
58
  }
55
59
  export interface ToolContext {
56
60
  readonly workflowService: WorkflowService;
@@ -4,11 +4,11 @@ exports.V2_TOOL_ANNOTATIONS = exports.V2_TOOL_TITLES = exports.V2ContinueWorkflo
4
4
  const zod_1 = require("zod");
5
5
  exports.V2ListWorkflowsInput = zod_1.z.object({});
6
6
  exports.V2InspectWorkflowInput = zod_1.z.object({
7
- workflowId: zod_1.z.string().min(1).describe('The workflow ID to inspect'),
7
+ workflowId: zod_1.z.string().min(1).regex(/^[A-Za-z0-9_-]+$/, 'Workflow ID must contain only letters, numbers, hyphens, and underscores').describe('The workflow ID to inspect'),
8
8
  mode: zod_1.z.enum(['metadata', 'preview']).default('preview').describe('Detail level'),
9
9
  });
10
10
  exports.V2StartWorkflowInput = zod_1.z.object({
11
- workflowId: zod_1.z.string().min(1).describe('The workflow ID to start'),
11
+ workflowId: zod_1.z.string().min(1).regex(/^[A-Za-z0-9_-]+$/, 'Workflow ID must contain only letters, numbers, hyphens, and underscores').describe('The workflow ID to start'),
12
12
  context: zod_1.z.record(zod_1.z.unknown()).optional().describe('External context inputs (conditions, parameters). Do not include workflow progress state.'),
13
13
  });
14
14
  exports.V2ContinueWorkflowInput = zod_1.z.object({
@@ -0,0 +1,7 @@
1
+ export type { Similarity, ValidationSuggestion, UnknownKeySuggestion, MissingRequiredSuggestion, InvalidEnumSuggestion, SuggestionResult, } from './suggestion-types.js';
2
+ export { similarity, EMPTY_SUGGESTION_RESULT, isUnknownKeySuggestion, isMissingRequiredSuggestion, isInvalidEnumSuggestion, } from './suggestion-types.js';
3
+ export type { SuggestionConfig } from './suggestion-config.js';
4
+ export { DEFAULT_SUGGESTION_CONFIG, MINIMAL_SUGGESTION_CONFIG } from './suggestion-config.js';
5
+ export { levenshteinDistance, computeSimilarity, computeSimilarityIgnoreCase, findClosestMatch, findAllMatches, type ClosestMatch, } from './string-similarity.js';
6
+ export { extractExpectedKeys, extractRequiredKeys, findUnknownKeys, findMissingRequiredKeys, generateExampleValue, generateTemplate, extractEnumValues, } from './schema-introspection.js';
7
+ export { generateSuggestions, formatSuggestionDetails, hasSuggestions, } from './suggestion-generator.js';
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hasSuggestions = exports.formatSuggestionDetails = exports.generateSuggestions = exports.extractEnumValues = exports.generateTemplate = exports.generateExampleValue = exports.findMissingRequiredKeys = exports.findUnknownKeys = exports.extractRequiredKeys = exports.extractExpectedKeys = exports.findAllMatches = exports.findClosestMatch = exports.computeSimilarityIgnoreCase = exports.computeSimilarity = exports.levenshteinDistance = exports.MINIMAL_SUGGESTION_CONFIG = exports.DEFAULT_SUGGESTION_CONFIG = exports.isInvalidEnumSuggestion = exports.isMissingRequiredSuggestion = exports.isUnknownKeySuggestion = exports.EMPTY_SUGGESTION_RESULT = exports.similarity = void 0;
4
+ var suggestion_types_js_1 = require("./suggestion-types.js");
5
+ Object.defineProperty(exports, "similarity", { enumerable: true, get: function () { return suggestion_types_js_1.similarity; } });
6
+ Object.defineProperty(exports, "EMPTY_SUGGESTION_RESULT", { enumerable: true, get: function () { return suggestion_types_js_1.EMPTY_SUGGESTION_RESULT; } });
7
+ Object.defineProperty(exports, "isUnknownKeySuggestion", { enumerable: true, get: function () { return suggestion_types_js_1.isUnknownKeySuggestion; } });
8
+ Object.defineProperty(exports, "isMissingRequiredSuggestion", { enumerable: true, get: function () { return suggestion_types_js_1.isMissingRequiredSuggestion; } });
9
+ Object.defineProperty(exports, "isInvalidEnumSuggestion", { enumerable: true, get: function () { return suggestion_types_js_1.isInvalidEnumSuggestion; } });
10
+ var suggestion_config_js_1 = require("./suggestion-config.js");
11
+ Object.defineProperty(exports, "DEFAULT_SUGGESTION_CONFIG", { enumerable: true, get: function () { return suggestion_config_js_1.DEFAULT_SUGGESTION_CONFIG; } });
12
+ Object.defineProperty(exports, "MINIMAL_SUGGESTION_CONFIG", { enumerable: true, get: function () { return suggestion_config_js_1.MINIMAL_SUGGESTION_CONFIG; } });
13
+ var string_similarity_js_1 = require("./string-similarity.js");
14
+ Object.defineProperty(exports, "levenshteinDistance", { enumerable: true, get: function () { return string_similarity_js_1.levenshteinDistance; } });
15
+ Object.defineProperty(exports, "computeSimilarity", { enumerable: true, get: function () { return string_similarity_js_1.computeSimilarity; } });
16
+ Object.defineProperty(exports, "computeSimilarityIgnoreCase", { enumerable: true, get: function () { return string_similarity_js_1.computeSimilarityIgnoreCase; } });
17
+ Object.defineProperty(exports, "findClosestMatch", { enumerable: true, get: function () { return string_similarity_js_1.findClosestMatch; } });
18
+ Object.defineProperty(exports, "findAllMatches", { enumerable: true, get: function () { return string_similarity_js_1.findAllMatches; } });
19
+ var schema_introspection_js_1 = require("./schema-introspection.js");
20
+ Object.defineProperty(exports, "extractExpectedKeys", { enumerable: true, get: function () { return schema_introspection_js_1.extractExpectedKeys; } });
21
+ Object.defineProperty(exports, "extractRequiredKeys", { enumerable: true, get: function () { return schema_introspection_js_1.extractRequiredKeys; } });
22
+ Object.defineProperty(exports, "findUnknownKeys", { enumerable: true, get: function () { return schema_introspection_js_1.findUnknownKeys; } });
23
+ Object.defineProperty(exports, "findMissingRequiredKeys", { enumerable: true, get: function () { return schema_introspection_js_1.findMissingRequiredKeys; } });
24
+ Object.defineProperty(exports, "generateExampleValue", { enumerable: true, get: function () { return schema_introspection_js_1.generateExampleValue; } });
25
+ Object.defineProperty(exports, "generateTemplate", { enumerable: true, get: function () { return schema_introspection_js_1.generateTemplate; } });
26
+ Object.defineProperty(exports, "extractEnumValues", { enumerable: true, get: function () { return schema_introspection_js_1.extractEnumValues; } });
27
+ var suggestion_generator_js_1 = require("./suggestion-generator.js");
28
+ Object.defineProperty(exports, "generateSuggestions", { enumerable: true, get: function () { return suggestion_generator_js_1.generateSuggestions; } });
29
+ Object.defineProperty(exports, "formatSuggestionDetails", { enumerable: true, get: function () { return suggestion_generator_js_1.formatSuggestionDetails; } });
30
+ Object.defineProperty(exports, "hasSuggestions", { enumerable: true, get: function () { return suggestion_generator_js_1.hasSuggestions; } });
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+ export declare function extractExpectedKeys(schema: z.ZodType): readonly string[];
3
+ export declare function extractRequiredKeys(schema: z.ZodType): readonly string[];
4
+ export declare function findUnknownKeys(args: unknown, schema: z.ZodType): readonly string[];
5
+ export declare function findMissingRequiredKeys(args: unknown, schema: z.ZodType): readonly string[];
6
+ export declare function generateExampleValue(schema: z.ZodType, depth?: number, maxDepth?: number): unknown;
7
+ export declare function generateTemplate(schema: z.ZodType, maxDepth?: number): Readonly<Record<string, unknown>> | null;
8
+ export declare function extractEnumValues(schema: z.ZodType, path: string): readonly string[];
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractExpectedKeys = extractExpectedKeys;
4
+ exports.extractRequiredKeys = extractRequiredKeys;
5
+ exports.findUnknownKeys = findUnknownKeys;
6
+ exports.findMissingRequiredKeys = findMissingRequiredKeys;
7
+ exports.generateExampleValue = generateExampleValue;
8
+ exports.generateTemplate = generateTemplate;
9
+ exports.extractEnumValues = extractEnumValues;
10
+ const zod_1 = require("zod");
11
+ function extractExpectedKeys(schema) {
12
+ if (schema instanceof zod_1.z.ZodObject) {
13
+ return Object.keys(schema._def.shape());
14
+ }
15
+ return [];
16
+ }
17
+ function extractRequiredKeys(schema) {
18
+ if (!(schema instanceof zod_1.z.ZodObject)) {
19
+ return [];
20
+ }
21
+ const shape = schema._def.shape();
22
+ const required = [];
23
+ for (const [key, value] of Object.entries(shape)) {
24
+ const field = value;
25
+ if (!(field instanceof zod_1.z.ZodOptional) && !(field instanceof zod_1.z.ZodDefault)) {
26
+ required.push(key);
27
+ }
28
+ }
29
+ return required;
30
+ }
31
+ function findUnknownKeys(args, schema) {
32
+ if (typeof args !== 'object' || args === null) {
33
+ return [];
34
+ }
35
+ const expectedKeys = new Set(extractExpectedKeys(schema));
36
+ const providedKeys = Object.keys(args);
37
+ return providedKeys.filter(key => !expectedKeys.has(key));
38
+ }
39
+ function findMissingRequiredKeys(args, schema) {
40
+ if (typeof args !== 'object' || args === null) {
41
+ return extractRequiredKeys(schema);
42
+ }
43
+ const providedKeys = new Set(Object.keys(args));
44
+ const requiredKeys = extractRequiredKeys(schema);
45
+ return requiredKeys.filter(key => !providedKeys.has(key));
46
+ }
47
+ function generateExampleValue(schema, depth = 0, maxDepth = 3) {
48
+ if (depth > maxDepth) {
49
+ return '...';
50
+ }
51
+ if (schema instanceof zod_1.z.ZodDefault) {
52
+ return schema._def.defaultValue();
53
+ }
54
+ if (schema instanceof zod_1.z.ZodOptional) {
55
+ return generateExampleValue(schema._def.innerType, depth, maxDepth);
56
+ }
57
+ if (schema instanceof zod_1.z.ZodObject) {
58
+ const shape = schema._def.shape();
59
+ const result = {};
60
+ for (const [key, value] of Object.entries(shape)) {
61
+ const field = value;
62
+ if (field instanceof zod_1.z.ZodOptional)
63
+ continue;
64
+ result[key] = generateExampleValue(field, depth + 1, maxDepth);
65
+ }
66
+ return result;
67
+ }
68
+ if (schema instanceof zod_1.z.ZodDiscriminatedUnion) {
69
+ const options = schema._def.options;
70
+ if (options.length > 0) {
71
+ return generateExampleValue(options[0], depth + 1, maxDepth);
72
+ }
73
+ return {};
74
+ }
75
+ if (schema instanceof zod_1.z.ZodString) {
76
+ const description = schema._def.description;
77
+ if (description) {
78
+ return `<${description}>`;
79
+ }
80
+ return '<string>';
81
+ }
82
+ if (schema instanceof zod_1.z.ZodNumber) {
83
+ return '<number>';
84
+ }
85
+ if (schema instanceof zod_1.z.ZodBoolean) {
86
+ return '<boolean>';
87
+ }
88
+ if (schema instanceof zod_1.z.ZodArray) {
89
+ return [];
90
+ }
91
+ if (schema instanceof zod_1.z.ZodEnum) {
92
+ const values = schema._def.values;
93
+ if (values.length > 0) {
94
+ return values[0];
95
+ }
96
+ return '<enum>';
97
+ }
98
+ if (schema instanceof zod_1.z.ZodLiteral) {
99
+ return schema._def.value;
100
+ }
101
+ if (schema instanceof zod_1.z.ZodRecord) {
102
+ return {};
103
+ }
104
+ if (schema instanceof zod_1.z.ZodUnknown || schema instanceof zod_1.z.ZodAny) {
105
+ return '<any>';
106
+ }
107
+ if (schema instanceof zod_1.z.ZodEffects) {
108
+ return generateExampleValue(schema._def.schema, depth, maxDepth);
109
+ }
110
+ return '<unknown>';
111
+ }
112
+ function generateTemplate(schema, maxDepth = 3) {
113
+ if (!(schema instanceof zod_1.z.ZodObject)) {
114
+ return null;
115
+ }
116
+ const example = generateExampleValue(schema, 0, maxDepth);
117
+ if (typeof example === 'object' && example !== null) {
118
+ return example;
119
+ }
120
+ return null;
121
+ }
122
+ function extractEnumValues(schema, path) {
123
+ const parts = path.split('.');
124
+ let current = schema;
125
+ for (const part of parts) {
126
+ if (current instanceof zod_1.z.ZodObject) {
127
+ const shape = current._def.shape();
128
+ const field = shape[part];
129
+ if (!field)
130
+ return [];
131
+ current = field;
132
+ }
133
+ else if (current instanceof zod_1.z.ZodOptional) {
134
+ current = current._def.innerType;
135
+ if (current instanceof zod_1.z.ZodObject) {
136
+ const shape = current._def.shape();
137
+ const field = shape[part];
138
+ if (!field)
139
+ return [];
140
+ current = field;
141
+ }
142
+ else {
143
+ return [];
144
+ }
145
+ }
146
+ else {
147
+ return [];
148
+ }
149
+ }
150
+ if (current instanceof zod_1.z.ZodOptional || current instanceof zod_1.z.ZodDefault) {
151
+ current = current._def.innerType;
152
+ }
153
+ if (current instanceof zod_1.z.ZodEnum) {
154
+ return current._def.values;
155
+ }
156
+ if (current instanceof zod_1.z.ZodLiteral) {
157
+ const value = current._def.value;
158
+ if (typeof value === 'string') {
159
+ return [value];
160
+ }
161
+ }
162
+ return [];
163
+ }
@@ -0,0 +1,10 @@
1
+ import { type Similarity } from './suggestion-types.js';
2
+ export declare function levenshteinDistance(a: string, b: string): number;
3
+ export declare function computeSimilarity(a: string, b: string): Similarity;
4
+ export declare function computeSimilarityIgnoreCase(a: string, b: string): Similarity;
5
+ export interface ClosestMatch {
6
+ readonly match: string;
7
+ readonly score: Similarity;
8
+ }
9
+ export declare function findClosestMatch(input: string, candidates: readonly string[], threshold: Similarity): ClosestMatch | null;
10
+ export declare function findAllMatches(input: string, candidates: readonly string[], threshold: Similarity, limit: number): readonly ClosestMatch[];
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.levenshteinDistance = levenshteinDistance;
4
+ exports.computeSimilarity = computeSimilarity;
5
+ exports.computeSimilarityIgnoreCase = computeSimilarityIgnoreCase;
6
+ exports.findClosestMatch = findClosestMatch;
7
+ exports.findAllMatches = findAllMatches;
8
+ const suggestion_types_js_1 = require("./suggestion-types.js");
9
+ function levenshteinDistance(a, b) {
10
+ if (a.length > b.length) {
11
+ [a, b] = [b, a];
12
+ }
13
+ const m = a.length;
14
+ const n = b.length;
15
+ if (m === 0)
16
+ return n;
17
+ if (n === 0)
18
+ return m;
19
+ let prevRow = new Array(m + 1);
20
+ let currRow = new Array(m + 1);
21
+ for (let i = 0; i <= m; i++) {
22
+ prevRow[i] = i;
23
+ }
24
+ for (let j = 1; j <= n; j++) {
25
+ currRow[0] = j;
26
+ for (let i = 1; i <= m; i++) {
27
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
28
+ currRow[i] = Math.min(prevRow[i] + 1, currRow[i - 1] + 1, prevRow[i - 1] + cost);
29
+ }
30
+ [prevRow, currRow] = [currRow, prevRow];
31
+ }
32
+ return prevRow[m];
33
+ }
34
+ function computeSimilarity(a, b) {
35
+ if (a === b)
36
+ return (0, suggestion_types_js_1.similarity)(1);
37
+ if (a.length === 0 || b.length === 0)
38
+ return (0, suggestion_types_js_1.similarity)(0);
39
+ const distance = levenshteinDistance(a, b);
40
+ const maxLength = Math.max(a.length, b.length);
41
+ return (0, suggestion_types_js_1.similarity)(1 - distance / maxLength);
42
+ }
43
+ function computeSimilarityIgnoreCase(a, b) {
44
+ return computeSimilarity(a.toLowerCase(), b.toLowerCase());
45
+ }
46
+ function findClosestMatch(input, candidates, threshold) {
47
+ if (candidates.length === 0)
48
+ return null;
49
+ let bestMatch = null;
50
+ let bestScore = (0, suggestion_types_js_1.similarity)(0);
51
+ for (const candidate of candidates) {
52
+ const score = computeSimilarityIgnoreCase(input, candidate);
53
+ if (score > bestScore && score >= threshold) {
54
+ bestScore = score;
55
+ bestMatch = candidate;
56
+ }
57
+ }
58
+ if (bestMatch === null)
59
+ return null;
60
+ return { match: bestMatch, score: bestScore };
61
+ }
62
+ function findAllMatches(input, candidates, threshold, limit) {
63
+ const matches = [];
64
+ for (const candidate of candidates) {
65
+ const score = computeSimilarityIgnoreCase(input, candidate);
66
+ if (score >= threshold) {
67
+ matches.push({ match: candidate, score });
68
+ }
69
+ }
70
+ matches.sort((a, b) => {
71
+ if (b.score !== a.score)
72
+ return b.score - a.score;
73
+ return a.match.localeCompare(b.match);
74
+ });
75
+ return matches.slice(0, limit);
76
+ }
@@ -0,0 +1,9 @@
1
+ import { type Similarity } from './suggestion-types.js';
2
+ export interface SuggestionConfig {
3
+ readonly similarityThreshold: Similarity;
4
+ readonly maxSuggestions: number;
5
+ readonly includeTemplate: boolean;
6
+ readonly maxTemplateDepth: number;
7
+ }
8
+ export declare const DEFAULT_SUGGESTION_CONFIG: SuggestionConfig;
9
+ export declare const MINIMAL_SUGGESTION_CONFIG: SuggestionConfig;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MINIMAL_SUGGESTION_CONFIG = exports.DEFAULT_SUGGESTION_CONFIG = void 0;
4
+ const suggestion_types_js_1 = require("./suggestion-types.js");
5
+ exports.DEFAULT_SUGGESTION_CONFIG = {
6
+ similarityThreshold: (0, suggestion_types_js_1.similarity)(0.6),
7
+ maxSuggestions: 3,
8
+ includeTemplate: true,
9
+ maxTemplateDepth: 3,
10
+ };
11
+ exports.MINIMAL_SUGGESTION_CONFIG = {
12
+ similarityThreshold: (0, suggestion_types_js_1.similarity)(0.7),
13
+ maxSuggestions: 1,
14
+ includeTemplate: false,
15
+ maxTemplateDepth: 1,
16
+ };
@@ -0,0 +1,6 @@
1
+ import { z } from 'zod';
2
+ import type { SuggestionConfig } from './suggestion-config.js';
3
+ import type { SuggestionResult } from './suggestion-types.js';
4
+ export declare function generateSuggestions(args: unknown, schema: z.ZodType, config: SuggestionConfig): SuggestionResult;
5
+ export declare function formatSuggestionDetails(result: SuggestionResult): Record<string, unknown>;
6
+ export declare function hasSuggestions(result: SuggestionResult): boolean;
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateSuggestions = generateSuggestions;
4
+ exports.formatSuggestionDetails = formatSuggestionDetails;
5
+ exports.hasSuggestions = hasSuggestions;
6
+ const zod_1 = require("zod");
7
+ const suggestion_types_js_1 = require("./suggestion-types.js");
8
+ const string_similarity_js_1 = require("./string-similarity.js");
9
+ const schema_introspection_js_1 = require("./schema-introspection.js");
10
+ function generateUnknownKeySuggestions(unknownKeys, expectedKeys, config) {
11
+ const suggestions = [];
12
+ for (const unknownKey of unknownKeys) {
13
+ const match = (0, string_similarity_js_1.findClosestMatch)(unknownKey, expectedKeys, config.similarityThreshold);
14
+ if (match) {
15
+ suggestions.push({
16
+ kind: 'unknown_key',
17
+ provided: unknownKey,
18
+ didYouMean: match.match,
19
+ similarity: match.score,
20
+ });
21
+ }
22
+ }
23
+ suggestions.sort((a, b) => b.similarity - a.similarity);
24
+ return suggestions.slice(0, config.maxSuggestions);
25
+ }
26
+ function generateMissingRequiredSuggestions(missingKeys, schema, config) {
27
+ if (!(schema instanceof zod_1.z.ZodObject)) {
28
+ return [];
29
+ }
30
+ const shape = schema._def.shape();
31
+ const suggestions = [];
32
+ for (const key of missingKeys) {
33
+ const field = shape[key];
34
+ if (field) {
35
+ suggestions.push({
36
+ kind: 'missing_required',
37
+ param: key,
38
+ example: (0, schema_introspection_js_1.generateExampleValue)(field, 0, config.maxTemplateDepth),
39
+ });
40
+ }
41
+ }
42
+ suggestions.sort((a, b) => a.param.localeCompare(b.param));
43
+ return suggestions.slice(0, config.maxSuggestions);
44
+ }
45
+ function generateSuggestions(args, schema, config) {
46
+ const suggestions = [];
47
+ const expectedKeys = (0, schema_introspection_js_1.extractExpectedKeys)(schema);
48
+ const unknownKeys = (0, schema_introspection_js_1.findUnknownKeys)(args, schema);
49
+ const unknownKeySuggestions = generateUnknownKeySuggestions(unknownKeys, expectedKeys, config);
50
+ suggestions.push(...unknownKeySuggestions);
51
+ const missingKeys = (0, schema_introspection_js_1.findMissingRequiredKeys)(args, schema);
52
+ const missingRequiredSuggestions = generateMissingRequiredSuggestions(missingKeys, schema, config);
53
+ suggestions.push(...missingRequiredSuggestions);
54
+ if (suggestions.length === 0 && !config.includeTemplate) {
55
+ return suggestion_types_js_1.EMPTY_SUGGESTION_RESULT;
56
+ }
57
+ const correctTemplate = config.includeTemplate
58
+ ? (0, schema_introspection_js_1.generateTemplate)(schema, config.maxTemplateDepth)
59
+ : null;
60
+ return {
61
+ suggestions,
62
+ correctTemplate,
63
+ };
64
+ }
65
+ function formatSuggestionDetails(result) {
66
+ const details = {};
67
+ if (result.suggestions.length > 0) {
68
+ details.suggestions = result.suggestions.map(s => {
69
+ switch (s.kind) {
70
+ case 'unknown_key':
71
+ return {
72
+ kind: s.kind,
73
+ provided: s.provided,
74
+ didYouMean: s.didYouMean,
75
+ similarity: Math.round(s.similarity * 100) / 100,
76
+ };
77
+ case 'missing_required':
78
+ return {
79
+ kind: s.kind,
80
+ param: s.param,
81
+ example: s.example,
82
+ };
83
+ case 'invalid_enum':
84
+ return {
85
+ kind: s.kind,
86
+ path: s.path,
87
+ provided: s.provided,
88
+ didYouMean: s.didYouMean,
89
+ allowedValues: s.allowedValues,
90
+ };
91
+ }
92
+ });
93
+ }
94
+ if (result.correctTemplate !== null) {
95
+ details.correctTemplate = result.correctTemplate;
96
+ }
97
+ return details;
98
+ }
99
+ function hasSuggestions(result) {
100
+ return result.suggestions.length > 0 || result.correctTemplate !== null;
101
+ }
@@ -0,0 +1,31 @@
1
+ export type Similarity = number & {
2
+ readonly __brand: 'Similarity';
3
+ };
4
+ export declare function similarity(n: number): Similarity;
5
+ export interface UnknownKeySuggestion {
6
+ readonly kind: 'unknown_key';
7
+ readonly provided: string;
8
+ readonly didYouMean: string;
9
+ readonly similarity: Similarity;
10
+ }
11
+ export interface MissingRequiredSuggestion {
12
+ readonly kind: 'missing_required';
13
+ readonly param: string;
14
+ readonly example: unknown;
15
+ }
16
+ export interface InvalidEnumSuggestion {
17
+ readonly kind: 'invalid_enum';
18
+ readonly path: string;
19
+ readonly provided: string;
20
+ readonly didYouMean: string | null;
21
+ readonly allowedValues: readonly string[];
22
+ }
23
+ export type ValidationSuggestion = UnknownKeySuggestion | MissingRequiredSuggestion | InvalidEnumSuggestion;
24
+ export interface SuggestionResult {
25
+ readonly suggestions: readonly ValidationSuggestion[];
26
+ readonly correctTemplate: Readonly<Record<string, unknown>> | null;
27
+ }
28
+ export declare const EMPTY_SUGGESTION_RESULT: SuggestionResult;
29
+ export declare function isUnknownKeySuggestion(s: ValidationSuggestion): s is UnknownKeySuggestion;
30
+ export declare function isMissingRequiredSuggestion(s: ValidationSuggestion): s is MissingRequiredSuggestion;
31
+ export declare function isInvalidEnumSuggestion(s: ValidationSuggestion): s is InvalidEnumSuggestion;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EMPTY_SUGGESTION_RESULT = void 0;
4
+ exports.similarity = similarity;
5
+ exports.isUnknownKeySuggestion = isUnknownKeySuggestion;
6
+ exports.isMissingRequiredSuggestion = isMissingRequiredSuggestion;
7
+ exports.isInvalidEnumSuggestion = isInvalidEnumSuggestion;
8
+ function similarity(n) {
9
+ return Math.max(0, Math.min(1, n));
10
+ }
11
+ exports.EMPTY_SUGGESTION_RESULT = {
12
+ suggestions: [],
13
+ correctTemplate: null,
14
+ };
15
+ function isUnknownKeySuggestion(s) {
16
+ return s.kind === 'unknown_key';
17
+ }
18
+ function isMissingRequiredSuggestion(s) {
19
+ return s.kind === 'missing_required';
20
+ }
21
+ function isInvalidEnumSuggestion(s) {
22
+ return s.kind === 'invalid_enum';
23
+ }
@@ -0,0 +1,4 @@
1
+ export type Base32LowerNoPad = string & {
2
+ readonly __brand: 'v2.Base32LowerNoPad';
3
+ };
4
+ export declare function encodeBase32LowerNoPad(bytes: Uint8Array): Base32LowerNoPad;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.encodeBase32LowerNoPad = encodeBase32LowerNoPad;
4
+ const BASE32_LOWER_ALPHABET = 'abcdefghijklmnopqrstuvwxyz234567';
5
+ function encodeBase32LowerNoPad(bytes) {
6
+ let out = '';
7
+ let buffer = 0n;
8
+ let bits = 0;
9
+ for (const b of bytes) {
10
+ buffer = (buffer << 8n) | BigInt(b);
11
+ bits += 8;
12
+ while (bits >= 5) {
13
+ const shift = BigInt(bits - 5);
14
+ const index = Number((buffer >> shift) & 31n);
15
+ out += BASE32_LOWER_ALPHABET[index];
16
+ bits -= 5;
17
+ if (bits === 0) {
18
+ buffer = 0n;
19
+ }
20
+ else {
21
+ buffer = buffer & ((1n << BigInt(bits)) - 1n);
22
+ }
23
+ }
24
+ }
25
+ if (bits > 0) {
26
+ const index = Number((buffer << BigInt(5 - bits)) & 31n);
27
+ out += BASE32_LOWER_ALPHABET[index];
28
+ }
29
+ return out;
30
+ }
@@ -0,0 +1,3 @@
1
+ import type { Sha256PortV2 } from '../../ports/sha256.port.js';
2
+ import type { AttemptId } from './index.js';
3
+ export declare function deriveChildAttemptId(parent: AttemptId, sha256: Sha256PortV2): AttemptId;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deriveChildAttemptId = deriveChildAttemptId;
4
+ const index_js_1 = require("./index.js");
5
+ const base32_lower_js_1 = require("../encoding/base32-lower.js");
6
+ const PREFIX = 'wr_attempt_next_v1:';
7
+ function hexToBytes(hex) {
8
+ if (hex.length % 2 !== 0) {
9
+ throw new Error('hex string must have even length');
10
+ }
11
+ const out = new Uint8Array(hex.length / 2);
12
+ for (let i = 0; i < out.length; i++) {
13
+ const byteHex = hex.slice(i * 2, i * 2 + 2);
14
+ const n = Number.parseInt(byteHex, 16);
15
+ if (Number.isNaN(n)) {
16
+ throw new Error(`invalid hex byte: ${byteHex}`);
17
+ }
18
+ out[i] = n;
19
+ }
20
+ return out;
21
+ }
22
+ const SHA256_DIGEST_RE = /^sha256:[0-9a-f]{64}$/;
23
+ function deriveChildAttemptId(parent, sha256) {
24
+ const bytes = new TextEncoder().encode(`${PREFIX}${String(parent)}`);
25
+ const digest = String(sha256.sha256(bytes));
26
+ if (!SHA256_DIGEST_RE.test(digest)) {
27
+ throw new Error(`expected sha256:<64hex> digest, got: ${digest}`);
28
+ }
29
+ const first16 = hexToBytes(digest.slice('sha256:'.length, 'sha256:'.length + 32));
30
+ const suffix = (0, base32_lower_js_1.encodeBase32LowerNoPad)(first16);
31
+ return (0, index_js_1.asAttemptId)(`attempt_${suffix}`);
32
+ }
@@ -8,10 +8,11 @@ const index_js_1 = require("../ids/index.js");
8
8
  const sha256DigestSchema = zod_1.z.string().regex(/^sha256:[0-9a-f]{64}$/, 'Expected sha256:<64 hex chars>');
9
9
  const workflowHashSchema = sha256DigestSchema.transform((v) => (0, index_js_1.asWorkflowHash)((0, index_js_1.asSha256Digest)(v)));
10
10
  const nonEmpty = zod_1.z.string().min(1);
11
- exports.AttemptIdSchema = nonEmpty.transform(index_js_1.asAttemptId);
12
- exports.SessionIdSchema = nonEmpty.transform(index_js_1.asSessionId);
13
- exports.RunIdSchema = nonEmpty.transform(index_js_1.asRunId);
14
- exports.NodeIdSchema = nonEmpty.transform(index_js_1.asNodeId);
11
+ const delimiterSafeId = nonEmpty.regex(/^[^:\s]+$/, 'Expected a delimiter-safe ID (no ":" or whitespace)');
12
+ exports.AttemptIdSchema = delimiterSafeId.transform(index_js_1.asAttemptId);
13
+ exports.SessionIdSchema = delimiterSafeId.transform(index_js_1.asSessionId);
14
+ exports.RunIdSchema = delimiterSafeId.transform(index_js_1.asRunId);
15
+ exports.NodeIdSchema = delimiterSafeId.transform(index_js_1.asNodeId);
15
16
  exports.StateTokenPayloadV1Schema = zod_1.z.object({
16
17
  tokenVersion: zod_1.z.literal(1),
17
18
  tokenKind: zod_1.z.literal('state'),
@@ -0,0 +1,11 @@
1
+ import type { RandomEntropyPortV2 } from '../../../ports/random-entropy.port.js';
2
+ import type { AttemptId, NodeId, RunId, SessionId } from '../../../durable-core/ids/index.js';
3
+ export declare class IdFactoryV2 {
4
+ private readonly entropy;
5
+ constructor(entropy: RandomEntropyPortV2);
6
+ mintSessionId(): SessionId;
7
+ mintRunId(): RunId;
8
+ mintNodeId(): NodeId;
9
+ mintAttemptId(): AttemptId;
10
+ mintEventId(): string;
11
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IdFactoryV2 = void 0;
4
+ const index_js_1 = require("../../../durable-core/ids/index.js");
5
+ const base32_lower_js_1 = require("../../../durable-core/encoding/base32-lower.js");
6
+ const BYTES = 16;
7
+ function mint(prefix, entropy) {
8
+ const bytes = entropy.generateBytes(BYTES);
9
+ const suffix = (0, base32_lower_js_1.encodeBase32LowerNoPad)(bytes);
10
+ return `${prefix}_${suffix}`;
11
+ }
12
+ class IdFactoryV2 {
13
+ constructor(entropy) {
14
+ this.entropy = entropy;
15
+ }
16
+ mintSessionId() {
17
+ return (0, index_js_1.asSessionId)(mint('sess', this.entropy));
18
+ }
19
+ mintRunId() {
20
+ return (0, index_js_1.asRunId)(mint('run', this.entropy));
21
+ }
22
+ mintNodeId() {
23
+ return (0, index_js_1.asNodeId)(mint('node', this.entropy));
24
+ }
25
+ mintAttemptId() {
26
+ return (0, index_js_1.asAttemptId)(mint('attempt', this.entropy));
27
+ }
28
+ mintEventId() {
29
+ return mint('evt', this.entropy);
30
+ }
31
+ }
32
+ exports.IdFactoryV2 = IdFactoryV2;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exaudeus/workrail",
3
- "version": "0.15.0",
3
+ "version": "0.17.0",
4
4
  "description": "Step-by-step workflow enforcement for AI agents via MCP",
5
5
  "license": "MIT",
6
6
  "repository": {