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
@@ -0,0 +1,361 @@
1
+ "use strict";
2
+ // Kimi Code CLI adapter for 0.27.0+.
3
+ //
4
+ // Official headless contract:
5
+ // kimi -m <configured-alias> -p <prompt> --output-format stream-json
6
+ // kimi -m <configured-alias> --session=<session-id> -p <prompt> --output-format stream-json
7
+ //
8
+ // Prompt mode owns its automatic permission policy and cannot be combined with
9
+ // --auto/--yolo/--plan. Kimi emits JSONL assistant/tool/meta records and a
10
+ // successful terminal `session.resume_hint`, but no authoritative token or USD
11
+ // cost envelope.
12
+ var __importDefault = (this && this.__importDefault) || function (mod) {
13
+ return (mod && mod.__esModule) ? mod : { "default": mod };
14
+ };
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports._KIMI_MODELS = exports._KIMI_MIN_VERSION = exports.kimiAdapter = void 0;
17
+ exports._compareSemver = compareSemver;
18
+ exports._normaliseKimiModel = normaliseKimiModel;
19
+ const child_process_1 = require("child_process");
20
+ const path_1 = __importDefault(require("path"));
21
+ const win_spawn_1 = require("../util/win-spawn");
22
+ const kimi_skill_prompt_1 = require("./kimi-skill-prompt");
23
+ const runtime_1 = require("./runtime");
24
+ const whichCommand = () => process.platform === 'win32' ? 'where' : 'which';
25
+ const KIMI_MIN_VERSION = '0.27.0';
26
+ exports._KIMI_MIN_VERSION = KIMI_MIN_VERSION;
27
+ const KIMI_MODELS = [
28
+ { value: 'k3', label: 'Kimi K3', default: true },
29
+ { value: 'kimi-for-coding', label: 'Kimi for Coding' },
30
+ { value: 'kimi-for-coding-highspeed', label: 'Kimi for Coding Highspeed' },
31
+ ];
32
+ exports._KIMI_MODELS = KIMI_MODELS;
33
+ const OFFICIAL_RAW_MODELS = new Set(KIMI_MODELS.map((model) => model.value));
34
+ const KIMI_EFFORTS = new Set(['low', 'high', 'max']);
35
+ const STREAM_JSON_FLAGS = ['--output-format', 'stream-json'];
36
+ // Keep this aligned with specrails-core's public Kimi runner contract. The
37
+ // host trusts a resume hint only after both parser and argv construction have
38
+ // enforced the same bounded grammar.
39
+ const KIMI_SESSION_ID_MAX_LENGTH = 128;
40
+ const KIMI_SESSION_ID_PATTERN = /^[A-Za-z0-9._-]+$/;
41
+ function normaliseKimiModel(model) {
42
+ return OFFICIAL_RAW_MODELS.has(model) ? `kimi-code/${model}` : model;
43
+ }
44
+ function isK3Model(model) {
45
+ return model === 'k3' || model === 'kimi-code/k3';
46
+ }
47
+ function isSafeKimiSessionId(sessionId) {
48
+ return sessionId.length > 0
49
+ && sessionId.length <= KIMI_SESSION_ID_MAX_LENGTH
50
+ && sessionId !== '.'
51
+ && sessionId !== '..'
52
+ && KIMI_SESSION_ID_PATTERN.test(sessionId);
53
+ }
54
+ function kimiSessionOption(sessionId) {
55
+ if (!isSafeKimiSessionId(sessionId)) {
56
+ throw new Error('invalid_kimi_session_id');
57
+ }
58
+ // Commander's optional `[id]` value can reinterpret a following `--value`
59
+ // as another flag. The equals form binds even option-shaped, otherwise-safe
60
+ // upstream ids to the session option.
61
+ return `--session=${sessionId}`;
62
+ }
63
+ function fold(systemPrompt, prompt) {
64
+ return systemPrompt ? `${systemPrompt}\n\n---\n\n${prompt}` : prompt;
65
+ }
66
+ function appendMediaGuidance(prompt, imagePaths) {
67
+ if (!imagePaths?.length)
68
+ return prompt;
69
+ const files = imagePaths.map((imagePath) => `- ${path_1.default.resolve(imagePath)}`).join('\n');
70
+ return [
71
+ prompt,
72
+ '',
73
+ 'Attached media files:',
74
+ files,
75
+ 'Use ReadMediaFile to inspect each attached media file before responding.',
76
+ ].join('\n');
77
+ }
78
+ function promptFor(action, opts) {
79
+ // Explore chat cwd owns AGENTS.md. Keeping the user turn short avoids
80
+ // overpowering it with a repeated system prompt on every resume.
81
+ const prompt = action === 'chat-turn' || action === 'chat-resume'
82
+ ? opts.prompt
83
+ : fold(opts.systemPrompt, opts.prompt);
84
+ return appendMediaGuidance(prompt, opts.imagePaths);
85
+ }
86
+ function buildKimiArgs(action, opts) {
87
+ if (action === 'chat-stream') {
88
+ throw new Error('kimi does not support persistent stdin streaming (chat-stream)');
89
+ }
90
+ // Print mode does not run Kimi's TUI/ACP slash-command interceptor. Every
91
+ // Core/skill spawn boundary must materialize the SKILL.md first; reject a
92
+ // missed callsite here so it cannot settle as a deceptive zero-work success.
93
+ if (/^\/(?:skill|specrails|sr|opsx):[^\s]+/.test(opts.prompt.trimStart())) {
94
+ throw new Error('kimi_headless_skill_not_materialized');
95
+ }
96
+ // Kimi Code 0.27 prompt mode creates/resumes sessions in `auto` permission
97
+ // mode and installs an approval handler that approves every tool call;
98
+ // `--prompt` also rejects `--plan`. Enforce the capability contract here as
99
+ // the final backstop: no caller may silently turn `none`/`read-only` into an
100
+ // autonomous invocation. AI auto-title is intrinsically pure-output, so it
101
+ // fails closed even if an older caller omitted the explicit policy.
102
+ const requestedToolPolicy = action === 'auto-title' ? 'none' : (opts.toolPolicy ?? 'default');
103
+ if (requestedToolPolicy !== 'default') {
104
+ throw new Error(`provider_tool_policy_unsupported:kimi:${requestedToolPolicy}`);
105
+ }
106
+ // Routes and selectors validate custom aliases, but restored queue state and
107
+ // internal callers can bypass those surfaces. Keep the spawn boundary
108
+ // authoritative so a corrupt value can never become a CLI flag.
109
+ if (!(0, runtime_1.isSafeCustomModelAlias)(opts.model)) {
110
+ throw new Error('invalid_provider_model_alias:kimi');
111
+ }
112
+ const requiresSession = action === 'chat-resume' || action === 'setup-enrich-resume';
113
+ if (requiresSession && !opts.sessionId)
114
+ throw new Error(`${action} requires sessionId`);
115
+ const args = ['-m', normaliseKimiModel(opts.model)];
116
+ if (opts.sessionId && (requiresSession || action === 'agent-refine')) {
117
+ args.push(kimiSessionOption(opts.sessionId));
118
+ }
119
+ args.push('-p', promptFor(action, opts), ...STREAM_JSON_FLAGS);
120
+ if (opts.extraArgs)
121
+ args.push(...opts.extraArgs);
122
+ return args;
123
+ }
124
+ function contentText(content) {
125
+ if (typeof content === 'string')
126
+ return content;
127
+ if (!Array.isArray(content))
128
+ return '';
129
+ return content
130
+ .map((part) => {
131
+ if (typeof part === 'string')
132
+ return part;
133
+ if (!part || typeof part !== 'object')
134
+ return '';
135
+ const record = part;
136
+ return typeof record.text === 'string' ? record.text : '';
137
+ })
138
+ .filter(Boolean)
139
+ .join('');
140
+ }
141
+ function stringifyPreview(value) {
142
+ if (typeof value === 'string')
143
+ return value.slice(0, 200);
144
+ try {
145
+ return JSON.stringify(value ?? '').slice(0, 200);
146
+ }
147
+ catch {
148
+ return String(value ?? '').slice(0, 200);
149
+ }
150
+ }
151
+ function errorMessage(parsed) {
152
+ if (typeof parsed.message === 'string')
153
+ return parsed.message;
154
+ if (typeof parsed.content === 'string')
155
+ return parsed.content;
156
+ if (parsed.error && typeof parsed.error === 'object') {
157
+ const nested = parsed.error;
158
+ if (typeof nested.message === 'string')
159
+ return nested.message;
160
+ return stringifyPreview(nested);
161
+ }
162
+ return 'Kimi invocation failed';
163
+ }
164
+ function assistantEvents(parsed) {
165
+ const events = [];
166
+ const text = contentText(parsed.content);
167
+ if (text)
168
+ events.push({ kind: 'text-delta', text });
169
+ const calls = Array.isArray(parsed.tool_calls) ? parsed.tool_calls : [];
170
+ for (const call of calls) {
171
+ if (!call || typeof call !== 'object')
172
+ continue;
173
+ const functionRecord = call.function;
174
+ if (!functionRecord || typeof functionRecord !== 'object')
175
+ continue;
176
+ const fn = functionRecord;
177
+ events.push({
178
+ kind: 'tool-use',
179
+ name: typeof fn.name === 'string' ? fn.name : '<unnamed>',
180
+ inputPreview: stringifyPreview(fn.arguments),
181
+ });
182
+ }
183
+ if (events.length === 0) {
184
+ return { kind: 'other', type: 'assistant', raw: parsed };
185
+ }
186
+ return events.length === 1 ? events[0] : events;
187
+ }
188
+ function parseKimiStreamLine(line) {
189
+ if (line.trim().length === 0)
190
+ return null;
191
+ let parsed;
192
+ try {
193
+ const value = JSON.parse(line);
194
+ if (!value || typeof value !== 'object' || Array.isArray(value))
195
+ return null;
196
+ parsed = value;
197
+ }
198
+ catch {
199
+ return null;
200
+ }
201
+ const role = typeof parsed.role === 'string' ? parsed.role : undefined;
202
+ const type = typeof parsed.type === 'string' ? parsed.type : undefined;
203
+ if (role === 'meta' && type === 'session.resume_hint') {
204
+ const sessionId = typeof parsed.session_id === 'string' ? parsed.session_id : '';
205
+ if (!sessionId)
206
+ return { kind: 'other', type, raw: parsed };
207
+ return isSafeKimiSessionId(sessionId)
208
+ ? { kind: 'session-started', sessionId }
209
+ : { kind: 'error', message: 'Kimi emitted an invalid session id' };
210
+ }
211
+ if (role === 'error' ||
212
+ type === 'error' ||
213
+ type === 'system.error' ||
214
+ type?.endsWith('.failed')) {
215
+ return { kind: 'error', message: errorMessage(parsed) };
216
+ }
217
+ if (role === 'assistant')
218
+ return assistantEvents(parsed);
219
+ // Tool results, retry records, system.version, and future meta records remain
220
+ // available as `other` diagnostics instead of being discarded.
221
+ return { kind: 'other', type: type ?? role ?? '<missing>', raw: parsed };
222
+ }
223
+ function extractKimiResult(events) {
224
+ let sessionId;
225
+ for (const event of events) {
226
+ if (event.kind === 'session-started')
227
+ sessionId = event.sessionId;
228
+ }
229
+ return {
230
+ session_id: sessionId,
231
+ };
232
+ }
233
+ function compareSemver(a, b) {
234
+ const left = a.split('.').map((value) => Number.parseInt(value, 10));
235
+ const right = b.split('.').map((value) => Number.parseInt(value, 10));
236
+ for (let index = 0; index < 3; index += 1) {
237
+ const delta = (left[index] ?? 0) - (right[index] ?? 0);
238
+ if (delta !== 0)
239
+ return delta > 0 ? 1 : -1;
240
+ }
241
+ return 0;
242
+ }
243
+ async function detectKimiInstalled() {
244
+ const env = (0, win_spawn_1.windowsSpawnEnv)();
245
+ try {
246
+ (0, child_process_1.execSync)(`${whichCommand()} kimi`, { stdio: 'ignore', env });
247
+ }
248
+ catch {
249
+ return { installed: false, executable: false };
250
+ }
251
+ try {
252
+ // The only official, non-billable bounded readiness probe is --version.
253
+ // Authentication has no safe probe in 0.27; setup directs users to login.
254
+ // `exec` intentionally uses the platform shell for this constant command:
255
+ // Windows npm installs expose `kimi.cmd`, which direct execFile cannot
256
+ // launch. No user-controlled text enters this command.
257
+ const raw = (0, child_process_1.execSync)('kimi --version', {
258
+ encoding: 'utf-8',
259
+ stdio: ['ignore', 'pipe', 'ignore'],
260
+ // ProviderAdapter.detectInstalled() is a UI/startup health probe. Keep
261
+ // the contract's hard three-second ceiling on every platform, including
262
+ // npm-installed Windows `.cmd` shims.
263
+ timeout: 3_000,
264
+ env,
265
+ }).trim();
266
+ const match = raw.match(/\d+\.\d+\.\d+/);
267
+ const version = match?.[0] ?? raw;
268
+ const meetsMinimum = !!match && compareSemver(version, KIMI_MIN_VERSION) >= 0;
269
+ return {
270
+ installed: true,
271
+ executable: true,
272
+ version,
273
+ meetsMinimum,
274
+ ...(!meetsMinimum
275
+ ? {
276
+ error: `kimi ${version || '?'} is older than required ${KIMI_MIN_VERSION}. ` +
277
+ 'Install the latest Kimi Code, run `kimi login`, then restart Specrails.',
278
+ }
279
+ : {}),
280
+ };
281
+ }
282
+ catch {
283
+ return { installed: true, executable: false };
284
+ }
285
+ }
286
+ function buildKimiEnv(opts) {
287
+ const effort = opts.reasoning_effort;
288
+ return {
289
+ KIMI_MODEL_THINKING_EFFORT: isK3Model(opts.model) && effort && KIMI_EFFORTS.has(effort)
290
+ ? effort
291
+ : undefined,
292
+ // Desktop's stream parser and permission analysis are qualified against
293
+ // Kimi Code 0.27's stable v1 engine. Never inherit the user's experimental
294
+ // v2 opt-in: it selects a different runtime with an unverified policy
295
+ // wiring and would silently invalidate those guarantees.
296
+ KIMI_CODE_EXPERIMENTAL_FLAG: undefined,
297
+ // Prompt mode auto-approves tools. Desktop has no scheduler lifecycle/UI
298
+ // for Kimi's persistent CronCreate facility, so prevent a managed child
299
+ // from leaving scheduled work behind after its owned process exits.
300
+ KIMI_DISABLE_CRON: '1',
301
+ // A managed invocation must run the version that passed Desktop's
302
+ // compatibility probe, not mutate the external CLI during startup.
303
+ KIMI_CODE_NO_AUTO_UPDATE: '1',
304
+ };
305
+ }
306
+ exports.kimiAdapter = {
307
+ id: 'kimi',
308
+ displayName: 'Kimi Code',
309
+ binary: 'kimi',
310
+ minCliVersion: KIMI_MIN_VERSION,
311
+ projectDirName: '.kimi-code',
312
+ // Unlike Codex's root AGENTS.md, Kimi's provider-local project instructions
313
+ // live inside its project tree. Keep the relative path explicit so isolated
314
+ // Explore workspaces and integration guidance land where Kimi actually
315
+ // loads them.
316
+ instructionsFilename: path_1.default.join('.kimi-code', 'AGENTS.md'),
317
+ mcpRegistration: 'project-json',
318
+ capabilities: {
319
+ nativeResume: true,
320
+ nativeStreamJson: true,
321
+ nativeCostUsd: false,
322
+ reportsUsage: false,
323
+ nativeOtelEnv: false,
324
+ profileEnvSupport: true,
325
+ systemPromptArg: false,
326
+ foldProjectChatSystemPrompt: true,
327
+ persistentStdin: false,
328
+ supportsReasoningEffort: true,
329
+ reasoningEfforts: ['low', 'high', 'max'],
330
+ // Kimi has no image argv; validated absolute paths are inspected through
331
+ // ReadMediaFile by provider-neutral workflow guidance.
332
+ supportsImageInput: true,
333
+ structuredActions: false,
334
+ toolPolicies: [],
335
+ profiles: true,
336
+ // Kimi aliases are configured by the user; the built-in catalog is only a
337
+ // convenient default/discovery set, not an exhaustive validation boundary.
338
+ customModelAliases: true,
339
+ customRoles: true,
340
+ materializeHeadlessSkills: true,
341
+ freestyle: true,
342
+ userMcp: false,
343
+ },
344
+ modelCatalog: () => KIMI_MODELS,
345
+ defaultModel: () => 'k3',
346
+ reasoningEffortsForModel: (model) => isK3Model(model) ? ['low', 'high', 'max'] : [],
347
+ buildArgs: buildKimiArgs,
348
+ buildEnv: buildKimiEnv,
349
+ formatCoreCommand: kimi_skill_prompt_1.formatKimiCoreCommand,
350
+ buildRepoAccessArgs: (paths) => paths.flatMap((repoPath) => ['--add-dir', repoPath]),
351
+ projectMcpPath: (root) => path_1.default.join(root, '.kimi-code', 'mcp.json'),
352
+ customRolePath: (root, roleId) =>
353
+ // Kimi discovers only direct children of each skills root:
354
+ // `.kimi-code/skills/<name>/SKILL.md`. A nested `skills/rails/<name>`
355
+ // catalog is not scanned by the upstream CLI.
356
+ path_1.default.join(root, '.kimi-code', 'skills', roleId, 'SKILL.md'),
357
+ parseStreamLine: parseKimiStreamLine,
358
+ extractResult: extractKimiResult,
359
+ baselineAgents: () => ['sr-architect', 'sr-developer', 'sr-reviewer'],
360
+ detectInstalled: detectKimiInstalled,
361
+ };
@@ -0,0 +1,332 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports._test = exports.KimiSkillResolutionError = void 0;
7
+ exports.parseKimiSkillDocument = parseKimiSkillDocument;
8
+ exports.validateKimiRoleDocument = validateKimiRoleDocument;
9
+ exports.formatKimiCoreCommand = formatKimiCoreCommand;
10
+ const node_fs_1 = require("node:fs");
11
+ const node_path_1 = __importDefault(require("node:path"));
12
+ const js_yaml_1 = require("js-yaml");
13
+ const SAFE_SKILL_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
14
+ const OPSX_TO_KIMI_SKILL = {
15
+ propose: 'openspec-propose',
16
+ ff: 'openspec-ff-change',
17
+ new: 'openspec-new-change',
18
+ apply: 'openspec-apply-change',
19
+ continue: 'openspec-continue-change',
20
+ archive: 'openspec-archive-change',
21
+ 'bulk-archive': 'openspec-bulk-archive-change',
22
+ sync: 'openspec-sync-specs',
23
+ verify: 'openspec-verify-change',
24
+ explore: 'openspec-explore',
25
+ onboard: 'openspec-onboard',
26
+ };
27
+ /**
28
+ * Raised before a provider process is spawned when a Kimi headless command
29
+ * cannot be resolved safely. Sending the original `/skill:*` text to `kimi -p`
30
+ * would be a silent no-op: Kimi 0.27 intercepts slash skills in its TUI/ACP
31
+ * clients, while print mode sends its prompt straight to `session.prompt()`.
32
+ */
33
+ class KimiSkillResolutionError extends Error {
34
+ constructor(message) {
35
+ super(message);
36
+ this.name = 'KimiSkillResolutionError';
37
+ }
38
+ }
39
+ exports.KimiSkillResolutionError = KimiSkillResolutionError;
40
+ function parseInvocation(command) {
41
+ const match = command.match(/^\/(skill|specrails|sr|opsx):([^\s]+)(?:\s+([\s\S]*))?$/);
42
+ if (!match)
43
+ return null;
44
+ const namespace = match[1];
45
+ const rawName = match[2];
46
+ const rawArgs = (match[3] ?? '').trim();
47
+ let skillName;
48
+ if (namespace === 'skill')
49
+ skillName = rawName;
50
+ else if (namespace === 'specrails' || namespace === 'sr') {
51
+ skillName = `specrails-${rawName}`;
52
+ }
53
+ else {
54
+ skillName = OPSX_TO_KIMI_SKILL[rawName];
55
+ if (!skillName)
56
+ return null;
57
+ }
58
+ if (!SAFE_SKILL_NAME_RE.test(skillName)) {
59
+ throw new KimiSkillResolutionError(`Unsafe Kimi skill name "${skillName}". Expected letters, digits, "_" or "-".`);
60
+ }
61
+ return { skillName, rawArgs };
62
+ }
63
+ function isRecord(value) {
64
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
65
+ }
66
+ function nonEmptyString(value) {
67
+ return typeof value === 'string' && value.trim() !== '' ? value.trim() : undefined;
68
+ }
69
+ function skillArgumentNames(value) {
70
+ const isValid = (name) => name.trim() !== '' && !/^\d+$/.test(name);
71
+ if (typeof value === 'string')
72
+ return value.split(/\s+/).filter(isValid);
73
+ if (!Array.isArray(value))
74
+ return [];
75
+ return value.filter((item) => typeof item === 'string' && isValid(item));
76
+ }
77
+ /** Parse a directory SKILL.md with Kimi 0.27's frontmatter requirements.
78
+ *
79
+ * This is intentionally exported as the single parser for both execution and
80
+ * Profiles CRUD. Keeping the js-yaml parse and type checks here prevents the
81
+ * editor from accepting a role that the headless execution path would later
82
+ * reject.
83
+ */
84
+ function parseKimiSkillDocument(source, skillPath = '<memory>') {
85
+ const lines = source.split(/\r?\n/);
86
+ if (lines[0]?.trim() !== '---') {
87
+ throw new KimiSkillResolutionError(`Missing frontmatter in ${skillPath}`);
88
+ }
89
+ const close = lines.findIndex((line, index) => index > 0 && line.trim() === '---');
90
+ if (close < 0) {
91
+ throw new KimiSkillResolutionError(`Invalid frontmatter in ${skillPath}: missing closing fence`);
92
+ }
93
+ const yamlText = lines.slice(1, close).join('\n').trim();
94
+ let parsed;
95
+ try {
96
+ parsed = yamlText === '' ? {} : ((0, js_yaml_1.load)(yamlText) ?? {});
97
+ }
98
+ catch (error) {
99
+ throw new KimiSkillResolutionError(`Invalid frontmatter in ${skillPath}: ` +
100
+ (error instanceof Error ? error.message : String(error)));
101
+ }
102
+ if (!isRecord(parsed)) {
103
+ throw new KimiSkillResolutionError(`Frontmatter in ${skillPath} must be a mapping at the top level`);
104
+ }
105
+ const name = nonEmptyString(parsed.name);
106
+ const description = nonEmptyString(parsed.description);
107
+ if (!name || !description) {
108
+ throw new KimiSkillResolutionError(`Missing required frontmatter field ${!name ? '"name"' : '"description"'} in ${skillPath}`);
109
+ }
110
+ const hasType = Object.prototype.hasOwnProperty.call(parsed, 'type');
111
+ if (hasType
112
+ && (typeof parsed.type !== 'string' || parsed.type.trim() === '')) {
113
+ throw new KimiSkillResolutionError(`Skill type "${String(parsed.type)}" is not supported in ${skillPath}`);
114
+ }
115
+ const type = nonEmptyString(parsed.type);
116
+ if (type !== undefined &&
117
+ type !== 'prompt' &&
118
+ type !== 'inline' &&
119
+ type !== 'flow' &&
120
+ type !== 'reference') {
121
+ throw new KimiSkillResolutionError(`Skill type "${type}" is not supported in ${skillPath}`);
122
+ }
123
+ if (type === 'reference') {
124
+ throw new KimiSkillResolutionError(`Kimi skill "${name}" has type "reference" and cannot be activated by the user.`);
125
+ }
126
+ return {
127
+ body: lines.slice(close + 1).join('\n').trim(),
128
+ metadataName: name,
129
+ description,
130
+ argumentNames: skillArgumentNames(parsed.arguments),
131
+ };
132
+ }
133
+ /**
134
+ * Validate a user-authored role against the same document contract used at
135
+ * execution time. The expected-name check is a Profiles invariant: the
136
+ * provider-native metadata must identify the direct-child role directory.
137
+ */
138
+ function validateKimiRoleDocument(source, expectedName, skillPath = '<memory>') {
139
+ let document;
140
+ try {
141
+ document = parseKimiSkillDocument(source, skillPath);
142
+ }
143
+ catch (error) {
144
+ return [
145
+ error instanceof Error
146
+ ? error.message
147
+ : `Invalid Kimi skill document in ${skillPath}`,
148
+ ];
149
+ }
150
+ const errors = [];
151
+ if (document.metadataName !== expectedName) {
152
+ errors.push(`frontmatter.name must exactly match '${expectedName}'`);
153
+ }
154
+ if (!document.body) {
155
+ errors.push(`Kimi skill "${expectedName}" has an empty body.`);
156
+ }
157
+ return errors;
158
+ }
159
+ function tokenizeArgs(raw) {
160
+ const out = [];
161
+ let current = '';
162
+ let quote;
163
+ let hasContent = false;
164
+ for (const char of raw) {
165
+ if (quote !== undefined) {
166
+ if (char === quote) {
167
+ quote = undefined;
168
+ }
169
+ else {
170
+ current += char;
171
+ hasContent = true;
172
+ }
173
+ continue;
174
+ }
175
+ if (char === '"' || char === "'") {
176
+ quote = char;
177
+ hasContent = true;
178
+ continue;
179
+ }
180
+ if (/\s/.test(char)) {
181
+ if (hasContent) {
182
+ out.push(current);
183
+ current = '';
184
+ hasContent = false;
185
+ }
186
+ continue;
187
+ }
188
+ current += char;
189
+ hasContent = true;
190
+ }
191
+ if (hasContent)
192
+ out.push(current);
193
+ return out;
194
+ }
195
+ function regexpEscape(value) {
196
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
197
+ }
198
+ function escapeXmlTags(value) {
199
+ return value.replaceAll('<', '&lt;').replaceAll('>', '&gt;');
200
+ }
201
+ function escapeXml(value) {
202
+ return value
203
+ .replaceAll('&', '&amp;')
204
+ .replaceAll('<', '&lt;')
205
+ .replaceAll('>', '&gt;')
206
+ .replaceAll('"', '&quot;');
207
+ }
208
+ function expandSkillParameters(body, rawArgs, skillDir, argumentNames, sessionId) {
209
+ const tokens = tokenizeArgs(rawArgs);
210
+ let content = body;
211
+ for (let index = 0; index < argumentNames.length; index += 1) {
212
+ const escaped = regexpEscape(argumentNames[index]);
213
+ content = content.replace(new RegExp(`\\$${escaped}(?![\\[\\w])`, 'g'), escapeXmlTags(tokens[index] ?? ''));
214
+ }
215
+ content = content
216
+ .replace(/\$ARGUMENTS\[(\d+)\]/g, (_match, indexText) => escapeXmlTags(tokens[Number.parseInt(indexText, 10)] ?? ''))
217
+ .replace(/\$(\d+)(?!\w)/g, (_match, indexText) => escapeXmlTags(tokens[Number.parseInt(indexText, 10)] ?? ''))
218
+ .replaceAll('$ARGUMENTS', escapeXmlTags(rawArgs));
219
+ const hasArgumentPlaceholder = content !== body;
220
+ content = content
221
+ .replaceAll('${KIMI_SKILL_DIR}', skillDir)
222
+ .replaceAll('${KIMI_SESSION_ID}', sessionId ?? '');
223
+ if (!hasArgumentPlaceholder && rawArgs.length > 0) {
224
+ return `${content}\n\nARGUMENTS: ${escapeXmlTags(rawArgs)}`;
225
+ }
226
+ return content;
227
+ }
228
+ function toKimiPath(nativePath) {
229
+ const slashPath = nativePath.replaceAll('\\', '/');
230
+ return /^[a-z]:\//.test(slashPath)
231
+ ? slashPath[0].toUpperCase() + slashPath.slice(1)
232
+ : slashPath;
233
+ }
234
+ function loadProjectSkill(cwd, requestedName) {
235
+ const skillsRoot = node_path_1.default.resolve(cwd, '.kimi-code', 'skills');
236
+ const directDir = node_path_1.default.join(skillsRoot, requestedName);
237
+ let directError;
238
+ let mismatchedDirectName;
239
+ const loadCandidate = (skillDir) => {
240
+ const skillPath = node_path_1.default.join(skillDir, 'SKILL.md');
241
+ if (!(0, node_fs_1.existsSync)(skillPath))
242
+ return null;
243
+ try {
244
+ const document = parseKimiSkillDocument((0, node_fs_1.readFileSync)(skillPath, 'utf8'), skillPath);
245
+ if (document.metadataName.toLowerCase() === requestedName.toLowerCase()) {
246
+ // Kimi resolves each discovered skill root through fs.realpath before
247
+ // parsing SKILL.md. Match that behavior so `${KIMI_SKILL_DIR}` and the
248
+ // activation envelope are identical for Desktop framework symlinks.
249
+ return { document, skillDir: toKimiPath((0, node_fs_1.realpathSync)(skillDir)) };
250
+ }
251
+ if (skillDir === directDir)
252
+ mismatchedDirectName = document.metadataName;
253
+ }
254
+ catch (error) {
255
+ // Kimi discovery skips unrelated malformed entries. Preserve the exact
256
+ // direct candidate error so the requested broken skill remains
257
+ // actionable instead of being reported as generically missing.
258
+ if (skillDir === directDir) {
259
+ directError = error instanceof Error ? error : new Error(String(error));
260
+ }
261
+ }
262
+ return null;
263
+ };
264
+ const direct = loadCandidate(directDir);
265
+ if (direct)
266
+ return direct;
267
+ if ((0, node_fs_1.existsSync)(skillsRoot)) {
268
+ let entries;
269
+ try {
270
+ entries = (0, node_fs_1.readdirSync)(skillsRoot, { withFileTypes: true });
271
+ }
272
+ catch (error) {
273
+ throw new KimiSkillResolutionError(`Cannot scan Kimi skills at ${skillsRoot}: ` +
274
+ (error instanceof Error ? error.message : String(error)));
275
+ }
276
+ for (const entry of entries) {
277
+ if (!entry.isDirectory() && !entry.isSymbolicLink())
278
+ continue;
279
+ const candidate = node_path_1.default.join(skillsRoot, entry.name);
280
+ if (candidate === directDir)
281
+ continue;
282
+ const resolved = loadCandidate(candidate);
283
+ if (resolved)
284
+ return resolved;
285
+ }
286
+ }
287
+ if (directError)
288
+ throw directError;
289
+ if (mismatchedDirectName) {
290
+ throw new KimiSkillResolutionError(`Kimi skill directory "${requestedName}" declares name "${mismatchedDirectName}".`);
291
+ }
292
+ throw new KimiSkillResolutionError(`Kimi skill "${requestedName}" is not installed under ${skillsRoot}. ` +
293
+ 'Run the SpecRails Core update for provider "kimi" before retrying.');
294
+ }
295
+ /**
296
+ * Resolve a provider/Core slash invocation into the same user-activated-skill
297
+ * prompt shape used by Kimi 0.27's `Session.activateSkill()` path.
298
+ */
299
+ function formatKimiCoreCommand(command, cwd, sessionId) {
300
+ const invocation = parseInvocation(command);
301
+ if (!invocation)
302
+ return command;
303
+ if (!cwd) {
304
+ throw new KimiSkillResolutionError(`Cannot resolve Kimi skill "${invocation.skillName}" without a project working directory.`);
305
+ }
306
+ const { document, skillDir } = loadProjectSkill(cwd, invocation.skillName);
307
+ if (!document.body) {
308
+ throw new KimiSkillResolutionError(`Kimi skill "${invocation.skillName}" has an empty body.`);
309
+ }
310
+ const effectiveSessionId = sessionId?.trim() || undefined;
311
+ if (document.body.includes('${KIMI_SESSION_ID}') && !effectiveSessionId) {
312
+ throw new KimiSkillResolutionError(`Kimi skill "${document.metadataName}" requires \${KIMI_SESSION_ID}, ` +
313
+ 'which is unavailable before a fresh `kimi -p` session emits its resume hint.');
314
+ }
315
+ const renderedName = document.metadataName;
316
+ const skillContent = expandSkillParameters(document.body, invocation.rawArgs, skillDir, document.argumentNames, effectiveSessionId);
317
+ return [
318
+ `User activated the skill "${escapeXml(renderedName)}". Follow the loaded skill instructions.`,
319
+ '',
320
+ `<kimi-skill-loaded name="${escapeXml(renderedName)}" trigger="user-slash" source="project" ` +
321
+ `dir="${escapeXml(skillDir)}" args="${escapeXml(invocation.rawArgs)}">`,
322
+ skillContent,
323
+ '</kimi-skill-loaded>',
324
+ ].join('\n');
325
+ }
326
+ exports._test = {
327
+ parseInvocation,
328
+ parseSkillDocument: parseKimiSkillDocument,
329
+ expandSkillParameters,
330
+ tokenizeArgs,
331
+ toKimiPath,
332
+ };