@exaudeus/workrail 3.72.0 → 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 (42) hide show
  1. package/dist/cli-worktrain.js +4 -6
  2. package/dist/console-ui/assets/{index-CTza1zb5.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 +3 -2
  9. package/dist/daemon/tools/_shared.d.ts +38 -0
  10. package/dist/daemon/tools/_shared.js +101 -0
  11. package/dist/daemon/tools/bash.d.ts +3 -0
  12. package/dist/daemon/tools/bash.js +57 -0
  13. package/dist/daemon/tools/continue-workflow.d.ts +6 -0
  14. package/dist/daemon/tools/continue-workflow.js +208 -0
  15. package/dist/daemon/tools/file-tools.d.ts +6 -0
  16. package/dist/daemon/tools/file-tools.js +195 -0
  17. package/dist/daemon/tools/glob-grep.d.ts +4 -0
  18. package/dist/daemon/tools/glob-grep.js +172 -0
  19. package/dist/daemon/tools/report-issue.d.ts +3 -0
  20. package/dist/daemon/tools/report-issue.js +129 -0
  21. package/dist/daemon/tools/signal-coordinator.d.ts +4 -0
  22. package/dist/daemon/tools/signal-coordinator.js +105 -0
  23. package/dist/daemon/tools/spawn-agent.d.ts +6 -0
  24. package/dist/daemon/tools/spawn-agent.js +135 -0
  25. package/dist/daemon/workflow-runner.d.ts +54 -29
  26. package/dist/daemon/workflow-runner.js +156 -980
  27. package/dist/infrastructure/storage/workflow-resolution.js +5 -6
  28. package/dist/manifest.json +131 -27
  29. package/dist/mcp/handlers/shared/request-workflow-reader.js +14 -0
  30. package/dist/trigger/coordinator-deps.d.ts +15 -0
  31. package/dist/trigger/coordinator-deps.js +322 -0
  32. package/dist/trigger/delivery-pipeline.d.ts +18 -0
  33. package/dist/trigger/delivery-pipeline.js +148 -0
  34. package/dist/trigger/dispatch-deduplicator.d.ts +6 -0
  35. package/dist/trigger/dispatch-deduplicator.js +24 -0
  36. package/dist/trigger/trigger-listener.d.ts +2 -3
  37. package/dist/trigger/trigger-listener.js +9 -276
  38. package/dist/trigger/trigger-router.d.ts +8 -7
  39. package/dist/trigger/trigger-router.js +19 -97
  40. package/dist/v2/usecases/console-routes.js +10 -2
  41. package/docs/ideas/backlog.md +82 -48
  42. package/package.json +1 -1
@@ -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-CTza1zb5.js": {
477
- "sha256": "9fbd911fd803739af06560ff0a69860ff9ef684edac4d6390434e02467b0f766",
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": "9bb88b082c668e32c1a972d77a97b5a3ff6aaa972be3a6f99b1805d530ccd813",
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
@@ -638,8 +654,8 @@
638
654
  "bytes": 247
639
655
  },
640
656
  "daemon/session-scope.d.ts": {
641
- "sha256": "569954160a5102f95a81acf88942fc4ff951b7ee7bc0ac7206be7209c78beebb",
642
- "bytes": 1341
657
+ "sha256": "1d4c5c8ad79bde16bf49d8f364f1e95a8294896caad8d9e4e16209301505496b",
658
+ "bytes": 1394
643
659
  },
644
660
  "daemon/session-scope.js": {
645
661
  "sha256": "2f5295aa36b8d46b162a2b1f4d6f13af00517796aa468956563a8de46e2ecd56",
@@ -661,6 +677,70 @@
661
677
  "sha256": "485b7407433f7246af41b6895dd8973efeb05228a9791f327e1dbc581a5c7ef8",
662
678
  "bytes": 5921
663
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
+ },
664
744
  "daemon/turn-end/conversation-flusher.d.ts": {
665
745
  "sha256": "5a8c1666ad18c31f49cb34ad2f4b5f134437bfb902dc5f89ea3db568ca44976d",
666
746
  "bytes": 314
@@ -686,12 +766,12 @@
686
766
  "bytes": 429
687
767
  },
688
768
  "daemon/workflow-runner.d.ts": {
689
- "sha256": "2d686ca9de2bcb88565782eb7070b3fddbe47ed423f2c0437e13fc9b900961d0",
690
- "bytes": 14002
769
+ "sha256": "7820de494fa093f097dda8782ebea9269d25d2524cf87c3f230bc823363db25e",
770
+ "bytes": 12965
691
771
  },
692
772
  "daemon/workflow-runner.js": {
693
- "sha256": "cc4f2255c2af8152f2e9a7e40839aa2eed84c8afc57d7e388024793f28d5fc00",
694
- "bytes": 119115
773
+ "sha256": "ea88f10400e10af68282fe233b0a34d7b1ab8dde6bde0f74a61665058544db48",
774
+ "bytes": 77654
695
775
  },
696
776
  "di/container.d.ts": {
697
777
  "sha256": "003bb7fb7478d627524b9b1e76bd0a963a243794a687ff233b96dc0e33a06d9f",
@@ -954,8 +1034,8 @@
954
1034
  "bytes": 2389
955
1035
  },
956
1036
  "infrastructure/storage/workflow-resolution.js": {
957
- "sha256": "ef0c0af68dd93e9e0ca05c81920e7e85e4725e3bd67f4a97667c4989ba1f0e03",
958
- "bytes": 6002
1037
+ "sha256": "476f99e6e9feb576c6ef4410bcc577d309815b9a874d924972090d9e86d1b93a",
1038
+ "bytes": 5978
959
1039
  },
960
1040
  "mcp-server.d.ts": {
961
1041
  "sha256": "7ead2e703f41c763d04b37a1cf433380bec3551fbde206af6694fe9286ad4714",
@@ -1026,8 +1106,8 @@
1026
1106
  "bytes": 2103
1027
1107
  },
1028
1108
  "mcp/handlers/shared/request-workflow-reader.js": {
1029
- "sha256": "cfd2946ec9deb52c21611b21fc07859f35edaaf2c85d15743833380352dedf6f",
1030
- "bytes": 11702
1109
+ "sha256": "29f648b1e806551703b8f961332d5e7ba5f8d0c1c472a63bc201332e14d9eb61",
1110
+ "bytes": 12198
1031
1111
  },
1032
1112
  "mcp/handlers/shared/with-timeout.d.ts": {
1033
1113
  "sha256": "31ca3db008cb5cd439e0d1132bc4b29be0900c403c452931e3a24a50e45beb54",
@@ -1701,6 +1781,14 @@
1701
1781
  "sha256": "6728a2169f4007b9ea0414fade6b21500500d9c79d0b09296d92ef8bcabb9c79",
1702
1782
  "bytes": 2763
1703
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
+ },
1704
1792
  "trigger/delivery-action.d.ts": {
1705
1793
  "sha256": "559e2b2645aa60528f73de351cd35ebf45c5b82f47797aa15ddd681319315d39",
1706
1794
  "bytes": 1759
@@ -1717,6 +1805,22 @@
1717
1805
  "sha256": "da358ced4e99c327493b6d3ca975a623aca21f72e68787a092b2760601801c99",
1718
1806
  "bytes": 1269
1719
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
+ },
1720
1824
  "trigger/github-queue-config.d.ts": {
1721
1825
  "sha256": "4dd68c2b880f808aa67c3b6be1867299c0b49ce5cf7e39f4f093dbd341d1a1e8",
1722
1826
  "bytes": 800
@@ -1758,20 +1862,20 @@
1758
1862
  "bytes": 22481
1759
1863
  },
1760
1864
  "trigger/trigger-listener.d.ts": {
1761
- "sha256": "cbd89c24cdfe89cb555946b0dcaa6836bf81f37db56c5e80d408dc4a2fe42fb9",
1762
- "bytes": 1798
1865
+ "sha256": "57192a2e0e01d472985acd6d17be41930d2c189e029a11137661f990e1446ed3",
1866
+ "bytes": 1744
1763
1867
  },
1764
1868
  "trigger/trigger-listener.js": {
1765
- "sha256": "540e3942790b8b00f22b43575d83db4aa96cfdaf4ad6ea1fcaa8470e793b3bee",
1766
- "bytes": 25847
1869
+ "sha256": "12a137a0ad256f2473171edc54bc624f4ad28f986d31bb4658538237b2082094",
1870
+ "bytes": 13222
1767
1871
  },
1768
1872
  "trigger/trigger-router.d.ts": {
1769
- "sha256": "618f1b346eb18d83ea76f71c0008be6f7ae76cc7734a93abd8afd30d26d24806",
1770
- "bytes": 3064
1873
+ "sha256": "24cc8e6abe08ca139af6599984e395863b5115076500b8faaae1d3b42bbe43b6",
1874
+ "bytes": 3220
1771
1875
  },
1772
1876
  "trigger/trigger-router.js": {
1773
- "sha256": "68a9dacf69468aef7cfb0f0da72122d33f34236e5296b176def5f40dbb0f0839",
1774
- "bytes": 24842
1877
+ "sha256": "9676fb57236040d46b923c8016394b519561ab18c99884dc190cf2221e2f1ecf",
1878
+ "bytes": 20550
1775
1879
  },
1776
1880
  "trigger/trigger-store.d.ts": {
1777
1881
  "sha256": "f846ca66494a2a1b834914652c845373d777bdeaaaefdc101ad1e78083d9ad5b",
@@ -3114,8 +3218,8 @@
3114
3218
  "bytes": 572
3115
3219
  },
3116
3220
  "v2/usecases/console-routes.js": {
3117
- "sha256": "cac41733df0270c8882c1ccc57e616862e422b7dd4aaf78783bb98a21c6edd81",
3118
- "bytes": 31338
3221
+ "sha256": "02e3be4472172bf03efb573376885fdb893af9b81b157370e25597750f77b03e",
3222
+ "bytes": 31729
3119
3223
  },
3120
3224
  "v2/usecases/console-service.d.ts": {
3121
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
+ }
@@ -0,0 +1,18 @@
1
+ import type { WorkflowRunSuccess } from '../daemon/workflow-runner.js';
2
+ import type { TriggerDefinition } from './types.js';
3
+ import type { ExecFn, HandoffArtifact } from './delivery-action.js';
4
+ export type DeliveryStageOutcome = {
5
+ readonly kind: 'continue';
6
+ } | {
7
+ readonly kind: 'stop';
8
+ readonly reason: string;
9
+ };
10
+ export interface DeliveryStage {
11
+ readonly name: string;
12
+ run(result: WorkflowRunSuccess, trigger: TriggerDefinition, execFn: ExecFn, ctx: PipelineContext): Promise<DeliveryStageOutcome>;
13
+ }
14
+ export interface PipelineContext {
15
+ handoffArtifact?: HandoffArtifact;
16
+ }
17
+ export declare function runDeliveryPipeline(stages: readonly DeliveryStage[], result: WorkflowRunSuccess, trigger: TriggerDefinition, execFn: ExecFn, triggerId: string): Promise<void>;
18
+ export declare const DEFAULT_DELIVERY_PIPELINE: readonly DeliveryStage[];