@exaudeus/workrail 3.71.1 → 3.72.1

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 (50) hide show
  1. package/dist/cli-worktrain.js +4 -6
  2. package/dist/console-ui/assets/{index-CsX-nVV7.js → index-Yj9NHqbR.js} +1 -1
  3. package/dist/console-ui/index.html +1 -1
  4. package/dist/daemon/active-sessions.d.ts +17 -0
  5. package/dist/daemon/active-sessions.js +55 -0
  6. package/dist/daemon/context-loader.d.ts +32 -0
  7. package/dist/daemon/context-loader.js +34 -0
  8. package/dist/daemon/session-scope.d.ts +28 -0
  9. package/dist/daemon/session-scope.js +21 -0
  10. package/dist/daemon/tools/_shared.d.ts +38 -0
  11. package/dist/daemon/tools/_shared.js +101 -0
  12. package/dist/daemon/tools/bash.d.ts +3 -0
  13. package/dist/daemon/tools/bash.js +57 -0
  14. package/dist/daemon/tools/continue-workflow.d.ts +6 -0
  15. package/dist/daemon/tools/continue-workflow.js +208 -0
  16. package/dist/daemon/tools/file-tools.d.ts +6 -0
  17. package/dist/daemon/tools/file-tools.js +195 -0
  18. package/dist/daemon/tools/glob-grep.d.ts +4 -0
  19. package/dist/daemon/tools/glob-grep.js +172 -0
  20. package/dist/daemon/tools/report-issue.d.ts +3 -0
  21. package/dist/daemon/tools/report-issue.js +129 -0
  22. package/dist/daemon/tools/signal-coordinator.d.ts +4 -0
  23. package/dist/daemon/tools/signal-coordinator.js +105 -0
  24. package/dist/daemon/tools/spawn-agent.d.ts +6 -0
  25. package/dist/daemon/tools/spawn-agent.js +135 -0
  26. package/dist/daemon/turn-end/conversation-flusher.d.ts +4 -0
  27. package/dist/daemon/turn-end/conversation-flusher.js +8 -0
  28. package/dist/daemon/turn-end/detect-stuck.d.ts +2 -0
  29. package/dist/daemon/turn-end/detect-stuck.js +5 -0
  30. package/dist/daemon/turn-end/step-injector.d.ts +8 -0
  31. package/dist/daemon/turn-end/step-injector.js +10 -0
  32. package/dist/daemon/workflow-runner.d.ts +54 -29
  33. package/dist/daemon/workflow-runner.js +175 -989
  34. package/dist/infrastructure/storage/workflow-resolution.js +5 -6
  35. package/dist/manifest.json +161 -25
  36. package/dist/mcp/handlers/shared/request-workflow-reader.js +14 -0
  37. package/dist/trigger/coordinator-deps.d.ts +15 -0
  38. package/dist/trigger/coordinator-deps.js +322 -0
  39. package/dist/trigger/delivery-pipeline.d.ts +18 -0
  40. package/dist/trigger/delivery-pipeline.js +148 -0
  41. package/dist/trigger/dispatch-deduplicator.d.ts +6 -0
  42. package/dist/trigger/dispatch-deduplicator.js +24 -0
  43. package/dist/trigger/trigger-listener.d.ts +2 -3
  44. package/dist/trigger/trigger-listener.js +9 -276
  45. package/dist/trigger/trigger-router.d.ts +8 -7
  46. package/dist/trigger/trigger-router.js +19 -97
  47. package/dist/v2/usecases/console-routes.js +10 -2
  48. package/docs/ideas/backlog.md +82 -48
  49. package/package.json +1 -1
  50. package/workflows/wr.research.json +158 -0
@@ -28,14 +28,13 @@ function resolveWorkflowCandidates(candidates, variantResolutions) {
28
28
  }
29
29
  else {
30
30
  const bundledSource = sources.find(s => s.workflow.source.kind === 'bundled');
31
- const projectShadowers = bundledSource
32
- ? sources.filter(s => s !== bundledSource && s.workflow.source.kind === 'project')
31
+ const isWrNamespace = id.startsWith('wr.');
32
+ const nonBundledShadowers = bundledSource && isWrNamespace
33
+ ? sources.filter(s => s !== bundledSource)
33
34
  : [];
34
- if (bundledSource && projectShadowers.length > 0) {
35
+ if (bundledSource && nonBundledShadowers.length > 0) {
35
36
  const { sourceRef: bundledRef, workflow } = bundledSource;
36
- const attemptedShadowRefs = sources
37
- .filter(s => s !== bundledSource)
38
- .map(s => s.sourceRef);
37
+ const attemptedShadowRefs = nonBundledShadowers.map(s => s.sourceRef);
39
38
  const variantResolution = variantResolutions.get(id)?.get(bundledRef);
40
39
  resolved.push({
41
40
  workflow,
@@ -238,8 +238,8 @@
238
238
  "bytes": 31
239
239
  },
240
240
  "cli-worktrain.js": {
241
- "sha256": "a06ebd9d6028e55cfaac8df55810fe199a3452caff552e4912879369512718d9",
242
- "bytes": 59952
241
+ "sha256": "8e356ca5fdb69b5695af24137ddc54466a1117668181c379b217831f45c46955",
242
+ "bytes": 59895
243
243
  },
244
244
  "cli.d.ts": {
245
245
  "sha256": "43e818adf60173644896298637f47b01d5819b17eda46eaa32d0c7d64724d012",
@@ -473,16 +473,16 @@
473
473
  "sha256": "5fe866e54f796975dec5d8ba9983aefd86074db212d3fccd64eed04bc9f0b3da",
474
474
  "bytes": 8011
475
475
  },
476
- "console-ui/assets/index-CsX-nVV7.js": {
477
- "sha256": "57fceecd0a6f6e93abe8744b152ff1e13e3c7634ffe16e23ea65a6c974365a44",
478
- "bytes": 768234
479
- },
480
476
  "console-ui/assets/index-DHrKiMCf.css": {
481
477
  "sha256": "40290b50e21ee7e82433efe13b1aa31c1ea608bd057a5c4e324982f284bc928b",
482
478
  "bytes": 60673
483
479
  },
480
+ "console-ui/assets/index-Yj9NHqbR.js": {
481
+ "sha256": "53bd3633e60fb67314e935d0e4b06c2a7ce92ad6c5ac622a44b8a1cdf2470462",
482
+ "bytes": 768234
483
+ },
484
484
  "console-ui/index.html": {
485
- "sha256": "21656fcb9f9c4ed223af103ec300e178cf512e9354ee92bd2c4e0278151ebff4",
485
+ "sha256": "0a06c276d8228a87c2ff7ea5d184e20a0358ca60edfa2583d1de98245235ecbe",
486
486
  "bytes": 417
487
487
  },
488
488
  "console/standalone-console.d.ts": {
@@ -597,6 +597,14 @@
597
597
  "sha256": "a3c7ee47d37f111561e2b73f7487670bb4dc894d45931a0745c26fe5acd8c759",
598
598
  "bytes": 3493
599
599
  },
600
+ "daemon/active-sessions.d.ts": {
601
+ "sha256": "26e768eafba633eb1585ec55759b14a1daffe7b13668116b7bc4cd54c3e559e9",
602
+ "bytes": 563
603
+ },
604
+ "daemon/active-sessions.js": {
605
+ "sha256": "12a7346bd7a7710939c44437f22b1532c5b540bca4effece866c878c723aab80",
606
+ "bytes": 1330
607
+ },
600
608
  "daemon/agent-loop.d.ts": {
601
609
  "sha256": "a05b27f2cdc7bacd35bb41b9b271367ba9d1f550c9cbf873f1a9b4fa092e8bbb",
602
610
  "bytes": 3779
@@ -605,6 +613,14 @@
605
613
  "sha256": "aa47bea99cf9a5ce35d2bc375b6dd51a9fbb68d36f2b185ee0a98176f67d647d",
606
614
  "bytes": 9803
607
615
  },
616
+ "daemon/context-loader.d.ts": {
617
+ "sha256": "db099ae68c8f0fd69503afd49daaf2f84fa0ada9791dc3c5e3278382506b13c5",
618
+ "bytes": 1375
619
+ },
620
+ "daemon/context-loader.js": {
621
+ "sha256": "a3db45565ef02ca178b8d66ea93cb2877def528f3008dc067787d9983c589bd0",
622
+ "bytes": 1255
623
+ },
608
624
  "daemon/daemon-env.d.ts": {
609
625
  "sha256": "4546caacd79c21b162d2d03c1cde24d4f6d232e684229828722be75d4a33920a",
610
626
  "bytes": 213
@@ -637,6 +653,14 @@
637
653
  "sha256": "497efb2389e49ec28c73624a580b4bddb4ae2c800c4f50c343bc931aacbe565a",
638
654
  "bytes": 247
639
655
  },
656
+ "daemon/session-scope.d.ts": {
657
+ "sha256": "1d4c5c8ad79bde16bf49d8f364f1e95a8294896caad8d9e4e16209301505496b",
658
+ "bytes": 1394
659
+ },
660
+ "daemon/session-scope.js": {
661
+ "sha256": "2f5295aa36b8d46b162a2b1f4d6f13af00517796aa468956563a8de46e2ecd56",
662
+ "bytes": 630
663
+ },
640
664
  "daemon/soul-template.d.ts": {
641
665
  "sha256": "abe720ac2d0bdc23b6e0a2b4aed78ae241b6553fd8f6784d0961a915f54d13c2",
642
666
  "bytes": 2245
@@ -653,13 +677,101 @@
653
677
  "sha256": "485b7407433f7246af41b6895dd8973efeb05228a9791f327e1dbc581a5c7ef8",
654
678
  "bytes": 5921
655
679
  },
680
+ "daemon/tools/_shared.d.ts": {
681
+ "sha256": "8cd108061918b5050211015498658ff0ca1a034749a81c5064ddb3e2d85213d3",
682
+ "bytes": 1670
683
+ },
684
+ "daemon/tools/_shared.js": {
685
+ "sha256": "665be333f6c300530410c7b87def06538442bb9b132c706992fbbf133ac2d0f8",
686
+ "bytes": 4410
687
+ },
688
+ "daemon/tools/bash.d.ts": {
689
+ "sha256": "7da73a970983f275477e513d348f6b9cf110edf1c7b72f83d4f2db7e1118a627",
690
+ "bytes": 301
691
+ },
692
+ "daemon/tools/bash.js": {
693
+ "sha256": "4a0cc6709a9a48a5ef1ca4e6531a1f038960865853dc757b4db58d17070653c1",
694
+ "bytes": 2841
695
+ },
696
+ "daemon/tools/continue-workflow.d.ts": {
697
+ "sha256": "592de45416a858a30069b4d55ef69f456c0da476122735918783f76838b49c75",
698
+ "bytes": 1124
699
+ },
700
+ "daemon/tools/continue-workflow.js": {
701
+ "sha256": "9d15df73d901875fe63efcc87533f22c118b6ed5b15b248fc5842e02711d2b0d",
702
+ "bytes": 11377
703
+ },
704
+ "daemon/tools/file-tools.d.ts": {
705
+ "sha256": "a05940e571d7e353007132b4264eb79eb37f1b68fc403e0fc1d4ed6125b54163",
706
+ "bytes": 819
707
+ },
708
+ "daemon/tools/file-tools.js": {
709
+ "sha256": "c47cfc384850bc4f823450fa44bebd507a608f848de7539c1bda537e4c805f68",
710
+ "bytes": 10714
711
+ },
712
+ "daemon/tools/glob-grep.d.ts": {
713
+ "sha256": "13b79eae6df2fa4b736543b821d868399a1659f3b05c60e5efac63fc5ea41b46",
714
+ "bytes": 488
715
+ },
716
+ "daemon/tools/glob-grep.js": {
717
+ "sha256": "44ae5bccd838e255096ff32e75b1f105a1591e605fbf6662a75ceae1dc491441",
718
+ "bytes": 7863
719
+ },
720
+ "daemon/tools/report-issue.d.ts": {
721
+ "sha256": "5f405011b3db32c72c6459912d698b2dcca50c81d224e18c8abd7db0fa876de0",
722
+ "bytes": 326
723
+ },
724
+ "daemon/tools/report-issue.js": {
725
+ "sha256": "33bb5a892edbebcbaa6da0ae94eed0c60ffaa044613acafb72fe02bf118855e7",
726
+ "bytes": 6285
727
+ },
728
+ "daemon/tools/signal-coordinator.d.ts": {
729
+ "sha256": "63e5a2bdfd6260a57365ae74aeb9d566c3233e52da36e246212b5ac9ab9ffbb8",
730
+ "bytes": 338
731
+ },
732
+ "daemon/tools/signal-coordinator.js": {
733
+ "sha256": "da4ffae6dec8930a995bf2452c128fcc05c30f06b96fbbd2a21de9b8c553908b",
734
+ "bytes": 4943
735
+ },
736
+ "daemon/tools/spawn-agent.d.ts": {
737
+ "sha256": "fc6f2f4403c96597041f81abb656fb3499a5d0e9a6f0800f273e444b60912d71",
738
+ "bytes": 605
739
+ },
740
+ "daemon/tools/spawn-agent.js": {
741
+ "sha256": "f740326855d0b051a4d99ce000046df2bc01d446c057980bfb0fe4539605738a",
742
+ "bytes": 7847
743
+ },
744
+ "daemon/turn-end/conversation-flusher.d.ts": {
745
+ "sha256": "5a8c1666ad18c31f49cb34ad2f4b5f134437bfb902dc5f89ea3db568ca44976d",
746
+ "bytes": 314
747
+ },
748
+ "daemon/turn-end/conversation-flusher.js": {
749
+ "sha256": "7a8f294be43e30c0c3a486418bcf42a31e507e2a1b7e793291e97d5b0ffe3c8e",
750
+ "bytes": 382
751
+ },
752
+ "daemon/turn-end/detect-stuck.d.ts": {
753
+ "sha256": "d2d88889b9397d0cb4893f73498c673ba57d264c052485449ef5c3fc50c1d806",
754
+ "bytes": 148
755
+ },
756
+ "daemon/turn-end/detect-stuck.js": {
757
+ "sha256": "a6ec84d4bca121179927ecb21ee7fb798999097bec52491be88e1f6d559357cf",
758
+ "bytes": 309
759
+ },
760
+ "daemon/turn-end/step-injector.d.ts": {
761
+ "sha256": "0f0e8dc1a1db140c2fc9a5b531f4990a284482a63795d13d4874f0f82e4ea6d3",
762
+ "bytes": 247
763
+ },
764
+ "daemon/turn-end/step-injector.js": {
765
+ "sha256": "073b6735f7bfa59c7e7ee398a9290fb15484465640d86f8bf28f06be83d6040f",
766
+ "bytes": 429
767
+ },
656
768
  "daemon/workflow-runner.d.ts": {
657
- "sha256": "2d686ca9de2bcb88565782eb7070b3fddbe47ed423f2c0437e13fc9b900961d0",
658
- "bytes": 14002
769
+ "sha256": "7820de494fa093f097dda8782ebea9269d25d2524cf87c3f230bc823363db25e",
770
+ "bytes": 12965
659
771
  },
660
772
  "daemon/workflow-runner.js": {
661
- "sha256": "bac1125ad3099821552a934580be7b9b7953e8361735c8f20e798a4b2674ee28",
662
- "bytes": 118834
773
+ "sha256": "ea88f10400e10af68282fe233b0a34d7b1ab8dde6bde0f74a61665058544db48",
774
+ "bytes": 77654
663
775
  },
664
776
  "di/container.d.ts": {
665
777
  "sha256": "003bb7fb7478d627524b9b1e76bd0a963a243794a687ff233b96dc0e33a06d9f",
@@ -922,8 +1034,8 @@
922
1034
  "bytes": 2389
923
1035
  },
924
1036
  "infrastructure/storage/workflow-resolution.js": {
925
- "sha256": "ef0c0af68dd93e9e0ca05c81920e7e85e4725e3bd67f4a97667c4989ba1f0e03",
926
- "bytes": 6002
1037
+ "sha256": "476f99e6e9feb576c6ef4410bcc577d309815b9a874d924972090d9e86d1b93a",
1038
+ "bytes": 5978
927
1039
  },
928
1040
  "mcp-server.d.ts": {
929
1041
  "sha256": "7ead2e703f41c763d04b37a1cf433380bec3551fbde206af6694fe9286ad4714",
@@ -994,8 +1106,8 @@
994
1106
  "bytes": 2103
995
1107
  },
996
1108
  "mcp/handlers/shared/request-workflow-reader.js": {
997
- "sha256": "cfd2946ec9deb52c21611b21fc07859f35edaaf2c85d15743833380352dedf6f",
998
- "bytes": 11702
1109
+ "sha256": "29f648b1e806551703b8f961332d5e7ba5f8d0c1c472a63bc201332e14d9eb61",
1110
+ "bytes": 12198
999
1111
  },
1000
1112
  "mcp/handlers/shared/with-timeout.d.ts": {
1001
1113
  "sha256": "31ca3db008cb5cd439e0d1132bc4b29be0900c403c452931e3a24a50e45beb54",
@@ -1669,6 +1781,14 @@
1669
1781
  "sha256": "6728a2169f4007b9ea0414fade6b21500500d9c79d0b09296d92ef8bcabb9c79",
1670
1782
  "bytes": 2763
1671
1783
  },
1784
+ "trigger/coordinator-deps.d.ts": {
1785
+ "sha256": "cf5ea595ed2e817318744042e1010aab8766617caba9b105a46b9d5d35d2caae",
1786
+ "bytes": 854
1787
+ },
1788
+ "trigger/coordinator-deps.js": {
1789
+ "sha256": "a1f112821bde6c31037442bb3679a3e8b5e9103e6801764cdba6ac9ab191d2bd",
1790
+ "bytes": 15023
1791
+ },
1672
1792
  "trigger/delivery-action.d.ts": {
1673
1793
  "sha256": "559e2b2645aa60528f73de351cd35ebf45c5b82f47797aa15ddd681319315d39",
1674
1794
  "bytes": 1759
@@ -1685,6 +1805,22 @@
1685
1805
  "sha256": "da358ced4e99c327493b6d3ca975a623aca21f72e68787a092b2760601801c99",
1686
1806
  "bytes": 1269
1687
1807
  },
1808
+ "trigger/delivery-pipeline.d.ts": {
1809
+ "sha256": "b22d6048844357996bff383cea6c3cf5fc7ba75a0ee4441c755e83654af4b77b",
1810
+ "bytes": 858
1811
+ },
1812
+ "trigger/delivery-pipeline.js": {
1813
+ "sha256": "a5628cbf46cb65090e9e34c86fc78cb0b5fe2be6558efa2a3ce2009600a42d0a",
1814
+ "bytes": 6796
1815
+ },
1816
+ "trigger/dispatch-deduplicator.d.ts": {
1817
+ "sha256": "e1b7f48f7c03a391812ff7b40aa8cff7784d175df7c58de1a152e2a2c4eff060",
1818
+ "bytes": 179
1819
+ },
1820
+ "trigger/dispatch-deduplicator.js": {
1821
+ "sha256": "4848b5046aa65db19069300245733650c986bacf4eb066f742bc9ae70c36ce54",
1822
+ "bytes": 734
1823
+ },
1688
1824
  "trigger/github-queue-config.d.ts": {
1689
1825
  "sha256": "4dd68c2b880f808aa67c3b6be1867299c0b49ce5cf7e39f4f093dbd341d1a1e8",
1690
1826
  "bytes": 800
@@ -1726,20 +1862,20 @@
1726
1862
  "bytes": 22481
1727
1863
  },
1728
1864
  "trigger/trigger-listener.d.ts": {
1729
- "sha256": "cbd89c24cdfe89cb555946b0dcaa6836bf81f37db56c5e80d408dc4a2fe42fb9",
1730
- "bytes": 1798
1865
+ "sha256": "57192a2e0e01d472985acd6d17be41930d2c189e029a11137661f990e1446ed3",
1866
+ "bytes": 1744
1731
1867
  },
1732
1868
  "trigger/trigger-listener.js": {
1733
- "sha256": "540e3942790b8b00f22b43575d83db4aa96cfdaf4ad6ea1fcaa8470e793b3bee",
1734
- "bytes": 25847
1869
+ "sha256": "12a137a0ad256f2473171edc54bc624f4ad28f986d31bb4658538237b2082094",
1870
+ "bytes": 13222
1735
1871
  },
1736
1872
  "trigger/trigger-router.d.ts": {
1737
- "sha256": "618f1b346eb18d83ea76f71c0008be6f7ae76cc7734a93abd8afd30d26d24806",
1738
- "bytes": 3064
1873
+ "sha256": "24cc8e6abe08ca139af6599984e395863b5115076500b8faaae1d3b42bbe43b6",
1874
+ "bytes": 3220
1739
1875
  },
1740
1876
  "trigger/trigger-router.js": {
1741
- "sha256": "68a9dacf69468aef7cfb0f0da72122d33f34236e5296b176def5f40dbb0f0839",
1742
- "bytes": 24842
1877
+ "sha256": "9676fb57236040d46b923c8016394b519561ab18c99884dc190cf2221e2f1ecf",
1878
+ "bytes": 20550
1743
1879
  },
1744
1880
  "trigger/trigger-store.d.ts": {
1745
1881
  "sha256": "f846ca66494a2a1b834914652c845373d777bdeaaaefdc101ad1e78083d9ad5b",
@@ -3082,8 +3218,8 @@
3082
3218
  "bytes": 572
3083
3219
  },
3084
3220
  "v2/usecases/console-routes.js": {
3085
- "sha256": "cac41733df0270c8882c1ccc57e616862e422b7dd4aaf78783bb98a21c6edd81",
3086
- "bytes": 31338
3221
+ "sha256": "02e3be4472172bf03efb573376885fdb893af9b81b157370e25597750f77b03e",
3222
+ "bytes": 31729
3087
3223
  },
3088
3224
  "v2/usecases/console-service.d.ts": {
3089
3225
  "sha256": "fc8fe65427fa9f4f3535344b385b36f66ca06b7e3bfaea708931817a3edcad2b",
@@ -209,6 +209,8 @@ async function listRememberedRoots(rememberedRootsStore) {
209
209
  async function discoverWorkflowDirectoriesUnderRoot(rootPath) {
210
210
  const discoveredPaths = [];
211
211
  try {
212
+ if (await isWorkrailPackageDir(rootPath))
213
+ return { discovered: [], stale: false };
212
214
  await walkForRootedWorkflowDirectories(rootPath, discoveredPaths);
213
215
  }
214
216
  catch (err) {
@@ -220,6 +222,8 @@ async function discoverWorkflowDirectoriesUnderRoot(rootPath) {
220
222
  return { discovered: discoveredPaths, stale: false };
221
223
  }
222
224
  async function walkForRootedWorkflowDirectories(currentDirectory, discoveredPaths, depth = 0) {
225
+ if (depth > 0 && await isWorkrailPackageDir(currentDirectory))
226
+ return;
223
227
  const entries = await promises_1.default.readdir(currentDirectory, { withFileTypes: true });
224
228
  const sortedEntries = [...entries].sort((a, b) => a.name.localeCompare(b.name));
225
229
  for (const entry of sortedEntries) {
@@ -250,6 +254,16 @@ async function walkForRootedWorkflowDirectories(currentDirectory, discoveredPath
250
254
  function shouldSkipDirectory(name) {
251
255
  return SKIP_DIRS.has(name);
252
256
  }
257
+ async function isWorkrailPackageDir(dirPath) {
258
+ try {
259
+ const pkgJson = await promises_1.default.readFile(path_1.default.join(dirPath, 'package.json'), 'utf-8');
260
+ const pkg = JSON.parse(pkgJson);
261
+ return pkg.name === '@exaudeus/workrail';
262
+ }
263
+ catch {
264
+ return false;
265
+ }
266
+ }
253
267
  async function isDirectory(targetPath) {
254
268
  try {
255
269
  return (await promises_1.default.stat(targetPath)).isDirectory();
@@ -0,0 +1,15 @@
1
+ import type { V2ToolContext } from '../mcp/types.js';
2
+ import type { AdaptiveCoordinatorDeps } from '../coordinators/adaptive-pipeline.js';
3
+ import type { WorkflowTrigger, SessionSource } from '../daemon/workflow-runner.js';
4
+ import type { ConsoleService } from '../v2/usecases/console-service.js';
5
+ export interface CoordinatorDepsDependencies {
6
+ readonly ctx: V2ToolContext;
7
+ readonly execFileAsync: (cmd: string, args: string[], opts?: object) => Promise<{
8
+ stdout: string;
9
+ }>;
10
+ readonly consoleService: InstanceType<typeof ConsoleService> | null;
11
+ }
12
+ export interface CoordinatorDepsWithDispatch extends AdaptiveCoordinatorDeps {
13
+ setDispatch(dispatch: (trigger: WorkflowTrigger, source?: SessionSource) => void): void;
14
+ }
15
+ export declare function createCoordinatorDeps(deps: CoordinatorDepsDependencies): CoordinatorDepsWithDispatch;
@@ -0,0 +1,322 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createCoordinatorDeps = createCoordinatorDeps;
37
+ const fs = __importStar(require("node:fs"));
38
+ const os = __importStar(require("node:os"));
39
+ const path = __importStar(require("node:path"));
40
+ const node_crypto_1 = require("node:crypto");
41
+ const start_js_1 = require("../mcp/handlers/v2-execution/start.js");
42
+ const v2_token_ops_js_1 = require("../mcp/handlers/v2-token-ops.js");
43
+ const index_js_1 = require("../context-assembly/index.js");
44
+ const infra_js_1 = require("../context-assembly/infra.js");
45
+ function createCoordinatorDeps(deps) {
46
+ const { ctx, execFileAsync, consoleService } = deps;
47
+ let dispatch = null;
48
+ return {
49
+ setDispatch(fn) {
50
+ if (dispatch !== null) {
51
+ process.stderr.write('[WARN coordinator-deps] setDispatch() called more than once -- ignoring reassignment\n');
52
+ return;
53
+ }
54
+ dispatch = fn;
55
+ },
56
+ spawnSession: async (workflowId, goal, workspace, context, agentConfig) => {
57
+ if (dispatch === null) {
58
+ return { kind: 'err', error: 'in-process router not initialized -- coordinator deps not ready' };
59
+ }
60
+ const startResult = await (0, start_js_1.executeStartWorkflow)({ workflowId, workspacePath: workspace, goal }, ctx, { is_autonomous: 'true', workspacePath: workspace });
61
+ if (startResult.isErr()) {
62
+ const detail = `${startResult.error.kind}${'message' in startResult.error ? ': ' + startResult.error.message : ''}`;
63
+ return { kind: 'err', error: `Session creation failed: ${detail}` };
64
+ }
65
+ const startContinueToken = startResult.value.response.continueToken;
66
+ if (!startContinueToken) {
67
+ return { kind: 'ok', value: workflowId };
68
+ }
69
+ const tokenResult = await (0, v2_token_ops_js_1.parseContinueTokenOrFail)(startContinueToken, ctx.v2.tokenCodecPorts, ctx.v2.tokenAliasStore);
70
+ if (tokenResult.isErr()) {
71
+ process.stderr.write(`[ERROR trigger-listener:spawnSession] Failed to decode session handle from new session: ${tokenResult.error.message}\n`);
72
+ return { kind: 'err', error: 'Internal error: could not extract session handle from new session' };
73
+ }
74
+ const sessionHandle = tokenResult.value.sessionId;
75
+ const trigger = {
76
+ workflowId,
77
+ goal,
78
+ workspacePath: workspace,
79
+ context,
80
+ ...(agentConfig !== undefined ? { agentConfig } : {}),
81
+ };
82
+ const r = startResult.value.response;
83
+ const allocatedSession = {
84
+ continueToken: r.continueToken ?? '',
85
+ checkpointToken: r.checkpointToken,
86
+ firstStepPrompt: r.pending?.prompt ?? '',
87
+ isComplete: r.isComplete,
88
+ triggerSource: 'daemon',
89
+ };
90
+ const source = { kind: 'pre_allocated', trigger, session: allocatedSession };
91
+ dispatch(trigger, source);
92
+ return { kind: 'ok', value: sessionHandle };
93
+ },
94
+ contextAssembler: (0, index_js_1.createContextAssembler)({
95
+ execGit: async (args, cwd) => {
96
+ try {
97
+ const { stdout } = await execFileAsync('git', [...args], { cwd });
98
+ return { kind: 'ok', value: stdout };
99
+ }
100
+ catch (e) {
101
+ return { kind: 'err', error: e instanceof Error ? e.message : String(e) };
102
+ }
103
+ },
104
+ execGh: async (args, cwd) => {
105
+ try {
106
+ const { stdout } = await execFileAsync('gh', [...args], { cwd });
107
+ return { kind: 'ok', value: stdout };
108
+ }
109
+ catch (e) {
110
+ return { kind: 'err', error: e instanceof Error ? e.message : String(e) };
111
+ }
112
+ },
113
+ listRecentSessions: (0, infra_js_1.createListRecentSessions)(),
114
+ nowIso: () => new Date().toISOString(),
115
+ }),
116
+ awaitSessions: async (handles, timeoutMs) => {
117
+ const POLL_INTERVAL_MS = 3000;
118
+ if (consoleService === null) {
119
+ process.stderr.write(`[WARN coord:reason=await_degraded] awaitSessions: ConsoleService unavailable -- returning all ${handles.length} session(s) as failed.\n`);
120
+ return {
121
+ results: [...handles].map((h) => ({
122
+ handle: h,
123
+ outcome: 'failed',
124
+ status: null,
125
+ durationMs: 0,
126
+ })),
127
+ allSucceeded: false,
128
+ };
129
+ }
130
+ const startMs = Date.now();
131
+ const pending = new Set(handles);
132
+ const results = new Map();
133
+ while (pending.size > 0) {
134
+ const elapsed = Date.now() - startMs;
135
+ if (elapsed >= timeoutMs) {
136
+ break;
137
+ }
138
+ for (const handle of [...pending]) {
139
+ try {
140
+ const detail = await consoleService.getSessionDetail(handle);
141
+ if (detail.isErr()) {
142
+ continue;
143
+ }
144
+ const run = detail.value.runs[0];
145
+ if (!run)
146
+ continue;
147
+ const status = run.status;
148
+ if (status === 'complete' || status === 'complete_with_gaps') {
149
+ results.set(handle, { handle, outcome: 'success', status, durationMs: Date.now() - startMs });
150
+ pending.delete(handle);
151
+ }
152
+ else if (status === 'blocked') {
153
+ results.set(handle, { handle, outcome: 'failed', status, durationMs: Date.now() - startMs });
154
+ pending.delete(handle);
155
+ }
156
+ }
157
+ catch {
158
+ results.set(handle, { handle, outcome: 'failed', status: null, durationMs: Date.now() - startMs });
159
+ pending.delete(handle);
160
+ }
161
+ }
162
+ if (pending.size > 0) {
163
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
164
+ }
165
+ }
166
+ for (const handle of pending) {
167
+ results.set(handle, { handle, outcome: 'timeout', status: null, durationMs: timeoutMs });
168
+ }
169
+ const resultsArray = [...results.values()];
170
+ return {
171
+ results: resultsArray,
172
+ allSucceeded: resultsArray.every((r) => r.outcome === 'success'),
173
+ };
174
+ },
175
+ getAgentResult: async (sessionHandle) => {
176
+ const emptyResult = { recapMarkdown: null, artifacts: [] };
177
+ if (consoleService === null) {
178
+ return emptyResult;
179
+ }
180
+ try {
181
+ const detailResult = await consoleService.getSessionDetail(sessionHandle);
182
+ if (detailResult.isErr())
183
+ return emptyResult;
184
+ const run = detailResult.value.runs[0];
185
+ if (!run)
186
+ return emptyResult;
187
+ const tipNodeId = run.preferredTipNodeId;
188
+ if (!tipNodeId)
189
+ return emptyResult;
190
+ const allNodeIds = run.nodes.map((n) => n.nodeId).filter((id) => typeof id === 'string' && id !== '');
191
+ const nodeIdsToFetch = allNodeIds.length > 0 ? allNodeIds : [tipNodeId];
192
+ let recap = null;
193
+ const collectedArtifacts = [];
194
+ for (const nodeId of nodeIdsToFetch) {
195
+ try {
196
+ const nodeResult = await consoleService.getNodeDetail(sessionHandle, nodeId);
197
+ if (nodeResult.isErr())
198
+ continue;
199
+ if (nodeId === tipNodeId) {
200
+ recap = nodeResult.value.recapMarkdown;
201
+ }
202
+ if (nodeResult.value.artifacts.length > 0) {
203
+ collectedArtifacts.push(...nodeResult.value.artifacts);
204
+ }
205
+ }
206
+ catch {
207
+ continue;
208
+ }
209
+ }
210
+ return { recapMarkdown: recap, artifacts: collectedArtifacts };
211
+ }
212
+ catch (e) {
213
+ const msg = e instanceof Error ? e.message : String(e);
214
+ process.stderr.write(`[WARN coord:reason=exception handle=${sessionHandle.slice(0, 16)}] getAgentResult: ${msg}\n`);
215
+ return emptyResult;
216
+ }
217
+ },
218
+ listOpenPRs: async (workspace) => {
219
+ try {
220
+ const { stdout } = await execFileAsync('gh', ['pr', 'list', '--json', 'number,title,headRefName'], {
221
+ cwd: workspace,
222
+ timeout: 30000,
223
+ });
224
+ const parsed = JSON.parse(stdout);
225
+ return parsed.map((p) => ({ number: p.number, title: p.title, headRef: p.headRefName }));
226
+ }
227
+ catch {
228
+ return [];
229
+ }
230
+ },
231
+ mergePR: async (prNumber, workspace) => {
232
+ try {
233
+ await execFileAsync('gh', ['pr', 'merge', String(prNumber), '--squash', '--auto'], {
234
+ cwd: workspace,
235
+ timeout: 60000,
236
+ });
237
+ return { kind: 'ok', value: undefined };
238
+ }
239
+ catch (e) {
240
+ const msg = e instanceof Error ? e.message : String(e);
241
+ return { kind: 'err', error: msg };
242
+ }
243
+ },
244
+ writeFile: async (filePath, content) => {
245
+ await fs.promises.writeFile(filePath, content, 'utf-8');
246
+ },
247
+ readFile: (filePath) => fs.promises.readFile(filePath, 'utf-8'),
248
+ appendFile: (filePath, content) => fs.promises.appendFile(filePath, content, 'utf-8'),
249
+ mkdir: (dirPath, opts) => fs.promises.mkdir(dirPath, opts),
250
+ homedir: os.homedir,
251
+ joinPath: path.join,
252
+ nowIso: () => new Date().toISOString(),
253
+ generateId: () => (0, node_crypto_1.randomUUID)(),
254
+ stderr: (line) => process.stderr.write(line + '\n'),
255
+ now: () => Date.now(),
256
+ fileExists: (p) => fs.existsSync(p),
257
+ archiveFile: (src, dest) => fs.promises.rename(src, dest),
258
+ pollForPR: async (branchPattern, timeoutMs) => {
259
+ const pollIntervalMs = 30000;
260
+ const deadline = Date.now() + timeoutMs;
261
+ while (Date.now() < deadline) {
262
+ try {
263
+ const { stdout } = await execFileAsync('gh', ['pr', 'list', '--head', branchPattern, '--json', 'url', '--limit', '1'], { timeout: 30000 });
264
+ const parsed = JSON.parse(stdout);
265
+ if (parsed.length > 0 && parsed[0] && parsed[0].url) {
266
+ return parsed[0].url;
267
+ }
268
+ }
269
+ catch {
270
+ }
271
+ const remaining = deadline - Date.now();
272
+ if (remaining <= 0)
273
+ break;
274
+ await new Promise((resolve) => setTimeout(resolve, Math.min(pollIntervalMs, remaining)));
275
+ }
276
+ return null;
277
+ },
278
+ postToOutbox: async (message, metadata) => {
279
+ const workrailDir = path.join(os.homedir(), '.workrail');
280
+ const outboxPath = path.join(workrailDir, 'outbox.jsonl');
281
+ await fs.promises.mkdir(workrailDir, { recursive: true });
282
+ const entry = JSON.stringify({
283
+ id: (0, node_crypto_1.randomUUID)(),
284
+ message,
285
+ metadata,
286
+ timestamp: new Date().toISOString(),
287
+ });
288
+ await fs.promises.appendFile(outboxPath, entry + '\n', 'utf-8');
289
+ },
290
+ pollOutboxAck: async (requestId, timeoutMs) => {
291
+ const pollIntervalMs = 5 * 60 * 1000;
292
+ const workrailDir = path.join(os.homedir(), '.workrail');
293
+ const outboxPath = path.join(workrailDir, 'outbox.jsonl');
294
+ const cursorPath = path.join(workrailDir, 'inbox-cursor.json');
295
+ let snapshotCount = 0;
296
+ try {
297
+ const outboxContent = await fs.promises.readFile(outboxPath, 'utf-8');
298
+ snapshotCount = outboxContent.split('\n').filter((l) => l.trim() !== '').length;
299
+ }
300
+ catch {
301
+ }
302
+ void requestId;
303
+ const deadline = Date.now() + timeoutMs;
304
+ while (Date.now() < deadline) {
305
+ const remaining = deadline - Date.now();
306
+ if (remaining <= 0)
307
+ break;
308
+ await new Promise((resolve) => setTimeout(resolve, Math.min(pollIntervalMs, remaining)));
309
+ try {
310
+ const cursorContent = await fs.promises.readFile(cursorPath, 'utf-8');
311
+ const cursor = JSON.parse(cursorContent);
312
+ if (typeof cursor.lastReadCount === 'number' && cursor.lastReadCount > snapshotCount) {
313
+ return 'acked';
314
+ }
315
+ }
316
+ catch {
317
+ }
318
+ }
319
+ return 'timeout';
320
+ },
321
+ };
322
+ }