@exaudeus/workrail 3.72.0 → 3.72.2
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.
- package/dist/cli-worktrain.js +4 -6
- package/dist/console-ui/assets/{index-CTza1zb5.js → index-J97yE18I.js} +1 -1
- package/dist/console-ui/index.html +1 -1
- package/dist/daemon/active-sessions.d.ts +17 -0
- package/dist/daemon/active-sessions.js +55 -0
- package/dist/daemon/context-loader.d.ts +32 -0
- package/dist/daemon/context-loader.js +34 -0
- package/dist/daemon/session-scope.d.ts +3 -2
- package/dist/daemon/tools/_shared.d.ts +38 -0
- package/dist/daemon/tools/_shared.js +101 -0
- package/dist/daemon/tools/bash.d.ts +3 -0
- package/dist/daemon/tools/bash.js +57 -0
- package/dist/daemon/tools/continue-workflow.d.ts +6 -0
- package/dist/daemon/tools/continue-workflow.js +208 -0
- package/dist/daemon/tools/file-tools.d.ts +6 -0
- package/dist/daemon/tools/file-tools.js +195 -0
- package/dist/daemon/tools/glob-grep.d.ts +4 -0
- package/dist/daemon/tools/glob-grep.js +172 -0
- package/dist/daemon/tools/report-issue.d.ts +3 -0
- package/dist/daemon/tools/report-issue.js +129 -0
- package/dist/daemon/tools/signal-coordinator.d.ts +4 -0
- package/dist/daemon/tools/signal-coordinator.js +105 -0
- package/dist/daemon/tools/spawn-agent.d.ts +6 -0
- package/dist/daemon/tools/spawn-agent.js +135 -0
- package/dist/daemon/workflow-runner.d.ts +56 -30
- package/dist/daemon/workflow-runner.js +172 -984
- package/dist/infrastructure/storage/workflow-resolution.js +5 -6
- package/dist/manifest.json +131 -27
- package/dist/mcp/handlers/shared/request-workflow-reader.js +14 -0
- package/dist/trigger/coordinator-deps.d.ts +15 -0
- package/dist/trigger/coordinator-deps.js +322 -0
- package/dist/trigger/delivery-pipeline.d.ts +18 -0
- package/dist/trigger/delivery-pipeline.js +148 -0
- package/dist/trigger/dispatch-deduplicator.d.ts +6 -0
- package/dist/trigger/dispatch-deduplicator.js +24 -0
- package/dist/trigger/trigger-listener.d.ts +2 -3
- package/dist/trigger/trigger-listener.js +9 -276
- package/dist/trigger/trigger-router.d.ts +8 -7
- package/dist/trigger/trigger-router.js +19 -97
- package/dist/v2/usecases/console-routes.js +10 -2
- package/docs/ideas/backlog.md +82 -48
- package/package.json +3 -2
|
@@ -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
|
|
32
|
-
|
|
31
|
+
const isWrNamespace = id.startsWith('wr.');
|
|
32
|
+
const nonBundledShadowers = bundledSource && isWrNamespace
|
|
33
|
+
? sources.filter(s => s !== bundledSource)
|
|
33
34
|
: [];
|
|
34
|
-
if (bundledSource &&
|
|
35
|
+
if (bundledSource && nonBundledShadowers.length > 0) {
|
|
35
36
|
const { sourceRef: bundledRef, workflow } = bundledSource;
|
|
36
|
-
const attemptedShadowRefs =
|
|
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,
|
package/dist/manifest.json
CHANGED
|
@@ -238,8 +238,8 @@
|
|
|
238
238
|
"bytes": 31
|
|
239
239
|
},
|
|
240
240
|
"cli-worktrain.js": {
|
|
241
|
-
"sha256": "
|
|
242
|
-
"bytes":
|
|
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-J97yE18I.js": {
|
|
481
|
+
"sha256": "0da2082fca8449f3023228d5f699719ea12dc4bac26f0ff7a8157b4095211fc6",
|
|
482
|
+
"bytes": 768234
|
|
483
|
+
},
|
|
484
484
|
"console-ui/index.html": {
|
|
485
|
-
"sha256": "
|
|
485
|
+
"sha256": "90dda75d0af1447bcd5f6acedf2c9c289d9e6532cacf2fb74cb643064baf5712",
|
|
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": "
|
|
642
|
-
"bytes":
|
|
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": "
|
|
690
|
-
"bytes":
|
|
769
|
+
"sha256": "cdea9422bff42b6c5833b343c100d947e164eb015a2a2777c89ab32fca70c426",
|
|
770
|
+
"bytes": 13073
|
|
691
771
|
},
|
|
692
772
|
"daemon/workflow-runner.js": {
|
|
693
|
-
"sha256": "
|
|
694
|
-
"bytes":
|
|
773
|
+
"sha256": "aabe365f2250461c2762e87eeff1b8742e48a80813cf49c6c1d0bac7c72d2242",
|
|
774
|
+
"bytes": 78676
|
|
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": "
|
|
958
|
-
"bytes":
|
|
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": "
|
|
1030
|
-
"bytes":
|
|
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": "
|
|
1762
|
-
"bytes":
|
|
1865
|
+
"sha256": "57192a2e0e01d472985acd6d17be41930d2c189e029a11137661f990e1446ed3",
|
|
1866
|
+
"bytes": 1744
|
|
1763
1867
|
},
|
|
1764
1868
|
"trigger/trigger-listener.js": {
|
|
1765
|
-
"sha256": "
|
|
1766
|
-
"bytes":
|
|
1869
|
+
"sha256": "12a137a0ad256f2473171edc54bc624f4ad28f986d31bb4658538237b2082094",
|
|
1870
|
+
"bytes": 13222
|
|
1767
1871
|
},
|
|
1768
1872
|
"trigger/trigger-router.d.ts": {
|
|
1769
|
-
"sha256": "
|
|
1770
|
-
"bytes":
|
|
1873
|
+
"sha256": "24cc8e6abe08ca139af6599984e395863b5115076500b8faaae1d3b42bbe43b6",
|
|
1874
|
+
"bytes": 3220
|
|
1771
1875
|
},
|
|
1772
1876
|
"trigger/trigger-router.js": {
|
|
1773
|
-
"sha256": "
|
|
1774
|
-
"bytes":
|
|
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": "
|
|
3118
|
-
"bytes":
|
|
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[];
|