specrails-desktop 2.30.2 → 2.31.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 (462) hide show
  1. package/README.md +28 -24
  2. package/client/dist/assets/{ActivityFeedPage-9DZOvIcY.js → ActivityFeedPage-CAhFRUO4.js} +1 -1
  3. package/client/dist/assets/{AgentBrowserCapture-DqyHbzk7.js → AgentBrowserCapture-Ct4G5lsE.js} +1 -1
  4. package/client/dist/assets/AgentModeCodePane-DQt9WIvu.js +2 -0
  5. package/client/dist/assets/{AgentModeJobsPane-CTIHMUKN.js → AgentModeJobsPane-podaJVl9.js} +1 -1
  6. package/client/dist/assets/AgentsPage-DTZdbW80.js +87 -0
  7. package/client/dist/assets/AnalyticsPage-BskgGPm0.js +1 -0
  8. package/client/dist/assets/CodePage-CvtYo1DU.js +2 -0
  9. package/client/dist/assets/{DesktopAnalyticsPage-CkXUFj3F.js → DesktopAnalyticsPage-Dnf99E8e.js} +1 -1
  10. package/client/dist/assets/{DocsDialog-PhdCJNVj.js → DocsDialog-DHi36rZ4.js} +1 -1
  11. package/client/dist/assets/{DocsPage-BY-wDthx.js → DocsPage-DIdVrQz1.js} +1 -1
  12. package/client/dist/assets/{InteractiveJobComposer-C9I0A4KR.js → InteractiveJobComposer-BHeB2inv.js} +1 -1
  13. package/client/dist/assets/{JobDetailModal-I_RoQJV4.js → JobDetailModal-CF1SKUHH.js} +1 -1
  14. package/client/dist/assets/JobDetailPage-De3rY18h.js +1 -0
  15. package/client/dist/assets/{JobsPage-DcllM4Ip.js → JobsPage-CfAqqJTx.js} +1 -1
  16. package/client/dist/assets/{LoopBuilderPage-DGm_iuff.js → LoopBuilderPage-DSBMuTb3.js} +2 -2
  17. package/client/dist/assets/{LoopPreviewModal-BC-TeFdD.js → LoopPreviewModal-B-c37kA0.js} +1 -1
  18. package/client/dist/assets/LoopsPage-DjnNXdmm.js +1 -0
  19. package/client/dist/assets/{MinimizedChatsContext-Cs34FPTz.js → MinimizedChatsContext-DIsnQMVz.js} +1 -1
  20. package/client/dist/assets/PluginsPage-DA5pQ_6u.js +2 -0
  21. package/client/dist/assets/{ProjectSettingsDialog-nEs-ENrE.js → ProjectSettingsDialog-DA23PSi6.js} +1 -1
  22. package/client/dist/assets/{TemplatePreviewModal-D4qW-J9B.js → TemplatePreviewModal-Cp7IQ-g2.js} +1 -1
  23. package/client/dist/assets/TicketDetailModal-BPD2i_0R.js +14 -0
  24. package/client/dist/assets/{Trans-CPISVji8.js → Trans-cWtExGkC.js} +1 -1
  25. package/client/dist/assets/addspec-4WmLJmBG.js +1 -0
  26. package/client/dist/assets/addspec-BRlk8jON.js +1 -0
  27. package/client/dist/assets/addspec-C7XRejU4.js +1 -0
  28. package/client/dist/assets/addspec-CHW9xf_X.js +1 -0
  29. package/client/dist/assets/addspec-DTmRrWrF.js +1 -0
  30. package/client/dist/assets/addspec-DhmnXER8.js +1 -0
  31. package/client/dist/assets/addspec-Di41DpYV.js +1 -0
  32. package/client/dist/assets/addspec-x3mizDxc.js +1 -0
  33. package/client/dist/assets/agent-BKsuIgIT.js +1 -0
  34. package/client/dist/assets/agent-Bs9NilfI.js +1 -0
  35. package/client/dist/assets/agent-C23h684q.js +1 -0
  36. package/client/dist/assets/agent-CqEjy3Z2.js +1 -0
  37. package/client/dist/assets/agent-D5DZTks1.js +1 -0
  38. package/client/dist/assets/agent-DE8hUYPl.js +1 -0
  39. package/client/dist/assets/agent-DsTuJGSc.js +1 -0
  40. package/client/dist/assets/agent-DwZM05-x.js +1 -0
  41. package/client/dist/assets/agents-45GbINfh.js +1 -0
  42. package/client/dist/assets/agents-BHp0_FQt.js +1 -0
  43. package/client/dist/assets/agents-Bvyi3y6R.js +1 -0
  44. package/client/dist/assets/agents-DMKFStHL.js +1 -0
  45. package/client/dist/assets/agents-DaYcxAr1.js +1 -0
  46. package/client/dist/assets/agents-IUOgqT5t.js +1 -0
  47. package/client/dist/assets/agents-ms7TwG16.js +1 -0
  48. package/client/dist/assets/agents-rzPnqoBR.js +1 -0
  49. package/client/dist/assets/agentstudio-8TQqBenW.js +1 -0
  50. package/client/dist/assets/agentstudio-B8Z_mmEX.js +1 -0
  51. package/client/dist/assets/agentstudio-BZR9YmLs.js +1 -0
  52. package/client/dist/assets/agentstudio-Bge9pAWb.js +1 -0
  53. package/client/dist/assets/agentstudio-Bz169Vzt.js +1 -0
  54. package/client/dist/assets/agentstudio-D6L2jpNi.js +1 -0
  55. package/client/dist/assets/agentstudio-K2-Z7CL0.js +1 -0
  56. package/client/dist/assets/agentstudio-Zmgzthv8.js +1 -0
  57. package/client/dist/assets/analytics-B8Qtptbl.js +1 -0
  58. package/client/dist/assets/analytics-BHqUazhP.js +1 -0
  59. package/client/dist/assets/analytics-BPptRY4f.js +1 -0
  60. package/client/dist/assets/analytics-BxDGOIwf.js +1 -0
  61. package/client/dist/assets/analytics-C9RaQcE3.js +1 -0
  62. package/client/dist/assets/analytics-CJIwqrEl.js +1 -0
  63. package/client/dist/assets/analytics-D_OZdQ9O.js +1 -0
  64. package/client/dist/assets/analytics-We6lUMI8.js +1 -0
  65. package/client/dist/assets/builder-3bygQtZi.js +1 -0
  66. package/client/dist/assets/builder-BiUG9Z5K.js +1 -0
  67. package/client/dist/assets/builder-CGRz_-zP.js +1 -0
  68. package/client/dist/assets/builder-CWYPw7Cw.js +1 -0
  69. package/client/dist/assets/builder-CX1437hF.js +1 -0
  70. package/client/dist/assets/{builder-CwA4T7gP.js → builder-Cowk9jtL.js} +1 -1
  71. package/client/dist/assets/builder-DwDexYRE.js +1 -0
  72. package/client/dist/assets/builder-skfnZ1uC.js +1 -0
  73. package/client/dist/assets/code-B0O8-p8k.js +1 -0
  74. package/client/dist/assets/code-B1VLZDhS.js +1 -0
  75. package/client/dist/assets/code-B86IMAfz.js +1 -0
  76. package/client/dist/assets/code-Bpj4Ddml.js +1 -0
  77. package/client/dist/assets/code-BykBZ5-e.js +1 -0
  78. package/client/dist/assets/code-CHPkOkDS.js +1 -0
  79. package/client/dist/assets/code-CkUuW4m9.js +1 -0
  80. package/client/dist/assets/code-cAqaqMTx.js +1 -0
  81. package/client/dist/assets/{dashboard-Dy2Um-US.js → dashboard-BVq6kRJe.js} +1 -1
  82. package/client/dist/assets/{dashboard-CHCEkds4.js → dashboard-BaKPPmLH.js} +1 -1
  83. package/client/dist/assets/{dashboard-CrlTV1ms.js → dashboard-Bm8e4zYG.js} +1 -1
  84. package/client/dist/assets/{dashboard-WhzOQw1S.js → dashboard-Bt6IesnM.js} +1 -1
  85. package/client/dist/assets/{dashboard-Cslu_GCH.js → dashboard-C_NQZle_.js} +1 -1
  86. package/client/dist/assets/{dashboard-DweT3Y4R.js → dashboard-CyZKoGoI.js} +1 -1
  87. package/client/dist/assets/{dashboard-DUU8-_Rg.js → dashboard-HIUdUBQ0.js} +1 -1
  88. package/client/dist/assets/{dashboard-Cqmmbh3l.js → dashboard-pm4Mr229.js} +1 -1
  89. package/client/dist/assets/{dist-js-jwoXo0YD.js → dist-js-BaP-xLOy.js} +1 -1
  90. package/client/dist/assets/{dist-js-Dj72W6qo.js → dist-js-CLlgOa5a.js} +1 -1
  91. package/client/dist/assets/format-command-C0D9IPmV.js +1 -0
  92. package/client/dist/assets/{formatDistanceToNow-ByKli7Q_.js → formatDistanceToNow-DUyzS4rr.js} +1 -1
  93. package/client/dist/assets/{getTimezoneOffsetInMilliseconds-qrcBaLW1.js → getTimezoneOffsetInMilliseconds-BCIwmmTj.js} +1 -1
  94. package/client/dist/assets/{i18n-Bf9Ckd10.js → i18n-D21Pr8Sj.js} +2 -2
  95. package/client/dist/assets/index-BdSDUFnA.css +2 -0
  96. package/client/dist/assets/index-Ci4-JKDr.js +77 -0
  97. package/client/dist/assets/{jobs-CVFD8rar.js → jobs-BAls3bWq.js} +1 -1
  98. package/client/dist/assets/{jobs-DoSaFzAa.js → jobs-B_TeSQxb.js} +1 -1
  99. package/client/dist/assets/jobs-Bgq-PZkC.js +1 -0
  100. package/client/dist/assets/jobs-Bpks6doU.js +1 -0
  101. package/client/dist/assets/jobs-CN_zv4Gr.js +1 -0
  102. package/client/dist/assets/jobs-DUlWSYq2.js +1 -0
  103. package/client/dist/assets/{jobs-B-sDHEay.js → jobs-DhxKgWFq.js} +1 -1
  104. package/client/dist/assets/{jobs-lk1_Dq1U.js → jobs-SwYS2M-B.js} +1 -1
  105. package/client/dist/assets/nav-BHDiSIVu.js +1 -0
  106. package/client/dist/assets/nav-CMiYAq4i.js +1 -0
  107. package/client/dist/assets/nav-CqS7NrDW.js +1 -0
  108. package/client/dist/assets/nav-D-0M7xfv.js +1 -0
  109. package/client/dist/assets/nav-D65O6u9I.js +1 -0
  110. package/client/dist/assets/nav-D_LKYvBr.js +1 -0
  111. package/client/dist/assets/nav-FDTJmU79.js +1 -0
  112. package/client/dist/assets/nav-VaB-C4k5.js +1 -0
  113. package/client/dist/assets/provider-capabilities-BvoExILy.js +1 -0
  114. package/client/dist/assets/settings-BveOJoaI.js +1 -0
  115. package/client/dist/assets/settings-Cj1C6F5k.js +1 -0
  116. package/client/dist/assets/settings-CuVwOpe0.js +1 -0
  117. package/client/dist/assets/settings-D5X4DfRc.js +1 -0
  118. package/client/dist/assets/settings-DXwxe-BW.js +1 -0
  119. package/client/dist/assets/settings-Di81Ba_V.js +1 -0
  120. package/client/dist/assets/settings-jbLjCYC_.js +1 -0
  121. package/client/dist/assets/settings-wIZNPFnn.js +1 -0
  122. package/client/dist/assets/setup-BBiHEO7h.js +1 -0
  123. package/client/dist/assets/setup-BlTWhNIQ.js +1 -0
  124. package/client/dist/assets/setup-Bp2L_oiP.js +1 -0
  125. package/client/dist/assets/setup-CInYXp1-.js +1 -0
  126. package/client/dist/assets/{setup-CITtPjed.js → setup-CYH3bP6K.js} +1 -1
  127. package/client/dist/assets/setup-DwcQ921P.js +1 -0
  128. package/client/dist/assets/setup-PBLjuDSs.js +1 -0
  129. package/client/dist/assets/setup-bx6FtoBp.js +1 -0
  130. package/client/dist/assets/{spending-DMnCXy84.js → spending-BCyUxoOI.js} +1 -1
  131. package/client/dist/assets/{tickets-B8BuAaj5.js → tickets-BL9r1G0e.js} +1 -1
  132. package/client/dist/assets/{tickets-DpmdE8tv.js → tickets-B_NyHJ8f.js} +1 -1
  133. package/client/dist/assets/{tickets-B_yh4qQk.js → tickets-BarF1wuG.js} +1 -1
  134. package/client/dist/assets/{tickets-pAUJkDTu.js → tickets-CclVhpQA.js} +1 -1
  135. package/client/dist/assets/{tickets-D_yDquEw.js → tickets-CqqOHbli.js} +1 -1
  136. package/client/dist/assets/{tickets-CFk2n2Or.js → tickets-DCkFSiqt.js} +1 -1
  137. package/client/dist/assets/{tickets-DQp7JS2R.js → tickets-Djn3ccfT.js} +1 -1
  138. package/client/dist/assets/{tickets-Bs37scwY.js → tickets-MiHBPsy_.js} +1 -1
  139. package/client/dist/assets/{useBrowserCaptureSession-CkBJShUw.js → useBrowserCaptureSession-CkVCDzer.js} +1 -1
  140. package/client/dist/assets/{useDesktop-B4pSBIDd.js → useDesktop-DCP_MHp9.js} +1 -1
  141. package/client/dist/index.html +25 -24
  142. package/docs/README.md +7 -3
  143. package/docs/cli.md +3 -3
  144. package/docs/codex.md +51 -64
  145. package/docs/creating-specs.md +36 -4
  146. package/docs/customizing.md +5 -5
  147. package/docs/gemini.md +35 -47
  148. package/docs/getting-started.md +15 -9
  149. package/docs/guide/de/agents/2-profiles-and-the-balanced-default.md +5 -1
  150. package/docs/guide/de/agents/4-custom-agents-catalog.md +7 -4
  151. package/docs/guide/de/getting-started/1-what-is-specrails.md +1 -0
  152. package/docs/guide/de/getting-started/2-installing-and-first-run.md +1 -0
  153. package/docs/guide/de/getting-started/4-the-dashboard-tour.md +4 -4
  154. package/docs/guide/de/integrations/1-ai-providers.md +29 -18
  155. package/docs/guide/de/integrations/2-plugins.md +3 -3
  156. package/docs/guide/de/integrations/6-agent-chat.md +8 -1
  157. package/docs/guide/de/pipeline/1-rails-and-jobs.md +9 -6
  158. package/docs/guide/de/pipeline/2-the-job-detail-view.md +3 -1
  159. package/docs/guide/de/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  160. package/docs/guide/de/pipeline/4-picking-an-engine-per-rail.md +13 -13
  161. package/docs/guide/de/pipeline/5-the-loop-builder.md +6 -2
  162. package/docs/guide/de/specs/2-add-spec-quick-mode.md +6 -1
  163. package/docs/guide/en/agents/2-profiles-and-the-balanced-default.md +7 -1
  164. package/docs/guide/en/agents/4-custom-agents-catalog.md +17 -4
  165. package/docs/guide/en/getting-started/1-what-is-specrails.md +2 -1
  166. package/docs/guide/en/getting-started/2-installing-and-first-run.md +2 -1
  167. package/docs/guide/en/getting-started/4-the-dashboard-tour.md +5 -5
  168. package/docs/guide/en/insights/3-code-explorer.md +5 -0
  169. package/docs/guide/en/integrations/1-ai-providers.md +63 -22
  170. package/docs/guide/en/integrations/2-plugins.md +3 -3
  171. package/docs/guide/en/integrations/6-agent-chat.md +14 -2
  172. package/docs/guide/en/pipeline/1-rails-and-jobs.md +19 -7
  173. package/docs/guide/en/pipeline/2-the-job-detail-view.md +3 -1
  174. package/docs/guide/en/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  175. package/docs/guide/en/pipeline/4-picking-an-engine-per-rail.md +25 -11
  176. package/docs/guide/en/pipeline/5-the-loop-builder.md +7 -2
  177. package/docs/guide/en/specs/2-add-spec-quick-mode.md +10 -1
  178. package/docs/guide/es/agents/2-profiles-and-the-balanced-default.md +5 -1
  179. package/docs/guide/es/agents/4-custom-agents-catalog.md +7 -4
  180. package/docs/guide/es/getting-started/1-what-is-specrails.md +1 -0
  181. package/docs/guide/es/getting-started/2-installing-and-first-run.md +1 -0
  182. package/docs/guide/es/getting-started/4-the-dashboard-tour.md +4 -4
  183. package/docs/guide/es/integrations/1-ai-providers.md +30 -18
  184. package/docs/guide/es/integrations/2-plugins.md +3 -3
  185. package/docs/guide/es/integrations/6-agent-chat.md +8 -1
  186. package/docs/guide/es/pipeline/1-rails-and-jobs.md +9 -6
  187. package/docs/guide/es/pipeline/2-the-job-detail-view.md +3 -1
  188. package/docs/guide/es/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  189. package/docs/guide/es/pipeline/4-picking-an-engine-per-rail.md +15 -13
  190. package/docs/guide/es/pipeline/5-the-loop-builder.md +6 -2
  191. package/docs/guide/es/specs/2-add-spec-quick-mode.md +6 -1
  192. package/docs/guide/fr/agents/2-profiles-and-the-balanced-default.md +5 -1
  193. package/docs/guide/fr/agents/4-custom-agents-catalog.md +7 -4
  194. package/docs/guide/fr/getting-started/1-what-is-specrails.md +1 -0
  195. package/docs/guide/fr/getting-started/2-installing-and-first-run.md +1 -0
  196. package/docs/guide/fr/getting-started/4-the-dashboard-tour.md +4 -4
  197. package/docs/guide/fr/integrations/1-ai-providers.md +29 -18
  198. package/docs/guide/fr/integrations/2-plugins.md +3 -3
  199. package/docs/guide/fr/integrations/6-agent-chat.md +8 -1
  200. package/docs/guide/fr/pipeline/1-rails-and-jobs.md +9 -6
  201. package/docs/guide/fr/pipeline/2-the-job-detail-view.md +3 -1
  202. package/docs/guide/fr/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  203. package/docs/guide/fr/pipeline/4-picking-an-engine-per-rail.md +15 -13
  204. package/docs/guide/fr/pipeline/5-the-loop-builder.md +6 -2
  205. package/docs/guide/fr/specs/2-add-spec-quick-mode.md +6 -1
  206. package/docs/guide/it/agents/2-profiles-and-the-balanced-default.md +5 -1
  207. package/docs/guide/it/agents/4-custom-agents-catalog.md +7 -4
  208. package/docs/guide/it/getting-started/1-what-is-specrails.md +1 -0
  209. package/docs/guide/it/getting-started/2-installing-and-first-run.md +1 -0
  210. package/docs/guide/it/getting-started/4-the-dashboard-tour.md +4 -4
  211. package/docs/guide/it/integrations/1-ai-providers.md +28 -18
  212. package/docs/guide/it/integrations/2-plugins.md +3 -3
  213. package/docs/guide/it/integrations/6-agent-chat.md +8 -1
  214. package/docs/guide/it/pipeline/1-rails-and-jobs.md +9 -6
  215. package/docs/guide/it/pipeline/2-the-job-detail-view.md +3 -1
  216. package/docs/guide/it/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  217. package/docs/guide/it/pipeline/4-picking-an-engine-per-rail.md +13 -13
  218. package/docs/guide/it/pipeline/5-the-loop-builder.md +6 -2
  219. package/docs/guide/it/specs/2-add-spec-quick-mode.md +6 -1
  220. package/docs/guide/ja/agents/2-profiles-and-the-balanced-default.md +6 -1
  221. package/docs/guide/ja/agents/4-custom-agents-catalog.md +7 -4
  222. package/docs/guide/ja/getting-started/1-what-is-specrails.md +1 -0
  223. package/docs/guide/ja/getting-started/2-installing-and-first-run.md +1 -0
  224. package/docs/guide/ja/getting-started/4-the-dashboard-tour.md +4 -4
  225. package/docs/guide/ja/integrations/1-ai-providers.md +28 -18
  226. package/docs/guide/ja/integrations/2-plugins.md +3 -3
  227. package/docs/guide/ja/integrations/6-agent-chat.md +7 -1
  228. package/docs/guide/ja/pipeline/1-rails-and-jobs.md +9 -6
  229. package/docs/guide/ja/pipeline/2-the-job-detail-view.md +3 -1
  230. package/docs/guide/ja/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  231. package/docs/guide/ja/pipeline/4-picking-an-engine-per-rail.md +14 -13
  232. package/docs/guide/ja/pipeline/5-the-loop-builder.md +6 -2
  233. package/docs/guide/ja/specs/2-add-spec-quick-mode.md +6 -1
  234. package/docs/guide/pt/agents/2-profiles-and-the-balanced-default.md +5 -1
  235. package/docs/guide/pt/agents/4-custom-agents-catalog.md +7 -4
  236. package/docs/guide/pt/getting-started/1-what-is-specrails.md +1 -0
  237. package/docs/guide/pt/getting-started/2-installing-and-first-run.md +1 -0
  238. package/docs/guide/pt/getting-started/4-the-dashboard-tour.md +4 -4
  239. package/docs/guide/pt/integrations/1-ai-providers.md +28 -18
  240. package/docs/guide/pt/integrations/2-plugins.md +3 -3
  241. package/docs/guide/pt/integrations/6-agent-chat.md +7 -1
  242. package/docs/guide/pt/pipeline/1-rails-and-jobs.md +9 -6
  243. package/docs/guide/pt/pipeline/2-the-job-detail-view.md +2 -1
  244. package/docs/guide/pt/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  245. package/docs/guide/pt/pipeline/4-picking-an-engine-per-rail.md +14 -13
  246. package/docs/guide/pt/pipeline/5-the-loop-builder.md +6 -2
  247. package/docs/guide/pt/specs/2-add-spec-quick-mode.md +6 -1
  248. package/docs/guide/zh/agents/2-profiles-and-the-balanced-default.md +4 -1
  249. package/docs/guide/zh/agents/4-custom-agents-catalog.md +7 -4
  250. package/docs/guide/zh/getting-started/1-what-is-specrails.md +1 -0
  251. package/docs/guide/zh/getting-started/2-installing-and-first-run.md +1 -0
  252. package/docs/guide/zh/getting-started/4-the-dashboard-tour.md +4 -4
  253. package/docs/guide/zh/integrations/1-ai-providers.md +26 -18
  254. package/docs/guide/zh/integrations/2-plugins.md +3 -3
  255. package/docs/guide/zh/integrations/6-agent-chat.md +6 -1
  256. package/docs/guide/zh/pipeline/1-rails-and-jobs.md +9 -6
  257. package/docs/guide/zh/pipeline/2-the-job-detail-view.md +2 -1
  258. package/docs/guide/zh/pipeline/3-batch-implement-and-multi-feature.md +1 -1
  259. package/docs/guide/zh/pipeline/4-picking-an-engine-per-rail.md +12 -12
  260. package/docs/guide/zh/pipeline/5-the-loop-builder.md +6 -2
  261. package/docs/guide/zh/specs/2-add-spec-quick-mode.md +6 -1
  262. package/docs/internals/README.md +4 -1
  263. package/docs/internals/adding-a-provider.md +32 -28
  264. package/docs/internals/api-reference.md +37 -13
  265. package/docs/internals/architecture.md +5 -5
  266. package/docs/internals/bundled-framework-build-plan.md +3 -3
  267. package/docs/internals/code-explorer-story.md +4 -0
  268. package/docs/internals/configuration.md +17 -5
  269. package/docs/internals/global-artifacts-alignment-contract.md +1 -1
  270. package/docs/internals/operations-runbook.md +1 -1
  271. package/docs/internals/profiles.md +37 -45
  272. package/docs/internals/project-builder.md +16 -0
  273. package/docs/kimi.md +291 -0
  274. package/docs/mcp.md +9 -2
  275. package/docs/platforms/macos.md +17 -7
  276. package/docs/platforms/windows.md +9 -4
  277. package/docs/running-pipelines.md +46 -12
  278. package/docs/terminal.md +1 -1
  279. package/docs/tracking-cost.md +25 -6
  280. package/package.json +4 -2
  281. package/server/dist/agent-chat-manager.js +74 -32
  282. package/server/dist/agent-chat-router.js +40 -17
  283. package/server/dist/agent-cwd-manager.js +14 -7
  284. package/server/dist/agent-generator.js +69 -85
  285. package/server/dist/agent-mcp-config.js +17 -11
  286. package/server/dist/agent-operator-prompt.js +29 -20
  287. package/server/dist/agent-refine-manager.js +58 -38
  288. package/server/dist/ai-invocations.js +65 -20
  289. package/server/dist/attachment-manager.js +49 -15
  290. package/server/dist/blueprint-chat-manager.js +41 -16
  291. package/server/dist/blueprint-router.js +40 -6
  292. package/server/dist/chat-manager.js +165 -89
  293. package/server/dist/code-explorer-router.js +26 -7
  294. package/server/dist/contract-refine-runner.js +146 -113
  295. package/server/dist/core-compat.js +57 -2
  296. package/server/dist/core-package.js +3 -3
  297. package/server/dist/core-update-manager.js +17 -1
  298. package/server/dist/db.js +60 -5
  299. package/server/dist/desktop-analytics.js +44 -6
  300. package/server/dist/desktop-router.js +127 -11
  301. package/server/dist/explore-cwd-manager.js +19 -3
  302. package/server/dist/feature-flags.js +1 -1
  303. package/server/dist/file-story-manager.js +3 -3
  304. package/server/dist/file-summary-generator.js +21 -15
  305. package/server/dist/file-summary-manager.js +6 -6
  306. package/server/dist/framework-manager.js +19 -2
  307. package/server/dist/framework-migration.js +27 -12
  308. package/server/dist/install-config-path.js +1 -1
  309. package/server/dist/interactive-job-session.js +8 -6
  310. package/server/dist/loop-command-catalog.js +27 -10
  311. package/server/dist/loop-executors.js +59 -27
  312. package/server/dist/loop-factory.js +2 -2
  313. package/server/dist/loop-run-manager.js +100 -39
  314. package/server/dist/loops-router.js +1 -1
  315. package/server/dist/mcp/guide.js +23 -16
  316. package/server/dist/mcp/tools/agents.js +47 -41
  317. package/server/dist/mcp/tools/analytics.js +2 -2
  318. package/server/dist/mcp/tools/loops.js +2 -2
  319. package/server/dist/mcp/tools/plugins.js +14 -9
  320. package/server/dist/mcp/tools/rails.js +12 -13
  321. package/server/dist/mcp/tools/support.js +1 -1
  322. package/server/dist/mobile/mobile-router.js +5 -1
  323. package/server/dist/offline-assemble.js +13 -1
  324. package/server/dist/path-resolver.js +2 -2
  325. package/server/dist/plugin-manager.js +391 -106
  326. package/server/dist/plugins/claude-md-mutation.js +5 -4
  327. package/server/dist/plugins/drift.js +32 -29
  328. package/server/dist/plugins/rail-integration.js +13 -2
  329. package/server/dist/plugins/serena/install.js +25 -17
  330. package/server/dist/plugins/serena/manifest.js +22 -5
  331. package/server/dist/plugins/serena/verify.js +46 -16
  332. package/server/dist/plugins-router.js +59 -8
  333. package/server/dist/profile-manager.js +148 -36
  334. package/server/dist/profiles-router.js +311 -82
  335. package/server/dist/project-registry.js +2 -2
  336. package/server/dist/project-router-chat.js +17 -8
  337. package/server/dist/project-router-helpers.js +93 -5
  338. package/server/dist/project-router-jobs.js +76 -12
  339. package/server/dist/project-router-loop-runs.js +42 -14
  340. package/server/dist/project-router-settings.js +31 -10
  341. package/server/dist/project-router-setup.js +4 -5
  342. package/server/dist/project-router-spending.js +15 -3
  343. package/server/dist/project-router-tickets.js +187 -181
  344. package/server/dist/project-router.js +1 -0
  345. package/server/dist/proposal-manager.js +125 -85
  346. package/server/dist/providers/claude-adapter.js +14 -0
  347. package/server/dist/providers/codex-adapter.js +20 -0
  348. package/server/dist/providers/gemini-adapter.js +14 -0
  349. package/server/dist/providers/index.js +18 -1
  350. package/server/dist/providers/kimi-adapter.js +361 -0
  351. package/server/dist/providers/kimi-skill-prompt.js +332 -0
  352. package/server/dist/providers/runtime.js +137 -0
  353. package/server/dist/queue-manager.js +103 -78
  354. package/server/dist/rail-isolated-launch.js +1 -1
  355. package/server/dist/rails-router.js +51 -38
  356. package/server/dist/result-event.js +5 -0
  357. package/server/dist/schemas/profile.v1.json +3 -4
  358. package/server/dist/setup-manager.js +222 -101
  359. package/server/dist/setup-prerequisites.js +7 -1
  360. package/server/dist/smash-runner.js +104 -57
  361. package/server/dist/spawn-lifecycle.js +18 -14
  362. package/server/dist/spec-launcher-manager.js +66 -54
  363. package/server/dist/spec-models.js +15 -6
  364. package/server/dist/spending.js +110 -17
  365. package/server/dist/util/cli-prompt.js +142 -5
  366. package/server/dist/util/stream-display.js +46 -0
  367. package/server/dist/workspace-manager.js +100 -37
  368. package/server/dist/worktree-manager.js +4 -0
  369. package/server/dist/worktree-overlay.js +12 -3
  370. package/client/dist/assets/AgentModeCodePane-BAYyFRmY.js +0 -2
  371. package/client/dist/assets/AgentsPage-DuyJuaFs.js +0 -86
  372. package/client/dist/assets/AnalyticsPage-BY7gtCx6.js +0 -1
  373. package/client/dist/assets/CodePage-vyQr40Vl.js +0 -2
  374. package/client/dist/assets/JobDetailPage-CU4FEnUC.js +0 -1
  375. package/client/dist/assets/LoopsPage-SqglnXlp.js +0 -1
  376. package/client/dist/assets/PluginsPage-B89S8o1a.js +0 -2
  377. package/client/dist/assets/TicketDetailModal-CI47Dq9E.js +0 -14
  378. package/client/dist/assets/addspec-BXjvkh5q.js +0 -1
  379. package/client/dist/assets/addspec-C4bwrmpi.js +0 -1
  380. package/client/dist/assets/addspec-CArHXUDM.js +0 -1
  381. package/client/dist/assets/addspec-DTKJcXiR.js +0 -1
  382. package/client/dist/assets/addspec-DbNBbrha.js +0 -1
  383. package/client/dist/assets/addspec-Rw8uVBC1.js +0 -1
  384. package/client/dist/assets/addspec-htHGZHOe.js +0 -1
  385. package/client/dist/assets/addspec-lr_LP6jk.js +0 -1
  386. package/client/dist/assets/agent-BABjRt0P.js +0 -1
  387. package/client/dist/assets/agent-BuUpgqVx.js +0 -1
  388. package/client/dist/assets/agent-CCDZesgU.js +0 -1
  389. package/client/dist/assets/agent-CVn64zWH.js +0 -1
  390. package/client/dist/assets/agent-CWeOny0E.js +0 -1
  391. package/client/dist/assets/agent-DOysmad_.js +0 -1
  392. package/client/dist/assets/agent-DSsjTBhn.js +0 -1
  393. package/client/dist/assets/agent-DlZMxfM9.js +0 -1
  394. package/client/dist/assets/agents-6ZOJXWVk.js +0 -1
  395. package/client/dist/assets/agents-BZ0XQKjg.js +0 -1
  396. package/client/dist/assets/agents-BqWklnHR.js +0 -1
  397. package/client/dist/assets/agents-Bz-thHkB.js +0 -1
  398. package/client/dist/assets/agents-CJclElx6.js +0 -1
  399. package/client/dist/assets/agents-D_l9L0VA.js +0 -1
  400. package/client/dist/assets/agents-DhG7mg6-.js +0 -1
  401. package/client/dist/assets/agents-u_C0jPB5.js +0 -1
  402. package/client/dist/assets/agentstudio-BF19hbXj.js +0 -1
  403. package/client/dist/assets/agentstudio-BIUe1Im2.js +0 -1
  404. package/client/dist/assets/agentstudio-BLGvxWBx.js +0 -1
  405. package/client/dist/assets/agentstudio-D9UKiWTj.js +0 -1
  406. package/client/dist/assets/agentstudio-Drs37nIM.js +0 -1
  407. package/client/dist/assets/agentstudio-nEnKkcXM.js +0 -1
  408. package/client/dist/assets/agentstudio-pyFcSBKy.js +0 -1
  409. package/client/dist/assets/agentstudio-zfTzQh3U.js +0 -1
  410. package/client/dist/assets/analytics-BC7mwR4s.js +0 -1
  411. package/client/dist/assets/analytics-BiNg8edP.js +0 -1
  412. package/client/dist/assets/analytics-C0s_T2GN.js +0 -1
  413. package/client/dist/assets/analytics-CdsAPAwZ.js +0 -1
  414. package/client/dist/assets/analytics-Cr1_q-lC.js +0 -1
  415. package/client/dist/assets/analytics-DZ8Aoq3I.js +0 -1
  416. package/client/dist/assets/analytics-IEsKZvpW.js +0 -1
  417. package/client/dist/assets/analytics-SRPf84OT.js +0 -1
  418. package/client/dist/assets/builder-BH8Fua-g.js +0 -1
  419. package/client/dist/assets/builder-BoV7DgKd.js +0 -1
  420. package/client/dist/assets/builder-Cc_Lf79C.js +0 -1
  421. package/client/dist/assets/builder-CwZ7Bme2.js +0 -1
  422. package/client/dist/assets/builder-CxW-JFsR.js +0 -1
  423. package/client/dist/assets/builder-D94lrV7x.js +0 -1
  424. package/client/dist/assets/builder-cqHpCyGa.js +0 -1
  425. package/client/dist/assets/code-76gS0IdL.js +0 -1
  426. package/client/dist/assets/code-BDXEM4ml.js +0 -1
  427. package/client/dist/assets/code-C1VwxlML.js +0 -1
  428. package/client/dist/assets/code-CnMZyJpr.js +0 -1
  429. package/client/dist/assets/code-D20ef9Cf.js +0 -1
  430. package/client/dist/assets/code-DdOXaWRY.js +0 -1
  431. package/client/dist/assets/code-Duohuf9l.js +0 -1
  432. package/client/dist/assets/code-geHmknB9.js +0 -1
  433. package/client/dist/assets/format-command-Dfa1o2d-.js +0 -1
  434. package/client/dist/assets/index-Dh9i4CnN.css +0 -2
  435. package/client/dist/assets/index-F9r8mWP_.js +0 -76
  436. package/client/dist/assets/jobs-BCtGfgUA.js +0 -1
  437. package/client/dist/assets/jobs-BHR_EnDI.js +0 -1
  438. package/client/dist/assets/jobs-BMbZJjJJ.js +0 -1
  439. package/client/dist/assets/jobs-DzSIR8V6.js +0 -1
  440. package/client/dist/assets/nav-BRJBxaGt.js +0 -1
  441. package/client/dist/assets/nav-CAGKv3_F.js +0 -1
  442. package/client/dist/assets/nav-CNskRJKQ.js +0 -1
  443. package/client/dist/assets/nav-DY93irBL.js +0 -1
  444. package/client/dist/assets/nav-DhjvYgqt.js +0 -1
  445. package/client/dist/assets/nav-Gb-r4wop.js +0 -1
  446. package/client/dist/assets/nav-TvumAFD2.js +0 -1
  447. package/client/dist/assets/nav-myFaXRHD.js +0 -1
  448. package/client/dist/assets/settings-B0ypw9uw.js +0 -1
  449. package/client/dist/assets/settings-B9ilOSYO.js +0 -1
  450. package/client/dist/assets/settings-BqlWHRHA.js +0 -1
  451. package/client/dist/assets/settings-D8dlqt4d.js +0 -1
  452. package/client/dist/assets/settings-DAZqjX2a.js +0 -1
  453. package/client/dist/assets/settings-DRh39v1S.js +0 -1
  454. package/client/dist/assets/settings-Mj1OJbfd.js +0 -1
  455. package/client/dist/assets/settings-lRReaSYm.js +0 -1
  456. package/client/dist/assets/setup-3832BJCo.js +0 -1
  457. package/client/dist/assets/setup-B8J-gECe.js +0 -1
  458. package/client/dist/assets/setup-BCIOxVsc.js +0 -1
  459. package/client/dist/assets/setup-BciLj_tU.js +0 -1
  460. package/client/dist/assets/setup-CTkE3cfh.js +0 -1
  461. package/client/dist/assets/setup-ajB4rYm-.js +0 -1
  462. package/client/dist/assets/setup-xFO1wNl0.js +0 -1
@@ -10,26 +10,26 @@ const crypto_1 = require("crypto");
10
10
  const tree_kill_1 = __importDefault(require("tree-kill"));
11
11
  const cli_prompt_1 = require("./util/cli-prompt");
12
12
  const providers_1 = require("./providers");
13
+ const runtime_1 = require("./providers/runtime");
13
14
  const result_event_1 = require("./result-event");
14
15
  const ai_invocations_1 = require("./ai-invocations");
15
16
  const process_admission_1 = require("./process-admission");
16
17
  const transient_children_1 = require("./transient-children");
17
- const AGENT_STUDIO_ADAPTER = (0, providers_1.getAdapter)('claude');
18
18
  /**
19
19
  * Finalise the accumulated adapter events (native cost, or pricing-table
20
20
  * estimate when the run was killed before its `result` event) and persist one
21
21
  * surface='agent-studio' row. Best-effort — a recording failure is logged, never
22
22
  * thrown, so it can never break the generate/test flow.
23
23
  */
24
- function recordAgentStudioInvocation(ctx, events, status, startedAtIso) {
24
+ function recordAgentStudioInvocation(ctx, adapter, events, status, startedAtIso) {
25
25
  try {
26
- const { result, estimated } = (0, result_event_1.finaliseInvocationResult)(AGENT_STUDIO_ADAPTER, events, {
27
- fallbackModel: AGENT_STUDIO_ADAPTER.defaultModel(),
26
+ const { result, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, events, {
27
+ fallbackModel: adapter.defaultModel(),
28
28
  });
29
29
  (0, ai_invocations_1.recordInvocation)(ctx.db, {
30
30
  id: (0, crypto_1.randomUUID)(),
31
31
  project_id: ctx.projectId,
32
- provider: AGENT_STUDIO_ADAPTER.id,
32
+ provider: adapter.id,
33
33
  surface: 'agent-studio',
34
34
  surface_ref_id: ctx.surfaceRefId ?? null,
35
35
  status,
@@ -78,23 +78,37 @@ function escalateKill(child) {
78
78
  catch { /* already gone */ }
79
79
  }
80
80
  }
81
+ function studioToolPolicy(adapter) {
82
+ const policies = adapter.capabilities.toolPolicies ?? [];
83
+ if (policies.includes('none'))
84
+ return 'none';
85
+ if (policies.includes('read-only'))
86
+ return 'read-only';
87
+ throw new Error(`provider_tool_policy_unsupported:${adapter.id}`);
88
+ }
81
89
  async function generateCustomAgent(cwd, opts) {
82
90
  const admission = opts.record
83
91
  ? (0, process_admission_1.captureProcessAdmission)(opts.record.projectId)
84
92
  : (0, process_admission_1.captureProcessAdmission)();
93
+ const adapter = (0, providers_1.getAdapter)(opts.providerId ?? 'claude');
94
+ const providerFrontmatter = adapter.id === 'claude'
95
+ ? [
96
+ ' - model: one of `sonnet`, `opus`, `haiku`',
97
+ ' - color: one of `blue`, `green`, `red`, `yellow`, `purple`, `cyan`',
98
+ ' - memory: `project`',
99
+ ]
100
+ : [];
85
101
  const systemPrompt = [
86
102
  'You are a specrails agent-authoring assistant.',
87
103
  '',
88
104
  'Your task: given a short description of what the user wants, produce a COMPLETE',
89
105
  'Markdown file for a specrails custom agent. The file MUST be valid input for',
90
- 'Claude Code: YAML frontmatter between `---` separators, followed by the agent body.',
106
+ `${adapter.displayName}: YAML frontmatter between \`---\` separators, followed by the agent body.`,
91
107
  '',
92
108
  'Required frontmatter fields:',
93
109
  ' - name: the exact agent id (starts with `custom-`, lowercase, kebab-case)',
94
110
  ' - description: one sentence saying when this agent should run (include tag hints in square brackets)',
95
- ' - model: one of `sonnet`, `opus`, `haiku`',
96
- ' - color: one of `blue`, `green`, `red`, `yellow`, `purple`, `cyan`',
97
- ' - memory: `project`',
111
+ ...providerFrontmatter,
98
112
  '',
99
113
  'Body sections (use `#` headings): Identity, Mission, Workflow protocol, Personality.',
100
114
  'Personality block: bullet list of tone, risk_tolerance, detail_level, focus_areas.',
@@ -108,22 +122,17 @@ async function generateCustomAgent(cwd, opts) {
108
122
  'Description of what it should do:',
109
123
  opts.description,
110
124
  ].join('\n');
125
+ const toolPolicy = studioToolPolicy(adapter);
111
126
  return new Promise((resolve, reject) => {
112
- const child = (0, cli_prompt_1.spawnClaude)([
113
- // This is a pure text transformation. The non-existent sentinel is
114
- // intentional: an empty tool list is dropped by some Claude versions
115
- // and silently restores the default toolkit.
116
- '--tools',
117
- '__none__',
118
- '--output-format',
119
- 'stream-json',
120
- '--verbose',
121
- '--append-system-prompt',
127
+ const spawnOptions = {
128
+ prompt: userPrompt,
122
129
  systemPrompt,
123
- '-p',
124
- userPrompt,
125
- ], {
126
- env: process.env,
130
+ model: adapter.defaultModel(),
131
+ toolPolicy,
132
+ };
133
+ const args = adapter.buildArgs('agent-refine', spawnOptions);
134
+ const child = (0, cli_prompt_1.spawnAiCli)(adapter.binary, args, {
135
+ env: (0, runtime_1.buildProviderEnv)(adapter, spawnOptions),
127
136
  stdio: ['ignore', 'pipe', 'pipe'],
128
137
  cwd,
129
138
  });
@@ -142,7 +151,7 @@ async function generateCustomAgent(cwd, opts) {
142
151
  settled = true;
143
152
  clearTimeout(killer);
144
153
  if (record && admission.isCurrent()) {
145
- recordAgentStudioInvocation(record, adapterEvents, status, startedAt);
154
+ recordAgentStudioInvocation(record, adapter, adapterEvents, status, startedAt);
146
155
  }
147
156
  complete();
148
157
  };
@@ -154,32 +163,11 @@ async function generateCustomAgent(cwd, opts) {
154
163
  }, 90_000);
155
164
  const reader = (0, readline_1.createInterface)({ input: child.stdout, crlfDelay: Infinity });
156
165
  reader.on('line', (line) => {
157
- if (record) {
158
- const ev = AGENT_STUDIO_ADAPTER.parseStreamLine(line);
159
- if (ev)
166
+ for (const ev of (0, runtime_1.parseStreamEvents)(adapter, line)) {
167
+ if (record)
160
168
  adapterEvents.push(ev);
161
- }
162
- let parsed;
163
- try {
164
- parsed = JSON.parse(line);
165
- }
166
- catch {
167
- return;
168
- }
169
- if (!parsed || typeof parsed !== 'object')
170
- return;
171
- // Claude stream-json format: {type:"assistant", message:{content:[{type:"text", text:"..."}]}}
172
- const p = parsed;
173
- const message = p.message;
174
- const content = message?.content;
175
- if (Array.isArray(content)) {
176
- for (const block of content) {
177
- if (block && typeof block === 'object' && block.type === 'text') {
178
- const text = block.text;
179
- if (typeof text === 'string')
180
- collected += text;
181
- }
182
- }
169
+ if (ev.kind === 'text-delta')
170
+ collected += ev.text;
183
171
  }
184
172
  });
185
173
  let stderr = '';
@@ -198,11 +186,11 @@ async function generateCustomAgent(cwd, opts) {
198
186
  const status = code === 0 && trimmed ? 'success' : 'failed';
199
187
  settle(status, () => {
200
188
  if (code !== 0) {
201
- reject(new Error(`claude exited with code ${code}${stderr ? `: ${stderr.slice(-500)}` : ''}`));
189
+ reject(new Error(`${adapter.binary} exited with code ${code}${stderr ? `: ${stderr.slice(-500)}` : ''}`));
202
190
  return;
203
191
  }
204
192
  if (!trimmed) {
205
- reject(new Error('claude returned empty output'));
193
+ reject(new Error(`${adapter.binary} returned empty output`));
206
194
  return;
207
195
  }
208
196
  resolve(trimmed);
@@ -226,6 +214,7 @@ async function testCustomAgent(cwd, opts) {
226
214
  ? (0, process_admission_1.captureProcessAdmission)(opts.record.projectId)
227
215
  : (0, process_admission_1.captureProcessAdmission)();
228
216
  const tokenCeiling = opts.tokenCeiling ?? 4000;
217
+ const adapter = (0, providers_1.getAdapter)(opts.providerId ?? 'claude');
229
218
  // Strip YAML frontmatter so we feed only the agent's instructions.
230
219
  const body = opts.draftBody.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, '').trim();
231
220
  if (!body) {
@@ -242,21 +231,17 @@ async function testCustomAgent(cwd, opts) {
242
231
  ].join('\n');
243
232
  const draftHash = (0, crypto_1.createHash)('sha256').update(opts.draftBody).digest('hex').slice(0, 16);
244
233
  const started = Date.now();
234
+ const toolPolicy = studioToolPolicy(adapter);
245
235
  return new Promise((resolve, reject) => {
246
- const child = (0, cli_prompt_1.spawnClaude)([
247
- // A Studio smoke test evaluates the supplied instructions and returns
248
- // text; it never needs authority over the project it is testing in.
249
- '--tools',
250
- '__none__',
251
- '--output-format',
252
- 'stream-json',
253
- '--verbose',
254
- '--append-system-prompt',
236
+ const spawnOptions = {
237
+ prompt: opts.sampleTask,
255
238
  systemPrompt,
256
- '-p',
257
- opts.sampleTask,
258
- ], {
259
- env: process.env,
239
+ model: adapter.defaultModel(),
240
+ toolPolicy,
241
+ };
242
+ const args = adapter.buildArgs('agent-refine', spawnOptions);
243
+ const child = (0, cli_prompt_1.spawnAiCli)(adapter.binary, args, {
244
+ env: (0, runtime_1.buildProviderEnv)(adapter, spawnOptions),
260
245
  stdio: ['ignore', 'pipe', 'pipe'],
261
246
  cwd,
262
247
  });
@@ -275,6 +260,7 @@ async function testCustomAgent(cwd, opts) {
275
260
  let msgTokensOut = 0;
276
261
  let resultTokensIn;
277
262
  let resultTokensOut;
263
+ let sawUsage = false;
278
264
  let truncated = false;
279
265
  // Accumulate adapter events for cost recording (surface='agent-studio', MED-3).
280
266
  const adapterEvents = [];
@@ -290,7 +276,7 @@ async function testCustomAgent(cwd, opts) {
290
276
  settled = true;
291
277
  clearTimeout(killer);
292
278
  if (record && admission.isCurrent()) {
293
- recordAgentStudioInvocation(record, adapterEvents, status, startedAt);
279
+ recordAgentStudioInvocation(record, adapter, adapterEvents, status, startedAt);
294
280
  }
295
281
  complete();
296
282
  };
@@ -302,10 +288,11 @@ async function testCustomAgent(cwd, opts) {
302
288
  }, 120_000);
303
289
  const reader = (0, readline_1.createInterface)({ input: child.stdout, crlfDelay: Infinity });
304
290
  reader.on('line', (line) => {
305
- if (record) {
306
- const ev = AGENT_STUDIO_ADAPTER.parseStreamLine(line);
307
- if (ev)
291
+ for (const ev of (0, runtime_1.parseStreamEvents)(adapter, line)) {
292
+ if (record)
308
293
  adapterEvents.push(ev);
294
+ if (ev.kind === 'text-delta')
295
+ collected += ev.text;
309
296
  }
310
297
  let parsed;
311
298
  try {
@@ -317,37 +304,34 @@ async function testCustomAgent(cwd, opts) {
317
304
  if (!parsed || typeof parsed !== 'object')
318
305
  return;
319
306
  const p = parsed;
320
- // Text blocks
321
307
  const message = p.message;
322
- const content = message?.content;
323
- if (Array.isArray(content)) {
324
- for (const block of content) {
325
- if (block && typeof block === 'object' && block.type === 'text') {
326
- const text = block.text;
327
- if (typeof text === 'string')
328
- collected += text;
329
- }
330
- }
331
- }
332
308
  // Usage: the terminal `result` frame carries the cumulative total at the
333
309
  // top level; assistant frames carry a per-call `message.usage`. Route each
334
310
  // to its own accumulator so they are never double-counted.
335
311
  if (p.type === 'result') {
336
312
  const usage = p.usage;
337
313
  if (usage) {
338
- if (typeof usage.input_tokens === 'number')
314
+ if (typeof usage.input_tokens === 'number') {
339
315
  resultTokensIn = usage.input_tokens;
340
- if (typeof usage.output_tokens === 'number')
316
+ sawUsage = true;
317
+ }
318
+ if (typeof usage.output_tokens === 'number') {
341
319
  resultTokensOut = usage.output_tokens;
320
+ sawUsage = true;
321
+ }
342
322
  }
343
323
  }
344
324
  else {
345
325
  const usage = message?.usage;
346
326
  if (usage) {
347
- if (typeof usage.input_tokens === 'number')
327
+ if (typeof usage.input_tokens === 'number') {
348
328
  msgTokensIn += usage.input_tokens;
349
- if (typeof usage.output_tokens === 'number')
329
+ sawUsage = true;
330
+ }
331
+ if (typeof usage.output_tokens === 'number') {
350
332
  msgTokensOut += usage.output_tokens;
333
+ sawUsage = true;
334
+ }
351
335
  }
352
336
  }
353
337
  // Enforce token ceiling on the corrected running total.
@@ -373,14 +357,14 @@ async function testCustomAgent(cwd, opts) {
373
357
  const status = truncated ? 'aborted' : failedHard ? 'failed' : 'success';
374
358
  settle(status, () => {
375
359
  if (failedHard) {
376
- reject(new Error(`claude exited with code ${code}${stderr ? `: ${stderr.slice(-500)}` : ''}`));
360
+ reject(new Error(`${adapter.binary} exited with code ${code}${stderr ? `: ${stderr.slice(-500)}` : ''}`));
377
361
  return;
378
362
  }
379
363
  resolve({
380
364
  output: truncated
381
365
  ? collected + `\n\n[… output truncated after reaching ${tokenCeiling}-token ceiling]`
382
366
  : collected,
383
- tokens: runningTotalTokens(),
367
+ tokens: sawUsage ? runningTotalTokens() : null,
384
368
  durationMs,
385
369
  draftHash,
386
370
  });
@@ -17,6 +17,7 @@ const crypto_1 = require("crypto");
17
17
  const path_resolver_1 = require("./path-resolver");
18
18
  const win_spawn_1 = require("./util/win-spawn");
19
19
  const agent_tier_1 = require("./agent-tier");
20
+ const providers_1 = require("./providers");
20
21
  const AGENT_CONVERSATION_ID_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;
21
22
  // ─── Agent MCP wiring (design D8 / D1) ────────────────────────────────────────
22
23
  //
@@ -101,11 +102,12 @@ function buildSpecrailsMcpEntry(opts) {
101
102
  * Additive + idempotent: preserves any existing (e.g. plugin) mcpServers entries,
102
103
  * writes atomically (temp + rename), inlines NO token. Returns true when written.
103
104
  */
104
- function mergeSpecrailsIntoWorkspaceMcp(workspaceDir, port) {
105
+ function mergeSpecrailsIntoWorkspaceMcp(workspaceDir, port, providerId = 'claude') {
105
106
  const entry = buildSpecrailsMcpEntry({ port });
106
107
  if (!entry)
107
108
  return false;
108
- const file = path_1.default.join(workspaceDir, '.mcp.json');
109
+ const adapter = (0, providers_1.getAdapter)(providerId);
110
+ const file = adapter.projectMcpPath?.(workspaceDir) ?? path_1.default.join(workspaceDir, '.mcp.json');
109
111
  let current = {};
110
112
  try {
111
113
  if (fs_1.default.existsSync(file)) {
@@ -121,7 +123,7 @@ function mergeSpecrailsIntoWorkspaceMcp(workspaceDir, port) {
121
123
  const mcpServers = { ...(current.mcpServers ?? {}), specrails: entry };
122
124
  const next = { ...current, mcpServers };
123
125
  const tmp = `${file}.tmp-${process.pid}`;
124
- fs_1.default.mkdirSync(workspaceDir, { recursive: true });
126
+ fs_1.default.mkdirSync(path_1.default.dirname(file), { recursive: true });
125
127
  fs_1.default.writeFileSync(tmp, JSON.stringify(next, null, 2));
126
128
  fs_1.default.renameSync(tmp, file);
127
129
  return true;
@@ -232,20 +234,22 @@ function codexMcpOverrides(entry) {
232
234
  * (agent then runs tool-less / degraded).
233
235
  */
234
236
  function prepareAgentMcp(opts) {
235
- if (opts.adapterId === 'claude') {
237
+ const adapter = (0, providers_1.getAdapter)(opts.adapterId);
238
+ if (adapter.id === 'claude') {
236
239
  return { extraArgs: buildAgentMcpArgs(opts), env: {} };
237
240
  }
238
241
  const entry = buildAgentTurnEntry(opts);
239
242
  if (!entry)
240
243
  return { extraArgs: [], env: {} };
241
- if (opts.adapterId === 'codex') {
244
+ if (adapter.mcpRegistration === 'cli-add') {
242
245
  // Inline -c overrides contain only the capability FILE PATH, never its secret.
243
246
  return { extraArgs: codexMcpOverrides(entry), env: {} };
244
247
  }
245
- // gemini + any other project-json provider: write .mcp.json in the spawn cwd.
246
- const file = path_1.default.join(opts.cwd, '.mcp.json');
248
+ // Project-json providers write only their native project config in the
249
+ // conversation-isolated cwd.
250
+ const file = adapter.projectMcpPath?.(opts.cwd) ?? path_1.default.join(opts.cwd, '.mcp.json');
247
251
  mergeServerIntoJsonFile(file, entry);
248
- if (opts.adapterId === 'gemini') {
252
+ if (adapter.id === 'gemini') {
249
253
  // gemini-cli has NEVER read .mcp.json (a Claude convention) — its only MCP
250
254
  // surface is `mcpServers` in settings.json (user or <cwd>/.gemini project
251
255
  // scope), and an UNTRUSTED cwd suppresses MCP entirely (headless run exits
@@ -254,9 +258,6 @@ function prepareAgentMcp(opts) {
254
258
  // via env — the same pattern every other gemini spawn path already uses
255
259
  // (chat-manager / queue-manager / cli-prompt). Verified empirically against
256
260
  // gemini-cli 0.49.0 (see docs/internals note on FQN tool prefixing).
257
- const geminiDir = path_1.default.join(opts.cwd, '.gemini');
258
- fs_1.default.mkdirSync(geminiDir, { recursive: true });
259
- mergeServerIntoJsonFile(path_1.default.join(geminiDir, 'settings.json'), entry);
260
261
  return { extraArgs: [], env: { GEMINI_CLI_TRUST_WORKSPACE: 'true' } };
261
262
  }
262
263
  return { extraArgs: [], env: {} };
@@ -278,5 +279,10 @@ function mergeServerIntoJsonFile(file, entry) {
278
279
  current = {};
279
280
  }
280
281
  const next = { ...current, mcpServers: { ...(current.mcpServers ?? {}), specrails: entry } };
282
+ fs_1.default.mkdirSync(path_1.default.dirname(file), { recursive: true, mode: 0o700 });
281
283
  fs_1.default.writeFileSync(file, JSON.stringify(next, null, 2), { mode: 0o600 });
284
+ try {
285
+ fs_1.default.chmodSync(file, 0o600);
286
+ }
287
+ catch { /* best-effort */ }
282
288
  }
@@ -1,10 +1,13 @@
1
1
  "use strict";
2
2
  // ─── Single source of truth for the in-app operator agent prompts ─────────────
3
- // OPERATOR_INSTRUCTIONS is the CANONICAL prompt: written to CLAUDE.md/AGENTS.md/
4
- // GEMINI.md in ~/.specrails/agent-cwd/ — the only channel that reaches all three
5
- // providers (codex/gemini have no --system-prompt flag). OPERATOR_SYSTEM_PROMPT
6
- // is a compact distillation passed via --system-prompt on claude only (it
7
- // REPLACES the CLI's default system prompt — keep it).
3
+ // OPERATOR_INSTRUCTIONS is the CANONICAL prompt written to CLAUDE.md,
4
+ // AGENTS.md, and GEMINI.md in ~/.specrails/agent-cwd/. Kimi's native
5
+ // instructions path is nested under `.kimi-code`, where its per-conversation
6
+ // MCP config also lives; AgentChatManager therefore folds
7
+ // OPERATOR_SYSTEM_PROMPT into Kimi's effective user turn instead of duplicating
8
+ // the prompt in that native file. Claude receives the compact distillation via
9
+ // --system-prompt (it REPLACES the CLI's default system prompt — keep it), while
10
+ // Codex and Gemini auto-load their app-owned instruction files.
8
11
  //
9
12
  // BYTE-STABILITY CONTRACT: both constants must stay static (no timestamps, no
10
13
  // interpolation, no live data) so Anthropic prompt caching hits on turns 2+.
@@ -39,10 +42,10 @@ coding pipelines over them.
39
42
  (one pipeline job — Architect → Developer → Reviewer → Ship — over the rail's
40
43
  tickets), \`batch-implement\` (dependency-aware waves), Freestyle (API mode
41
44
  value \`freestyle\` only — call it \`Freestyle\` in prose; it sends a free-form
42
- autonomous prompt straight to Claude, one job per ticket, Claude-only,
43
- optional interactive in-job chat), \`loop\` (runs a saved workflow graph per
44
- ticket). Launching spawns AI CLI processes that WRITE CODE, RUN TESTS and
45
- COMMIT in the repo — it costs money and runs for minutes.
45
+ autonomous prompt straight to a capable provider, one job per ticket; Claude
46
+ also supports optional interactive in-job chat), \`loop\` (runs a saved
47
+ workflow graph per ticket). Launching spawns AI CLI processes that WRITE
48
+ CODE, RUN TESTS and COMMIT in the repo — it costs money and runs for minutes.
46
49
  - **Job** — one spawned run. Outcomes mutate spec status AUTOMATICALLY: launch →
47
50
  \`in_progress\`; success → \`done\`; revert → back to \`todo\`; partial confidence →
48
51
  \`done\` + \`needs_review\`. NEVER patch a status the pipeline manages; only
@@ -51,11 +54,13 @@ coding pipelines over them.
51
54
  publish with \`specrails_loops\`; RUN it with
52
55
  \`specrails_rails(launch, mode:'loop', loopId)\`.
53
56
  - **Profile** — per-project agent-chain config (which agents, which models,
54
- routing). Claude-only; forced to null on codex/gemini rails.
55
- - **Provider / engine** — claude, codex or gemini. A project installs one or
56
- more; AI-spawning actions may pick any installed one. Claude-only features:
57
- profiles, Contract Refine, SMASH, Freestyle, interactive jobs. Cost is
58
- authoritative on claude, estimated (~) on codex/gemini.
57
+ routing). Supported by Claude and Kimi; forced to null on Codex/Gemini rails.
58
+ - **Provider / engine** — claude, codex, gemini or kimi. A project installs one
59
+ or more; AI-spawning actions may pick any installed one. Claude and Kimi
60
+ support profiles and Freestyle; Contract Refine and SMASH require Claude's
61
+ structured-action boundary. Persistent interactive jobs remain Claude-only.
62
+ Cost is authoritative on Claude, estimated (~) on Codex/Gemini, and
63
+ unavailable when Kimi does not report it.
59
64
 
60
65
  ## How to work
61
66
 
@@ -214,7 +219,8 @@ those through \`specrails_support\` instead.
214
219
  Only when the user hands you finished text and wants it untouched; otherwise
215
220
  prefer \`commit_draft\`.
216
221
  - **Big features**: offer SMASH (\`specrails_specs(smash)\`) to split an epic
217
- into children (Claude-only). **Recurring work**: offer a loop.
222
+ into children when the effective provider supports structured actions
223
+ (currently Claude). **Recurring work**: offer a loop.
218
224
 
219
225
  ## Spec refinement mode (super specs)
220
226
 
@@ -335,8 +341,9 @@ summary later.
335
341
  spec lands, one short background AI pass appends a \`## Contract Layer\`
336
342
  section (naming contract, data shapes, state machine, invariants, file touch
337
343
  list). Pass \`contractRefine: false\` to skip it when the user declined it or
338
- wants zero AI spend. Claude-only; respects the app-wide kill switch; when it
339
- cannot run, the spec still lands unenriched.
344
+ wants zero AI spend. It requires a structured-action provider (currently
345
+ Claude), respects the app-wide kill switch, and leaves the spec unenriched when
346
+ it cannot run.
340
347
  - The enrichment is asynchronous: the commit returns immediately and the
341
348
  ticket updates in place when the Contract Layer arrives. To re-fire it
342
349
  later, use \`specrails_specs(contract_refine, id)\` — it also works on
@@ -394,7 +401,8 @@ summary later.
394
401
  never quote the raw railIndex as the rail's name.
395
402
  - Configure then launch: \`specrails_rails(set_tickets, railIndex, ticketIds)\` →
396
403
  \`specrails_rails(launch, railIndex, mode, …)\`. Setting a profile and then
397
- switching the rail's engine to codex/gemini silently drops the profile.
404
+ switching the rail's engine to a provider without profile support
405
+ (Codex/Gemini) silently drops the profile.
398
406
  - When relaunching an \`on_review\` spec that already has an OPEN GitHub PR,
399
407
  \`launch\` automatically tries to continue that PR's head branch (matched by
400
408
  Jira key / spec id / title) instead of starting from the integration branch.
@@ -503,8 +511,9 @@ summary later.
503
511
  spec's status (done / reverted to todo / done with the needs-review flag —
504
512
  these are pipeline-managed; do not "fix" them yourself), duration, and cost —
505
513
  prefix the cost with \`~\` when the provider reports an estimate
506
- (codex/gemini). Offer the Analytics page for detail. On failure, report the
507
- failure faithfully and offer the diagnostic export.
514
+ (Codex/Gemini); say cost is unavailable when Kimi reports none. Offer the
515
+ Analytics page for detail. On failure, report the failure faithfully and
516
+ offer the diagnostic export.
508
517
 
509
518
  ## Stance
510
519