issue-flow 0.18.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/README.md +43 -97
  2. package/dist/agent-4DHRKZ2Z.js +32 -0
  3. package/dist/{analyze-Q4ONIWRZ.js → analyze-UEJ2R3H5.js} +42 -41
  4. package/dist/analyze-UEJ2R3H5.js.map +1 -0
  5. package/dist/{apply-EEFPY2W4.js → apply-QDYNQMUX.js} +22 -24
  6. package/dist/apply-QDYNQMUX.js.map +1 -0
  7. package/dist/artifacts-AMJQJFFV.js +82 -0
  8. package/dist/artifacts-AMJQJFFV.js.map +1 -0
  9. package/dist/{bench-WWWXLTFH.js → bench-RNRXVEFK.js} +42 -42
  10. package/dist/{chunk-RYOUZ6EK.js → chunk-23VHVVKW.js} +3 -3
  11. package/dist/chunk-2EYLOS5I.js +99 -0
  12. package/dist/chunk-2EYLOS5I.js.map +1 -0
  13. package/dist/{chunk-C5TL7T4V.js → chunk-2YM2VH6R.js} +2 -2
  14. package/dist/{chunk-XUEMATVY.js → chunk-37O2FMAN.js} +28 -25
  15. package/dist/chunk-37O2FMAN.js.map +1 -0
  16. package/dist/chunk-44RF3VFG.js +717 -0
  17. package/dist/chunk-44RF3VFG.js.map +1 -0
  18. package/dist/chunk-6AOZCWN2.js +21 -0
  19. package/dist/chunk-6AOZCWN2.js.map +1 -0
  20. package/dist/chunk-7MJGYPHF.js +1571 -0
  21. package/dist/chunk-7MJGYPHF.js.map +1 -0
  22. package/dist/{chunk-SA6HXL4Y.js → chunk-7WBUEBD5.js} +9 -9
  23. package/dist/chunk-7WBUEBD5.js.map +1 -0
  24. package/dist/chunk-7ZZUSMBJ.js +35 -0
  25. package/dist/chunk-7ZZUSMBJ.js.map +1 -0
  26. package/dist/{chunk-QJ44VG5G.js → chunk-ADH6RJNX.js} +3 -3
  27. package/dist/{chunk-34OCSKOB.js → chunk-AKL5UPR6.js} +159 -114
  28. package/dist/chunk-AKL5UPR6.js.map +1 -0
  29. package/dist/{chunk-7F7LGMVO.js → chunk-BTBJ5UOO.js} +12 -12
  30. package/dist/{chunk-7F7LGMVO.js.map → chunk-BTBJ5UOO.js.map} +1 -1
  31. package/dist/{chunk-HOAHMERN.js → chunk-CLZ6RRZL.js} +21 -21
  32. package/dist/chunk-DBLXLKGU.js +1201 -0
  33. package/dist/chunk-DBLXLKGU.js.map +1 -0
  34. package/dist/{chunk-DUS5ZNKL.js → chunk-DIMDAYZS.js} +7 -6
  35. package/dist/chunk-DZ3DZ3EN.js +278 -0
  36. package/dist/chunk-DZ3DZ3EN.js.map +1 -0
  37. package/dist/{chunk-CRGIQFUQ.js → chunk-E2H3JV2E.js} +3 -1
  38. package/dist/chunk-E2H3JV2E.js.map +1 -0
  39. package/dist/{chunk-45WZ6GMI.js → chunk-EORDSKWZ.js} +17 -17
  40. package/dist/chunk-EORDSKWZ.js.map +1 -0
  41. package/dist/{chunk-LTH6XYZ3.js → chunk-EYKPWHT7.js} +40 -30
  42. package/dist/chunk-EYKPWHT7.js.map +1 -0
  43. package/dist/{chunk-OODXFCQV.js → chunk-FU2FQ4JE.js} +14 -16
  44. package/dist/{chunk-OODXFCQV.js.map → chunk-FU2FQ4JE.js.map} +1 -1
  45. package/dist/{chunk-V7QOIQYC.js → chunk-G442RDFX.js} +9 -23
  46. package/dist/{chunk-V7QOIQYC.js.map → chunk-G442RDFX.js.map} +1 -1
  47. package/dist/{chunk-QPGEFLMY.js → chunk-I64N6RL6.js} +7 -7
  48. package/dist/{chunk-KRAGAUKD.js → chunk-JBYXJOJJ.js} +201 -64
  49. package/dist/chunk-JBYXJOJJ.js.map +1 -0
  50. package/dist/{chunk-SOM4QA6C.js → chunk-JCR5C5A7.js} +93 -18
  51. package/dist/chunk-JCR5C5A7.js.map +1 -0
  52. package/dist/{chunk-RNFUVKC3.js → chunk-K5NM26NV.js} +30 -13
  53. package/dist/chunk-K5NM26NV.js.map +1 -0
  54. package/dist/{chunk-YVPZUN6X.js → chunk-KUA6KBBD.js} +335 -38
  55. package/dist/chunk-KUA6KBBD.js.map +1 -0
  56. package/dist/{chunk-KMCS76ZW.js → chunk-KUL64XUF.js} +44 -12
  57. package/dist/chunk-KUL64XUF.js.map +1 -0
  58. package/dist/{chunk-HAKDLR6N.js → chunk-MAJ6QDRL.js} +65 -78
  59. package/dist/chunk-MAJ6QDRL.js.map +1 -0
  60. package/dist/{chunk-DGRTJD5R.js → chunk-MML2G7IC.js} +7 -7
  61. package/dist/chunk-NP47HRX2.js +136 -0
  62. package/dist/chunk-NP47HRX2.js.map +1 -0
  63. package/dist/{chunk-3R27MJ5R.js → chunk-PFWHHYEO.js} +3 -3
  64. package/dist/{chunk-ECU7YO7S.js → chunk-PM5YWJYO.js} +22 -6
  65. package/dist/chunk-PM5YWJYO.js.map +1 -0
  66. package/dist/{chunk-E4I6MMHD.js → chunk-PXPTIXJF.js} +154 -101
  67. package/dist/chunk-PXPTIXJF.js.map +1 -0
  68. package/dist/{chunk-CWSQVHVV.js → chunk-QJHZ3HYJ.js} +248 -102
  69. package/dist/chunk-QJHZ3HYJ.js.map +1 -0
  70. package/dist/{chunk-LI35PIIS.js → chunk-RDPK7LYK.js} +20 -117
  71. package/dist/chunk-RDPK7LYK.js.map +1 -0
  72. package/dist/{chunk-PMLE7KAQ.js → chunk-RMIBLFG3.js} +30 -14
  73. package/dist/chunk-RMIBLFG3.js.map +1 -0
  74. package/dist/{chunk-62GVVZQO.js → chunk-T736DSZI.js} +32 -316
  75. package/dist/chunk-T736DSZI.js.map +1 -0
  76. package/dist/{chunk-TZYINKCC.js → chunk-UDUUUFQF.js} +57 -29
  77. package/dist/chunk-UDUUUFQF.js.map +1 -0
  78. package/dist/{chunk-NEWNXZ65.js → chunk-V7GETODQ.js} +36 -28
  79. package/dist/{chunk-NEWNXZ65.js.map → chunk-V7GETODQ.js.map} +1 -1
  80. package/dist/{chunk-PPZ3K4YM.js → chunk-VHQMMY2D.js} +2 -2
  81. package/dist/{chunk-ZVZMWNCG.js → chunk-VJ3PF6B7.js} +50 -16
  82. package/dist/chunk-VJ3PF6B7.js.map +1 -0
  83. package/dist/{chunk-L6HSKTQE.js → chunk-W7LZLJAF.js} +4 -4
  84. package/dist/{chunk-6K2LCFG6.js → chunk-WB4FA2EH.js} +70 -81
  85. package/dist/chunk-WB4FA2EH.js.map +1 -0
  86. package/dist/{chunk-LGHND47K.js → chunk-WQSGL5LX.js} +22 -16
  87. package/dist/chunk-WQSGL5LX.js.map +1 -0
  88. package/dist/{chunk-ICM463EO.js → chunk-XNK5UN2D.js} +5 -649
  89. package/dist/chunk-XNK5UN2D.js.map +1 -0
  90. package/dist/{chunk-7UMMFOL2.js → chunk-Y2KOWABB.js} +39 -24
  91. package/dist/chunk-Y2KOWABB.js.map +1 -0
  92. package/dist/{chunk-QF7VEL3M.js → chunk-YC24E66P.js} +568 -158
  93. package/dist/chunk-YC24E66P.js.map +1 -0
  94. package/dist/{chunk-EG2MGDP5.js → chunk-Z6RCKCVB.js} +52 -46
  95. package/dist/chunk-Z6RCKCVB.js.map +1 -0
  96. package/dist/{chunk-YUNBOUQH.js → chunk-ZPGNVBWY.js} +8 -8
  97. package/dist/cli.js +132 -62
  98. package/dist/cli.js.map +1 -1
  99. package/dist/compat-OJG76J4I.js +24 -0
  100. package/dist/{config-LEBZZCJP.js → config-6YTWPDBK.js} +20 -17
  101. package/dist/{contract-JH2WBIO6.js → contract-HWLFFL3F.js} +2 -2
  102. package/dist/{conventions-XOT6YW5L.js → conventions-5UPOTU42.js} +20 -16
  103. package/dist/{conventions-XOT6YW5L.js.map → conventions-5UPOTU42.js.map} +1 -1
  104. package/dist/db-QAZG4LQD.js +264 -0
  105. package/dist/db-QAZG4LQD.js.map +1 -0
  106. package/dist/diagnostics-YEFB42E5.js +25 -0
  107. package/dist/execute-QCT64D37.js +38 -0
  108. package/dist/{generate-JGW5JSKB.js → generate-QATMDKOK.js} +46 -43
  109. package/dist/generate-QATMDKOK.js.map +1 -0
  110. package/dist/{git-A2IP32PQ.js → git-XGOECXWG.js} +2 -3
  111. package/dist/history-NBPUZVGQ.js +101 -0
  112. package/dist/history-NBPUZVGQ.js.map +1 -0
  113. package/dist/init-4LB2YKWP.js +28 -0
  114. package/dist/{operations-O4FORFIH.js → operations-RUQP2Y2F.js} +78 -52
  115. package/dist/operations-RUQP2Y2F.js.map +1 -0
  116. package/dist/{permissions-G4XCAESF.js → permissions-QZPUUBSO.js} +5 -6
  117. package/dist/plan-2NMSHTMD.js +38 -0
  118. package/dist/{policy-U5NBFAO5.js → policy-RKKFF5A2.js} +17 -15
  119. package/dist/{policy-U5NBFAO5.js.map → policy-RKKFF5A2.js.map} +1 -1
  120. package/dist/pr-QKFO5HI3.js +42 -0
  121. package/dist/pr-review-H2BFD6F2.js +33 -0
  122. package/dist/prd-ET6XKYRS.js +37 -0
  123. package/dist/{ps-76L6ZAZL.js → ps-UIKSOUAQ.js} +26 -15
  124. package/dist/ps-UIKSOUAQ.js.map +1 -0
  125. package/dist/{recorder-2BAKPBRA.js → recorder-LOU3PTIE.js} +11 -7
  126. package/dist/registry-HV7M6MAH.js +17 -0
  127. package/dist/repository-RCRR6RDE.js +80 -0
  128. package/dist/resume-BWJZGBLZ.js +278 -0
  129. package/dist/resume-BWJZGBLZ.js.map +1 -0
  130. package/dist/review-2MTZLNSS.js +38 -0
  131. package/dist/routing-RM5ABHHD.js +35 -0
  132. package/dist/run-XMACQBRJ.js +61 -0
  133. package/dist/{session-publisher-KAJQRHNZ.js → session-publisher-Q5TNEZPX.js} +3 -3
  134. package/dist/session-publisher-Q5TNEZPX.js.map +1 -0
  135. package/dist/{state-manager-UPHO2EA2.js → state-manager-SRN4VJSX.js} +9 -4
  136. package/dist/state-manager-SRN4VJSX.js.map +1 -0
  137. package/dist/{usage-KTMYXAPF.js → usage-JOODVE5O.js} +69 -63
  138. package/dist/usage-JOODVE5O.js.map +1 -0
  139. package/dist/web-TLMWJ2BM.js +205 -0
  140. package/dist/web-TLMWJ2BM.js.map +1 -0
  141. package/package.json +22 -8
  142. package/prompts/analyze.md +16 -19
  143. package/prompts/execute.md +73 -144
  144. package/prompts/generate.md +23 -10
  145. package/prompts/plan.md +32 -60
  146. package/prompts/pr-review.md +58 -40
  147. package/prompts/pr.md +50 -16
  148. package/prompts/prd.md +26 -19
  149. package/prompts/review.md +41 -18
  150. package/web/public/app.js +111 -112
  151. package/dist/agent-HMZTXCRT.js +0 -30
  152. package/dist/analyze-Q4ONIWRZ.js.map +0 -1
  153. package/dist/apply-EEFPY2W4.js.map +0 -1
  154. package/dist/chunk-34OCSKOB.js.map +0 -1
  155. package/dist/chunk-45WZ6GMI.js.map +0 -1
  156. package/dist/chunk-62GVVZQO.js.map +0 -1
  157. package/dist/chunk-6K2LCFG6.js.map +0 -1
  158. package/dist/chunk-7UMMFOL2.js.map +0 -1
  159. package/dist/chunk-CRGIQFUQ.js.map +0 -1
  160. package/dist/chunk-CWSQVHVV.js.map +0 -1
  161. package/dist/chunk-E4I6MMHD.js.map +0 -1
  162. package/dist/chunk-ECU7YO7S.js.map +0 -1
  163. package/dist/chunk-EG2MGDP5.js.map +0 -1
  164. package/dist/chunk-HAKDLR6N.js.map +0 -1
  165. package/dist/chunk-ICM463EO.js.map +0 -1
  166. package/dist/chunk-KMCS76ZW.js.map +0 -1
  167. package/dist/chunk-KRAGAUKD.js.map +0 -1
  168. package/dist/chunk-LGHND47K.js.map +0 -1
  169. package/dist/chunk-LI35PIIS.js.map +0 -1
  170. package/dist/chunk-LTH6XYZ3.js.map +0 -1
  171. package/dist/chunk-PMLE7KAQ.js.map +0 -1
  172. package/dist/chunk-QF7VEL3M.js.map +0 -1
  173. package/dist/chunk-RNFUVKC3.js.map +0 -1
  174. package/dist/chunk-SA6HXL4Y.js.map +0 -1
  175. package/dist/chunk-SOM4QA6C.js.map +0 -1
  176. package/dist/chunk-TZYINKCC.js.map +0 -1
  177. package/dist/chunk-WCCZJL7W.js +0 -141
  178. package/dist/chunk-WCCZJL7W.js.map +0 -1
  179. package/dist/chunk-XEYH6ZZI.js +0 -289
  180. package/dist/chunk-XEYH6ZZI.js.map +0 -1
  181. package/dist/chunk-XUEMATVY.js.map +0 -1
  182. package/dist/chunk-XZUEFTUP.js +0 -243
  183. package/dist/chunk-XZUEFTUP.js.map +0 -1
  184. package/dist/chunk-YVPZUN6X.js.map +0 -1
  185. package/dist/chunk-ZVZMWNCG.js.map +0 -1
  186. package/dist/diagnostics-HTCWF7F4.js +0 -23
  187. package/dist/execute-LELOSR5T.js +0 -37
  188. package/dist/generate-JGW5JSKB.js.map +0 -1
  189. package/dist/init-TO6MUXO4.js +0 -26
  190. package/dist/operations-O4FORFIH.js.map +0 -1
  191. package/dist/plan-OXAT344Q.js +0 -34
  192. package/dist/pr-UZHNKKZC.js +0 -39
  193. package/dist/pr-review-Q4ACAWDM.js +0 -32
  194. package/dist/prd-6CYEMLDY.js +0 -33
  195. package/dist/ps-76L6ZAZL.js.map +0 -1
  196. package/dist/registry-XLHHYLTR.js +0 -15
  197. package/dist/resume-URCU6CIJ.js +0 -244
  198. package/dist/resume-URCU6CIJ.js.map +0 -1
  199. package/dist/review-LVZT2TMW.js +0 -35
  200. package/dist/routing-EK6RBZM4.js +0 -33
  201. package/dist/run-2RXJCJKT.js +0 -56
  202. package/dist/usage-KTMYXAPF.js.map +0 -1
  203. package/dist/web-B5UPHHR5.js +0 -172
  204. package/dist/web-B5UPHHR5.js.map +0 -1
  205. /package/dist/{agent-HMZTXCRT.js.map → agent-4DHRKZ2Z.js.map} +0 -0
  206. /package/dist/{bench-WWWXLTFH.js.map → bench-RNRXVEFK.js.map} +0 -0
  207. /package/dist/{chunk-RYOUZ6EK.js.map → chunk-23VHVVKW.js.map} +0 -0
  208. /package/dist/{chunk-C5TL7T4V.js.map → chunk-2YM2VH6R.js.map} +0 -0
  209. /package/dist/{chunk-QJ44VG5G.js.map → chunk-ADH6RJNX.js.map} +0 -0
  210. /package/dist/{chunk-HOAHMERN.js.map → chunk-CLZ6RRZL.js.map} +0 -0
  211. /package/dist/{chunk-DUS5ZNKL.js.map → chunk-DIMDAYZS.js.map} +0 -0
  212. /package/dist/{chunk-QPGEFLMY.js.map → chunk-I64N6RL6.js.map} +0 -0
  213. /package/dist/{chunk-DGRTJD5R.js.map → chunk-MML2G7IC.js.map} +0 -0
  214. /package/dist/{chunk-3R27MJ5R.js.map → chunk-PFWHHYEO.js.map} +0 -0
  215. /package/dist/{chunk-PPZ3K4YM.js.map → chunk-VHQMMY2D.js.map} +0 -0
  216. /package/dist/{chunk-L6HSKTQE.js.map → chunk-W7LZLJAF.js.map} +0 -0
  217. /package/dist/{chunk-YUNBOUQH.js.map → chunk-ZPGNVBWY.js.map} +0 -0
  218. /package/dist/{config-LEBZZCJP.js.map → compat-OJG76J4I.js.map} +0 -0
  219. /package/dist/{contract-JH2WBIO6.js.map → config-6YTWPDBK.js.map} +0 -0
  220. /package/dist/{diagnostics-HTCWF7F4.js.map → contract-HWLFFL3F.js.map} +0 -0
  221. /package/dist/{execute-LELOSR5T.js.map → diagnostics-YEFB42E5.js.map} +0 -0
  222. /package/dist/{git-A2IP32PQ.js.map → execute-QCT64D37.js.map} +0 -0
  223. /package/dist/{init-TO6MUXO4.js.map → git-XGOECXWG.js.map} +0 -0
  224. /package/dist/{permissions-G4XCAESF.js.map → init-4LB2YKWP.js.map} +0 -0
  225. /package/dist/{plan-OXAT344Q.js.map → permissions-QZPUUBSO.js.map} +0 -0
  226. /package/dist/{pr-UZHNKKZC.js.map → plan-2NMSHTMD.js.map} +0 -0
  227. /package/dist/{pr-review-Q4ACAWDM.js.map → pr-QKFO5HI3.js.map} +0 -0
  228. /package/dist/{prd-6CYEMLDY.js.map → pr-review-H2BFD6F2.js.map} +0 -0
  229. /package/dist/{recorder-2BAKPBRA.js.map → prd-ET6XKYRS.js.map} +0 -0
  230. /package/dist/{registry-XLHHYLTR.js.map → recorder-LOU3PTIE.js.map} +0 -0
  231. /package/dist/{review-LVZT2TMW.js.map → registry-HV7M6MAH.js.map} +0 -0
  232. /package/dist/{routing-EK6RBZM4.js.map → repository-RCRR6RDE.js.map} +0 -0
  233. /package/dist/{run-2RXJCJKT.js.map → review-2MTZLNSS.js.map} +0 -0
  234. /package/dist/{session-publisher-KAJQRHNZ.js.map → routing-RM5ABHHD.js.map} +0 -0
  235. /package/dist/{state-manager-UPHO2EA2.js.map → run-XMACQBRJ.js.map} +0 -0
@@ -1,146 +1,59 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- resolveIssuePaths
4
- } from "./chunk-LI35PIIS.js";
5
- import {
3
+ GLOBAL_CONFIG_FILENAME,
4
+ PROJECT_CONFIG_FILENAME,
6
5
  formatDuration,
7
- printWarning
8
- } from "./chunk-XZUEFTUP.js";
9
- import {
10
- getGlobalRoot
11
- } from "./chunk-HAKDLR6N.js";
12
- import {
13
- RETRY_CONFIG_KEYS,
14
- getProjectRoot,
15
- run
16
- } from "./chunk-YVPZUN6X.js";
6
+ loadGlobalConfig,
7
+ printWarning,
8
+ readProjectConfigFile,
9
+ resolveIssuePaths
10
+ } from "./chunk-DBLXLKGU.js";
17
11
  import {
18
12
  DEFAULT_TELEMETRY_CONFIG
19
- } from "./chunk-6K2LCFG6.js";
13
+ } from "./chunk-WB4FA2EH.js";
20
14
  import {
21
15
  parseCodexUsage,
22
16
  parseUsage
23
- } from "./chunk-SOM4QA6C.js";
17
+ } from "./chunk-JCR5C5A7.js";
24
18
  import {
25
19
  AGENT_PHASES,
20
+ AGENT_PROVIDER_IDS,
26
21
  ANTIGRAVITY_CAPABILITIES,
27
22
  CLAUDE_CAPABILITIES,
28
23
  CODEX_CAPABILITIES,
29
24
  CURSOR_CAPABILITIES,
25
+ OPENCODE_CAPABILITIES,
30
26
  agentConfigInputSchema,
31
- globalConfigSchema,
32
27
  isAgentPhase,
33
28
  isAgentProviderId,
34
- issuesConfigSchema,
35
29
  parsePhasesInput,
30
+ resilienceConfigSchema,
31
+ telemetryConfigInputSchema
32
+ } from "./chunk-44RF3VFG.js";
33
+ import {
34
+ issuesConfigSchema,
36
35
  policyConfigInputSchema,
37
36
  policyConfigSchema,
38
37
  prReviewConfigSchema,
39
- resilienceConfigSchema,
40
38
  routingConfigInputSchema,
41
39
  routingConfigSchema,
42
- telemetryConfigInputSchema,
43
40
  verifyConfigSchema,
44
41
  webConfigSchema
45
- } from "./chunk-ICM463EO.js";
46
-
47
- // src/config/sources.ts
48
- import { existsSync } from "fs";
49
- import { readFile } from "fs/promises";
50
- import { dirname, join } from "path";
51
- var PROJECT_CONFIG_FILENAME = ".issue-flow.json";
52
- function findProjectRootFromCwd(start = process.cwd()) {
53
- let dir = start;
54
- while (true) {
55
- if (existsSync(join(dir, PROJECT_CONFIG_FILENAME)) || existsSync(join(dir, ".git"))) {
56
- return dir;
57
- }
58
- const parent = dirname(dir);
59
- if (parent === dir) return void 0;
60
- dir = parent;
61
- }
62
- }
63
- async function readProjectConfigFile(projectRoot, warn) {
64
- const root = projectRoot ?? findProjectRootFromCwd();
65
- if (root === void 0) {
66
- return null;
67
- }
68
- const filePath = join(root, PROJECT_CONFIG_FILENAME);
69
- let raw;
70
- try {
71
- raw = await readFile(filePath, "utf-8");
72
- } catch {
73
- return null;
74
- }
75
- let parsed;
76
- try {
77
- parsed = JSON.parse(raw);
78
- } catch {
79
- warn(`Ignoring ${PROJECT_CONFIG_FILENAME}: invalid JSON.`);
80
- return null;
81
- }
82
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
83
- warn(`Ignoring ${PROJECT_CONFIG_FILENAME}: expected a JSON object.`);
84
- return null;
85
- }
86
- return parsed;
87
- }
88
- var GLOBAL_CONFIG_FILENAME = "config.json";
89
- async function loadGlobalConfig(options = {}) {
90
- const warn = options.warn ?? printWarning;
91
- let root;
92
- try {
93
- root = options.globalRoot ?? getGlobalRoot({ env: options.env ?? process.env });
94
- } catch (err) {
95
- warn(`Ignoring ${GLOBAL_CONFIG_FILENAME}: ${err.message}`);
96
- return {};
97
- }
98
- const filePath = join(root, GLOBAL_CONFIG_FILENAME);
99
- let raw;
100
- try {
101
- raw = await readFile(filePath, "utf-8");
102
- } catch (err) {
103
- if (err.code !== "ENOENT") {
104
- warn(`Ignoring ${GLOBAL_CONFIG_FILENAME}: ${err.message}`);
105
- }
106
- return {};
107
- }
108
- let parsed;
109
- try {
110
- parsed = JSON.parse(raw);
111
- } catch {
112
- warn(`Ignoring ${GLOBAL_CONFIG_FILENAME}: invalid JSON.`);
113
- return {};
114
- }
115
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
116
- warn(`Ignoring ${GLOBAL_CONFIG_FILENAME}: expected a JSON object.`);
117
- return {};
118
- }
119
- const config = {};
120
- for (const [key, value] of Object.entries(parsed)) {
121
- const result = globalConfigSchema.safeParse({ [key]: value });
122
- if (!result.success) {
123
- warn(
124
- `Ignoring "${key}" key of ${GLOBAL_CONFIG_FILENAME}: ${result.error.issues[0]?.message ?? "invalid value"}.`
125
- );
126
- continue;
127
- }
128
- Object.assign(config, result.data);
129
- }
130
- return config;
131
- }
42
+ } from "./chunk-XNK5UN2D.js";
43
+ import {
44
+ RETRY_CONFIG_KEYS,
45
+ getProjectRoot,
46
+ run
47
+ } from "./chunk-KUA6KBBD.js";
132
48
 
133
49
  // src/config/dependencies.ts
134
- import { platform } from "os";
50
+ import { platform } from "node:os";
135
51
 
136
52
  // src/agents/availability.ts
137
- import { execa as execa6 } from "execa";
138
-
139
- // src/agents/registry.ts
140
- import { execa as execa5 } from "execa";
53
+ import { execa as execa7 } from "execa";
141
54
 
142
- // src/agents/antigravity.ts
143
- import { execa as execa2 } from "execa";
55
+ // src/agents/opencode.ts
56
+ import { execa as execa3 } from "execa";
144
57
 
145
58
  // src/core/shutdown.ts
146
59
  var SHUTDOWN_GRACE_MS = 15e3;
@@ -336,11 +249,14 @@ function describeStall(silentMs, provider = "claude") {
336
249
  return `${provider} produced no output for ${Math.round(silentMs / 1e3)}s and was stopped (stalled)`;
337
250
  }
338
251
 
252
+ // src/agents/antigravity.ts
253
+ import { execa as execa2 } from "execa";
254
+
339
255
  // src/agents/claude.ts
340
256
  import { execa } from "execa";
341
257
 
342
258
  // src/core/stream.ts
343
- import { createInterface } from "readline";
259
+ import { createInterface } from "node:readline";
344
260
  async function readClaudeStream(stdout, options = {}) {
345
261
  const outcome = { result: "", isError: false, usage: null, events: 0, raw: "" };
346
262
  const collected = [];
@@ -1064,11 +980,382 @@ ${stdout}`
1064
980
  }
1065
981
  };
1066
982
 
983
+ // src/agents/opencode.ts
984
+ var OPENCODE_MIN_VERSION = "1.15.0";
985
+ var DEFAULT_MAX_PROMPT_BYTES2 = 1e5;
986
+ var OPENCODE_INSTALL_URL = "https://opencode.ai/docs";
987
+ var MUTATING_BASH = [
988
+ "rm *",
989
+ "rmdir *",
990
+ "mv *",
991
+ "cp *",
992
+ "chmod *",
993
+ "chown *",
994
+ "mkdir *",
995
+ "touch *",
996
+ "tee *",
997
+ "git add *",
998
+ "git commit *",
999
+ "git push *",
1000
+ "git checkout *",
1001
+ "git reset *",
1002
+ "git rebase *",
1003
+ "npm install *",
1004
+ "npm ci *",
1005
+ "pnpm install *",
1006
+ "yarn add *"
1007
+ ];
1008
+ function isRecord2(value) {
1009
+ return typeof value === "object" && value !== null;
1010
+ }
1011
+ function maxPromptBytesOf2(settings) {
1012
+ return settings.maxPromptBytes ?? DEFAULT_MAX_PROMPT_BYTES2;
1013
+ }
1014
+ function interpretOpenCodeAuth(text) {
1015
+ const cleaned = text.replaceAll(`${String.fromCharCode(27)}[`, "[").trim();
1016
+ if (cleaned === "") return false;
1017
+ if (/no credentials|not logged|not authenticated|no providers/i.test(cleaned)) return false;
1018
+ return /[a-z0-9][a-z0-9._-]*/i.test(cleaned);
1019
+ }
1020
+ function parseOpenCodeUsage(tokens) {
1021
+ if (!isRecord2(tokens)) return null;
1022
+ const result = {};
1023
+ if (typeof tokens.input === "number" && Number.isFinite(tokens.input)) {
1024
+ result.inputTokens = tokens.input;
1025
+ }
1026
+ if (typeof tokens.output === "number" && Number.isFinite(tokens.output)) {
1027
+ result.outputTokens = tokens.output;
1028
+ }
1029
+ const cache = isRecord2(tokens.cache) ? tokens.cache : {};
1030
+ if (typeof cache.read === "number" && Number.isFinite(cache.read)) {
1031
+ result.cacheReadTokens = cache.read;
1032
+ }
1033
+ if (typeof cache.write === "number" && Number.isFinite(cache.write)) {
1034
+ result.cacheCreationTokens = cache.write;
1035
+ }
1036
+ return Object.keys(result).length === 0 ? null : result;
1037
+ }
1038
+ function isPermissionDenial2(message) {
1039
+ return /permission|denied|not allowed|external_directory/i.test(message);
1040
+ }
1041
+ function toolDetail(name, input) {
1042
+ const key = name === "bash" || name === "read" || name === "edit" || name === "write" ? ["command", "path", "filePath", "file"] : ["path", "pattern", "query", "url", "command"];
1043
+ for (const field of key) {
1044
+ const value = input[field];
1045
+ if (typeof value === "string" && value !== "") {
1046
+ return value.length > 80 ? `${value.slice(0, 77)}...` : value;
1047
+ }
1048
+ }
1049
+ return "";
1050
+ }
1051
+ function extractError(event) {
1052
+ if (typeof event.error === "string" && event.error !== "") return event.error;
1053
+ const error = isRecord2(event.error) ? event.error : {};
1054
+ const data = isRecord2(error.data) ? error.data : {};
1055
+ if (typeof data.message === "string" && data.message !== "") return data.message;
1056
+ if (typeof error.message === "string" && error.message !== "") return error.message;
1057
+ if (typeof error.name === "string" && error.name !== "") return error.name;
1058
+ return "OpenCode reported an error";
1059
+ }
1060
+ function consumeOpenCodeEvent(event, onEvent, acc) {
1061
+ if (typeof event.sessionID === "string" && event.sessionID !== "") {
1062
+ acc.sessionId = event.sessionID;
1063
+ }
1064
+ if (event.type === "text") {
1065
+ const part = isRecord2(event.part) ? event.part : {};
1066
+ if (typeof part.text === "string" && part.text !== "") {
1067
+ acc.result += part.text;
1068
+ onEvent?.({ kind: "text", text: part.text });
1069
+ }
1070
+ return;
1071
+ }
1072
+ if (event.type === "tool_use") {
1073
+ const part = isRecord2(event.part) ? event.part : {};
1074
+ const name = typeof part.tool === "string" ? part.tool : "tool";
1075
+ const state = isRecord2(part.state) ? part.state : {};
1076
+ const input = isRecord2(state.input) ? state.input : {};
1077
+ const detail = toolDetail(name, input);
1078
+ onEvent?.({ kind: "tool", name, ...detail === "" ? {} : { detail } });
1079
+ const error = isRecord2(state.error) ? state.error : {};
1080
+ const message = typeof error.message === "string" ? error.message : typeof state.status === "string" && state.status === "error" ? `${name} failed` : "";
1081
+ if (message !== "" && isPermissionDenial2(message)) {
1082
+ acc.permissionDenied = { tool: name, message };
1083
+ }
1084
+ return;
1085
+ }
1086
+ if (event.type === "step_finish") {
1087
+ const part = isRecord2(event.part) ? event.part : {};
1088
+ if (part.reason === "stop") acc.seenTerminal = true;
1089
+ const usage = parseOpenCodeUsage(part.tokens);
1090
+ if (usage) acc.usage = usage;
1091
+ return;
1092
+ }
1093
+ if (event.type === "error") {
1094
+ acc.error = extractError(event);
1095
+ acc.seenTerminal = true;
1096
+ }
1097
+ }
1098
+ function parseOpenCodeStream(raw, onEvent) {
1099
+ const acc = {
1100
+ result: "",
1101
+ sessionId: null,
1102
+ model: null,
1103
+ usage: null,
1104
+ seenTerminal: false,
1105
+ error: null,
1106
+ permissionDenied: null
1107
+ };
1108
+ for (const line of raw.split("\n")) {
1109
+ const trimmed = line.trim();
1110
+ if (trimmed === "") continue;
1111
+ try {
1112
+ const event = JSON.parse(trimmed);
1113
+ if (!isRecord2(event)) continue;
1114
+ consumeOpenCodeEvent(event, onEvent, acc);
1115
+ } catch {
1116
+ }
1117
+ }
1118
+ return acc;
1119
+ }
1120
+ function buildOpenCodePermission(permission, addDirs = []) {
1121
+ const external = { "*": "deny" };
1122
+ for (const dir of addDirs) {
1123
+ const normalized = dir.replace(/\\/g, "/").replace(/\/$/, "");
1124
+ if (normalized === "") continue;
1125
+ external[normalized] = "allow";
1126
+ external[`${normalized}/**`] = "allow";
1127
+ }
1128
+ const bash = permission === "read-only" ? Object.fromEntries([["*", "allow"], ...MUTATING_BASH.map((rule) => [rule, "deny"])]) : "allow";
1129
+ return {
1130
+ edit: permission === "read-only" ? "deny" : "allow",
1131
+ bash,
1132
+ question: "deny",
1133
+ external_directory: external
1134
+ };
1135
+ }
1136
+ function buildOpenCodeArgv(invocation, settings) {
1137
+ if (settings.model && !settings.model.includes("/")) {
1138
+ return {
1139
+ error: "configuration: OpenCode model must be provider/model (for example opencode-go/qwen3.8-flash)."
1140
+ };
1141
+ }
1142
+ const promptBytes = Buffer.byteLength(invocation.prompt, "utf8");
1143
+ const limit = maxPromptBytesOf2(settings.opencode);
1144
+ if (promptBytes > limit) {
1145
+ return {
1146
+ error: `configuration: prompt exceeds OpenCode argv limit (${promptBytes} bytes > ${limit} maxPromptBytes). The promptChannel is argv; shorten the prompt or raise agent.opencode.maxPromptBytes.`
1147
+ };
1148
+ }
1149
+ const workspace = invocation.workingDirectory ?? process.cwd();
1150
+ const args = ["run", "--format", "json", "--dir", workspace, "--auto"];
1151
+ if (settings.model) args.push("--model", settings.model);
1152
+ if (settings.opencode.variant) args.push("--variant", settings.opencode.variant);
1153
+ args.push(invocation.prompt);
1154
+ return {
1155
+ command: "opencode",
1156
+ args,
1157
+ env: {
1158
+ ...process.env,
1159
+ OPENCODE_PERMISSION: JSON.stringify(
1160
+ buildOpenCodePermission(invocation.permission, invocation.addDirs ?? [])
1161
+ )
1162
+ }
1163
+ };
1164
+ }
1165
+ function opencodeRunVerdict(input) {
1166
+ if (input.parsed.permissionDenied) {
1167
+ return {
1168
+ success: false,
1169
+ error: `configuration: permission denied for ${input.parsed.permissionDenied.tool}. ${input.parsed.permissionDenied.message}`
1170
+ };
1171
+ }
1172
+ if (input.parsed.error) {
1173
+ return { success: false, error: input.parsed.error };
1174
+ }
1175
+ const hasTerminalEvidence = input.parsed.seenTerminal || input.parsed.result.trim() !== "" || input.parsed.error !== null;
1176
+ if (!hasTerminalEvidence) {
1177
+ return {
1178
+ success: false,
1179
+ error: "configuration: OpenCode finished without a terminal event in the stream."
1180
+ };
1181
+ }
1182
+ if (input.exitCode !== 0 || input.timedOut) {
1183
+ return {
1184
+ success: false,
1185
+ error: input.parsed.error ?? `opencode exited with code ${input.exitCode}`
1186
+ };
1187
+ }
1188
+ return { success: true, error: null };
1189
+ }
1190
+ function configurationFailure2(agent, message, rawOutput = message) {
1191
+ return {
1192
+ success: false,
1193
+ result: "",
1194
+ rawOutput,
1195
+ exitCode: 1,
1196
+ usage: null,
1197
+ error: message,
1198
+ agent,
1199
+ harnessVersion: peekHarnessVersion("opencode")
1200
+ };
1201
+ }
1202
+ var OpenCodeRunner = class {
1203
+ id = "opencode";
1204
+ capabilities = OPENCODE_CAPABILITIES;
1205
+ versionCommand() {
1206
+ return { command: "opencode", args: ["--version"] };
1207
+ }
1208
+ authCommand() {
1209
+ return { command: "opencode", args: ["auth", "list"] };
1210
+ }
1211
+ async run(invocation, settings) {
1212
+ const agent = { provider: this.id, model: settings.model };
1213
+ const built = buildOpenCodeArgv(invocation, settings);
1214
+ if ("error" in built) return configurationFailure2(agent, built.error);
1215
+ const minimum = settings.opencode.minVersion ?? OPENCODE_MIN_VERSION;
1216
+ const installed2 = peekHarnessVersion(this.id);
1217
+ if (typeof installed2 === "string" && compareVersions(installed2, minimum) < 0) {
1218
+ return configurationFailure2(
1219
+ agent,
1220
+ `configuration: opencode ${installed2} is below the minimum ${minimum}. Update OpenCode CLI.`
1221
+ );
1222
+ }
1223
+ const { command, args, env } = built;
1224
+ const startTime = Date.now();
1225
+ const timeoutMs = invocation.timeout;
1226
+ let cleanup = null;
1227
+ try {
1228
+ const subprocess = execa3(command, args, {
1229
+ reject: false,
1230
+ timeout: timeoutMs > 0 ? timeoutMs : void 0,
1231
+ stripFinalNewline: false,
1232
+ stdin: "ignore",
1233
+ env,
1234
+ ...invocation.workingDirectory ? { cwd: invocation.workingDirectory } : {}
1235
+ });
1236
+ const unregister = registerChild({
1237
+ kill: (signal) => subprocess.kill(signal),
1238
+ done: subprocess.then(
1239
+ () => void 0,
1240
+ () => void 0
1241
+ )
1242
+ });
1243
+ const watchdog = createWatchdog({
1244
+ ...invocation.inactivityTimeoutMs === void 0 ? {} : { inactivityTimeoutMs: invocation.inactivityTimeoutMs },
1245
+ child: {
1246
+ kill: (signal) => subprocess.kill(signal),
1247
+ done: subprocess.then(
1248
+ () => void 0,
1249
+ () => void 0
1250
+ )
1251
+ }
1252
+ });
1253
+ cleanup = () => {
1254
+ watchdog.stop();
1255
+ unregister();
1256
+ };
1257
+ const chunks = [];
1258
+ if (subprocess.stdout) {
1259
+ subprocess.stdout.on("data", (chunk) => {
1260
+ watchdog.beat();
1261
+ const text = chunk.toString();
1262
+ chunks.push(text);
1263
+ invocation.onLine?.(text);
1264
+ });
1265
+ }
1266
+ if (subprocess.stderr) {
1267
+ subprocess.stderr.on("data", () => {
1268
+ watchdog.beat();
1269
+ });
1270
+ }
1271
+ const proc = await subprocess;
1272
+ watchdog.stop();
1273
+ unregister();
1274
+ const stdout = chunks.join("") || proc.stdout?.toString() || "";
1275
+ const stderr = proc.stderr?.toString() ?? "";
1276
+ const parsed = parseOpenCodeStream(stdout, invocation.onEvent);
1277
+ const rawOutput = stdout + (stderr ? `
1278
+ ${stderr}` : "");
1279
+ const exitCode = proc.exitCode ?? 1;
1280
+ const elapsedMs = Date.now() - startTime;
1281
+ const timedOut = wasTimedOut(proc, timeoutMs, elapsedMs);
1282
+ const stalled = watchdog.stalled;
1283
+ const authFailed = /not authenticated|unauthorized|no api key|auth required|login required/i.test(
1284
+ `${stderr}
1285
+ ${stdout}`
1286
+ );
1287
+ if (stalled) {
1288
+ return {
1289
+ success: false,
1290
+ result: "",
1291
+ rawOutput: describeStall(watchdog.silentMs, "opencode"),
1292
+ exitCode: 1,
1293
+ usage: parsed.usage,
1294
+ error: describeStall(watchdog.silentMs, "opencode"),
1295
+ agent: { provider: this.id, model: parsed.model ?? settings.model },
1296
+ sessionId: parsed.sessionId ?? void 0,
1297
+ harnessVersion: peekHarnessVersion(this.id)
1298
+ };
1299
+ }
1300
+ if (authFailed) {
1301
+ return {
1302
+ success: false,
1303
+ result: parsed.result,
1304
+ rawOutput,
1305
+ exitCode: timedOut ? 1 : exitCode,
1306
+ usage: parsed.usage,
1307
+ error: stderr.trim() || "OpenCode is not authenticated.",
1308
+ agent: { provider: this.id, model: parsed.model ?? settings.model },
1309
+ sessionId: parsed.sessionId ?? void 0,
1310
+ harnessVersion: peekHarnessVersion(this.id)
1311
+ };
1312
+ }
1313
+ const verdict = opencodeRunVerdict({ exitCode, parsed, timedOut });
1314
+ if (!verdict.success) {
1315
+ return {
1316
+ success: false,
1317
+ result: parsed.result,
1318
+ rawOutput,
1319
+ exitCode: timedOut || exitCode === 0 && verdict.error?.startsWith("configuration:") === true ? 1 : exitCode,
1320
+ usage: parsed.usage,
1321
+ error: timedOut ? describeAgentFailure(proc, stderr || rawOutput, timeoutMs, elapsedMs, command) : verdict.error ?? parsed.error ?? (stderr.trim() || rawOutput),
1322
+ agent: { provider: this.id, model: parsed.model ?? settings.model },
1323
+ sessionId: parsed.sessionId ?? void 0,
1324
+ harnessVersion: peekHarnessVersion(this.id)
1325
+ };
1326
+ }
1327
+ return {
1328
+ success: true,
1329
+ result: parsed.result,
1330
+ rawOutput,
1331
+ exitCode,
1332
+ usage: parsed.usage,
1333
+ error: null,
1334
+ agent: { provider: this.id, model: parsed.model ?? settings.model },
1335
+ sessionId: parsed.sessionId ?? void 0,
1336
+ harnessVersion: peekHarnessVersion(this.id)
1337
+ };
1338
+ } catch (err) {
1339
+ const message = err instanceof Error ? err.message : String(err);
1340
+ const missing = /ENOENT|not found|command not found/i.test(message);
1341
+ return configurationFailure2(
1342
+ agent,
1343
+ missing ? `configuration: opencode is not installed. Install OpenCode CLI: ${OPENCODE_INSTALL_URL}` : message
1344
+ );
1345
+ } finally {
1346
+ cleanup?.();
1347
+ }
1348
+ }
1349
+ };
1350
+
1351
+ // src/agents/registry.ts
1352
+ import { execa as execa6 } from "execa";
1353
+
1067
1354
  // src/agents/codex.ts
1068
- import { mkdtemp, readFile as readFile2, rm } from "fs/promises";
1069
- import { tmpdir } from "os";
1070
- import { join as join2 } from "path";
1071
- import { execa as execa3 } from "execa";
1355
+ import { mkdtemp, readFile, rm } from "node:fs/promises";
1356
+ import { tmpdir } from "node:os";
1357
+ import { join } from "node:path";
1358
+ import { execa as execa4 } from "execa";
1072
1359
  var BANNED_CODEX_FLAGS = [
1073
1360
  "--dangerously-bypass-approvals-and-sandbox",
1074
1361
  "--dangerously-bypass-hook-trust"
@@ -1221,15 +1508,15 @@ var CodexRunner = class {
1221
1508
  return { command: "codex", args: ["login", "status"] };
1222
1509
  }
1223
1510
  async run(invocation, settings) {
1224
- const tmp = await mkdtemp(join2(tmpdir(), "issue-flow-codex-"));
1225
- const outputFile = join2(tmp, "last-message.txt");
1511
+ const tmp = await mkdtemp(join(tmpdir(), "issue-flow-codex-"));
1512
+ const outputFile = join(tmp, "last-message.txt");
1226
1513
  const args = buildCodexArgv(invocation, settings, outputFile);
1227
1514
  const agent = { provider: this.id, model: settings.model };
1228
1515
  const base = { agent, harnessVersion: peekHarnessVersion(this.id) };
1229
1516
  const startTime = Date.now();
1230
1517
  let cleanup = null;
1231
1518
  try {
1232
- const subprocess = execa3("codex", args, {
1519
+ const subprocess = execa4("codex", args, {
1233
1520
  input: invocation.prompt,
1234
1521
  reject: false,
1235
1522
  timeout: invocation.timeout,
@@ -1259,7 +1546,7 @@ var CodexRunner = class {
1259
1546
  };
1260
1547
  const collected = [];
1261
1548
  if (subprocess.stdout) {
1262
- const { createInterface: createInterface2 } = await import("readline");
1549
+ const { createInterface: createInterface2 } = await import("node:readline");
1263
1550
  const lines = createInterface2({ input: subprocess.stdout });
1264
1551
  for await (const line of lines) {
1265
1552
  watchdog.beat();
@@ -1279,7 +1566,7 @@ ${stderr}` : "");
1279
1566
  const parsed = parseCodexStream(collected, invocation.onEvent);
1280
1567
  let lastMessage = "";
1281
1568
  try {
1282
- lastMessage = (await readFile2(outputFile, "utf-8")).trimEnd();
1569
+ lastMessage = (await readFile(outputFile, "utf-8")).trimEnd();
1283
1570
  } catch {
1284
1571
  lastMessage = "";
1285
1572
  }
@@ -1352,17 +1639,17 @@ ${stderr}` : "");
1352
1639
  };
1353
1640
 
1354
1641
  // src/agents/cursor.ts
1355
- import { execa as execa4 } from "execa";
1356
- function isRecord2(value) {
1642
+ import { execa as execa5 } from "execa";
1643
+ function isRecord3(value) {
1357
1644
  return typeof value === "object" && value !== null;
1358
1645
  }
1359
1646
  function toolName(call) {
1360
- if (isRecord2(call.readToolCall)) {
1361
- const args = isRecord2(call.readToolCall.args) ? call.readToolCall.args : {};
1647
+ if (isRecord3(call.readToolCall)) {
1648
+ const args = isRecord3(call.readToolCall.args) ? call.readToolCall.args : {};
1362
1649
  return { name: "Read", detail: typeof args.path === "string" ? args.path : "" };
1363
1650
  }
1364
- if (isRecord2(call.writeToolCall)) {
1365
- const args = isRecord2(call.writeToolCall.args) ? call.writeToolCall.args : {};
1651
+ if (isRecord3(call.writeToolCall)) {
1652
+ const args = isRecord3(call.writeToolCall.args) ? call.writeToolCall.args : {};
1366
1653
  return { name: "Edit", detail: typeof args.path === "string" ? args.path : "" };
1367
1654
  }
1368
1655
  const key = Object.keys(call).find((name) => name.endsWith("ToolCall"));
@@ -1376,18 +1663,18 @@ function consumeCursorEvent(event, onEvent) {
1376
1663
  };
1377
1664
  }
1378
1665
  if (event.type === "assistant") {
1379
- const message = isRecord2(event.message) ? event.message : {};
1666
+ const message = isRecord3(event.message) ? event.message : {};
1380
1667
  const content = Array.isArray(message.content) ? message.content : [];
1381
1668
  const texts = [];
1382
1669
  for (const block of content) {
1383
- if (isRecord2(block) && typeof block.text === "string") texts.push(block.text);
1670
+ if (isRecord3(block) && typeof block.text === "string") texts.push(block.text);
1384
1671
  }
1385
1672
  const text = texts.join("");
1386
1673
  if (text && onEvent) onEvent({ kind: "text", text });
1387
1674
  return { text };
1388
1675
  }
1389
1676
  if (event.type === "tool_call" && event.subtype === "started") {
1390
- const call = isRecord2(event.tool_call) ? event.tool_call : {};
1677
+ const call = isRecord3(event.tool_call) ? event.tool_call : {};
1391
1678
  const { name, detail } = toolName(call);
1392
1679
  onEvent?.({ kind: "tool", name, ...detail === "" ? {} : { detail } });
1393
1680
  return {};
@@ -1412,7 +1699,7 @@ function parseCursorStream(raw, onEvent) {
1412
1699
  if (trimmed === "") continue;
1413
1700
  try {
1414
1701
  const event = JSON.parse(trimmed);
1415
- if (!isRecord2(event)) continue;
1702
+ if (!isRecord3(event)) continue;
1416
1703
  const seen = consumeCursorEvent(event, onEvent);
1417
1704
  if (seen.result !== void 0) result = seen.result;
1418
1705
  if (seen.isError === true) isError = true;
@@ -1457,7 +1744,7 @@ var CursorRunner = class {
1457
1744
  const agent = { provider: this.id, model: settings.model };
1458
1745
  let cleanup = null;
1459
1746
  try {
1460
- const subprocess = execa4(command, args, {
1747
+ const subprocess = execa5(command, args, {
1461
1748
  reject: false,
1462
1749
  timeout: invocation.timeout,
1463
1750
  stripFinalNewline: false,
@@ -1575,6 +1862,7 @@ function ensureRunnersRegistered() {
1575
1862
  if (!registered.has("codex")) registerRunner(new CodexRunner());
1576
1863
  if (!registered.has("cursor")) registerRunner(new CursorRunner());
1577
1864
  if (!registered.has("antigravity")) registerRunner(new AntigravityRunner());
1865
+ if (!registered.has("opencode")) registerRunner(new OpenCodeRunner());
1578
1866
  }
1579
1867
  function runnerFor(providerId) {
1580
1868
  ensureRunnersRegistered();
@@ -1592,7 +1880,7 @@ async function ensureHarnessVersion(providerId) {
1592
1880
  const runner = runnerFor(providerId);
1593
1881
  const { command, args } = runner.versionCommand();
1594
1882
  try {
1595
- const proc = await execa5(command, args, { reject: false, timeout: 1e4 });
1883
+ const proc = await execa6(command, args, { reject: false, timeout: 1e4 });
1596
1884
  const version = proc.exitCode === 0 ? proc.stdout?.toString().trim() ?? null : null;
1597
1885
  cacheHarnessVersion(providerId, version);
1598
1886
  return version;
@@ -1602,6 +1890,92 @@ async function ensureHarnessVersion(providerId) {
1602
1890
  }
1603
1891
  }
1604
1892
 
1893
+ // src/routing/opencode-go.ts
1894
+ var OPENCODE_GO_POLICY_VERSION = "1";
1895
+ var OPENCODE_GO_MODELS = {
1896
+ cheap: "opencode-go/mimo-v2.5",
1897
+ default: "opencode-go/qwen3.8-flash",
1898
+ codingCheap: "opencode-go/deepseek-v4-flash",
1899
+ escalate: "opencode-go/gpt-5.6-luna",
1900
+ specialist: "opencode-go/kimi-k2.7-code"
1901
+ };
1902
+ var OPENCODE_GO_LADDER = [
1903
+ OPENCODE_GO_MODELS.cheap,
1904
+ OPENCODE_GO_MODELS.default,
1905
+ OPENCODE_GO_MODELS.escalate,
1906
+ OPENCODE_GO_MODELS.specialist
1907
+ ];
1908
+ var ROLE_BY_MODEL = {
1909
+ [OPENCODE_GO_MODELS.cheap]: "cheap",
1910
+ [OPENCODE_GO_MODELS.default]: "default",
1911
+ [OPENCODE_GO_MODELS.codingCheap]: "coding-cheap",
1912
+ [OPENCODE_GO_MODELS.escalate]: "escalate",
1913
+ [OPENCODE_GO_MODELS.specialist]: "specialist"
1914
+ };
1915
+ function choice(role, reasonCodes) {
1916
+ return {
1917
+ model: OPENCODE_GO_MODELS[role === "coding-cheap" ? "codingCheap" : role],
1918
+ role,
1919
+ reasonCodes
1920
+ };
1921
+ }
1922
+ function phaseDefault(phase) {
1923
+ if (phase === "analyze") return "cheap";
1924
+ if (phase === "pr-review") return "escalate";
1925
+ return "default";
1926
+ }
1927
+ function correctionRole(cycle) {
1928
+ if (cycle <= 1) return "coding-cheap";
1929
+ if (cycle === 2) return "default";
1930
+ if (cycle === 3) return "escalate";
1931
+ return "specialist";
1932
+ }
1933
+ function resolveOpenCodeGoModel(input) {
1934
+ const reasons = ["OPENCODE_GO_POLICY"];
1935
+ if ((input.correctionCycle ?? 0) >= 1 && input.phase === "execute") {
1936
+ const role2 = correctionRole(input.correctionCycle ?? 1);
1937
+ if (role2 === "specialist") reasons.push("OPENCODE_GO_SPECIALIST");
1938
+ else if (role2 === "escalate") reasons.push("OPENCODE_GO_ESCALATE");
1939
+ else if (role2 === "coding-cheap") reasons.push("OPENCODE_GO_CODING_CHEAP");
1940
+ return choice(role2, reasons);
1941
+ }
1942
+ const taskClass = input.taskClass ?? "feature";
1943
+ const risk = input.risk ?? "low";
1944
+ let role = phaseDefault(input.phase);
1945
+ if (input.phase === "analyze" && risk === "high") {
1946
+ role = "default";
1947
+ } else if (input.phase === "generate" && taskClass === "docs") {
1948
+ role = "cheap";
1949
+ reasons.push("OPENCODE_GO_CHEAP");
1950
+ } else if (input.phase === "prd" && (risk === "high" || taskClass === "infra")) {
1951
+ role = "escalate";
1952
+ reasons.push("OPENCODE_GO_ESCALATE");
1953
+ } else if (input.phase === "plan" && risk === "high") {
1954
+ role = "escalate";
1955
+ reasons.push("OPENCODE_GO_ESCALATE");
1956
+ } else if (input.phase === "plan" && input.profile === "economy" && risk === "low") {
1957
+ role = "cheap";
1958
+ reasons.push("OPENCODE_GO_CHEAP");
1959
+ } else if (input.phase === "execute") {
1960
+ if (risk === "high" || taskClass === "infra" || taskClass === "refactor" && risk !== "low") {
1961
+ role = "escalate";
1962
+ reasons.push("OPENCODE_GO_ESCALATE");
1963
+ } else if ((taskClass === "bugfix" || taskClass === "test") && risk === "low") {
1964
+ role = "coding-cheap";
1965
+ reasons.push("OPENCODE_GO_CODING_CHEAP");
1966
+ }
1967
+ } else if (input.phase === "review" && risk === "high") {
1968
+ role = "escalate";
1969
+ reasons.push("OPENCODE_GO_ESCALATE");
1970
+ } else if (input.phase === "pr" && taskClass === "bugfix" && risk === "low") {
1971
+ role = "coding-cheap";
1972
+ reasons.push("OPENCODE_GO_CODING_CHEAP");
1973
+ } else if (input.phase === "pr-review" && risk === "low" && taskClass === "docs") {
1974
+ role = "default";
1975
+ }
1976
+ return choice(role, reasons);
1977
+ }
1978
+
1605
1979
  // src/agents/origins.ts
1606
1980
  var trackedOrigins = null;
1607
1981
  function setTrackedOrigins(origins) {
@@ -1620,7 +1994,8 @@ function mergeAgentBlocks(base, overlay) {
1620
1994
  claude: { ...base.claude, ...dropUndefined(overlay.claude ?? {}) },
1621
1995
  codex: { ...base.codex, ...dropUndefined(overlay.codex ?? {}) },
1622
1996
  cursor: { ...base.cursor, ...dropUndefined(overlay.cursor ?? {}) },
1623
- antigravity: { ...base.antigravity, ...dropUndefined(overlay.antigravity ?? {}) }
1997
+ antigravity: { ...base.antigravity, ...dropUndefined(overlay.antigravity ?? {}) },
1998
+ opencode: { ...base.opencode, ...dropUndefined(overlay.opencode ?? {}) }
1624
1999
  };
1625
2000
  }
1626
2001
  function dropUndefined(value) {
@@ -1631,7 +2006,7 @@ function dropUndefined(value) {
1631
2006
  return result;
1632
2007
  }
1633
2008
  async function resolveAgentFor(phase, options = {}) {
1634
- const { getAgentCliOverrides: getAgentCliOverrides2, loadAgentConfig: loadAgentConfig2 } = await import("./config-LEBZZCJP.js");
2009
+ const { getAgentCliOverrides: getAgentCliOverrides2, loadAgentConfig: loadAgentConfig2 } = await import("./config-6YTWPDBK.js");
1635
2010
  const config = options.config ?? await loadAgentConfig2();
1636
2011
  const cli = options.cli ?? getAgentCliOverrides2();
1637
2012
  const defaultBlock = {
@@ -1640,7 +2015,8 @@ async function resolveAgentFor(phase, options = {}) {
1640
2015
  claude: config.claude,
1641
2016
  codex: config.codex,
1642
2017
  cursor: config.cursor,
1643
- antigravity: config.antigravity
2018
+ antigravity: config.antigravity,
2019
+ opencode: config.opencode
1644
2020
  };
1645
2021
  const phaseBlock = mergeAgentBlocks(config.phases[phase] ?? {}, cli.phases?.[phase]);
1646
2022
  const merged = mergeAgentBlocks(defaultBlock, phaseBlock);
@@ -1657,6 +2033,9 @@ async function resolveAgentFor(phase, options = {}) {
1657
2033
  model = cli.forceModel;
1658
2034
  modelOrigin = "cli";
1659
2035
  }
2036
+ if (provider === "opencode" && model === null) {
2037
+ model = resolveOpenCodeGoModel({ phase }).model;
2038
+ }
1660
2039
  return {
1661
2040
  provider,
1662
2041
  model,
@@ -1664,6 +2043,7 @@ async function resolveAgentFor(phase, options = {}) {
1664
2043
  codex: merged.codex ?? {},
1665
2044
  cursor: merged.cursor ?? {},
1666
2045
  antigravity: merged.antigravity ?? {},
2046
+ opencode: merged.opencode ?? {},
1667
2047
  origin: { provider: providerOrigin, model: modelOrigin }
1668
2048
  };
1669
2049
  }
@@ -1706,7 +2086,7 @@ function parseAgentPhaseFlag(value) {
1706
2086
  const [providerRaw, ...modelParts] = rest.split(":");
1707
2087
  if (!providerRaw || !isAgentProviderId(providerRaw)) {
1708
2088
  throw new Error(
1709
- `Unknown agent provider "${providerRaw ?? ""}". Valid providers: claude, codex, cursor, antigravity.`
2089
+ `Unknown agent provider "${providerRaw ?? ""}". Valid providers: claude, codex, cursor, antigravity, opencode.`
1710
2090
  );
1711
2091
  }
1712
2092
  const model = modelParts.length > 0 ? modelParts.join(":") : void 0;
@@ -1718,6 +2098,14 @@ function parseAgentPhaseFlag(value) {
1718
2098
  }
1719
2099
  };
1720
2100
  }
2101
+ function applyOpenCodeGoModel(settings, input) {
2102
+ if (settings.provider !== "opencode" || settings.origin.model !== "default") {
2103
+ return settings;
2104
+ }
2105
+ const model = resolveOpenCodeGoModel(input).model;
2106
+ if (model === settings.model) return settings;
2107
+ return { ...settings, model };
2108
+ }
1721
2109
  async function describeRunAgents(phases = AGENT_PHASES) {
1722
2110
  const target = phases.length > 0 ? phases : AGENT_PHASES;
1723
2111
  const byPhase = {};
@@ -1737,7 +2125,7 @@ async function describeRunAgents(phases = AGENT_PHASES) {
1737
2125
  defaultModel = settings.model;
1738
2126
  }
1739
2127
  }
1740
- const { loadAgentConfig: loadAgentConfig2 } = await import("./config-LEBZZCJP.js");
2128
+ const { loadAgentConfig: loadAgentConfig2 } = await import("./config-6YTWPDBK.js");
1741
2129
  const config = await loadAgentConfig2();
1742
2130
  defaultProvider = config.provider;
1743
2131
  defaultModel = config.model;
@@ -1775,9 +2163,10 @@ var PROVIDER_HARNESS = {
1775
2163
  claude: "claude-code",
1776
2164
  codex: "codex-cli",
1777
2165
  cursor: "cursor-cli",
1778
- antigravity: "antigravity-cli"
2166
+ antigravity: "antigravity-cli",
2167
+ opencode: "opencode-cli"
1779
2168
  };
1780
- var ALL_PROVIDERS = ["claude", "codex", "cursor", "antigravity"];
2169
+ var ALL_PROVIDERS = AGENT_PROVIDER_IDS;
1781
2170
  var probeCache = /* @__PURE__ */ new Map();
1782
2171
  var inventoryCache = null;
1783
2172
  function deriveState(installed2, authentication, cooldownUntil, nowMs) {
@@ -1821,7 +2210,7 @@ async function probeAgentUncached(id, options = {}) {
1821
2210
  let installed2 = false;
1822
2211
  try {
1823
2212
  const { command, args } = runner.versionCommand();
1824
- const proc = await execa6(command, args, { reject: false, timeout: 1e4 });
2213
+ const proc = await execa7(command, args, { reject: false, timeout: 1e4 });
1825
2214
  installed2 = proc.exitCode === 0;
1826
2215
  version = installed2 ? proc.stdout?.toString().trim() || "unknown" : null;
1827
2216
  } catch {
@@ -1836,10 +2225,10 @@ async function probeAgentUncached(id, options = {}) {
1836
2225
  } else if (runner.authCommand && runner.capabilities.authProbe !== "none") {
1837
2226
  try {
1838
2227
  const { command, args } = runner.authCommand();
1839
- const auth = await execa6(command, args, { reject: false, timeout: 1e4 });
2228
+ const auth = await execa7(command, args, { reject: false, timeout: 1e4 });
1840
2229
  const text = `${auth.stdout?.toString() ?? ""}
1841
2230
  ${auth.stderr?.toString() ?? ""}`;
1842
- const ok = runner.capabilities.authProbe === "text" ? !/not logged in|not authenticated|no models available/i.test(text) : auth.exitCode === 0;
2231
+ const ok = runner.capabilities.authProbe === "text" ? id === "opencode" ? interpretOpenCodeAuth(text) : !/not logged in|not authenticated|no models available/i.test(text) : auth.exitCode === 0;
1843
2232
  authentication = ok ? "confirmed" : "failed";
1844
2233
  detail = ok ? `${version} (authenticated)` : `${version} (not authenticated)`;
1845
2234
  } catch {
@@ -1917,6 +2306,9 @@ function installHint(id) {
1917
2306
  if (id === "antigravity") {
1918
2307
  return "Install Antigravity CLI: https://antigravity.google/docs/cli/install/";
1919
2308
  }
2309
+ if (id === "opencode") {
2310
+ return "Install OpenCode CLI: https://opencode.ai/docs";
2311
+ }
1920
2312
  return "Install Claude Code: https://docs.anthropic.com/en/docs/claude-code";
1921
2313
  }
1922
2314
 
@@ -1982,7 +2374,7 @@ function readAgentEnv(env, warn) {
1982
2374
  layer.provider = env.ISSUE_FLOW_AGENT;
1983
2375
  } else {
1984
2376
  warn(
1985
- `Ignoring ISSUE_FLOW_AGENT="${env.ISSUE_FLOW_AGENT}": expected claude, codex, cursor or antigravity.`
2377
+ `Ignoring ISSUE_FLOW_AGENT="${env.ISSUE_FLOW_AGENT}": expected claude, codex, cursor, antigravity or opencode.`
1986
2378
  );
1987
2379
  }
1988
2380
  }
@@ -2043,6 +2435,14 @@ function readAgentEnv(env, warn) {
2043
2435
  antigravity.executeTimeout = env.ISSUE_FLOW_ANTIGRAVITY_EXECUTE_TIMEOUT;
2044
2436
  }
2045
2437
  if (Object.keys(antigravity).length > 0) layer.antigravity = antigravity;
2438
+ const opencode = {};
2439
+ if (env.ISSUE_FLOW_OPENCODE_VARIANT !== void 0 && env.ISSUE_FLOW_OPENCODE_VARIANT !== "") {
2440
+ opencode.variant = env.ISSUE_FLOW_OPENCODE_VARIANT;
2441
+ }
2442
+ if (env.ISSUE_FLOW_OPENCODE_MIN_VERSION !== void 0 && env.ISSUE_FLOW_OPENCODE_MIN_VERSION !== "") {
2443
+ opencode.minVersion = env.ISSUE_FLOW_OPENCODE_MIN_VERSION;
2444
+ }
2445
+ if (Object.keys(opencode).length > 0) layer.opencode = opencode;
2046
2446
  return layer;
2047
2447
  }
2048
2448
  function readAgentKey(raw, label, warn) {
@@ -2065,6 +2465,7 @@ function readAgentKey(raw, label, warn) {
2065
2465
  ...parsed.data.codex !== void 0 ? { codex: parsed.data.codex } : {},
2066
2466
  ...parsed.data.cursor !== void 0 ? { cursor: parsed.data.cursor } : {},
2067
2467
  ...parsed.data.antigravity !== void 0 ? { antigravity: parsed.data.antigravity } : {},
2468
+ ...parsed.data.opencode !== void 0 ? { opencode: parsed.data.opencode } : {},
2068
2469
  ...Object.keys(phases).length > 0 ? { phases } : {}
2069
2470
  };
2070
2471
  }
@@ -2087,7 +2488,8 @@ function mergeAgentBlockLayers(layers) {
2087
2488
  claude: { ...merged.claude, ...layer.block.claude },
2088
2489
  codex: { ...merged.codex, ...layer.block.codex },
2089
2490
  cursor: { ...merged.cursor, ...layer.block.cursor },
2090
- antigravity: { ...merged.antigravity, ...layer.block.antigravity }
2491
+ antigravity: { ...merged.antigravity, ...layer.block.antigravity },
2492
+ opencode: { ...merged.opencode, ...layer.block.opencode }
2091
2493
  };
2092
2494
  }
2093
2495
  return any ? merged : void 0;
@@ -2100,6 +2502,7 @@ function dropUndefinedBlock(block) {
2100
2502
  if (block.codex !== void 0) result.codex = block.codex;
2101
2503
  if (block.cursor !== void 0) result.cursor = block.cursor;
2102
2504
  if (block.antigravity !== void 0) result.antigravity = block.antigravity;
2505
+ if (block.opencode !== void 0) result.opencode = block.opencode;
2103
2506
  return result;
2104
2507
  }
2105
2508
  async function loadAgentConfig(options = {}) {
@@ -2143,6 +2546,12 @@ async function loadAgentConfig(options = {}) {
2143
2546
  env: envLayer.antigravity,
2144
2547
  cli: cli.antigravity
2145
2548
  });
2549
+ const opencode = mergeConfigLayers({
2550
+ global: globalLayer.opencode,
2551
+ project: projectLayer.opencode,
2552
+ env: envLayer.opencode,
2553
+ cli: cli.opencode
2554
+ });
2146
2555
  const phases = {};
2147
2556
  const phaseOrigins = {};
2148
2557
  for (const phase of AGENT_PHASES) {
@@ -2187,7 +2596,7 @@ async function loadAgentConfig(options = {}) {
2187
2596
  ]),
2188
2597
  phases: phaseOrigins
2189
2598
  });
2190
- const resolved = { provider, model, claude, codex, cursor, antigravity, phases };
2599
+ const resolved = { provider, model, claude, codex, cursor, antigravity, opencode, phases };
2191
2600
  if (canCache) cachedAgentConfig = resolved;
2192
2601
  return resolved;
2193
2602
  }
@@ -2229,7 +2638,7 @@ async function validateDependencies() {
2229
2638
  }
2230
2639
 
2231
2640
  // src/config/engine.ts
2232
- import { join as join3 } from "path";
2641
+ import { join as join2 } from "node:path";
2233
2642
  var DEFAULTS = {
2234
2643
  retryLimit: 10,
2235
2644
  retryForever: false,
@@ -2239,6 +2648,7 @@ var DEFAULTS = {
2239
2648
  function createConfig(options) {
2240
2649
  return {
2241
2650
  issueNumber: options.issueNumber,
2651
+ inPipeline: options.inPipeline,
2242
2652
  maxIterations: options.maxIterations,
2243
2653
  retryLimit: options.retryLimit ?? DEFAULTS.retryLimit,
2244
2654
  retryForever: options.retryForever ?? DEFAULTS.retryForever,
@@ -2264,13 +2674,13 @@ async function resolvePaths(config, scriptDir) {
2264
2674
  }
2265
2675
  const base = scriptDir ?? projectRoot;
2266
2676
  const standalone = {
2267
- prdFile: join3(base, "prd.json"),
2268
- progressFile: join3(base, "progress.txt"),
2269
- archiveDir: join3(base, "archive"),
2270
- lastBranchFile: join3(base, ".last-branch"),
2677
+ prdFile: join2(base, "prd.json"),
2678
+ progressFile: join2(base, "progress.txt"),
2679
+ archiveDir: join2(base, "archive"),
2680
+ lastBranchFile: join2(base, ".last-branch"),
2271
2681
  projectRoot
2272
2682
  };
2273
- const { bindTelemetry } = await import("./recorder-2BAKPBRA.js");
2683
+ const { bindTelemetry } = await import("./recorder-LOU3PTIE.js");
2274
2684
  bindTelemetry({ tasksPath: standalone.prdFile });
2275
2685
  return standalone;
2276
2686
  }
@@ -2828,9 +3238,8 @@ async function loadWebConfig(options = {}) {
2828
3238
  var WEB_CONFIG_FILENAME = PROJECT_CONFIG_FILENAME;
2829
3239
 
2830
3240
  export {
2831
- PROJECT_CONFIG_FILENAME,
2832
- GLOBAL_CONFIG_FILENAME,
2833
- loadGlobalConfig,
3241
+ OPENCODE_GO_POLICY_VERSION,
3242
+ resolveOpenCodeGoModel,
2834
3243
  getShutdownSignal,
2835
3244
  onShutdown,
2836
3245
  installShutdownHandlers,
@@ -2872,7 +3281,8 @@ export {
2872
3281
  WEB_CONFIG_FILENAME,
2873
3282
  resolveAgentFor,
2874
3283
  parseAgentPhaseFlag,
3284
+ applyOpenCodeGoModel,
2875
3285
  describeRunAgents,
2876
3286
  hasExplicitAgentSelection
2877
3287
  };
2878
- //# sourceMappingURL=chunk-QF7VEL3M.js.map
3288
+ //# sourceMappingURL=chunk-YC24E66P.js.map