specrails-desktop 2.2.1 → 2.4.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 (350) hide show
  1. package/client/dist/assets/ActivityFeedPage-DJJlZ3mF.js +1 -0
  2. package/client/dist/assets/AgentsPage-49JaEDjR.js +86 -0
  3. package/client/dist/assets/{AnalyticsPage-BD0paa75.js → AnalyticsPage-BUd3gWYC.js} +1 -1
  4. package/client/dist/assets/{BarChart-D8ZZRab3.js → BarChart-HDe_YoUD.js} +1 -1
  5. package/client/dist/assets/CodePage-CqPPND47.js +2 -0
  6. package/client/dist/assets/{DesktopAnalyticsPage-mwd8460_.js → DesktopAnalyticsPage-CgvmSvF0.js} +1 -1
  7. package/client/dist/assets/DocsDialog-hHFd3Ejs.js +11 -0
  8. package/client/dist/assets/DocsPage-B4R1aksg.js +11 -0
  9. package/client/dist/assets/{ExportDropdown-CLYmQhic.js → ExportDropdown-f4dwQjlT.js} +1 -1
  10. package/client/dist/assets/IntegrationsPage-CX2Ybxx0.js +3 -0
  11. package/client/dist/assets/JobDetailPage-DN2Jc8Ti.js +16 -0
  12. package/client/dist/assets/JobsPage-DmdpqijT.js +1 -0
  13. package/client/dist/assets/code-BwIz8agY.js +1 -0
  14. package/client/dist/assets/code-CD7yNSK0.js +1 -0
  15. package/client/dist/assets/code-CDFlxUFC.js +1 -0
  16. package/client/dist/assets/code-CY85RXZU.js +1 -0
  17. package/client/dist/assets/code-Cp3Fdng-.js +1 -0
  18. package/client/dist/assets/code-D24e1Crx.js +1 -0
  19. package/client/dist/assets/code-DtZBQTi9.js +1 -0
  20. package/client/dist/assets/code-nKa0fkm_.js +1 -0
  21. package/client/dist/assets/{cssMode-Cc6ozl-J.js → cssMode-DzNPAYFh.js} +1 -1
  22. package/client/dist/assets/{dist-js-D3MxtOYa.js → dist-js-COfIfLRE.js} +1 -1
  23. package/client/dist/assets/{dist-js-BOu_cXw3.js → dist-js-CvScGQU_.js} +1 -1
  24. package/client/dist/assets/{editor.main-CfXxHimg.js → editor.main-C7Rmw-hR.js} +2 -2
  25. package/client/dist/assets/{freemarker2-DP7J1gG3.js → freemarker2-Cszs4SVo.js} +1 -1
  26. package/client/dist/assets/{handlebars-BjRlucw6.js → handlebars-Dp7Lsuym.js} +1 -1
  27. package/client/dist/assets/{html-OumBQJ-U.js → html-BURidrEm.js} +1 -1
  28. package/client/dist/assets/{htmlMode-CStc3zXM.js → htmlMode--k5M7GjZ.js} +1 -1
  29. package/client/dist/assets/index-DBpvYrDK.css +2 -0
  30. package/client/dist/assets/index-DGIXKRHE.js +142 -0
  31. package/client/dist/assets/{integrations-Cublz3m6.js → integrations-2C7MkGT0.js} +1 -1
  32. package/client/dist/assets/{integrations-HIlUxXVs.js → integrations-BDC670cg.js} +1 -1
  33. package/client/dist/assets/integrations-BqUmRUef.js +1 -0
  34. package/client/dist/assets/{integrations-DmQYCUvN.js → integrations-C2jQtv-s.js} +1 -1
  35. package/client/dist/assets/{integrations-DRdbki5W.js → integrations-CB98NeH5.js} +1 -1
  36. package/client/dist/assets/{integrations-C3p12Ms6.js → integrations-CX4p_bij.js} +1 -1
  37. package/client/dist/assets/{integrations-DaC4SzzL.js → integrations-_SuVeQIG.js} +1 -1
  38. package/client/dist/assets/{integrations-Cr6hH7XR.js → integrations-eQPHAYsE.js} +1 -1
  39. package/client/dist/assets/{javascript-CMk--e7g.js → javascript-kJQz__44.js} +1 -1
  40. package/client/dist/assets/jira-C-ATCti0.js +1 -0
  41. package/client/dist/assets/jira-CmVfRM-b.js +1 -0
  42. package/client/dist/assets/jira-D7bkKAX8.js +1 -0
  43. package/client/dist/assets/jira-DKImM1YH.js +1 -0
  44. package/client/dist/assets/jira-DOw8bkIR.js +1 -0
  45. package/client/dist/assets/jira-DlA-wGp-.js +1 -0
  46. package/client/dist/assets/jira-Fob8EGxN.js +1 -0
  47. package/client/dist/assets/jira-xZA2lixb.js +1 -0
  48. package/client/dist/assets/{jsonMode-C2h3ZcjZ.js → jsonMode-v5JYPpnz.js} +1 -1
  49. package/client/dist/assets/{lib-DQ2hrj8m.js → lib-Bro9Z0gp.js} +1 -1
  50. package/client/dist/assets/{liquid-mI3KJrBE.js → liquid-Dl9I6gWt.js} +1 -1
  51. package/client/dist/assets/{lspLanguageFeatures-DU09ggWi.js → lspLanguageFeatures-CPlEe0NK.js} +1 -1
  52. package/client/dist/assets/{mdx-C41VDTR_.js → mdx-Byl7TtzQ.js} +1 -1
  53. package/client/dist/assets/{monaco.contribution-CPObAXMC.js → monaco.contribution-YMAkHQcQ.js} +2 -2
  54. package/client/dist/assets/{python-Y27rKQtk.js → python-jWQwT6j2.js} +1 -1
  55. package/client/dist/assets/{razor-Cd5-q9Bp.js → razor-BWS3sP-E.js} +1 -1
  56. package/client/dist/assets/setup-C0dzw8j4.js +1 -0
  57. package/client/dist/assets/setup-C1IA-9YS.js +1 -0
  58. package/client/dist/assets/setup-CpfjaNut.js +1 -0
  59. package/client/dist/assets/setup-D3rNZA9A.js +1 -0
  60. package/client/dist/assets/setup-UD2aanGs.js +1 -0
  61. package/client/dist/assets/setup-WP6WOYQh.js +1 -0
  62. package/client/dist/assets/setup-gzLG8T6F.js +1 -0
  63. package/client/dist/assets/setup-pjgmYHx6.js +1 -0
  64. package/client/dist/assets/specs-4lA_u79w.js +1 -0
  65. package/client/dist/assets/{specs-D2FzlLn9.js → specs-BHjxcjOf.js} +1 -1
  66. package/client/dist/assets/{specs-CZ1PsXsC.js → specs-CXNQzPk9.js} +1 -1
  67. package/client/dist/assets/{specs-Dyc5hYeE.js → specs-DFnc2Huj.js} +1 -1
  68. package/client/dist/assets/{specs-BFfu3u-a.js → specs-DZCLH2-l.js} +1 -1
  69. package/client/dist/assets/{specs-B__C8-8a.js → specs-DgmyAE3N.js} +1 -1
  70. package/client/dist/assets/{specs-DaUTrNF9.js → specs-DicWhvwi.js} +1 -1
  71. package/client/dist/assets/{specs-k0PyLDVt.js → specs-dkro6lSM.js} +1 -1
  72. package/client/dist/assets/{tsMode-B0y_xEci.js → tsMode-BbOGOuSV.js} +1 -1
  73. package/client/dist/assets/{typescript-BzK0OgwW.js → typescript-eBtFQJLs.js} +1 -1
  74. package/client/dist/assets/{useProjectCache-BxY4aTjd.js → useProjectCache-D9juBhsO.js} +1 -1
  75. package/client/dist/assets/{workers-rt--R2Qy.js → workers-BvicOoDf.js} +1 -1
  76. package/client/dist/assets/{xml-eX9QXAmI.js → xml-BJepAPyM.js} +1 -1
  77. package/client/dist/assets/{yaml-fcsNkpOt.js → yaml-DabgV-eA.js} +1 -1
  78. package/client/dist/index.html +13 -12
  79. package/docs/jira-integration-plan.md +321 -0
  80. package/package.json +1 -1
  81. package/server/dist/agent-refine-manager.js +128 -153
  82. package/server/dist/chat-manager.js +242 -0
  83. package/server/dist/code-explorer-router.js +78 -0
  84. package/server/dist/command-resolver.js +17 -0
  85. package/server/dist/contract-refine-runner.js +42 -10
  86. package/server/dist/db.js +86 -0
  87. package/server/dist/desktop-db.js +3 -0
  88. package/server/dist/explore-stdin-session.js +129 -0
  89. package/server/dist/feature-flags.js +11 -0
  90. package/server/dist/jira/jira-adf.js +113 -0
  91. package/server/dist/jira/jira-backlog-config.js +58 -0
  92. package/server/dist/jira/jira-client.js +279 -0
  93. package/server/dist/jira/jira-credential-store.js +103 -0
  94. package/server/dist/jira/jira-db.js +341 -0
  95. package/server/dist/jira/jira-issue-fields.js +428 -0
  96. package/server/dist/jira/jira-materializer.js +250 -0
  97. package/server/dist/jira/jira-status-resolver.js +211 -0
  98. package/server/dist/jira/jira-sync-manager.js +1014 -0
  99. package/server/dist/jira/types.js +9 -0
  100. package/server/dist/jira-router.js +304 -0
  101. package/server/dist/mobile/mobile-auth.js +16 -0
  102. package/server/dist/project-registry.js +43 -1
  103. package/server/dist/project-router-chat.js +218 -0
  104. package/server/dist/project-router-helpers.js +275 -0
  105. package/server/dist/project-router-jobs.js +389 -0
  106. package/server/dist/project-router-settings.js +312 -0
  107. package/server/dist/project-router-setup.js +456 -0
  108. package/server/dist/project-router-spending.js +320 -0
  109. package/server/dist/project-router-terminals.js +312 -0
  110. package/server/dist/project-router-tickets.js +1815 -0
  111. package/server/dist/project-router.js +31 -3950
  112. package/server/dist/providers/claude-adapter.js +23 -0
  113. package/server/dist/providers/codex-adapter.js +6 -0
  114. package/server/dist/rails-router.js +12 -0
  115. package/server/dist/spawn-lifecycle.js +117 -0
  116. package/client/dist/assets/ActivityFeedPage-BpjXuX2H.js +0 -1
  117. package/client/dist/assets/AgentsPage-D-7fDbTc.js +0 -86
  118. package/client/dist/assets/CodePage-B6q6CiYJ.js +0 -2
  119. package/client/dist/assets/DocsDialog-D_dyF2h9.js +0 -11
  120. package/client/dist/assets/DocsPage-C9-Ru8wE.js +0 -11
  121. package/client/dist/assets/IntegrationsPage-3WWtx9hi.js +0 -3
  122. package/client/dist/assets/JobDetailPage-DgN-79s-.js +0 -16
  123. package/client/dist/assets/JobsPage-Du8_w1ob.js +0 -1
  124. package/client/dist/assets/code-AL1rVIMb.js +0 -1
  125. package/client/dist/assets/code-C0BKpkht.js +0 -1
  126. package/client/dist/assets/code-C0FTS3ew.js +0 -1
  127. package/client/dist/assets/code-CPcHxzxw.js +0 -1
  128. package/client/dist/assets/code-D3ryDniw.js +0 -1
  129. package/client/dist/assets/code-D3zVVQTj.js +0 -1
  130. package/client/dist/assets/code-PCmfS3dn.js +0 -1
  131. package/client/dist/assets/code-exI0G5Wd.js +0 -1
  132. package/client/dist/assets/index-D17R4Cjc.css +0 -2
  133. package/client/dist/assets/index-D9G_K4L-.js +0 -142
  134. package/client/dist/assets/integrations-D28q1kF6.js +0 -1
  135. package/client/dist/assets/setup--FMCsnQS.js +0 -1
  136. package/client/dist/assets/setup-B19ZpBNi.js +0 -1
  137. package/client/dist/assets/setup-BZPmkjSN.js +0 -1
  138. package/client/dist/assets/setup-BqYA02rS.js +0 -1
  139. package/client/dist/assets/setup-ChKQDHN9.js +0 -1
  140. package/client/dist/assets/setup-D2n9jMfM.js +0 -1
  141. package/client/dist/assets/setup-P3r6YP1D.js +0 -1
  142. package/client/dist/assets/setup-fnfEbwlv.js +0 -1
  143. package/client/dist/assets/specs-cKEh2LXt.js +0 -1
  144. /package/client/dist/assets/{abap-Bw6f2wDG.js → abap-s65oMlhi.js} +0 -0
  145. /package/client/dist/assets/{activity-BdrPln96.js → activity-BqqwnH_h.js} +0 -0
  146. /package/client/dist/assets/{activity-BEIp_Y1A.js → activity-C8qqEIoP.js} +0 -0
  147. /package/client/dist/assets/{activity-CpkRS8Sx.js → activity-CZVM4nlJ.js} +0 -0
  148. /package/client/dist/assets/{activity-DOUVEjJi.js → activity-Cyy07Tgo.js} +0 -0
  149. /package/client/dist/assets/{activity-DRwkql_y.js → activity-DlbWCa4y.js} +0 -0
  150. /package/client/dist/assets/{activity-DKCpESPt.js → activity-Dwq0heud.js} +0 -0
  151. /package/client/dist/assets/{activity-DcDQ7tjw.js → activity-qFTcMyW9.js} +0 -0
  152. /package/client/dist/assets/{addon-image-3WCl5Vhd.js → addon-image-CpF0L0jM.js} +0 -0
  153. /package/client/dist/assets/{addon-ligatures-C5OdliKs.js → addon-ligatures-hXysGZrA.js} +0 -0
  154. /package/client/dist/assets/{addon-webgl-BbX6pSjl.js → addon-webgl-Cn1slavz.js} +0 -0
  155. /package/client/dist/assets/{addspec-D33ocMxf.js → addspec-B1FTtI2a.js} +0 -0
  156. /package/client/dist/assets/{addspec-DFswZ0jK.js → addspec-BCT9vm_c.js} +0 -0
  157. /package/client/dist/assets/{addspec-DVZ15Jp8.js → addspec-DeDOztDr.js} +0 -0
  158. /package/client/dist/assets/{addspec-Fkv91Opc.js → addspec-DpRgmfmx.js} +0 -0
  159. /package/client/dist/assets/{addspec-BEeF5-zc.js → addspec-Dw-0Dg-4.js} +0 -0
  160. /package/client/dist/assets/{addspec-B5yl4Loj.js → addspec-rp496P_F.js} +0 -0
  161. /package/client/dist/assets/{addspec-DRE-jZv7.js → addspec-v8j6A7CD.js} +0 -0
  162. /package/client/dist/assets/{agents-DK-Dlc0i.js → agents-23iPejcA.js} +0 -0
  163. /package/client/dist/assets/{agents-Q6Ldfpxx.js → agents-BDx1RXcl.js} +0 -0
  164. /package/client/dist/assets/{agents-TeOSy-ax.js → agents-BFr3kUhK.js} +0 -0
  165. /package/client/dist/assets/{agents-Bm9rPqnt.js → agents-B_1L9xRg.js} +0 -0
  166. /package/client/dist/assets/{agents-1nCDWRmP.js → agents-BlPnx-mz.js} +0 -0
  167. /package/client/dist/assets/{agents-iTqjRajS.js → agents-DcxZHzNr.js} +0 -0
  168. /package/client/dist/assets/{agents-s87sMGzL.js → agents-G3shOewU.js} +0 -0
  169. /package/client/dist/assets/{agentstudio-B6Wb59E7.js → agentstudio-B-CMAQqy.js} +0 -0
  170. /package/client/dist/assets/{agentstudio-D3I62TLJ.js → agentstudio-Bk1eZcv4.js} +0 -0
  171. /package/client/dist/assets/{agentstudio-DuH9TogZ.js → agentstudio-ChxNuGAu.js} +0 -0
  172. /package/client/dist/assets/{agentstudio-Kw88_dUF.js → agentstudio-DNlme601.js} +0 -0
  173. /package/client/dist/assets/{agentstudio-BdidyBzZ.js → agentstudio-DpP9caEE.js} +0 -0
  174. /package/client/dist/assets/{agentstudio-BSnWLR63.js → agentstudio-Y3G0ddJ2.js} +0 -0
  175. /package/client/dist/assets/{agentstudio-BADhZ41e.js → agentstudio-kk9RB7Se.js} +0 -0
  176. /package/client/dist/assets/{aiedit-DJMny-D5.js → aiedit-5ETerMK1.js} +0 -0
  177. /package/client/dist/assets/{aiedit-D2ji6Qy0.js → aiedit-BBCrOpHq.js} +0 -0
  178. /package/client/dist/assets/{aiedit-DAhZTvtk.js → aiedit-BMtcGYNE.js} +0 -0
  179. /package/client/dist/assets/{aiedit-DvrcbwGv.js → aiedit-D9ddlgkM.js} +0 -0
  180. /package/client/dist/assets/{aiedit-WBSjT_C1.js → aiedit-De0SOH6S.js} +0 -0
  181. /package/client/dist/assets/{aiedit-BWxHGsYA.js → aiedit-DrfzQroF.js} +0 -0
  182. /package/client/dist/assets/{aiedit-DOcxERkU.js → aiedit-fMltW101.js} +0 -0
  183. /package/client/dist/assets/{analytics-C9Zc-rkM.js → analytics-BeTyviO8.js} +0 -0
  184. /package/client/dist/assets/{analytics-CrPCZRJ-.js → analytics-C4eEO260.js} +0 -0
  185. /package/client/dist/assets/{analytics-CYj0tfj7.js → analytics-C67cIA1b.js} +0 -0
  186. /package/client/dist/assets/{analytics-C6EzgtdE.js → analytics-CAguvW28.js} +0 -0
  187. /package/client/dist/assets/{analytics-CVx3YOc0.js → analytics-DBtt8Mgk.js} +0 -0
  188. /package/client/dist/assets/{analytics-CnY4kNG3.js → analytics-DUPtODxX.js} +0 -0
  189. /package/client/dist/assets/{analytics-BIdr0YfL.js → analytics-YIpQvPAc.js} +0 -0
  190. /package/client/dist/assets/{apex-Cw8_REBo.js → apex-BLUBIldB.js} +0 -0
  191. /package/client/dist/assets/{attachments-DYHGA2Dj.js → attachments-CCWasu-P.js} +0 -0
  192. /package/client/dist/assets/{attachments-Dd92KpUH.js → attachments-CHaDUfjB.js} +0 -0
  193. /package/client/dist/assets/{attachments-DzdU6DV6.js → attachments-CVSAbGNl.js} +0 -0
  194. /package/client/dist/assets/{attachments-Bcf6BG6V.js → attachments-Chg5poG1.js} +0 -0
  195. /package/client/dist/assets/{attachments-BW4L3l2L.js → attachments-DazTVJbH.js} +0 -0
  196. /package/client/dist/assets/{attachments-COcrGRFz.js → attachments-Dn-JImAK.js} +0 -0
  197. /package/client/dist/assets/{attachments-Bke8sCU4.js → attachments-LDA9kp2X.js} +0 -0
  198. /package/client/dist/assets/{azcli-Cz6HAoOw.js → azcli-DuWxh9mO.js} +0 -0
  199. /package/client/dist/assets/{bat-CcJ-xyqL.js → bat-UKoTejQm.js} +0 -0
  200. /package/client/dist/assets/{bicep-z1WDCKYz.js → bicep-4sTT4B3D.js} +0 -0
  201. /package/client/dist/assets/{browser-DGITz3fC.js → browser-BDd1dbFa.js} +0 -0
  202. /package/client/dist/assets/{browser-JsAIGCEW.js → browser-BWSgbfdX.js} +0 -0
  203. /package/client/dist/assets/{browser-M5-rbPlw.js → browser-D2Y_UAKA.js} +0 -0
  204. /package/client/dist/assets/{browser-BlYF4OOq.js → browser-DH9SGVfM.js} +0 -0
  205. /package/client/dist/assets/{browser-Bc-YdlVg.js → browser-DWOVYMlg.js} +0 -0
  206. /package/client/dist/assets/{browser-CT-ReZGt.js → browser-Dxc_VIRK.js} +0 -0
  207. /package/client/dist/assets/{browser-5ErDlJoR.js → browser-lTQwcDCI.js} +0 -0
  208. /package/client/dist/assets/{cameligo-BRewOpfa.js → cameligo-CAAryRYO.js} +0 -0
  209. /package/client/dist/assets/{chat-DwUm6W9z.js → chat-BO9MvVID.js} +0 -0
  210. /package/client/dist/assets/{chat-BEGuC03z.js → chat-CPgmgZOj.js} +0 -0
  211. /package/client/dist/assets/{chat-CboQguCi.js → chat-CUrG1eVg.js} +0 -0
  212. /package/client/dist/assets/{chat-DRCa9pOt.js → chat-CvOOKB2s.js} +0 -0
  213. /package/client/dist/assets/{chat-BEW60P_u.js → chat-DIh3hr6y.js} +0 -0
  214. /package/client/dist/assets/{chat-yoXwguQu.js → chat-UVVZqA57.js} +0 -0
  215. /package/client/dist/assets/{chat-BQNMD0PL.js → chat-mPn3UlMl.js} +0 -0
  216. /package/client/dist/assets/{clojure-DBjRWN6g.js → clojure-BlMERO1w.js} +0 -0
  217. /package/client/dist/assets/{clsx-DnqN-uhr.js → clsx-CnH-HMk3.js} +0 -0
  218. /package/client/dist/assets/{coffee-Cfk_XHGR.js → coffee-Cj8D-Wl1.js} +0 -0
  219. /package/client/dist/assets/{commands-sqrqsxyE.js → commands-B-MVT-2F.js} +0 -0
  220. /package/client/dist/assets/{commands-UD1NzmwX.js → commands-B0yFTp7e.js} +0 -0
  221. /package/client/dist/assets/{commands-DLrvnPNg.js → commands-BR1kDkHQ.js} +0 -0
  222. /package/client/dist/assets/{commands-CJxCry-o.js → commands-Cb21pDlG.js} +0 -0
  223. /package/client/dist/assets/{commands-CfgY-_of.js → commands-DWgp-8W1.js} +0 -0
  224. /package/client/dist/assets/{commands-B772IyDa.js → commands-ddsl1V91.js} +0 -0
  225. /package/client/dist/assets/{commands-BDDp6xFG.js → commands-t4frzhB0.js} +0 -0
  226. /package/client/dist/assets/{common-Dmm1GhdD.js → common-5ilvMOcH.js} +0 -0
  227. /package/client/dist/assets/{common-DltqHaAe.js → common-B4sqsKp7.js} +0 -0
  228. /package/client/dist/assets/{common-GbpxfPG8.js → common-BKpVwUIf.js} +0 -0
  229. /package/client/dist/assets/{common-DeDELLZJ.js → common-BzEC3kJU.js} +0 -0
  230. /package/client/dist/assets/{common-DnjcgkPH.js → common-CALKUpYm.js} +0 -0
  231. /package/client/dist/assets/{common-Dard9UNH.js → common-CTEbWVZS.js} +0 -0
  232. /package/client/dist/assets/{common-DCr6VzJ7.js → common-DQiza2Xp.js} +0 -0
  233. /package/client/dist/assets/{cpp-BVob6BaP.js → cpp-BPfKnaj_.js} +0 -0
  234. /package/client/dist/assets/{csharp-C4fbRuOu.js → csharp-gX-x5uD6.js} +0 -0
  235. /package/client/dist/assets/{csp-DthFP_vT.js → csp-DKGVt8SM.js} +0 -0
  236. /package/client/dist/assets/{css-CGMH0hcW.js → css-CPMdnAVq.js} +0 -0
  237. /package/client/dist/assets/{cypher-Pnf68BRV.js → cypher-ClMDrj9S.js} +0 -0
  238. /package/client/dist/assets/{dart-PMMOtxZX.js → dart-C4zbzpVv.js} +0 -0
  239. /package/client/dist/assets/{dashboard-BZBADHSj.js → dashboard--Y6yzMlf.js} +0 -0
  240. /package/client/dist/assets/{dashboard-I19DXBxw.js → dashboard--a4-6oYE.js} +0 -0
  241. /package/client/dist/assets/{dashboard-CB6Le1yN.js → dashboard-BiJ3CDTG.js} +0 -0
  242. /package/client/dist/assets/{dashboard-B4ixDVk8.js → dashboard-CiXjk63Z.js} +0 -0
  243. /package/client/dist/assets/{dashboard-C1MfeUHs.js → dashboard-Cx5VjCea.js} +0 -0
  244. /package/client/dist/assets/{dashboard-C7SK6xu5.js → dashboard-D7jg25XR.js} +0 -0
  245. /package/client/dist/assets/{dashboard-CoTpMOBM.js → dashboard-DpGYK2s1.js} +0 -0
  246. /package/client/dist/assets/{dockerfile-di1nsJCc.js → dockerfile-D9xw73D1.js} +0 -0
  247. /package/client/dist/assets/{ecl-D_WVcB5M.js → ecl-gqO8tIR9.js} +0 -0
  248. /package/client/dist/assets/{editor.api2-XLGzZfbc.js → editor.api2-BPnIxMjz.js} +0 -0
  249. /package/client/dist/assets/{elixir-OAdJEMOn.js → elixir-DSAhVF3_.js} +0 -0
  250. /package/client/dist/assets/{explore-D2EFgt8J.js → explore-BE5UmlbD.js} +0 -0
  251. /package/client/dist/assets/{explore-BV5Xxlsn.js → explore-BmTaI8dX.js} +0 -0
  252. /package/client/dist/assets/{explore-A8Ltoblq.js → explore-CCwkqoWq.js} +0 -0
  253. /package/client/dist/assets/{explore-4mFpnrKU.js → explore-CMdEoPDx.js} +0 -0
  254. /package/client/dist/assets/{explore-C3FSE42C.js → explore-CtdCL4QU.js} +0 -0
  255. /package/client/dist/assets/{explore-B9A3iN2W.js → explore-DHjxSkqQ.js} +0 -0
  256. /package/client/dist/assets/{explore-BrBJvfjP.js → explore-__BeALjE.js} +0 -0
  257. /package/client/dist/assets/{flow9-D3QEZjgn.js → flow9-DeQCSPOd.js} +0 -0
  258. /package/client/dist/assets/{format-command-CwGuwzGA.js → format-command-2VNoNnMv.js} +0 -0
  259. /package/client/dist/assets/{fsharp-BF0k_8N8.js → fsharp-CEfaXL-S.js} +0 -0
  260. /package/client/dist/assets/{go-BAQO5Jsz.js → go-Xp1OkZCh.js} +0 -0
  261. /package/client/dist/assets/{graphql-hdFVFkiV.js → graphql-BwRXrUwe.js} +0 -0
  262. /package/client/dist/assets/{hcl-DWnl1o-X.js → hcl-u06DtVFk.js} +0 -0
  263. /package/client/dist/assets/{ini-CB-6OVu3.js → ini-AmeIpFND.js} +0 -0
  264. /package/client/dist/assets/{java-d1CmfiHX.js → java-CyDbRQjX.js} +0 -0
  265. /package/client/dist/assets/{jobs-DPPT6bV6.js → jobs-8viuHLDV.js} +0 -0
  266. /package/client/dist/assets/{jobs-3j3_npyo.js → jobs-AW2eB5D-.js} +0 -0
  267. /package/client/dist/assets/{jobs-2N3RXDAM.js → jobs-BSm89DL5.js} +0 -0
  268. /package/client/dist/assets/{jobs-BqEbCCxD.js → jobs-BZ3sQHjZ.js} +0 -0
  269. /package/client/dist/assets/{jobs-cHYInoau.js → jobs-Bd8AdOTb.js} +0 -0
  270. /package/client/dist/assets/{jobs-DRzjWI9u.js → jobs-CRtsq_u0.js} +0 -0
  271. /package/client/dist/assets/{jobs-2f6Hdc72.js → jobs-CSRwFQ6K.js} +0 -0
  272. /package/client/dist/assets/{jobs-vGfzIDQa.js → jobs-CbEl7WMI.js} +0 -0
  273. /package/client/dist/assets/{julia-Bgv08lKa.js → julia-BqialFRG.js} +0 -0
  274. /package/client/dist/assets/{kotlin-u98kaVTf.js → kotlin-Dzz8TWAt.js} +0 -0
  275. /package/client/dist/assets/{less-CjYwpgg5.js → less-DHRJD3TR.js} +0 -0
  276. /package/client/dist/assets/{lexon-YTjaAFBB.js → lexon-5Y3QgTmT.js} +0 -0
  277. /package/client/dist/assets/{lua-BzmkWv27.js → lua-sKvhfPn5.js} +0 -0
  278. /package/client/dist/assets/{m3-CFwk9fw0.js → m3-DWDVwkFG.js} +0 -0
  279. /package/client/dist/assets/{markdown-CR5iMpSZ.js → markdown-CD_aSBxW.js} +0 -0
  280. /package/client/dist/assets/{mips-CcEalc17.js → mips-687T03hg.js} +0 -0
  281. /package/client/dist/assets/{msdax-BQbkawnr.js → msdax-C1St-dIV.js} +0 -0
  282. /package/client/dist/assets/{mysql-GTlaaW_P.js → mysql-BG7r8oBS.js} +0 -0
  283. /package/client/dist/assets/{nav-C2YXcbZS.js → nav-B05EYB0b.js} +0 -0
  284. /package/client/dist/assets/{nav-D2bOGSEg.js → nav-BNGCq-0y.js} +0 -0
  285. /package/client/dist/assets/{nav-BEL3MTwK.js → nav-BRInPX8a.js} +0 -0
  286. /package/client/dist/assets/{nav-CtYwmMgu.js → nav-Bf87DRHD.js} +0 -0
  287. /package/client/dist/assets/{nav-iH1V5j6o.js → nav-BkVzzFpc.js} +0 -0
  288. /package/client/dist/assets/{nav-0fwkrgHt.js → nav-BzFLtS1W.js} +0 -0
  289. /package/client/dist/assets/{nav-ClzOE4mA.js → nav-DBDbQOYn.js} +0 -0
  290. /package/client/dist/assets/{nav-B_G-TJDW.js → nav-X9sVtUWC.js} +0 -0
  291. /package/client/dist/assets/{objective-c-Byu1T5if.js → objective-c-Ds1-m05L.js} +0 -0
  292. /package/client/dist/assets/{pascal-BrfzBfRm.js → pascal-BKK9FpIi.js} +0 -0
  293. /package/client/dist/assets/{pascaligo-BXXKFUeo.js → pascaligo-SRS3nwtO.js} +0 -0
  294. /package/client/dist/assets/{perl-B3OikKq-.js → perl-B2hTOlrF.js} +0 -0
  295. /package/client/dist/assets/{pgsql-CTsa0Acc.js → pgsql-DIQJYNpL.js} +0 -0
  296. /package/client/dist/assets/{php-DiQh3FUW.js → php-BEaVe8X2.js} +0 -0
  297. /package/client/dist/assets/{pla-92uH8Fzm.js → pla-oPLHpZ-Q.js} +0 -0
  298. /package/client/dist/assets/{postiats-BbeWkKUr.js → postiats-D_vzrAzD.js} +0 -0
  299. /package/client/dist/assets/{powerquery-DgDMzpsm.js → powerquery-BKG6w-FH.js} +0 -0
  300. /package/client/dist/assets/{powershell-BfdUUzaG.js → powershell-B3dLhDt4.js} +0 -0
  301. /package/client/dist/assets/{protobuf-BojW2ftW.js → protobuf-DC8SGjcl.js} +0 -0
  302. /package/client/dist/assets/{pug-BxqTg3IU.js → pug-D5E-4fI0.js} +0 -0
  303. /package/client/dist/assets/{qsharp-BX_A-MW9.js → qsharp-6vJAWv0x.js} +0 -0
  304. /package/client/dist/assets/{r-D9BMnxvJ.js → r-CDwsEcbM.js} +0 -0
  305. /package/client/dist/assets/{redis-5cJqEQJJ.js → redis-CuQbbESS.js} +0 -0
  306. /package/client/dist/assets/{redshift-d8BBqiwb.js → redshift-B9e1k-qI.js} +0 -0
  307. /package/client/dist/assets/{restructuredtext-C8a6yIcZ.js → restructuredtext-BiJ5IwaU.js} +0 -0
  308. /package/client/dist/assets/{ruby-egeh-6KX.js → ruby-B0UAHY9b.js} +0 -0
  309. /package/client/dist/assets/{rust-a3r9IInB.js → rust-Dg_spmFr.js} +0 -0
  310. /package/client/dist/assets/{sb-y8iRIDei.js → sb-DjU66I8Q.js} +0 -0
  311. /package/client/dist/assets/{scala-BPDK2AmK.js → scala-qvStIdfG.js} +0 -0
  312. /package/client/dist/assets/{scheme-BIWUEoOs.js → scheme-FstEk5Rh.js} +0 -0
  313. /package/client/dist/assets/{scss-CA-PSzwg.js → scss-w0U3rQLK.js} +0 -0
  314. /package/client/dist/assets/{settings-CTcwN9RE.js → settings-5tzo0Rn3.js} +0 -0
  315. /package/client/dist/assets/{settings-D_dujJZI.js → settings-BDAW3trC.js} +0 -0
  316. /package/client/dist/assets/{settings-Bg0A3zoS.js → settings-BEWv3VEu.js} +0 -0
  317. /package/client/dist/assets/{settings-BgPqg2nv.js → settings-BORg56um.js} +0 -0
  318. /package/client/dist/assets/{settings-BSze3_9q.js → settings-D3LurcR5.js} +0 -0
  319. /package/client/dist/assets/{settings-CSJ0ahZ8.js → settings-DcqWIEM6.js} +0 -0
  320. /package/client/dist/assets/{settings-DYIV89nV.js → settings-Dfz8QbZS.js} +0 -0
  321. /package/client/dist/assets/{settings-DDcfx_ca.js → settings-yMubjqYw.js} +0 -0
  322. /package/client/dist/assets/{shell--LiT1Bja.js → shell-DJ78wREd.js} +0 -0
  323. /package/client/dist/assets/{solidity-DdqZccZg.js → solidity-1aGIVsdX.js} +0 -0
  324. /package/client/dist/assets/{sophia-S6-YxNG_.js → sophia-40LqcGjB.js} +0 -0
  325. /package/client/dist/assets/{sparql-BSf5kMp2.js → sparql-Cz5dqG_g.js} +0 -0
  326. /package/client/dist/assets/{sql-D7KgjR8G.js → sql-64f62Ni4.js} +0 -0
  327. /package/client/dist/assets/{st-BnoDa-Ml.js → st-gJe2yG8J.js} +0 -0
  328. /package/client/dist/assets/{swift-DEUHTkUX.js → swift-C6ME22mv.js} +0 -0
  329. /package/client/dist/assets/{systemverilog-Tqb_KPnW.js → systemverilog-CEWz259w.js} +0 -0
  330. /package/client/dist/assets/{tcl-BmBFS2qq.js → tcl-CcLVIi3m.js} +0 -0
  331. /package/client/dist/assets/{terminal-Bje4ziIa.js → terminal-BYtreaaF.js} +0 -0
  332. /package/client/dist/assets/{terminal-CSONJOex.js → terminal-C0xx0SjA.js} +0 -0
  333. /package/client/dist/assets/{terminal-DeWzh6ys.js → terminal-CPpK58RC.js} +0 -0
  334. /package/client/dist/assets/{terminal-C2WYcFHF.js → terminal-CdxkpafL.js} +0 -0
  335. /package/client/dist/assets/{terminal-DEqzGtcr.js → terminal-Ciia0wh2.js} +0 -0
  336. /package/client/dist/assets/{terminal-80yDMgMF.js → terminal-DHIkiWcs.js} +0 -0
  337. /package/client/dist/assets/{terminal-lkZYR4wJ.js → terminal-DY42QANg.js} +0 -0
  338. /package/client/dist/assets/{terminal-YOlsJCQj.js → terminal-DoxtVdma.js} +0 -0
  339. /package/client/dist/assets/{tickets-DYvafSaY.js → tickets-0rM0lIXd.js} +0 -0
  340. /package/client/dist/assets/{tickets-DNOANUXr.js → tickets-1UIGf_oA.js} +0 -0
  341. /package/client/dist/assets/{tickets-DlpC_iTg.js → tickets-9kdPXInd.js} +0 -0
  342. /package/client/dist/assets/{tickets-CF2PYelu.js → tickets-C6pwZwt4.js} +0 -0
  343. /package/client/dist/assets/{tickets-CB7N30gm.js → tickets-DAjtxAVb.js} +0 -0
  344. /package/client/dist/assets/{tickets-DU1aqsbr.js → tickets-DNmXcAwu.js} +0 -0
  345. /package/client/dist/assets/{tickets-clefmXLv.js → tickets-n23kDqJT.js} +0 -0
  346. /package/client/dist/assets/{tickets-DucYgtdl.js → tickets-tGx5AR5b.js} +0 -0
  347. /package/client/dist/assets/{twig-BQV8igWC.js → twig-DvsO-WjW.js} +0 -0
  348. /package/client/dist/assets/{typespec-DlFroUGY.js → typespec-Brkt3IAA.js} +0 -0
  349. /package/client/dist/assets/{vb-BlrJpIMX.js → vb-r121Uzxt.js} +0 -0
  350. /package/client/dist/assets/{wgsl-BWgIc6FZ.js → wgsl-BRX8uYh4.js} +0 -0
@@ -9,13 +9,12 @@ exports.buildFirstTurnPrompt = buildFirstTurnPrompt;
9
9
  exports.refineSessionToJson = refineSessionToJson;
10
10
  const fs_1 = __importDefault(require("fs"));
11
11
  const path_1 = __importDefault(require("path"));
12
- const readline_1 = require("readline");
13
12
  const crypto_1 = require("crypto");
14
13
  const tree_kill_1 = __importDefault(require("tree-kill"));
15
- const cli_prompt_1 = require("./util/cli-prompt");
16
14
  const agent_generator_1 = require("./agent-generator");
17
15
  const ai_invocations_1 = require("./ai-invocations");
18
16
  const result_event_1 = require("./result-event");
17
+ const spawn_lifecycle_1 = require("./spawn-lifecycle");
19
18
  const providers_1 = require("./providers");
20
19
  const agent_refine_db_1 = require("./agent-refine-db");
21
20
  const CUSTOM_PREFIX = /^custom-[a-z0-9][a-z0-9-]*$/;
@@ -219,164 +218,140 @@ class AgentRefineManager {
219
218
  sessionId: session.session_id ?? undefined,
220
219
  });
221
220
  let drafted = false;
222
- const child = (0, cli_prompt_1.spawnAiCli)(this._adapter.binary, args, {
223
- env: process.env,
224
- stdio: ['ignore', 'pipe', 'pipe'],
225
- cwd: this._projectPath,
226
- });
227
- this._activeProcesses.set(refineId, child);
228
221
  this._bodyBuffers.set(refineId, '');
229
- let capturedSessionId = null;
230
- const adapterEvents = [];
231
222
  const turnStartedAt = new Date().toISOString();
232
- const reader = (0, readline_1.createInterface)({ input: child.stdout, crlfDelay: Infinity });
233
- reader.on('line', (line) => {
234
- const ev = this._adapter.parseStreamLine(line);
235
- if (!ev)
236
- return;
237
- adapterEvents.push(ev);
238
- switch (ev.kind) {
239
- case 'session-started':
240
- if (!capturedSessionId)
241
- capturedSessionId = ev.sessionId;
242
- break;
243
- case 'result': {
244
- const sid = ev.payload.session_id;
245
- if (sid && !capturedSessionId)
246
- capturedSessionId = sid;
247
- break;
248
- }
249
- case 'text-delta': {
250
- if (!drafted) {
251
- drafted = true;
252
- (0, agent_refine_db_1.updateRefineSession)(this._db, refineId, { phase: 'drafting' });
253
- this._emitPhase(refineId, 'drafting');
254
- }
255
- const prev = this._bodyBuffers.get(refineId) ?? '';
256
- const next = prev + ev.text;
257
- this._bodyBuffers.set(refineId, next);
258
- this._broadcast({
259
- type: 'agent_refine_stream',
260
- projectId: '',
261
- refineId,
262
- delta: ev.text,
263
- timestamp: new Date().toISOString(),
264
- });
265
- (0, agent_refine_db_1.updateRefineSession)(this._db, refineId, { draft_body: next });
266
- break;
267
- }
268
- case 'tool-use':
269
- this._broadcast({
270
- type: 'agent_refine_stream',
271
- projectId: '',
272
- refineId,
273
- delta: `<!--tool:${ev.name}-->`,
274
- timestamp: new Date().toISOString(),
275
- });
276
- break;
277
- case 'other':
278
- break;
279
- }
280
- });
281
- let stderr = '';
282
- child.stderr.on('data', (chunk) => { stderr += chunk.toString(); });
283
- return new Promise((resolve) => {
284
- child.on('error', (err) => {
285
- this._activeProcesses.delete(refineId);
286
- this._bodyBuffers.delete(refineId);
287
- if (this._disposed) {
288
- resolve();
289
- return;
290
- } // M12: project removed mid-flight; DB closing
291
- this._emitError(refineId, `Failed to launch claude: ${err.message}`);
292
- (0, agent_refine_db_1.updateRefineSession)(this._db, refineId, { status: 'error', phase: 'idle' });
293
- resolve();
294
- });
295
- child.on('close', (code) => {
296
- this._activeProcesses.delete(refineId);
297
- const fullDraft = this._bodyBuffers.get(refineId) ?? '';
298
- this._bodyBuffers.delete(refineId);
299
- if (this._disposed) {
300
- resolve();
301
- return;
302
- } // M12: project removed mid-flight; DB closing
303
- // ai_invocations capture (surface='ai-edit'). One row per refine turn.
304
- if (this._projectId) {
305
- try {
306
- const invStatus = code === 0 && fullDraft.trim() ? 'success' : 'failed';
307
- const { result: normalised, estimated } = (0, result_event_1.finaliseInvocationResult)(this._adapter, adapterEvents, { fallbackModel: refineModel });
308
- (0, ai_invocations_1.recordInvocation)(this._db, {
309
- id: (0, crypto_1.randomUUID)(),
310
- project_id: this._projectId,
311
- provider: this._adapter.id,
312
- surface: 'ai-edit',
313
- surface_ref_id: refineId,
314
- status: invStatus,
315
- started_at: turnStartedAt,
316
- finished_at: new Date().toISOString(),
317
- total_cost_usd_estimated: estimated,
318
- ...normalised,
223
+ const spawnState = { err: null };
224
+ // Spawn / stream / settlement is owned by the shared spawn-lifecycle; the
225
+ // refine-specific draft buffering, accounting, validation and history all
226
+ // stay here unchanged.
227
+ const run = await (0, spawn_lifecycle_1.runAiCliInvocation)({
228
+ adapter: this._adapter,
229
+ action,
230
+ buildOpts: { prompt, model: refineModel, sessionId: session.session_id ?? undefined },
231
+ cwd: this._projectPath,
232
+ onSpawn: (child) => this._activeProcesses.set(refineId, child),
233
+ onSpawnError: (err) => { spawnState.err = err; },
234
+ onEvent: (ev) => {
235
+ switch (ev.kind) {
236
+ case 'text-delta': {
237
+ if (!drafted) {
238
+ drafted = true;
239
+ (0, agent_refine_db_1.updateRefineSession)(this._db, refineId, { phase: 'drafting' });
240
+ this._emitPhase(refineId, 'drafting');
241
+ }
242
+ const prev = this._bodyBuffers.get(refineId) ?? '';
243
+ const next = prev + ev.text;
244
+ this._bodyBuffers.set(refineId, next);
245
+ this._broadcast({
246
+ type: 'agent_refine_stream',
247
+ projectId: '',
248
+ refineId,
249
+ delta: ev.text,
250
+ timestamp: new Date().toISOString(),
319
251
  });
320
- this._broadcast({ type: 'spending.invalidated', projectId: this._projectId });
252
+ (0, agent_refine_db_1.updateRefineSession)(this._db, refineId, { draft_body: next });
253
+ break;
321
254
  }
322
- catch (err) {
323
- console.error('[agent-refine-manager] recordInvocation failed:', err);
324
- }
325
- }
326
- if (code !== 0 || !fullDraft.trim()) {
327
- this._emitError(refineId, code !== 0
328
- ? `claude exited with code ${code}${stderr ? `: ${stderr.slice(-300)}` : ''}`
329
- : 'claude returned empty output');
330
- (0, agent_refine_db_1.updateRefineSession)(this._db, refineId, { status: 'error', phase: 'idle' });
331
- resolve();
332
- return;
333
- }
334
- // Validation phase.
335
- (0, agent_refine_db_1.updateRefineSession)(this._db, refineId, { phase: 'validating' });
336
- this._emitPhase(refineId, 'validating');
337
- const stripped = stripToolMarkers(fullDraft);
338
- const validation = validateAgentBody(stripped, this._adapter.id);
339
- if (!validation.ok) {
340
- this._emitError(refineId, `Frontmatter invalid: ${validation.error}`);
341
- (0, agent_refine_db_1.updateRefineSession)(this._db, refineId, { status: 'error', phase: 'idle', draft_body: stripped });
342
- resolve();
343
- return;
255
+ case 'tool-use':
256
+ this._broadcast({
257
+ type: 'agent_refine_stream',
258
+ projectId: '',
259
+ refineId,
260
+ delta: `<!--tool:${ev.name}-->`,
261
+ timestamp: new Date().toISOString(),
262
+ });
263
+ break;
264
+ default:
265
+ break;
344
266
  }
345
- // Append assistant turn to history (use stripped body — markers gone).
346
- this._appendHistory(refineId, {
347
- role: 'assistant',
348
- content: stripped,
349
- timestamp: Date.now(),
350
- });
351
- const patch = {
352
- status: 'ready',
353
- phase: 'done',
354
- draft_body: stripped,
355
- ...(capturedSessionId ? { session_id: capturedSessionId } : {}),
356
- };
357
- (0, agent_refine_db_1.updateRefineSession)(this._db, refineId, patch);
358
- this._broadcast({
359
- type: 'agent_refine_ready',
360
- projectId: '',
361
- refineId,
362
- draftBody: stripped,
363
- timestamp: new Date().toISOString(),
267
+ },
268
+ });
269
+ this._activeProcesses.delete(refineId);
270
+ const fullDraft = this._bodyBuffers.get(refineId) ?? '';
271
+ this._bodyBuffers.delete(refineId);
272
+ if (this._disposed)
273
+ return; // M12: project removed mid-flight; DB closing
274
+ if (run.spawnFailed) {
275
+ this._emitError(refineId, `Failed to launch claude: ${spawnState.err?.message ?? 'spawn error'}`);
276
+ (0, agent_refine_db_1.updateRefineSession)(this._db, refineId, { status: 'error', phase: 'idle' });
277
+ return;
278
+ }
279
+ const capturedSessionId = run.sessionId;
280
+ const adapterEvents = run.events;
281
+ const code = run.code;
282
+ const stderr = run.stderrTail;
283
+ // ai_invocations capture (surface='ai-edit'). One row per refine turn.
284
+ if (this._projectId) {
285
+ try {
286
+ const invStatus = code === 0 && fullDraft.trim() ? 'success' : 'failed';
287
+ const { result: normalised, estimated } = (0, result_event_1.finaliseInvocationResult)(this._adapter, adapterEvents, { fallbackModel: refineModel });
288
+ (0, ai_invocations_1.recordInvocation)(this._db, {
289
+ id: (0, crypto_1.randomUUID)(),
290
+ project_id: this._projectId,
291
+ provider: this._adapter.id,
292
+ surface: 'ai-edit',
293
+ surface_ref_id: refineId,
294
+ status: invStatus,
295
+ started_at: turnStartedAt,
296
+ finished_at: new Date().toISOString(),
297
+ total_cost_usd_estimated: estimated,
298
+ ...normalised,
364
299
  });
365
- this._emitPhase(refineId, 'done');
366
- // Smart-mode auto-test: only run if enabled, body changed since last
367
- // test, and >5s elapsed. Best-effort; failures are non-fatal.
368
- const session2 = (0, agent_refine_db_1.getRefineSession)(this._db, refineId);
369
- if (session2 && session2.auto_test === 1) {
370
- const draftHash = sha256(stripped);
371
- const recent = session2.last_test_at !== null && Date.now() - session2.last_test_at < SMART_TEST_DEBOUNCE_MS;
372
- const sameBody = session2.last_test_hash === draftHash;
373
- if (!recent && !sameBody) {
374
- void this._runAutoTest(refineId, session2.agent_id, stripped, draftHash);
375
- }
376
- }
377
- resolve();
378
- });
300
+ this._broadcast({ type: 'spending.invalidated', projectId: this._projectId });
301
+ }
302
+ catch (err) {
303
+ console.error('[agent-refine-manager] recordInvocation failed:', err);
304
+ }
305
+ }
306
+ if (code !== 0 || !fullDraft.trim()) {
307
+ this._emitError(refineId, code !== 0
308
+ ? `claude exited with code ${code}${stderr ? `: ${stderr.slice(-300)}` : ''}`
309
+ : 'claude returned empty output');
310
+ (0, agent_refine_db_1.updateRefineSession)(this._db, refineId, { status: 'error', phase: 'idle' });
311
+ return;
312
+ }
313
+ // Validation phase.
314
+ (0, agent_refine_db_1.updateRefineSession)(this._db, refineId, { phase: 'validating' });
315
+ this._emitPhase(refineId, 'validating');
316
+ const stripped = stripToolMarkers(fullDraft);
317
+ const validation = validateAgentBody(stripped, this._adapter.id);
318
+ if (!validation.ok) {
319
+ this._emitError(refineId, `Frontmatter invalid: ${validation.error}`);
320
+ (0, agent_refine_db_1.updateRefineSession)(this._db, refineId, { status: 'error', phase: 'idle', draft_body: stripped });
321
+ return;
322
+ }
323
+ // Append assistant turn to history (use stripped body — markers gone).
324
+ this._appendHistory(refineId, {
325
+ role: 'assistant',
326
+ content: stripped,
327
+ timestamp: Date.now(),
328
+ });
329
+ const patch = {
330
+ status: 'ready',
331
+ phase: 'done',
332
+ draft_body: stripped,
333
+ ...(capturedSessionId ? { session_id: capturedSessionId } : {}),
334
+ };
335
+ (0, agent_refine_db_1.updateRefineSession)(this._db, refineId, patch);
336
+ this._broadcast({
337
+ type: 'agent_refine_ready',
338
+ projectId: '',
339
+ refineId,
340
+ draftBody: stripped,
341
+ timestamp: new Date().toISOString(),
379
342
  });
343
+ this._emitPhase(refineId, 'done');
344
+ // Smart-mode auto-test: only run if enabled, body changed since last
345
+ // test, and >5s elapsed. Best-effort; failures are non-fatal.
346
+ const session2 = (0, agent_refine_db_1.getRefineSession)(this._db, refineId);
347
+ if (session2 && session2.auto_test === 1) {
348
+ const draftHash = sha256(stripped);
349
+ const recent = session2.last_test_at !== null && Date.now() - session2.last_test_at < SMART_TEST_DEBOUNCE_MS;
350
+ const sameBody = session2.last_test_hash === draftHash;
351
+ if (!recent && !sameBody) {
352
+ void this._runAutoTest(refineId, session2.agent_id, stripped, draftHash);
353
+ }
354
+ }
380
355
  }
381
356
  async _runAutoTest(refineId, agentId, draftBody, draftHash) {
382
357
  (0, agent_refine_db_1.updateRefineSession)(this._db, refineId, { phase: 'testing' });
@@ -20,6 +20,7 @@ const providers_1 = require("./providers");
20
20
  const context_scope_1 = require("./context-scope");
21
21
  const user_mcp_config_1 = require("./user-mcp-config");
22
22
  const binary_probe_1 = require("./binary-probe");
23
+ const explore_stdin_session_1 = require("./explore-stdin-session");
23
24
  const COMMAND_INSTRUCTION = 'When you want to suggest a SpecRails command for the user to execute, wrap it in a command block like this: ' +
24
25
  ':::command\n/specrails:implement #42\n::: ' +
25
26
  'The user will be prompted to confirm before the command runs.';
@@ -60,6 +61,9 @@ class ChatManager {
60
61
  _exploreLifecycle;
61
62
  /** FIFO queue of Explore turns waiting for a concurrency slot. */
62
63
  _exploreQueue;
64
+ /** Persistent-stdin Explore transport (big bet #3, flag-gated default OFF).
65
+ * Holds long-lived claude children that survive between turns. */
66
+ _stdinSessions = new explore_stdin_session_1.ExploreStdinSessions();
63
67
  _cwd;
64
68
  _projectName;
65
69
  _adapter;
@@ -142,6 +146,9 @@ class ChatManager {
142
146
  }
143
147
  catch { /* best-effort */ }
144
148
  }
149
+ // Persistent-stdin children live OUTSIDE _activeProcesses between turns —
150
+ // idle-kill must reach them too (the next turn re-spawns with --resume).
151
+ this._stdinSessions.kill(conversationId);
145
152
  }, exports.EXPLORE_IDLE_KILL_MS);
146
153
  }
147
154
  /**
@@ -223,6 +230,8 @@ class ChatManager {
223
230
  }
224
231
  catch { /* best-effort */ }
225
232
  }
233
+ // Reclaim the slot from a persistent-stdin child parked between turns.
234
+ this._stdinSessions.kill(victim);
226
235
  this._clearIdleTimer(victim);
227
236
  this._exploreLifecycle.delete(victim);
228
237
  if (this._countStreamingExplore() < exports.EXPLORE_MAX_CONCURRENCY)
@@ -547,6 +556,19 @@ class ChatManager {
547
556
  // not pipeline jobs. Telemetry is scoped to QueueManager pipeline runs only.
548
557
  // spawnAiCli reroutes multi-line argv values through stdin on Windows.
549
558
  const spawnCwd = this._resolveSpawnCwd(conversation.kind, conversationScope, adapter.id);
559
+ // Big bet #3 fast-path: persistent-stdin multi-turn for Explore (claude
560
+ // only, flag-gated default OFF). Reuses a single long-lived child across
561
+ // turns so turns 2+ skip spawn + session rehydration. Full fallback to the
562
+ // legacy spawn-per-turn path below when disabled / unsupported.
563
+ if ((0, explore_stdin_session_1.isExplorePersistentStdinEnabled)() &&
564
+ conversation.kind === 'explore' &&
565
+ adapter.capabilities.persistentStdin === true) {
566
+ return await this._streamPersistentExploreTurn({
567
+ conversationId, conversation, adapter, binary, model, systemPrompt,
568
+ scopeFlags, spawnCwd, promptForAdapter, isFirstTurn, userText,
569
+ lightweight, conversationScope,
570
+ });
571
+ }
550
572
  const child = (0, cli_prompt_1.spawnAiCli)(binary, args, {
551
573
  env: process.env,
552
574
  stdio: ['ignore', 'pipe', 'pipe'],
@@ -866,6 +888,223 @@ class ChatManager {
866
888
  this._reservedTurns.delete(conversationId);
867
889
  }
868
890
  }
891
+ /**
892
+ * Persistent-stdin Explore turn (big bet #3). Reuses one long-lived claude
893
+ * child per conversation via `--input-format stream-json`: the user turn is
894
+ * written to the child's stdin, and the turn ends on the `result` event
895
+ * (NOT process close — the child stays alive for the next turn). Mirrors the
896
+ * legacy close-handler's finalisation (spec-draft parse, persist, session
897
+ * capture, chat_done, invocation accounting, lifecycle) without crash-respawn
898
+ * — a dead persistent child is evicted and the next turn re-spawns with
899
+ * `--resume`. Only reached when the flag is on; the legacy path is untouched.
900
+ */
901
+ async _streamPersistentExploreTurn(p) {
902
+ const { conversationId, conversation, adapter, binary, model, systemPrompt, scopeFlags, spawnCwd, promptForAdapter, isFirstTurn, userText, lightweight, conversationScope, } = p;
903
+ const sessionArgs = adapter.buildArgs('chat-stream', {
904
+ prompt: '',
905
+ systemPrompt,
906
+ model,
907
+ sessionId: conversation.session_id ?? undefined,
908
+ extraArgs: scopeFlags,
909
+ loadUserEnv: adapter.id === 'claude' && !!conversationScope?.userMcp,
910
+ });
911
+ const { child } = this._stdinSessions.getOrSpawn(conversationId, {
912
+ binary, args: sessionArgs, cwd: spawnCwd, env: process.env,
913
+ });
914
+ this._activeProcesses.set(conversationId, child);
915
+ this._buffers.set(conversationId, '');
916
+ this._emittedProposals.set(conversationId, new Set());
917
+ this._streamFilters.set(conversationId, { inBlock: false, pendingTail: '' });
918
+ const adapterEvents = [];
919
+ let capturedSessionId = null;
920
+ let stderrBuf = '';
921
+ const turnStartedAt = new Date().toISOString();
922
+ const emitDelta = (newText) => {
923
+ const prev = this._buffers.get(conversationId) ?? '';
924
+ this._buffers.set(conversationId, prev + newText);
925
+ const filter = this._streamFilters.get(conversationId);
926
+ const visibleDelta = filter ? filterDraftBlocksLive(filter, newText) : newText;
927
+ if (visibleDelta) {
928
+ this._broadcast({
929
+ type: 'chat_stream',
930
+ conversationId,
931
+ delta: visibleDelta,
932
+ timestamp: new Date().toISOString(),
933
+ });
934
+ }
935
+ const proposals = extractCommandProposals(this._buffers.get(conversationId) ?? '');
936
+ const emitted = this._emittedProposals.get(conversationId);
937
+ if (emitted) {
938
+ for (const proposal of proposals) {
939
+ if (!emitted.has(proposal)) {
940
+ emitted.add(proposal);
941
+ this._broadcast({
942
+ type: 'chat_command_proposal',
943
+ conversationId,
944
+ command: proposal,
945
+ timestamp: new Date().toISOString(),
946
+ });
947
+ }
948
+ }
949
+ }
950
+ };
951
+ const recordInv = (status) => {
952
+ if (!this._projectId)
953
+ return;
954
+ try {
955
+ const { result, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, adapterEvents, {
956
+ fallbackModel: model,
957
+ });
958
+ (0, ai_invocations_1.recordInvocation)(this._db, {
959
+ id: (0, crypto_1.randomUUID)(),
960
+ project_id: this._projectId,
961
+ provider: adapter.id,
962
+ surface: 'explore-spec',
963
+ surface_ref_id: conversationId,
964
+ conversation_id: conversationId,
965
+ status,
966
+ started_at: turnStartedAt,
967
+ finished_at: new Date().toISOString(),
968
+ total_cost_usd_estimated: estimated,
969
+ ...result,
970
+ });
971
+ this._broadcast({ type: 'spending.invalidated', projectId: this._projectId });
972
+ }
973
+ catch (err) {
974
+ console.error('[chat-manager] recordInvocation failed:', err);
975
+ }
976
+ };
977
+ const cleanupTurnState = () => {
978
+ this._activeProcesses.delete(conversationId);
979
+ this._buffers.delete(conversationId);
980
+ this._emittedProposals.delete(conversationId);
981
+ this._streamFilters.delete(conversationId);
982
+ };
983
+ const markStreamingEnded = (success) => {
984
+ const life = this._exploreLifecycle.get(conversationId);
985
+ if (life) {
986
+ life.isStreaming = false;
987
+ life.lastActivityAt = Date.now();
988
+ if (success)
989
+ life.crashCount = 0;
990
+ if (life.isMinimized)
991
+ this._startIdleTimer(conversationId);
992
+ }
993
+ this._drainExploreQueue();
994
+ };
995
+ return new Promise((resolve) => {
996
+ let settled = false;
997
+ const finishTurn = () => {
998
+ if (settled)
999
+ return;
1000
+ settled = true;
1001
+ this._stdinSessions.clearHandlers(conversationId);
1002
+ const fullText = this._buffers.get(conversationId) ?? '';
1003
+ const wasAborting = this._abortingConversations.has(conversationId);
1004
+ cleanupTurnState();
1005
+ this._abortingConversations.delete(conversationId);
1006
+ markStreamingEnded(true);
1007
+ recordInv(wasAborting ? 'aborted' : 'success');
1008
+ const parsed = (0, spec_draft_parser_1.parseSpecDraftBlocks)(fullText);
1009
+ const persistedText = parsed.blocks.length > 0 ? parsed.stripped : fullText;
1010
+ if (parsed.blocks.length > 0) {
1011
+ const prevState = this._specDraftStates.get(conversationId);
1012
+ const nextState = (0, spec_draft_parser_1.applyBlocks)(prevState, parsed.blocks);
1013
+ this._specDraftStates.set(conversationId, nextState);
1014
+ this._broadcast({
1015
+ type: 'spec_draft.update',
1016
+ conversationId,
1017
+ draft: nextState.draft,
1018
+ ready: nextState.ready,
1019
+ chips: nextState.chips,
1020
+ changedFields: nextState.lastChangedFields,
1021
+ timestamp: new Date().toISOString(),
1022
+ });
1023
+ }
1024
+ if (persistedText) {
1025
+ (0, db_1.addMessage)(this._db, { conversation_id: conversationId, role: 'assistant', content: persistedText });
1026
+ }
1027
+ if (capturedSessionId) {
1028
+ (0, db_1.updateConversation)(this._db, conversationId, { session_id: capturedSessionId });
1029
+ }
1030
+ this._broadcast({
1031
+ type: 'chat_done',
1032
+ conversationId,
1033
+ fullText: persistedText,
1034
+ timestamp: new Date().toISOString(),
1035
+ });
1036
+ if (isFirstTurn && fullText && !lightweight) {
1037
+ this._autoTitle(conversationId, userText, fullText);
1038
+ }
1039
+ resolve();
1040
+ };
1041
+ const onClose = (code) => {
1042
+ // The persistent child died (crash / idle-kill / shutdown). If the turn
1043
+ // already finished on its `result` event, ignore. No crash-respawn —
1044
+ // the session is evicted by the transport; the next turn re-spawns with
1045
+ // `--resume`, so no persisted state is lost.
1046
+ if (settled)
1047
+ return;
1048
+ settled = true;
1049
+ this._stdinSessions.clearHandlers(conversationId);
1050
+ const wasAborting = this._abortingConversations.has(conversationId);
1051
+ cleanupTurnState();
1052
+ this._abortingConversations.delete(conversationId);
1053
+ markStreamingEnded(false);
1054
+ recordInv(wasAborting ? 'aborted' : 'failed');
1055
+ if (wasAborting) {
1056
+ resolve();
1057
+ return;
1058
+ }
1059
+ const stderrTail = stderrBuf.trim().slice(-500);
1060
+ this._broadcast({
1061
+ type: 'chat_error',
1062
+ conversationId,
1063
+ error: stderrTail
1064
+ ? `${binary} exited with code ${code ?? 'unknown'}: ${stderrTail}`
1065
+ : `Process exited with code ${code ?? 'unknown'}`,
1066
+ timestamp: new Date().toISOString(),
1067
+ });
1068
+ resolve();
1069
+ };
1070
+ const onLine = (line) => {
1071
+ const ev = adapter.parseStreamLine(line);
1072
+ if (!ev)
1073
+ return;
1074
+ adapterEvents.push(ev);
1075
+ switch (ev.kind) {
1076
+ case 'text-delta':
1077
+ emitDelta(ev.text);
1078
+ break;
1079
+ case 'session-started':
1080
+ if (ev.sessionId)
1081
+ capturedSessionId = ev.sessionId;
1082
+ break;
1083
+ case 'result': {
1084
+ const sid = ev.payload.session_id;
1085
+ if (sid)
1086
+ capturedSessionId = sid;
1087
+ finishTurn();
1088
+ break;
1089
+ }
1090
+ default:
1091
+ break;
1092
+ }
1093
+ };
1094
+ this._stdinSessions.setHandlers(conversationId, {
1095
+ onLine,
1096
+ onStderr: (s) => {
1097
+ stderrBuf += s;
1098
+ console.error(`[chat-manager] ${binary} stderr (${conversationId}):`, s.trim());
1099
+ },
1100
+ onClose,
1101
+ });
1102
+ if (!this._stdinSessions.writeTurn(conversationId, promptForAdapter)) {
1103
+ // stdin already gone (child died between spawn and write) — fail the turn.
1104
+ onClose(null);
1105
+ }
1106
+ });
1107
+ }
869
1108
  abort(conversationId) {
870
1109
  const child = this._activeProcesses.get(conversationId);
871
1110
  if (!child || !child.pid)
@@ -893,6 +1132,7 @@ class ChatManager {
893
1132
  clearTimeout(this._exploreQueue[idx].timeoutTimer);
894
1133
  this._exploreQueue.splice(idx, 1);
895
1134
  }
1135
+ this._stdinSessions.kill(conversationId);
896
1136
  this._exploreLifecycle.delete(conversationId);
897
1137
  }
898
1138
  /**
@@ -911,6 +1151,8 @@ class ChatManager {
911
1151
  catch { /* best-effort */ }
912
1152
  }
913
1153
  }
1154
+ // Persistent-stdin children outlive individual turns — tear them down too.
1155
+ this._stdinSessions.killAll();
914
1156
  for (const id of this._exploreLifecycle.keys()) {
915
1157
  this._clearIdleTimer(id);
916
1158
  }