specrails-desktop 2.0.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 (455) hide show
  1. package/.claude/commands/specrails/batch-implement.md +287 -0
  2. package/.claude/commands/specrails/compat-check.md +271 -0
  3. package/.claude/commands/specrails/doctor.md +62 -0
  4. package/.claude/commands/specrails/enrich.md +1635 -0
  5. package/.claude/commands/specrails/explore-spec.md +173 -0
  6. package/.claude/commands/specrails/health-check.md +527 -0
  7. package/.claude/commands/specrails/implement.md +1457 -0
  8. package/.claude/commands/specrails/memory-inspect.md +259 -0
  9. package/.claude/commands/specrails/opsx-diff.md +419 -0
  10. package/.claude/commands/specrails/propose-spec.md +102 -0
  11. package/.claude/commands/specrails/reconfig.md +89 -0
  12. package/.claude/commands/specrails/refactor-recommender.md +212 -0
  13. package/.claude/commands/specrails/retry.md +363 -0
  14. package/.claude/commands/specrails/telemetry.md +552 -0
  15. package/.claude/commands/specrails/why.md +96 -0
  16. package/LICENSE +21 -0
  17. package/README.md +290 -0
  18. package/cli/dist/specrails-desktop.js +1098 -0
  19. package/client/dist/assets/ActivityFeedPage-Gy4x8dBt.js +1 -0
  20. package/client/dist/assets/AgentsPage-CPgu--Fb.js +86 -0
  21. package/client/dist/assets/AnalyticsPage-B5sJEee2.js +1 -0
  22. package/client/dist/assets/BarChart-7IMQ8HY1.js +33 -0
  23. package/client/dist/assets/CodePage-CBdFvbwe.js +2 -0
  24. package/client/dist/assets/DesktopAnalyticsPage-w0rdTq4w.js +1 -0
  25. package/client/dist/assets/DocsDialog-BZUYM7wm.js +11 -0
  26. package/client/dist/assets/DocsPage-9QglWl46.js +11 -0
  27. package/client/dist/assets/ExportDropdown-BLZFXtNi.js +1 -0
  28. package/client/dist/assets/IntegrationsPage-BxBE4y99.js +3 -0
  29. package/client/dist/assets/JobDetailPage-DydWx_5S.js +16 -0
  30. package/client/dist/assets/JobsPage-20ibw0IO.js +1 -0
  31. package/client/dist/assets/abap-Bw6f2wDG.js +1 -0
  32. package/client/dist/assets/activity-BEIp_Y1A.js +1 -0
  33. package/client/dist/assets/activity-BdrPln96.js +1 -0
  34. package/client/dist/assets/activity-CpkRS8Sx.js +1 -0
  35. package/client/dist/assets/activity-DKCpESPt.js +1 -0
  36. package/client/dist/assets/activity-DOUVEjJi.js +1 -0
  37. package/client/dist/assets/activity-DRwkql_y.js +1 -0
  38. package/client/dist/assets/activity-DcDQ7tjw.js +1 -0
  39. package/client/dist/assets/activity-Dv6H7wEr.js +1 -0
  40. package/client/dist/assets/addon-image-3WCl5Vhd.js +1 -0
  41. package/client/dist/assets/addon-ligatures-C5OdliKs.js +2 -0
  42. package/client/dist/assets/addon-webgl-BbX6pSjl.js +44 -0
  43. package/client/dist/assets/addspec-B5yl4Loj.js +1 -0
  44. package/client/dist/assets/addspec-BEeF5-zc.js +1 -0
  45. package/client/dist/assets/addspec-D33ocMxf.js +1 -0
  46. package/client/dist/assets/addspec-DFswZ0jK.js +1 -0
  47. package/client/dist/assets/addspec-DRE-jZv7.js +1 -0
  48. package/client/dist/assets/addspec-DVZ15Jp8.js +1 -0
  49. package/client/dist/assets/addspec-Fkv91Opc.js +1 -0
  50. package/client/dist/assets/addspec-GWm4ffKl.js +1 -0
  51. package/client/dist/assets/agents-1nCDWRmP.js +1 -0
  52. package/client/dist/assets/agents-Bm9rPqnt.js +1 -0
  53. package/client/dist/assets/agents-CMxtJMLD.js +1 -0
  54. package/client/dist/assets/agents-DK-Dlc0i.js +1 -0
  55. package/client/dist/assets/agents-Q6Ldfpxx.js +1 -0
  56. package/client/dist/assets/agents-TeOSy-ax.js +1 -0
  57. package/client/dist/assets/agents-iTqjRajS.js +1 -0
  58. package/client/dist/assets/agents-s87sMGzL.js +1 -0
  59. package/client/dist/assets/agentstudio-B6Wb59E7.js +1 -0
  60. package/client/dist/assets/agentstudio-BADhZ41e.js +1 -0
  61. package/client/dist/assets/agentstudio-BSnWLR63.js +1 -0
  62. package/client/dist/assets/agentstudio-BdidyBzZ.js +1 -0
  63. package/client/dist/assets/agentstudio-CxlUllqI.js +1 -0
  64. package/client/dist/assets/agentstudio-D3I62TLJ.js +1 -0
  65. package/client/dist/assets/agentstudio-DuH9TogZ.js +1 -0
  66. package/client/dist/assets/agentstudio-Kw88_dUF.js +1 -0
  67. package/client/dist/assets/aiedit-BWxHGsYA.js +1 -0
  68. package/client/dist/assets/aiedit-D2ji6Qy0.js +1 -0
  69. package/client/dist/assets/aiedit-DAhZTvtk.js +1 -0
  70. package/client/dist/assets/aiedit-DJMny-D5.js +1 -0
  71. package/client/dist/assets/aiedit-DOcxERkU.js +1 -0
  72. package/client/dist/assets/aiedit-DvrcbwGv.js +1 -0
  73. package/client/dist/assets/aiedit-TTwzL1TS.js +1 -0
  74. package/client/dist/assets/aiedit-WBSjT_C1.js +1 -0
  75. package/client/dist/assets/analytics-BIdr0YfL.js +1 -0
  76. package/client/dist/assets/analytics-C6EzgtdE.js +1 -0
  77. package/client/dist/assets/analytics-C9Zc-rkM.js +1 -0
  78. package/client/dist/assets/analytics-CVx3YOc0.js +1 -0
  79. package/client/dist/assets/analytics-CYj0tfj7.js +1 -0
  80. package/client/dist/assets/analytics-CnY4kNG3.js +1 -0
  81. package/client/dist/assets/analytics-CrPCZRJ-.js +1 -0
  82. package/client/dist/assets/analytics-DMCto-TF.js +1 -0
  83. package/client/dist/assets/apex-Cw8_REBo.js +1 -0
  84. package/client/dist/assets/atom-one-dark-B-oHczHB.css +1 -0
  85. package/client/dist/assets/attachments-BIsSSnHJ.js +1 -0
  86. package/client/dist/assets/attachments-BW4L3l2L.js +1 -0
  87. package/client/dist/assets/attachments-Bcf6BG6V.js +1 -0
  88. package/client/dist/assets/attachments-Bke8sCU4.js +1 -0
  89. package/client/dist/assets/attachments-COcrGRFz.js +1 -0
  90. package/client/dist/assets/attachments-DYHGA2Dj.js +1 -0
  91. package/client/dist/assets/attachments-Dd92KpUH.js +1 -0
  92. package/client/dist/assets/attachments-DzdU6DV6.js +1 -0
  93. package/client/dist/assets/azcli-Cz6HAoOw.js +1 -0
  94. package/client/dist/assets/bat-CcJ-xyqL.js +1 -0
  95. package/client/dist/assets/bicep-z1WDCKYz.js +2 -0
  96. package/client/dist/assets/browser-5ErDlJoR.js +1 -0
  97. package/client/dist/assets/browser-Bc-YdlVg.js +1 -0
  98. package/client/dist/assets/browser-BlYF4OOq.js +1 -0
  99. package/client/dist/assets/browser-CT-ReZGt.js +1 -0
  100. package/client/dist/assets/browser-DGITz3fC.js +1 -0
  101. package/client/dist/assets/browser-JsAIGCEW.js +1 -0
  102. package/client/dist/assets/browser-M5-rbPlw.js +1 -0
  103. package/client/dist/assets/browser-Qya9cARy.js +1 -0
  104. package/client/dist/assets/cameligo-BRewOpfa.js +1 -0
  105. package/client/dist/assets/chat-BEGuC03z.js +1 -0
  106. package/client/dist/assets/chat-BEW60P_u.js +1 -0
  107. package/client/dist/assets/chat-BQNMD0PL.js +1 -0
  108. package/client/dist/assets/chat-BsbNGPW9.js +1 -0
  109. package/client/dist/assets/chat-CboQguCi.js +1 -0
  110. package/client/dist/assets/chat-DRCa9pOt.js +1 -0
  111. package/client/dist/assets/chat-DwUm6W9z.js +1 -0
  112. package/client/dist/assets/chat-yoXwguQu.js +1 -0
  113. package/client/dist/assets/chunk-CilyBKbf.js +1 -0
  114. package/client/dist/assets/clojure-DBjRWN6g.js +1 -0
  115. package/client/dist/assets/clsx-DnqN-uhr.js +1 -0
  116. package/client/dist/assets/code-AL1rVIMb.js +1 -0
  117. package/client/dist/assets/code-C0BKpkht.js +1 -0
  118. package/client/dist/assets/code-C0FTS3ew.js +1 -0
  119. package/client/dist/assets/code-CPcHxzxw.js +1 -0
  120. package/client/dist/assets/code-D3ryDniw.js +1 -0
  121. package/client/dist/assets/code-D3zVVQTj.js +1 -0
  122. package/client/dist/assets/code-PCmfS3dn.js +1 -0
  123. package/client/dist/assets/code-exI0G5Wd.js +1 -0
  124. package/client/dist/assets/codicon-ngg6Pgfi.ttf +0 -0
  125. package/client/dist/assets/coffee-Cfk_XHGR.js +1 -0
  126. package/client/dist/assets/commands-B772IyDa.js +1 -0
  127. package/client/dist/assets/commands-BDDp6xFG.js +1 -0
  128. package/client/dist/assets/commands-CJxCry-o.js +1 -0
  129. package/client/dist/assets/commands-CfgY-_of.js +1 -0
  130. package/client/dist/assets/commands-DLrvnPNg.js +1 -0
  131. package/client/dist/assets/commands-IXMOKBYt.js +1 -0
  132. package/client/dist/assets/commands-UD1NzmwX.js +1 -0
  133. package/client/dist/assets/commands-sqrqsxyE.js +1 -0
  134. package/client/dist/assets/common-DCr6VzJ7.js +1 -0
  135. package/client/dist/assets/common-Dard9UNH.js +1 -0
  136. package/client/dist/assets/common-DeDELLZJ.js +1 -0
  137. package/client/dist/assets/common-DltqHaAe.js +1 -0
  138. package/client/dist/assets/common-Dmm1GhdD.js +1 -0
  139. package/client/dist/assets/common-DnjcgkPH.js +1 -0
  140. package/client/dist/assets/common-GbpxfPG8.js +1 -0
  141. package/client/dist/assets/common-wA36jmj1.js +1 -0
  142. package/client/dist/assets/cpp-BVob6BaP.js +1 -0
  143. package/client/dist/assets/csharp-C4fbRuOu.js +1 -0
  144. package/client/dist/assets/csp-DthFP_vT.js +1 -0
  145. package/client/dist/assets/css-CGMH0hcW.js +3 -0
  146. package/client/dist/assets/css.worker-Wv5dxAWO.js +89 -0
  147. package/client/dist/assets/cssMode-Cc6ozl-J.js +1 -0
  148. package/client/dist/assets/cypher-Pnf68BRV.js +1 -0
  149. package/client/dist/assets/dart-PMMOtxZX.js +1 -0
  150. package/client/dist/assets/dashboard-B4ixDVk8.js +1 -0
  151. package/client/dist/assets/dashboard-BZBADHSj.js +1 -0
  152. package/client/dist/assets/dashboard-C1MfeUHs.js +1 -0
  153. package/client/dist/assets/dashboard-C7SK6xu5.js +1 -0
  154. package/client/dist/assets/dashboard-CB6Le1yN.js +1 -0
  155. package/client/dist/assets/dashboard-CoTpMOBM.js +1 -0
  156. package/client/dist/assets/dashboard-Duo4DDCW.js +1 -0
  157. package/client/dist/assets/dashboard-I19DXBxw.js +1 -0
  158. package/client/dist/assets/dist-js-BY-Fv_fg.js +1 -0
  159. package/client/dist/assets/dist-js-Bakc4uxT.js +1 -0
  160. package/client/dist/assets/dockerfile-di1nsJCc.js +1 -0
  161. package/client/dist/assets/ecl-D_WVcB5M.js +1 -0
  162. package/client/dist/assets/editor-Br_kD0ds.css +1 -0
  163. package/client/dist/assets/editor.api2-XLGzZfbc.js +872 -0
  164. package/client/dist/assets/editor.main-CfXxHimg.js +6 -0
  165. package/client/dist/assets/editor.worker-Bd9IXS8d.js +26 -0
  166. package/client/dist/assets/elixir-OAdJEMOn.js +1 -0
  167. package/client/dist/assets/explore-4mFpnrKU.js +1 -0
  168. package/client/dist/assets/explore-A8Ltoblq.js +1 -0
  169. package/client/dist/assets/explore-B9A3iN2W.js +1 -0
  170. package/client/dist/assets/explore-BV5Xxlsn.js +1 -0
  171. package/client/dist/assets/explore-BrBJvfjP.js +1 -0
  172. package/client/dist/assets/explore-C3FSE42C.js +1 -0
  173. package/client/dist/assets/explore-D2EFgt8J.js +1 -0
  174. package/client/dist/assets/explore-hFc3HFcp.js +1 -0
  175. package/client/dist/assets/flow9-D3QEZjgn.js +1 -0
  176. package/client/dist/assets/format-command-CwGuwzGA.js +1 -0
  177. package/client/dist/assets/freemarker2-DP7J1gG3.js +3 -0
  178. package/client/dist/assets/fsharp-BF0k_8N8.js +1 -0
  179. package/client/dist/assets/go-BAQO5Jsz.js +1 -0
  180. package/client/dist/assets/graphql-hdFVFkiV.js +1 -0
  181. package/client/dist/assets/handlebars-BjRlucw6.js +1 -0
  182. package/client/dist/assets/hcl-DWnl1o-X.js +1 -0
  183. package/client/dist/assets/html-OumBQJ-U.js +1 -0
  184. package/client/dist/assets/html.worker-CQP8QQsS.js +502 -0
  185. package/client/dist/assets/htmlMode-CStc3zXM.js +1 -0
  186. package/client/dist/assets/index-CimDRRi7.css +2 -0
  187. package/client/dist/assets/index-XGZaKl_u.js +142 -0
  188. package/client/dist/assets/ini-CB-6OVu3.js +1 -0
  189. package/client/dist/assets/integrations-C3p12Ms6.js +1 -0
  190. package/client/dist/assets/integrations-Cr6hH7XR.js +1 -0
  191. package/client/dist/assets/integrations-Cublz3m6.js +1 -0
  192. package/client/dist/assets/integrations-D28q1kF6.js +1 -0
  193. package/client/dist/assets/integrations-DRdbki5W.js +1 -0
  194. package/client/dist/assets/integrations-DaC4SzzL.js +1 -0
  195. package/client/dist/assets/integrations-DmQYCUvN.js +1 -0
  196. package/client/dist/assets/integrations-HIlUxXVs.js +1 -0
  197. package/client/dist/assets/java-d1CmfiHX.js +1 -0
  198. package/client/dist/assets/javascript-CMk--e7g.js +1 -0
  199. package/client/dist/assets/jobs-BE1siB0M.js +1 -0
  200. package/client/dist/assets/jobs-BHcQ_Faf.js +1 -0
  201. package/client/dist/assets/jobs-CFfc2dNX.js +1 -0
  202. package/client/dist/assets/jobs-CSi5n8X_.js +1 -0
  203. package/client/dist/assets/jobs-Dc3X86PY.js +1 -0
  204. package/client/dist/assets/jobs-De5tASex.js +1 -0
  205. package/client/dist/assets/jobs-DsoXEdo7.js +1 -0
  206. package/client/dist/assets/jobs-Wl-ApPMb.js +1 -0
  207. package/client/dist/assets/json.worker-DzV-CpCQ.js +58 -0
  208. package/client/dist/assets/jsonMode-C2h3ZcjZ.js +7 -0
  209. package/client/dist/assets/julia-Bgv08lKa.js +1 -0
  210. package/client/dist/assets/kotlin-u98kaVTf.js +1 -0
  211. package/client/dist/assets/less-CjYwpgg5.js +2 -0
  212. package/client/dist/assets/lexon-YTjaAFBB.js +1 -0
  213. package/client/dist/assets/lib-CPxTMOAq.js +7 -0
  214. package/client/dist/assets/liquid-mI3KJrBE.js +1 -0
  215. package/client/dist/assets/lspLanguageFeatures-DU09ggWi.js +4 -0
  216. package/client/dist/assets/lua-BzmkWv27.js +1 -0
  217. package/client/dist/assets/m3-CFwk9fw0.js +1 -0
  218. package/client/dist/assets/markdown-CR5iMpSZ.js +1 -0
  219. package/client/dist/assets/mdx-C41VDTR_.js +1 -0
  220. package/client/dist/assets/mips-CcEalc17.js +1 -0
  221. package/client/dist/assets/monaco.contribution-CPObAXMC.js +2 -0
  222. package/client/dist/assets/msdax-BQbkawnr.js +1 -0
  223. package/client/dist/assets/mysql-GTlaaW_P.js +1 -0
  224. package/client/dist/assets/nav-0fwkrgHt.js +1 -0
  225. package/client/dist/assets/nav-BEL3MTwK.js +1 -0
  226. package/client/dist/assets/nav-B_G-TJDW.js +1 -0
  227. package/client/dist/assets/nav-C2YXcbZS.js +1 -0
  228. package/client/dist/assets/nav-ClzOE4mA.js +1 -0
  229. package/client/dist/assets/nav-CtYwmMgu.js +1 -0
  230. package/client/dist/assets/nav-D2bOGSEg.js +1 -0
  231. package/client/dist/assets/nav-iH1V5j6o.js +1 -0
  232. package/client/dist/assets/objective-c-Byu1T5if.js +1 -0
  233. package/client/dist/assets/pascal-BrfzBfRm.js +1 -0
  234. package/client/dist/assets/pascaligo-BXXKFUeo.js +1 -0
  235. package/client/dist/assets/perl-B3OikKq-.js +1 -0
  236. package/client/dist/assets/pgsql-CTsa0Acc.js +1 -0
  237. package/client/dist/assets/php-DiQh3FUW.js +1 -0
  238. package/client/dist/assets/pla-92uH8Fzm.js +1 -0
  239. package/client/dist/assets/postiats-BbeWkKUr.js +1 -0
  240. package/client/dist/assets/powerquery-DgDMzpsm.js +1 -0
  241. package/client/dist/assets/powershell-BfdUUzaG.js +1 -0
  242. package/client/dist/assets/preload-helper-DSXbuxSR.js +1 -0
  243. package/client/dist/assets/protobuf-BojW2ftW.js +2 -0
  244. package/client/dist/assets/pug-BxqTg3IU.js +1 -0
  245. package/client/dist/assets/python-Y27rKQtk.js +1 -0
  246. package/client/dist/assets/qsharp-BX_A-MW9.js +1 -0
  247. package/client/dist/assets/r-D9BMnxvJ.js +1 -0
  248. package/client/dist/assets/razor-Cd5-q9Bp.js +1 -0
  249. package/client/dist/assets/redis-5cJqEQJJ.js +1 -0
  250. package/client/dist/assets/redshift-d8BBqiwb.js +1 -0
  251. package/client/dist/assets/restructuredtext-C8a6yIcZ.js +1 -0
  252. package/client/dist/assets/ruby-egeh-6KX.js +1 -0
  253. package/client/dist/assets/rust-a3r9IInB.js +1 -0
  254. package/client/dist/assets/sb-y8iRIDei.js +1 -0
  255. package/client/dist/assets/scala-BPDK2AmK.js +1 -0
  256. package/client/dist/assets/scheme-BIWUEoOs.js +1 -0
  257. package/client/dist/assets/scss-CA-PSzwg.js +3 -0
  258. package/client/dist/assets/settings-55oDcbSh.js +1 -0
  259. package/client/dist/assets/settings-Bd4Tq1RB.js +1 -0
  260. package/client/dist/assets/settings-CCSM-Fhn.js +1 -0
  261. package/client/dist/assets/settings-D3e_bDoW.js +1 -0
  262. package/client/dist/assets/settings-DKbTkbn7.js +1 -0
  263. package/client/dist/assets/settings-Dxpo6_w7.js +1 -0
  264. package/client/dist/assets/settings-bt84e3Aa.js +1 -0
  265. package/client/dist/assets/settings-nu68QukM.js +1 -0
  266. package/client/dist/assets/setup-BMqwfbW9.js +1 -0
  267. package/client/dist/assets/setup-Bb5LcG28.js +1 -0
  268. package/client/dist/assets/setup-BeEx2_da.js +1 -0
  269. package/client/dist/assets/setup-CCCrB53Q.js +1 -0
  270. package/client/dist/assets/setup-CJA0ATmd.js +1 -0
  271. package/client/dist/assets/setup-CeiDbZcb.js +1 -0
  272. package/client/dist/assets/setup-Cus7TApA.js +1 -0
  273. package/client/dist/assets/setup-D9qOs2Xo.js +1 -0
  274. package/client/dist/assets/shell--LiT1Bja.js +1 -0
  275. package/client/dist/assets/solidity-DdqZccZg.js +1 -0
  276. package/client/dist/assets/sophia-S6-YxNG_.js +1 -0
  277. package/client/dist/assets/sparql-BSf5kMp2.js +1 -0
  278. package/client/dist/assets/specs-BFfu3u-a.js +1 -0
  279. package/client/dist/assets/specs-B__C8-8a.js +1 -0
  280. package/client/dist/assets/specs-CZ1PsXsC.js +1 -0
  281. package/client/dist/assets/specs-D2FzlLn9.js +1 -0
  282. package/client/dist/assets/specs-DaUTrNF9.js +1 -0
  283. package/client/dist/assets/specs-Dyc5hYeE.js +1 -0
  284. package/client/dist/assets/specs-cKEh2LXt.js +1 -0
  285. package/client/dist/assets/specs-k0PyLDVt.js +1 -0
  286. package/client/dist/assets/sql-D7KgjR8G.js +1 -0
  287. package/client/dist/assets/st-BnoDa-Ml.js +1 -0
  288. package/client/dist/assets/swift-DEUHTkUX.js +1 -0
  289. package/client/dist/assets/systemverilog-Tqb_KPnW.js +1 -0
  290. package/client/dist/assets/tcl-BmBFS2qq.js +1 -0
  291. package/client/dist/assets/terminal-80yDMgMF.js +1 -0
  292. package/client/dist/assets/terminal-Bje4ziIa.js +1 -0
  293. package/client/dist/assets/terminal-C2WYcFHF.js +1 -0
  294. package/client/dist/assets/terminal-CSONJOex.js +1 -0
  295. package/client/dist/assets/terminal-DEqzGtcr.js +1 -0
  296. package/client/dist/assets/terminal-DeWzh6ys.js +1 -0
  297. package/client/dist/assets/terminal-YOlsJCQj.js +1 -0
  298. package/client/dist/assets/terminal-lkZYR4wJ.js +1 -0
  299. package/client/dist/assets/tickets-CB7N30gm.js +1 -0
  300. package/client/dist/assets/tickets-CF2PYelu.js +1 -0
  301. package/client/dist/assets/tickets-DNOANUXr.js +1 -0
  302. package/client/dist/assets/tickets-DU1aqsbr.js +1 -0
  303. package/client/dist/assets/tickets-DYvafSaY.js +1 -0
  304. package/client/dist/assets/tickets-DlpC_iTg.js +1 -0
  305. package/client/dist/assets/tickets-DucYgtdl.js +1 -0
  306. package/client/dist/assets/tickets-clefmXLv.js +1 -0
  307. package/client/dist/assets/ts.worker-METxwbDZ.js +67719 -0
  308. package/client/dist/assets/tsMode-B0y_xEci.js +11 -0
  309. package/client/dist/assets/twig-BQV8igWC.js +1 -0
  310. package/client/dist/assets/typescript-BzK0OgwW.js +1 -0
  311. package/client/dist/assets/typespec-DlFroUGY.js +1 -0
  312. package/client/dist/assets/useProjectCache-DSaiGFjV.js +1 -0
  313. package/client/dist/assets/vb-BlrJpIMX.js +1 -0
  314. package/client/dist/assets/wgsl-BWgIc6FZ.js +298 -0
  315. package/client/dist/assets/workers-rt--R2Qy.js +1 -0
  316. package/client/dist/assets/xml-eX9QXAmI.js +1 -0
  317. package/client/dist/assets/yaml-fcsNkpOt.js +1 -0
  318. package/client/dist/index.html +246 -0
  319. package/docs/README.md +54 -0
  320. package/docs/cli.md +198 -0
  321. package/docs/codex.md +210 -0
  322. package/docs/creating-specs.md +197 -0
  323. package/docs/customizing.md +197 -0
  324. package/docs/getting-started.md +140 -0
  325. package/docs/internals/README.md +25 -0
  326. package/docs/internals/adding-a-provider.md +238 -0
  327. package/docs/internals/api-reference.md +634 -0
  328. package/docs/internals/architecture.md +332 -0
  329. package/docs/internals/configuration.md +172 -0
  330. package/docs/internals/openspec-workflow.md +282 -0
  331. package/docs/internals/operations-runbook.md +198 -0
  332. package/docs/internals/profiles.md +152 -0
  333. package/docs/platforms/macos.md +130 -0
  334. package/docs/platforms/windows.md +81 -0
  335. package/docs/running-pipelines.md +240 -0
  336. package/docs/terminal.md +138 -0
  337. package/docs/tracking-cost.md +155 -0
  338. package/package.json +82 -0
  339. package/server/dist/agent-generator.js +232 -0
  340. package/server/dist/agent-refine-db.js +124 -0
  341. package/server/dist/agent-refine-manager.js +526 -0
  342. package/server/dist/ai-invocations.js +111 -0
  343. package/server/dist/attachment-manager.js +299 -0
  344. package/server/dist/auth.js +207 -0
  345. package/server/dist/binary-probe.js +35 -0
  346. package/server/dist/browser-capture-manager.js +576 -0
  347. package/server/dist/browser-capture-types.js +28 -0
  348. package/server/dist/browser-network.js +149 -0
  349. package/server/dist/browser-playwright.js +888 -0
  350. package/server/dist/build-dirs.js +44 -0
  351. package/server/dist/changes-reader.js +120 -0
  352. package/server/dist/chat-manager.js +1060 -0
  353. package/server/dist/chromium-resolver.js +311 -0
  354. package/server/dist/code-explorer-router.js +788 -0
  355. package/server/dist/codex-otel-bridge.js +235 -0
  356. package/server/dist/command-resolver.js +102 -0
  357. package/server/dist/config.js +306 -0
  358. package/server/dist/context-budget.js +113 -0
  359. package/server/dist/context-scope.js +279 -0
  360. package/server/dist/contract-refine-runner.js +521 -0
  361. package/server/dist/core-compat.js +207 -0
  362. package/server/dist/core-package.js +14 -0
  363. package/server/dist/db.js +1034 -0
  364. package/server/dist/desktop-analytics.js +156 -0
  365. package/server/dist/desktop-db.js +456 -0
  366. package/server/dist/desktop-router.js +735 -0
  367. package/server/dist/docs-router.js +207 -0
  368. package/server/dist/explore-contract-refine.js +421 -0
  369. package/server/dist/explore-cwd-manager.js +242 -0
  370. package/server/dist/explore-draft-title.js +47 -0
  371. package/server/dist/explore-smash.js +450 -0
  372. package/server/dist/feature-flags.js +17 -0
  373. package/server/dist/file-provenance.js +382 -0
  374. package/server/dist/file-summary-generator.js +221 -0
  375. package/server/dist/file-summary-manager.js +689 -0
  376. package/server/dist/hooks.js +102 -0
  377. package/server/dist/ids.js +7 -0
  378. package/server/dist/index.js +586 -0
  379. package/server/dist/metrics.js +136 -0
  380. package/server/dist/mobile/index.js +16 -0
  381. package/server/dist/mobile/mobile-admin-router.js +84 -0
  382. package/server/dist/mobile/mobile-auth.js +67 -0
  383. package/server/dist/mobile/mobile-devices.js +80 -0
  384. package/server/dist/mobile/mobile-event-bus.js +39 -0
  385. package/server/dist/mobile/mobile-gateway.js +285 -0
  386. package/server/dist/mobile/mobile-mdns.js +81 -0
  387. package/server/dist/mobile/mobile-pairing.js +179 -0
  388. package/server/dist/mobile/mobile-redact.js +53 -0
  389. package/server/dist/mobile/mobile-router.js +411 -0
  390. package/server/dist/mobile/mobile-tls.js +86 -0
  391. package/server/dist/mobile/mobile-types.js +9 -0
  392. package/server/dist/mobile/mobile-ws.js +275 -0
  393. package/server/dist/path-resolver.js +298 -0
  394. package/server/dist/plugin-manager.js +617 -0
  395. package/server/dist/plugins/claude-approval.js +179 -0
  396. package/server/dist/plugins/claude-md-mutation.js +146 -0
  397. package/server/dist/plugins/codex-mcp.js +108 -0
  398. package/server/dist/plugins/contributors.js +72 -0
  399. package/server/dist/plugins/drift.js +58 -0
  400. package/server/dist/plugins/index.js +14 -0
  401. package/server/dist/plugins/json-mutation.js +120 -0
  402. package/server/dist/plugins/manager.js +32 -0
  403. package/server/dist/plugins/ownership.js +86 -0
  404. package/server/dist/plugins/paths.js +37 -0
  405. package/server/dist/plugins/prereq-installer.js +104 -0
  406. package/server/dist/plugins/rail-integration.js +79 -0
  407. package/server/dist/plugins/serena/index.js +13 -0
  408. package/server/dist/plugins/serena/install.js +91 -0
  409. package/server/dist/plugins/serena/instructions-content.js +21 -0
  410. package/server/dist/plugins/serena/manifest.js +111 -0
  411. package/server/dist/plugins/serena/verify.js +78 -0
  412. package/server/dist/plugins-router.js +215 -0
  413. package/server/dist/pricing.js +89 -0
  414. package/server/dist/profile-manager.js +310 -0
  415. package/server/dist/profiles-router.js +759 -0
  416. package/server/dist/project-registry.js +443 -0
  417. package/server/dist/project-router.js +4016 -0
  418. package/server/dist/proposal-manager.js +291 -0
  419. package/server/dist/provider-selection.js +69 -0
  420. package/server/dist/providers/claude-adapter.js +281 -0
  421. package/server/dist/providers/codex-adapter.js +264 -0
  422. package/server/dist/providers/index.js +23 -0
  423. package/server/dist/providers/registry.js +37 -0
  424. package/server/dist/providers/types.js +22 -0
  425. package/server/dist/queue-manager.js +1511 -0
  426. package/server/dist/rails-router.js +362 -0
  427. package/server/dist/rails-store.js +116 -0
  428. package/server/dist/result-event.js +106 -0
  429. package/server/dist/schemas/profile.v1.json +151 -0
  430. package/server/dist/setup-manager.js +1165 -0
  431. package/server/dist/setup-prerequisites.js +372 -0
  432. package/server/dist/smash-runner.js +663 -0
  433. package/server/dist/spec-draft-parser.js +133 -0
  434. package/server/dist/spec-launcher-manager.js +174 -0
  435. package/server/dist/spec-models.js +32 -0
  436. package/server/dist/specrails-tech-client.js +82 -0
  437. package/server/dist/spending.js +448 -0
  438. package/server/dist/telemetry-compactor.js +180 -0
  439. package/server/dist/telemetry-export.js +317 -0
  440. package/server/dist/telemetry-receiver.js +224 -0
  441. package/server/dist/terminal-manager.js +633 -0
  442. package/server/dist/terminal-marks-store.js +117 -0
  443. package/server/dist/terminal-osc-parser.js +159 -0
  444. package/server/dist/terminal-settings.js +282 -0
  445. package/server/dist/terminal-shell-integration.js +196 -0
  446. package/server/dist/ticket-broadcast.js +47 -0
  447. package/server/dist/ticket-store.js +397 -0
  448. package/server/dist/ticket-watcher.js +117 -0
  449. package/server/dist/types.js +10 -0
  450. package/server/dist/user-mcp-config.js +117 -0
  451. package/server/dist/util/cli-prompt.js +181 -0
  452. package/server/dist/util/secure-fs.js +50 -0
  453. package/server/dist/util/win-spawn.js +43 -0
  454. package/server/dist/webhook-manager.js +89 -0
  455. package/server/dist/ws-routing.js +47 -0
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SERENA_MCP_ENTRY = exports.serenaManifest = void 0;
4
+ exports.serenaManifest = {
5
+ name: 'serena',
6
+ version: '1.0.0',
7
+ description: 'Semantic code navigation via Language Server Protocol. Lets agents look up symbols, references, and definitions instead of grepping or reading whole files — typically cutting input tokens 40–60% on real workloads.',
8
+ whatItDoes: [
9
+ 'Adds a Serena MCP server backed by uvx (Python).',
10
+ 'Exposes find_symbol, find_referencing_symbols, find_declaration, find_implementations, get_symbols_overview, and replace_symbol_body to all agents.',
11
+ 'Auto-detects project language; supports TS/JS, Python, Go, Rust, Java, and more.',
12
+ 'Runs locally — your code never leaves your machine.',
13
+ ],
14
+ platformNotes: {
15
+ 'darwin-arm64': 'On Apple Silicon, macOS may prompt to install Rosetta the first time Serena runs. Some Python language-server dependencies ship x86_64 only; click "Install" on the Apple prompt — it is safe and only happens once.',
16
+ },
17
+ category: 'code-navigation',
18
+ requirements: [
19
+ { name: 'uv', minVersion: '0.1.0' },
20
+ ],
21
+ owns: {
22
+ mcpServers: ['serena'],
23
+ agentFragments: ['.claude/agents/custom-serena.md'],
24
+ },
25
+ providerSupport: {
26
+ // claude: project-json `.mcp.json` merge (existing path).
27
+ claude: {
28
+ mcpEntry: {
29
+ command: 'uvx',
30
+ args: [
31
+ '--from',
32
+ 'git+https://github.com/oraios/serena',
33
+ 'serena',
34
+ 'start-mcp-server',
35
+ '--context',
36
+ 'ide-assistant',
37
+ '--project',
38
+ '.',
39
+ '--enable-web-dashboard',
40
+ 'false',
41
+ ],
42
+ },
43
+ },
44
+ // codex: cli-add via `codex mcp add` with per-project CODEX_HOME.
45
+ // Same `uvx ...` command; the adapter just registers it differently.
46
+ codex: {
47
+ mcpEntry: {
48
+ command: 'uvx',
49
+ args: [
50
+ '--from',
51
+ 'git+https://github.com/oraios/serena',
52
+ 'serena',
53
+ 'start-mcp-server',
54
+ '--context',
55
+ 'ide-assistant',
56
+ '--project',
57
+ '.',
58
+ '--enable-web-dashboard',
59
+ 'false',
60
+ ],
61
+ },
62
+ },
63
+ },
64
+ // Format: structured "when / tools / why / fallback" block. Lets generic
65
+ // agent prompts (specrails-core sr-* "Tool Selection — Honor Project-
66
+ // Documented MCP Tools" section) match the right entry to the task.
67
+ //
68
+ // Tool names below are verified against Serena's actual exposed tools
69
+ // (visible in Claude session init's tools list). Keep this list aligned
70
+ // with upstream — wrong names cause agents to mistrust the whole block.
71
+ claudeMdInstructions: `## Plugin: serena (semantic code navigation)
72
+
73
+ **When to use**: Locating symbols, references, definitions, or implementations in source code; renaming or refactoring a single function in place; getting a file-level symbol skeleton without reading the whole file.
74
+
75
+ **Tools** (all prefixed \`mcp__serena__\`):
76
+ - \`find_symbol\` — locate a class, function, or method by name path.
77
+ - \`find_referencing_symbols\` — list every caller / usage of a symbol.
78
+ - \`find_declaration\` — jump to where a symbol is defined.
79
+ - \`find_implementations\` — find concrete implementations of an interface or abstract method.
80
+ - \`get_symbols_overview\` — file-level symbol skeleton (signatures only, no bodies).
81
+ - \`replace_symbol_body\` — replace one function's body without re-reading or re-writing the rest of the file.
82
+ - \`insert_before_symbol\` / \`insert_after_symbol\` — splice new code adjacent to a known symbol without rewriting the file.
83
+ - \`rename_symbol\` — rename a symbol and update its references.
84
+ - \`safe_delete_symbol\` — remove a symbol and its references.
85
+ - \`replace_content\` — surgical text replace inside a single file when symbol-aware tools don't fit.
86
+ - \`get_diagnostics_for_file\` — language-server diagnostics for a file.
87
+
88
+ **Why prefer over built-ins**: Serena returns only the relevant symbol body, not whole files. Empirically cuts input tokens 40–60% on real workloads compared to \`Read\` / \`Grep\`.
89
+
90
+ **Fallback to \`Read\` / \`Grep\` for**: binary files, free-form prose, structured data without symbols (logs, JSON without schema, plain Markdown).
91
+
92
+ **Subagents**: MCP access is inherited from the parent Claude session; pass these tool names through when delegating via the \`Task\` tool.`,
93
+ };
94
+ exports.SERENA_MCP_ENTRY = {
95
+ command: 'uvx',
96
+ args: [
97
+ '--from',
98
+ 'git+https://github.com/oraios/serena',
99
+ 'serena',
100
+ 'start-mcp-server',
101
+ '--context',
102
+ 'ide-assistant',
103
+ '--project',
104
+ '.',
105
+ // Suppress the auto-opened web dashboard. Serena defaults to launching a
106
+ // local browser tab on start; users running rail jobs find the popup
107
+ // disruptive.
108
+ '--enable-web-dashboard',
109
+ 'false',
110
+ ],
111
+ };
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.verifySerena = verifySerena;
4
+ const child_process_1 = require("child_process");
5
+ const TIMEOUT_MS = 1800;
6
+ /**
7
+ * Verify Serena availability. We only probe `uv --version` here — proxy for
8
+ * "uvx will be able to launch serena-mcp-server when claude actually calls it".
9
+ *
10
+ * We intentionally do NOT shell out to `uvx --from git+... serena-mcp-server`:
11
+ * that would download the git repo + dependencies on every verify, which is
12
+ * slow (multi-second) and would fail offline. The Claude CLI itself triggers
13
+ * the lazy install through uvx's own cache, so as long as `uv` is on PATH and
14
+ * executable, install + spawn-time verify can both pass quickly.
15
+ *
16
+ * Cross-platform spawn: on Windows we set `shell: true` so PATH resolution
17
+ * picks up `uv.exe` (or, if astral installed via winget, the .cmd shim) the
18
+ * same way it does in `setup-prerequisites.ts`.
19
+ */
20
+ async function verifySerena() {
21
+ const checkedAt = new Date().toISOString();
22
+ const isWin = process.platform === 'win32';
23
+ return new Promise((resolve) => {
24
+ let settled = false;
25
+ let stderr = '';
26
+ let stdout = '';
27
+ let child;
28
+ try {
29
+ child = (0, child_process_1.spawn)('uv', ['--version'], {
30
+ stdio: ['ignore', 'pipe', 'pipe'],
31
+ shell: isWin,
32
+ });
33
+ }
34
+ catch {
35
+ resolve({ ok: false, reason: 'uv-not-on-path', checkedAt });
36
+ return;
37
+ }
38
+ const timer = setTimeout(() => {
39
+ if (settled)
40
+ return;
41
+ settled = true;
42
+ try {
43
+ child.kill('SIGKILL');
44
+ }
45
+ catch { /* ignore */ }
46
+ resolve({ ok: false, reason: 'verify-timeout', checkedAt });
47
+ }, TIMEOUT_MS);
48
+ child.stdout?.on('data', (b) => { stdout += b.toString(); });
49
+ child.stderr?.on('data', (b) => { stderr += b.toString(); });
50
+ child.on('error', (err) => {
51
+ if (settled)
52
+ return;
53
+ settled = true;
54
+ clearTimeout(timer);
55
+ const code = err.code;
56
+ if (code === 'ENOENT')
57
+ resolve({ ok: false, reason: 'uv-not-on-path', checkedAt });
58
+ else
59
+ resolve({ ok: false, reason: `verify-exception: ${err.message}`, checkedAt });
60
+ });
61
+ child.on('close', (code) => {
62
+ if (settled)
63
+ return;
64
+ settled = true;
65
+ clearTimeout(timer);
66
+ if (code === 0) {
67
+ resolve({ ok: true, reason: undefined, checkedAt });
68
+ }
69
+ else {
70
+ resolve({
71
+ ok: false,
72
+ reason: `uv-non-zero-exit: code=${code} ${stderr.trim().slice(0, 200) || stdout.trim().slice(0, 200)}`,
73
+ checkedAt,
74
+ });
75
+ }
76
+ });
77
+ });
78
+ }
@@ -0,0 +1,215 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createPluginsRouter = createPluginsRouter;
4
+ const express_1 = require("express");
5
+ const plugin_manager_1 = require("./plugin-manager");
6
+ const manager_1 = require("./plugins/manager");
7
+ const prereq_installer_1 = require("./plugins/prereq-installer");
8
+ const path_resolver_1 = require("./path-resolver");
9
+ const claude_approval_1 = require("./plugins/claude-approval");
10
+ function pluginsSectionEnabled() {
11
+ return process.env.SPECRAILS_PLUGINS_SECTION !== 'false';
12
+ }
13
+ function handleError(res, err) {
14
+ if (err instanceof plugin_manager_1.PluginNotFoundError) {
15
+ res.status(404).json({ error: err.message });
16
+ return;
17
+ }
18
+ if (err instanceof plugin_manager_1.PluginNotInstalledError) {
19
+ res.status(404).json({ error: err.message });
20
+ return;
21
+ }
22
+ if (err instanceof plugin_manager_1.PluginAlreadyInstalledError) {
23
+ res.status(409).json({ error: err.message });
24
+ return;
25
+ }
26
+ if (err instanceof plugin_manager_1.PluginInstallError) {
27
+ res.status(409).json({ error: err.message });
28
+ return;
29
+ }
30
+ const message = err instanceof Error ? err.message : 'unknown error';
31
+ res.status(500).json({ error: message });
32
+ }
33
+ function createPluginsRouter() {
34
+ const router = (0, express_1.Router)({ mergeParams: true });
35
+ function ctx(req) {
36
+ return req.projectCtx;
37
+ }
38
+ router.use((_req, res, next) => {
39
+ if (!pluginsSectionEnabled()) {
40
+ res.status(404).json({ error: 'Plugins section disabled on this server' });
41
+ return;
42
+ }
43
+ next();
44
+ });
45
+ // GET /api/projects/:projectId/plugins — catalog
46
+ router.get('/', async (req, res) => {
47
+ try {
48
+ const { project } = ctx(req);
49
+ const list = await (0, manager_1.getPluginManager)().listAvailable(project.path, project.provider);
50
+ res.json({ plugins: list });
51
+ }
52
+ catch (err) {
53
+ handleError(res, err);
54
+ }
55
+ });
56
+ // GET /api/projects/:projectId/plugins/:name/preview-install
57
+ router.get('/:name/preview-install', async (req, res) => {
58
+ try {
59
+ const { project } = ctx(req);
60
+ const result = await (0, manager_1.getPluginManager)().previewInstall(project.path, project.id, req.params.name);
61
+ res.json(result);
62
+ }
63
+ catch (err) {
64
+ handleError(res, err);
65
+ }
66
+ });
67
+ // POST /api/projects/:projectId/plugins/:name/install
68
+ router.post('/:name/install', async (req, res) => {
69
+ try {
70
+ const { project, broadcast } = ctx(req);
71
+ await (0, manager_1.getPluginManager)().install(project.path, project.id, req.params.name, broadcast, project.provider);
72
+ res.status(200).json({ ok: true });
73
+ }
74
+ catch (err) {
75
+ handleError(res, err);
76
+ }
77
+ });
78
+ // DELETE /api/projects/:projectId/plugins/:name — uninstall (or orphan removal)
79
+ router.delete('/:name', async (req, res) => {
80
+ try {
81
+ const { project, broadcast } = ctx(req);
82
+ await (0, manager_1.getPluginManager)().uninstall(project.path, project.id, req.params.name, broadcast, project.provider);
83
+ res.status(200).json({ ok: true });
84
+ }
85
+ catch (err) {
86
+ handleError(res, err);
87
+ }
88
+ });
89
+ // POST /api/projects/:projectId/plugins/_prerequisites/:prereq/install
90
+ // Streams installer output via the project broadcast as
91
+ // `plugin.prereq_install_progress`; emits `plugin.prereq_installed` on done.
92
+ router.post('/_prerequisites/:prereq/install', async (req, res) => {
93
+ const { project, broadcast } = ctx(req);
94
+ const prereq = req.params.prereq;
95
+ const allowed = ['uv'];
96
+ if (!allowed.includes(prereq)) {
97
+ res.status(404).json({ error: `unknown prerequisite '${prereq}'` });
98
+ return;
99
+ }
100
+ res.status(202).json({ ok: true, message: 'install started' });
101
+ try {
102
+ const result = await (0, prereq_installer_1.installPrerequisite)(prereq, project.id, broadcast);
103
+ // After a successful install, the new binary lives in `~/.local/bin`
104
+ // (POSIX) or `%USERPROFILE%\.local\bin` (Windows). Refresh the app's
105
+ // PATH from a login shell so the next verify spawn finds it without a
106
+ // app restart. On Windows this is a no-op — surface the hint as part
107
+ // of the reason field instead.
108
+ let hint;
109
+ if (result.ok) {
110
+ if (process.platform === 'win32') {
111
+ hint = 'Installed. If verify still fails, restart Specrails so Windows refreshes PATH.';
112
+ }
113
+ else {
114
+ try {
115
+ await (0, path_resolver_1.augmentPathFromLoginShell)({ timeoutMs: 3000 });
116
+ hint = 'Installed. PATH refreshed.';
117
+ }
118
+ catch {
119
+ hint = 'Installed. If verify still fails, restart Specrails.';
120
+ }
121
+ }
122
+ }
123
+ broadcast({
124
+ type: 'plugin.prereq_installed',
125
+ projectId: project.id,
126
+ prereq,
127
+ ok: result.ok,
128
+ reason: result.ok ? hint : result.reason,
129
+ timestamp: new Date().toISOString(),
130
+ });
131
+ }
132
+ catch (err) {
133
+ broadcast({
134
+ type: 'plugin.prereq_installed',
135
+ projectId: project.id,
136
+ prereq,
137
+ ok: false,
138
+ reason: err?.message ?? 'unknown error',
139
+ timestamp: new Date().toISOString(),
140
+ });
141
+ }
142
+ });
143
+ // POST /api/projects/:projectId/plugins/_marketplace/disable
144
+ // Body: { key: "<plugin-name>@<source>" } — sets enabledPlugins[key]=false
145
+ // in `~/.claude/settings.json`. The only place the app mutates Claude's
146
+ // per-user config; surfaced via an explicit user action.
147
+ router.post('/_marketplace/disable', async (req, res) => {
148
+ const { project, broadcast } = ctx(req);
149
+ const key = req.body?.key;
150
+ if (!key || typeof key !== 'string' || !key.includes('@')) {
151
+ res.status(400).json({ error: 'body must be { key: "<plugin>@<source>" }' });
152
+ return;
153
+ }
154
+ const result = (0, claude_approval_1.disableMarketplacePlugin)(key);
155
+ if (!result.ok) {
156
+ res.status(500).json({ error: result.reason ?? 'unknown' });
157
+ return;
158
+ }
159
+ // Refetch catalog so UI updates conflicts/status without manual refresh.
160
+ broadcast({
161
+ type: 'plugin.health_changed',
162
+ projectId: project.id,
163
+ name: key.split('@')[0],
164
+ status: 'unknown',
165
+ reason: 'marketplace-disabled',
166
+ timestamp: new Date().toISOString(),
167
+ });
168
+ res.json({ ok: true });
169
+ });
170
+ // POST /api/projects/:projectId/plugins/:name/activate
171
+ router.post('/:name/activate', async (req, res) => {
172
+ try {
173
+ const { project, broadcast } = ctx(req);
174
+ await (0, manager_1.getPluginManager)().setActive(project.path, project.id, req.params.name, true, broadcast, project.provider);
175
+ res.json({ ok: true });
176
+ }
177
+ catch (err) {
178
+ handleError(res, err);
179
+ }
180
+ });
181
+ // POST /api/projects/:projectId/plugins/:name/deactivate
182
+ router.post('/:name/deactivate', async (req, res) => {
183
+ try {
184
+ const { project, broadcast } = ctx(req);
185
+ await (0, manager_1.getPluginManager)().setActive(project.path, project.id, req.params.name, false, broadcast, project.provider);
186
+ res.json({ ok: true });
187
+ }
188
+ catch (err) {
189
+ handleError(res, err);
190
+ }
191
+ });
192
+ // POST /api/projects/:projectId/plugins/:name/update — apply manifest drift
193
+ router.post('/:name/update', async (req, res) => {
194
+ try {
195
+ const { project, broadcast } = ctx(req);
196
+ await (0, manager_1.getPluginManager)().updateMcpEntry(project.path, project.id, req.params.name, broadcast, project.provider);
197
+ res.json({ ok: true });
198
+ }
199
+ catch (err) {
200
+ handleError(res, err);
201
+ }
202
+ });
203
+ // GET /api/projects/:projectId/plugins/:name/health
204
+ router.get('/:name/health', async (req, res) => {
205
+ try {
206
+ const { project, broadcast } = ctx(req);
207
+ const result = await (0, manager_1.getPluginManager)().verify(project.path, project.id, req.params.name, broadcast);
208
+ res.json(result);
209
+ }
210
+ catch (err) {
211
+ handleError(res, err);
212
+ }
213
+ });
214
+ return router;
215
+ }
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ // Local pricing table for providers whose CLI does NOT report `total_cost_usd`
3
+ // natively. The app uses this to populate `ai_invocations.total_cost_usd` from
4
+ // captured token usage so the Spending dashboard, daily-budget enforcement, and
5
+ // cost alerts continue to function uniformly across providers.
6
+ //
7
+ // IMPORTANT — review cadence:
8
+ //
9
+ // Every quarter, the maintainer is expected to:
10
+ // 1. Confirm each entry's per-1M-token prices against the provider's
11
+ // published rate card (https://openai.com/pricing for OpenAI / Codex).
12
+ // 2. Bump the entry's `lastReviewedAt` to the verification date.
13
+ // 3. Add new models that have shipped since the last review.
14
+ //
15
+ // If a model is encountered at runtime that is NOT in the table,
16
+ // `estimateCostUsd` returns `null` and the consuming row is persisted with
17
+ // `total_cost_usd = NULL`. This is the deliberate fail-soft behaviour: never
18
+ // fabricate a cost from an unknown rate card.
19
+ //
20
+ // Spec: openspec/changes/add-multi-provider-support/specs/project-spending/spec.md
21
+ // - "Pricing-table fallback for non-native-cost providers"
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.PRICING = void 0;
24
+ exports.estimateCostUsd = estimateCostUsd;
25
+ exports.lastReviewedAt = lastReviewedAt;
26
+ exports.providerNeedsCostEstimation = providerNeedsCostEstimation;
27
+ const registry_1 = require("./providers/registry");
28
+ /** Key shape: `<providerId>:<model>` (case-sensitive). */
29
+ exports.PRICING = {
30
+ // Codex (OpenAI). Reference: https://openai.com/pricing
31
+ 'codex:gpt-5.5': { inputPer1M: 1.25, outputPer1M: 10.00, cacheReadPer1M: 0.125, lastReviewedAt: '2026-05-17' },
32
+ 'codex:gpt-5.4': { inputPer1M: 2.50, outputPer1M: 10.00, cacheReadPer1M: 0.25, lastReviewedAt: '2026-05-17' },
33
+ 'codex:gpt-5.4-mini': { inputPer1M: 0.25, outputPer1M: 2.00, cacheReadPer1M: 0.025, lastReviewedAt: '2026-05-17' },
34
+ 'codex:gpt-5.3-codex': { inputPer1M: 1.50, outputPer1M: 6.00, cacheReadPer1M: 0.15, lastReviewedAt: '2026-05-17' },
35
+ };
36
+ /**
37
+ * Estimate cost in USD from a token usage breakdown. Returns `null` when:
38
+ * - the model is null/empty,
39
+ * - the `${providerId}:${model}` key is not in the pricing table.
40
+ *
41
+ * Cache-creation tokens are not modelled (OpenAI does not surface a separate
42
+ * cache-write tier as of 2026-05-17). When `tokens_cache_create` is present we
43
+ * silently ignore it — including it as ordinary input tokens would double-count
44
+ * against the rate card.
45
+ */
46
+ function estimateCostUsd(providerId, model, usage) {
47
+ if (!model)
48
+ return null;
49
+ const entry = exports.PRICING[`${providerId}:${model}`];
50
+ if (!entry)
51
+ return null;
52
+ // `tokens_in` is the TOTAL prompt token count and `tokens_cache_read` is a
53
+ // SUBSET already inside it (OpenAI/codex usage semantics: input_tokens
54
+ // includes cached_input_tokens). Bill the cached portion at the cache rate
55
+ // ONLY, and the remaining fresh input at the full input rate. Charging the
56
+ // full input rate over the whole `tokens_in` AND a separate cache-read cost
57
+ // would double-charge every cached token. Clamp at 0 to guard a malformed
58
+ // payload where the reported cache subset exceeds the total.
59
+ const freshInput = Math.max(0, (usage.tokens_in ?? 0) - (usage.tokens_cache_read ?? 0));
60
+ const inputCost = freshInput * entry.inputPer1M / 1_000_000;
61
+ const outputCost = (usage.tokens_out ?? 0) * entry.outputPer1M / 1_000_000;
62
+ const cacheReadCost = (usage.tokens_cache_read ?? 0) * entry.cacheReadPer1M / 1_000_000;
63
+ return inputCost + outputCost + cacheReadCost;
64
+ }
65
+ /**
66
+ * Returns the oldest `lastReviewedAt` date across the table. Surfaced by an
67
+ * optional diagnostic endpoint so the maintainer can spot staleness quickly.
68
+ */
69
+ function lastReviewedAt() {
70
+ let oldest = null;
71
+ for (const entry of Object.values(exports.PRICING)) {
72
+ if (oldest === null || entry.lastReviewedAt < oldest)
73
+ oldest = entry.lastReviewedAt;
74
+ }
75
+ return oldest ?? '0000-00-00';
76
+ }
77
+ /**
78
+ * Returns true when the resolved adapter for the given provider id declares
79
+ * `capabilities.nativeCostUsd === false`. Used by callsites to decide whether
80
+ * to fall back to estimation vs trust the provider's terminal event.
81
+ *
82
+ * Returns false for unknown ids (defensive: do not call the estimator for an
83
+ * unrecognised provider).
84
+ */
85
+ function providerNeedsCostEstimation(providerId) {
86
+ if (!(0, registry_1.hasAdapter)(providerId))
87
+ return false;
88
+ return (0, registry_1.getAdapter)(providerId).capabilities.nativeCostUsd === false;
89
+ }