specrails-desktop 2.16.0 → 2.17.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 (354) hide show
  1. package/client/dist/assets/{ActivityFeedPage-C_clKk8d.js → ActivityFeedPage-BLDMBgwL.js} +1 -1
  2. package/client/dist/assets/AgentsPage-CFaIiyAA.js +86 -0
  3. package/client/dist/assets/{AnalyticsPage-DZkVU3yd.js → AnalyticsPage-DY8ECq2R.js} +1 -1
  4. package/client/dist/assets/{BarChart-Dq1h8eYR.js → BarChart-ouivqe5L.js} +2 -2
  5. package/client/dist/assets/CodePage-DAFtRafz.js +2 -0
  6. package/client/dist/assets/{DesktopAnalyticsPage-CYhXhJoQ.js → DesktopAnalyticsPage-DIMhuuv0.js} +1 -1
  7. package/client/dist/assets/{DocsDialog-CS3Syf61.js → DocsDialog-DBYhv3SM.js} +2 -2
  8. package/client/dist/assets/{DocsPage-l3ZcTO2E.js → DocsPage-DeLRn8W_.js} +2 -2
  9. package/client/dist/assets/{ExportDropdown-DdB2ncYh.js → ExportDropdown-2XwQ08sz.js} +1 -1
  10. package/client/dist/assets/{IntegrationsPage-CJ_Om1zu.js → IntegrationsPage-DB-a4FDV.js} +3 -3
  11. package/client/dist/assets/JobDetailPage-C3lljMiV.js +16 -0
  12. package/client/dist/assets/JobsPage-CzquwJ6G.js +1 -0
  13. package/client/dist/assets/LoopBuilderPage-TkoalfW5.js +7 -0
  14. package/client/dist/assets/LoopsPage-ypooVAQ5.js +1 -0
  15. package/client/dist/assets/{agents-CQlu1nOm.js → agents-4fnKlwcG.js} +1 -1
  16. package/client/dist/assets/{agents-DcoUUFZl.js → agents-B-rVIhuw.js} +1 -1
  17. package/client/dist/assets/{agents-DVYpVGur.js → agents-BRUz6RJs.js} +1 -1
  18. package/client/dist/assets/{agents-DCX9D3-Q.js → agents-CZQvKDIb.js} +1 -1
  19. package/client/dist/assets/{agents-BYjUOrLD.js → agents-CuRY-Zg_.js} +1 -1
  20. package/client/dist/assets/{agents-Jc-CjBDB.js → agents-D7nWnLg6.js} +1 -1
  21. package/client/dist/assets/{agents-CIhRSOna.js → agents-DzhSlNZd.js} +1 -1
  22. package/client/dist/assets/{agents-1lhqEcXH.js → agents-E-42N3b1.js} +1 -1
  23. package/client/dist/assets/{cssMode-DSHXamUH.js → cssMode-BijCvCxs.js} +1 -1
  24. package/client/dist/assets/{dist-js-Ele_sHO7.js → dist-js-D7m9--SN.js} +1 -1
  25. package/client/dist/assets/{dist-js-D27I-bfi.js → dist-js-nZhsq1qo.js} +1 -1
  26. package/client/dist/assets/{editor.main-Cd8qBRAT.js → editor.main-DMIcqwXb.js} +2 -2
  27. package/client/dist/assets/{freemarker2-CkEKTBm2.js → freemarker2-CP2AizpZ.js} +1 -1
  28. package/client/dist/assets/{handlebars-BRGx0JpL.js → handlebars-8ElanPOm.js} +1 -1
  29. package/client/dist/assets/{html-BfRIaGgN.js → html-Mu3b73tG.js} +1 -1
  30. package/client/dist/assets/{htmlMode-BTpSnsDE.js → htmlMode-tHprGCEv.js} +1 -1
  31. package/client/dist/assets/index-CDEQ4aU_.js +144 -0
  32. package/client/dist/assets/{javascript-DMmE2kKN.js → javascript-DlG0apUe.js} +1 -1
  33. package/client/dist/assets/{jsonMode-hYuaUleY.js → jsonMode-Cr0T4SXO.js} +1 -1
  34. package/client/dist/assets/{lib-qdRfWwE1.js → lib-Bu76JzdB.js} +2 -2
  35. package/client/dist/assets/{liquid-C-VbuTr7.js → liquid-QgTgbClC.js} +1 -1
  36. package/client/dist/assets/{lspLanguageFeatures-BALx-vjn.js → lspLanguageFeatures-D-BxkRza.js} +1 -1
  37. package/client/dist/assets/mcp-BSCAtU6Y.js +1 -0
  38. package/client/dist/assets/mcp-Cb6fUaFJ.js +1 -0
  39. package/client/dist/assets/mcp-CyP0quZ7.js +1 -0
  40. package/client/dist/assets/mcp-D-zQCO5E.js +1 -0
  41. package/client/dist/assets/mcp-DCTNWpfB.js +1 -0
  42. package/client/dist/assets/mcp-DEFGJ1OJ.js +1 -0
  43. package/client/dist/assets/mcp-DFG9OEXM.js +1 -0
  44. package/client/dist/assets/mcp-DyERgHA2.js +1 -0
  45. package/client/dist/assets/{mdx-Cs8MNCzn.js → mdx-B2QTaeRe.js} +1 -1
  46. package/client/dist/assets/{monaco.contribution-CIvCAJs4.js → monaco.contribution-CkdGfXCC.js} +2 -2
  47. package/client/dist/assets/{python-CGShLxuI.js → python-BlF0qnMQ.js} +1 -1
  48. package/client/dist/assets/{razor-CvOBQGd5.js → razor--3PSy3lb.js} +1 -1
  49. package/client/dist/assets/setup-BiQ7ut8d.js +1 -0
  50. package/client/dist/assets/setup-BxvjG5Xp.js +1 -0
  51. package/client/dist/assets/setup-CQ-F6Ciq.js +1 -0
  52. package/client/dist/assets/setup-D2JlpJEz.js +1 -0
  53. package/client/dist/assets/setup-DG1R6J6o.js +1 -0
  54. package/client/dist/assets/setup-DuFJZJsm.js +1 -0
  55. package/client/dist/assets/setup-DyJszDqm.js +1 -0
  56. package/client/dist/assets/setup-Ynw19V8w.js +1 -0
  57. package/client/dist/assets/{tsMode-04uOpiiP.js → tsMode-CHfsvcOI.js} +1 -1
  58. package/client/dist/assets/{typescript-CX0CwyIZ.js → typescript-Bjxf6BOp.js} +1 -1
  59. package/client/dist/assets/{upload-DPG87J4t.js → upload-x42OZJr2.js} +1 -1
  60. package/client/dist/assets/{value-BRVOAvhY.js → value-fEDhg5Bd.js} +1 -1
  61. package/client/dist/assets/{workers-yr2u4c3C.js → workers-CAAvSda9.js} +1 -1
  62. package/client/dist/assets/{xml-C0OFlt5X.js → xml-iYCSJ4oL.js} +1 -1
  63. package/client/dist/assets/{yaml-DgabaPs5.js → yaml-DtO-_yDY.js} +1 -1
  64. package/client/dist/index.html +10 -9
  65. package/docs/README.md +2 -0
  66. package/docs/guide/de/integrations/5-mcp-server.md +74 -0
  67. package/docs/guide/en/integrations/5-mcp-server.md +74 -0
  68. package/docs/guide/es/integrations/5-mcp-server.md +74 -0
  69. package/docs/guide/fr/integrations/5-mcp-server.md +74 -0
  70. package/docs/guide/it/integrations/5-mcp-server.md +74 -0
  71. package/docs/guide/ja/integrations/5-mcp-server.md +74 -0
  72. package/docs/guide/pt/integrations/5-mcp-server.md +74 -0
  73. package/docs/guide/zh/integrations/5-mcp-server.md +74 -0
  74. package/docs/mcp.md +249 -0
  75. package/package.json +8 -5
  76. package/server/dist/index.js +30 -0
  77. package/server/dist/mcp/guide.js +82 -0
  78. package/server/dist/mcp/index.js +21 -0
  79. package/server/dist/mcp/mcp-admin-router.js +71 -0
  80. package/server/dist/mcp/mcp-server.js +143 -0
  81. package/server/dist/mcp/mcp-tiers.js +48 -0
  82. package/server/dist/mcp/mcp-token.js +119 -0
  83. package/server/dist/mcp/resources.js +24 -0
  84. package/server/dist/mcp/tools/agents.js +319 -0
  85. package/server/dist/mcp/tools/analytics.js +168 -0
  86. package/server/dist/mcp/tools/app-settings.js +81 -0
  87. package/server/dist/mcp/tools/catalog.js +45 -0
  88. package/server/dist/mcp/tools/chat.js +147 -0
  89. package/server/dist/mcp/tools/code.js +145 -0
  90. package/server/dist/mcp/tools/jira.js +222 -0
  91. package/server/dist/mcp/tools/jobs.js +258 -0
  92. package/server/dist/mcp/tools/loops.js +229 -0
  93. package/server/dist/mcp/tools/meta.js +96 -0
  94. package/server/dist/mcp/tools/plugins.js +83 -0
  95. package/server/dist/mcp/tools/projects.js +62 -0
  96. package/server/dist/mcp/tools/rails.js +181 -0
  97. package/server/dist/mcp/tools/setup.js +187 -0
  98. package/server/dist/mcp/tools/specs.js +327 -0
  99. package/server/dist/mcp/tools/types.js +137 -0
  100. package/server/dist/mcp/tools/watch.js +93 -0
  101. package/server/dist/mobile/mobile-event-bus.js +2 -0
  102. package/server/dist/project-router-tickets.js +2 -2
  103. package/server/dist/rails-router.js +5 -0
  104. package/client/dist/assets/AgentsPage-jcPUtPhP.js +0 -86
  105. package/client/dist/assets/CodePage-BcbZT88K.js +0 -2
  106. package/client/dist/assets/JobDetailPage-D5Cxw0md.js +0 -16
  107. package/client/dist/assets/JobsPage-3v_iX83r.js +0 -1
  108. package/client/dist/assets/LoopBuilderPage-4s_adZy5.js +0 -7
  109. package/client/dist/assets/LoopsPage-DA94-o0j.js +0 -1
  110. package/client/dist/assets/index-meTWPBzY.js +0 -144
  111. package/client/dist/assets/setup-BOmQ4vh2.js +0 -1
  112. package/client/dist/assets/setup-BwO2-kuK.js +0 -1
  113. package/client/dist/assets/setup-CUTNWz-0.js +0 -1
  114. package/client/dist/assets/setup-Cf3hjChU.js +0 -1
  115. package/client/dist/assets/setup-CsuXrbJ2.js +0 -1
  116. package/client/dist/assets/setup-Df4cJOqu.js +0 -1
  117. package/client/dist/assets/setup-Do0fWx6W.js +0 -1
  118. package/client/dist/assets/setup-GlkDhBlJ.js +0 -1
  119. /package/client/dist/assets/{abap-CK68cr9-.js → abap-BFJA_Joo.js} +0 -0
  120. /package/client/dist/assets/{activity-D4dhNEwO.js → activity-BXBMi28x.js} +0 -0
  121. /package/client/dist/assets/{activity-usnNa7FX.js → activity-By6I70Ws.js} +0 -0
  122. /package/client/dist/assets/{activity-BbNkUmW4.js → activity-CfedQaof.js} +0 -0
  123. /package/client/dist/assets/{activity-B2MvEH54.js → activity-D62CDlQz.js} +0 -0
  124. /package/client/dist/assets/{activity-DHjfmAyT.js → activity-DAFuSwnt.js} +0 -0
  125. /package/client/dist/assets/{activity-C7VdmeGb.js → activity-Did0FnrH.js} +0 -0
  126. /package/client/dist/assets/{activity-Di2f50_Z.js → activity-oLgwaVyt.js} +0 -0
  127. /package/client/dist/assets/{addon-image-biWX2UUm.js → addon-image-bPlduuUZ.js} +0 -0
  128. /package/client/dist/assets/{addon-ligatures-D4EiDb5r.js → addon-ligatures-BexpF7xb.js} +0 -0
  129. /package/client/dist/assets/{addon-webgl-CDCIZQ03.js → addon-webgl-Zy4IOieH.js} +0 -0
  130. /package/client/dist/assets/{addspec-BxMn39wn.js → addspec-B2fTENuq.js} +0 -0
  131. /package/client/dist/assets/{addspec-DAveBiCE.js → addspec-BmggyuCD.js} +0 -0
  132. /package/client/dist/assets/{addspec-1HEtmLv1.js → addspec-CFsLeQKV.js} +0 -0
  133. /package/client/dist/assets/{addspec-DfuR6EAl.js → addspec-CkHI5c5H.js} +0 -0
  134. /package/client/dist/assets/{addspec-CO1xv6BL.js → addspec-Cvm06hGe.js} +0 -0
  135. /package/client/dist/assets/{addspec-IozoiiGs.js → addspec-DwoLTocx.js} +0 -0
  136. /package/client/dist/assets/{addspec-CNyAUGz_.js → addspec-gthH-H1g.js} +0 -0
  137. /package/client/dist/assets/{agentstudio-Q0Sq_jTg.js → agentstudio-BtASTJl7.js} +0 -0
  138. /package/client/dist/assets/{agentstudio-9NbsoGXk.js → agentstudio-CIe9C892.js} +0 -0
  139. /package/client/dist/assets/{agentstudio-B-jQgYV-.js → agentstudio-CYGk-jjo.js} +0 -0
  140. /package/client/dist/assets/{agentstudio-Bwa72b1S.js → agentstudio-CwiS3BTp.js} +0 -0
  141. /package/client/dist/assets/{agentstudio-B1y0JWY-.js → agentstudio-D0bQBWpI.js} +0 -0
  142. /package/client/dist/assets/{agentstudio-DCyDW8sy.js → agentstudio-Dq-bZrI3.js} +0 -0
  143. /package/client/dist/assets/{agentstudio-1E-bag77.js → agentstudio-n0pmwz2I.js} +0 -0
  144. /package/client/dist/assets/{aiedit-qTGI_PGs.js → aiedit-1Z-UYKFb.js} +0 -0
  145. /package/client/dist/assets/{aiedit-CGxeml8D.js → aiedit-BAJM9Cch.js} +0 -0
  146. /package/client/dist/assets/{aiedit-CfBNanHE.js → aiedit-CYnsp1Iv.js} +0 -0
  147. /package/client/dist/assets/{aiedit-CvSspQmE.js → aiedit-CZBZAyeK.js} +0 -0
  148. /package/client/dist/assets/{aiedit-kAU7KADg.js → aiedit-CunYxmW0.js} +0 -0
  149. /package/client/dist/assets/{aiedit-DUpe7NxI.js → aiedit-s1T1EMK8.js} +0 -0
  150. /package/client/dist/assets/{aiedit-DSLtsYIu.js → aiedit-uIDh2tlc.js} +0 -0
  151. /package/client/dist/assets/{analytics-DBGO8B6-.js → analytics-B95FiMuD.js} +0 -0
  152. /package/client/dist/assets/{analytics-CgEkAUiP.js → analytics-DPIkvuTS.js} +0 -0
  153. /package/client/dist/assets/{analytics-DDqve9Ma.js → analytics-DPmCEzvJ.js} +0 -0
  154. /package/client/dist/assets/{analytics-D1ElChhs.js → analytics-DRexho82.js} +0 -0
  155. /package/client/dist/assets/{analytics-DEsEAJZL.js → analytics-DVFNjjAv.js} +0 -0
  156. /package/client/dist/assets/{analytics-BDlELxc7.js → analytics-DZKGAUdm.js} +0 -0
  157. /package/client/dist/assets/{analytics-CQqu1yE5.js → analytics-g9ASAR_r.js} +0 -0
  158. /package/client/dist/assets/{apex-BHHyAVNb.js → apex-C1f-z6NO.js} +0 -0
  159. /package/client/dist/assets/{atom-one-dark-DrWoEEbZ.js → atom-one-dark-CT4DolNR.js} +0 -0
  160. /package/client/dist/assets/{attachments-3CuBBRFu.js → attachments--jr2QLGv.js} +0 -0
  161. /package/client/dist/assets/{attachments-pW3zm9nu.js → attachments-BgqfeoOx.js} +0 -0
  162. /package/client/dist/assets/{attachments-BNgH6Tcu.js → attachments-Bj3HHTXV.js} +0 -0
  163. /package/client/dist/assets/{attachments-D5fVsMgb.js → attachments-C3skjFyH.js} +0 -0
  164. /package/client/dist/assets/{attachments-UJtEq892.js → attachments-CnPS8YWu.js} +0 -0
  165. /package/client/dist/assets/{attachments-CppM7de8.js → attachments-DejzxE0C.js} +0 -0
  166. /package/client/dist/assets/{attachments-BLqqPGyy.js → attachments-FFb2xHc_.js} +0 -0
  167. /package/client/dist/assets/{azcli-C56lfIEP.js → azcli-Dr0WBJTP.js} +0 -0
  168. /package/client/dist/assets/{bat-BLamSaf-.js → bat-BKG3k49W.js} +0 -0
  169. /package/client/dist/assets/{bicep-lrOcEItS.js → bicep-DXs2wTcS.js} +0 -0
  170. /package/client/dist/assets/{browser-C91MQBxx.js → browser-BS9t1qMc.js} +0 -0
  171. /package/client/dist/assets/{browser-B7i7Ysc8.js → browser-BpMo-amf.js} +0 -0
  172. /package/client/dist/assets/{browser-DwE289IS.js → browser-CsC3NOZ-.js} +0 -0
  173. /package/client/dist/assets/{browser-C__Vz7KR.js → browser-DS6xnywt.js} +0 -0
  174. /package/client/dist/assets/{browser-DhwTc0ry.js → browser-Dm6F9bqQ.js} +0 -0
  175. /package/client/dist/assets/{browser-EFmPpkvO.js → browser-Dm_Of27q.js} +0 -0
  176. /package/client/dist/assets/{browser-BVQgd1_1.js → browser-U3iouSXn.js} +0 -0
  177. /package/client/dist/assets/{cameligo-BK_p0bgU.js → cameligo-Detknuxp.js} +0 -0
  178. /package/client/dist/assets/{chat-PVakYp92.js → chat-B2tWTbZL.js} +0 -0
  179. /package/client/dist/assets/{chat-BnJPyeUK.js → chat-CXOJHDUZ.js} +0 -0
  180. /package/client/dist/assets/{chat-CE8bx6Rz.js → chat-Cy78lw1n.js} +0 -0
  181. /package/client/dist/assets/{chat-UMl6H55K.js → chat-D78VMi-v.js} +0 -0
  182. /package/client/dist/assets/{chat-BXVx6rb5.js → chat-De1RgOXU.js} +0 -0
  183. /package/client/dist/assets/{chat-C5nJF6L0.js → chat-DyTbH-0F.js} +0 -0
  184. /package/client/dist/assets/{chat-9RcD5Lcn.js → chat-sqZyn0C4.js} +0 -0
  185. /package/client/dist/assets/{clojure-BQ7JOykv.js → clojure-CCu4UNKg.js} +0 -0
  186. /package/client/dist/assets/{clsx-CjLeUJfG.js → clsx-pVRQNNR0.js} +0 -0
  187. /package/client/dist/assets/{code-u9Sg9ohM.js → code-6LokPmIE.js} +0 -0
  188. /package/client/dist/assets/{code-OoLqhjoI.js → code-CLTuhuvM.js} +0 -0
  189. /package/client/dist/assets/{code-Lg4awa35.js → code-CwGlPuwb.js} +0 -0
  190. /package/client/dist/assets/{code-BPMR8_Vp.js → code-DFCDV5e1.js} +0 -0
  191. /package/client/dist/assets/{code-eh4vO2-_.js → code-Djq48g0s.js} +0 -0
  192. /package/client/dist/assets/{code-aCUqkVN_.js → code-Do27r8WG.js} +0 -0
  193. /package/client/dist/assets/{code-BsOBm1Fb.js → code-Drc7f197.js} +0 -0
  194. /package/client/dist/assets/{coffee-BD3DiL5s.js → coffee-Bam7Y9IR.js} +0 -0
  195. /package/client/dist/assets/{commands-B9XEyMj-.js → commands-CxReviyc.js} +0 -0
  196. /package/client/dist/assets/{commands-Ic1DJDxm.js → commands-CzP1qQyD.js} +0 -0
  197. /package/client/dist/assets/{commands-BdI0CtOL.js → commands-DGP46UxM.js} +0 -0
  198. /package/client/dist/assets/{commands-DSX3yJyr.js → commands-DQvoMqa7.js} +0 -0
  199. /package/client/dist/assets/{commands-yNn4IA4C.js → commands-DeKaz04Q.js} +0 -0
  200. /package/client/dist/assets/{commands-BI1Ta-E7.js → commands-DwYhwQsF.js} +0 -0
  201. /package/client/dist/assets/{commands-C2ewlyXo.js → commands-lm6Vlght.js} +0 -0
  202. /package/client/dist/assets/{common-CzCQ0rpW.js → common-B0crwfK0.js} +0 -0
  203. /package/client/dist/assets/{common-CNoRVpnA.js → common-BlqmiTj4.js} +0 -0
  204. /package/client/dist/assets/{common-CcHFVATT.js → common-CIUPtPdu.js} +0 -0
  205. /package/client/dist/assets/{common-LDwESeCX.js → common-C_-0fZsp.js} +0 -0
  206. /package/client/dist/assets/{common-C9VyfY7g.js → common-DH9A-wTo.js} +0 -0
  207. /package/client/dist/assets/{common-Dmpyh323.js → common-DJM41wFl.js} +0 -0
  208. /package/client/dist/assets/{common-ULlk84G4.js → common-SyTaRc_K.js} +0 -0
  209. /package/client/dist/assets/{cpp-splnCwCh.js → cpp-BhOkAe-9.js} +0 -0
  210. /package/client/dist/assets/{csharp-BCpsl-o3.js → csharp-BgHArJNx.js} +0 -0
  211. /package/client/dist/assets/{csp-tkCWrZmb.js → csp-Xzh56_3-.js} +0 -0
  212. /package/client/dist/assets/{css-B_xdnReq.js → css-CD7-RYRS.js} +0 -0
  213. /package/client/dist/assets/{cypher-OL1zq-y3.js → cypher-l2xAdF3X.js} +0 -0
  214. /package/client/dist/assets/{dart-CtTlOkrm.js → dart-CDOWeyzt.js} +0 -0
  215. /package/client/dist/assets/{dashboard-C-dXxut-.js → dashboard-B1rs1wki.js} +0 -0
  216. /package/client/dist/assets/{dashboard-CUjyhohl.js → dashboard-D9QPCmv3.js} +0 -0
  217. /package/client/dist/assets/{dashboard-C52PElPV.js → dashboard-Dxgb47lO.js} +0 -0
  218. /package/client/dist/assets/{dashboard-03EpOoMM.js → dashboard-TuElRCZX.js} +0 -0
  219. /package/client/dist/assets/{dashboard-Ch6H-457.js → dashboard-UWXs9_wy.js} +0 -0
  220. /package/client/dist/assets/{dashboard-zH9quXks.js → dashboard-ajT8usAi.js} +0 -0
  221. /package/client/dist/assets/{dashboard-C2owt3eN.js → dashboard-zwN2xswo.js} +0 -0
  222. /package/client/dist/assets/{dockerfile-DcQ5CNiW.js → dockerfile-Dv8atx7v.js} +0 -0
  223. /package/client/dist/assets/{ecl-DZpiDRt6.js → ecl-DIYTlbD_.js} +0 -0
  224. /package/client/dist/assets/{editor.api2-Cwla1nvV.js → editor.api2-CrNrMVfe.js} +0 -0
  225. /package/client/dist/assets/{elixir-Dzj2lqtK.js → elixir-CR7PLJja.js} +0 -0
  226. /package/client/dist/assets/{explore-4SD1DxR0.js → explore-BYFCCka4.js} +0 -0
  227. /package/client/dist/assets/{explore-xQoaak6e.js → explore-CE0wSNV1.js} +0 -0
  228. /package/client/dist/assets/{explore-CZt4Ncpa.js → explore-CSDcRUNj.js} +0 -0
  229. /package/client/dist/assets/{explore-DQ0XEjed.js → explore-CvM08PpD.js} +0 -0
  230. /package/client/dist/assets/{explore-CCcPXrHg.js → explore-Jkw93usp.js} +0 -0
  231. /package/client/dist/assets/{explore-BxR9q8Hq.js → explore-kK239uoZ.js} +0 -0
  232. /package/client/dist/assets/{explore-B2n8r9Ye.js → explore-mLI5eXks.js} +0 -0
  233. /package/client/dist/assets/{flow9-CFENCHIZ.js → flow9-DCK5-6NG.js} +0 -0
  234. /package/client/dist/assets/{format-command-CMsBTOPN.js → format-command-rVyGPxWE.js} +0 -0
  235. /package/client/dist/assets/{fsharp-D-4bv7FB.js → fsharp-DJ1xiUVU.js} +0 -0
  236. /package/client/dist/assets/{go-djxbTJq7.js → go-BEvbHcbb.js} +0 -0
  237. /package/client/dist/assets/{graphql-DHIFrkZ6.js → graphql-DN1ktXnz.js} +0 -0
  238. /package/client/dist/assets/{hcl-CXVoowNb.js → hcl-DJaIjIEr.js} +0 -0
  239. /package/client/dist/assets/{ini-Crzc5kly.js → ini-PlKfLEnb.js} +0 -0
  240. /package/client/dist/assets/{integrations-A9f08E0o.js → integrations-B8hT0Qf_.js} +0 -0
  241. /package/client/dist/assets/{integrations-DwSVdCpf.js → integrations-Bdk5dMyv.js} +0 -0
  242. /package/client/dist/assets/{integrations-B46ac3sf.js → integrations-CYqz7YFS.js} +0 -0
  243. /package/client/dist/assets/{integrations-9qxUNhPD.js → integrations-Cj_BsXxJ.js} +0 -0
  244. /package/client/dist/assets/{integrations-B17KyA-i.js → integrations-D8M8eJH2.js} +0 -0
  245. /package/client/dist/assets/{integrations-DkBi-Gsh.js → integrations-TJuDBl-9.js} +0 -0
  246. /package/client/dist/assets/{integrations-C7u7SInG.js → integrations-TwQV3sLw.js} +0 -0
  247. /package/client/dist/assets/{java-CYLaJrdE.js → java-3PUwMlx-.js} +0 -0
  248. /package/client/dist/assets/{jira-01H1RfQj.js → jira--rI5PfuE.js} +0 -0
  249. /package/client/dist/assets/{jira-CBU0200d.js → jira-BoRyckbb.js} +0 -0
  250. /package/client/dist/assets/{jira-BpnpUFlb.js → jira-C95FN3yk.js} +0 -0
  251. /package/client/dist/assets/{jira-DzIVvNmy.js → jira-CNUUgTs4.js} +0 -0
  252. /package/client/dist/assets/{jira-Dht8qNck.js → jira-DHFnvEm8.js} +0 -0
  253. /package/client/dist/assets/{jira-4Fin3fu7.js → jira-NhkbrDXe.js} +0 -0
  254. /package/client/dist/assets/{jira-0ldfMByG.js → jira-wiIvGma5.js} +0 -0
  255. /package/client/dist/assets/{jobs-Oz3UtLQn.js → jobs-Bjp7v9aA.js} +0 -0
  256. /package/client/dist/assets/{jobs-jEQidSIb.js → jobs-Bjt5PyVv.js} +0 -0
  257. /package/client/dist/assets/{jobs-BF9raUkL.js → jobs-BmTs4Bn3.js} +0 -0
  258. /package/client/dist/assets/{jobs-DcCONARH.js → jobs-Cchy-18B.js} +0 -0
  259. /package/client/dist/assets/{jobs-DM9owF1j.js → jobs-D2QVTPbz.js} +0 -0
  260. /package/client/dist/assets/{jobs-Bw4hqEro.js → jobs-LK1ImiDH.js} +0 -0
  261. /package/client/dist/assets/{jobs-ym72SIR9.js → jobs-yPz4Dvi-.js} +0 -0
  262. /package/client/dist/assets/{julia-BJ7tUU-T.js → julia-DC6LnY15.js} +0 -0
  263. /package/client/dist/assets/{kotlin-CeWcU3lC.js → kotlin-CoGntbZF.js} +0 -0
  264. /package/client/dist/assets/{less-CviwWNG4.js → less-DCFflTXL.js} +0 -0
  265. /package/client/dist/assets/{lexon-Dt28jqDS.js → lexon-BTOivnjP.js} +0 -0
  266. /package/client/dist/assets/{loops-Fv4Bs-9A.js → loops-BFIcYvpy.js} +0 -0
  267. /package/client/dist/assets/{loops-D_ZxkD4l.js → loops-BU314kSd.js} +0 -0
  268. /package/client/dist/assets/{loops-DE-2cmLw.js → loops-C3OaXou9.js} +0 -0
  269. /package/client/dist/assets/{loops-mcoeFMat.js → loops-Cv6Aeszq.js} +0 -0
  270. /package/client/dist/assets/{loops-B_w7STrw.js → loops-IQe23ef6.js} +0 -0
  271. /package/client/dist/assets/{loops-BYNUJVyD.js → loops-LqZ4MC6J.js} +0 -0
  272. /package/client/dist/assets/{loops-B_gS4Pqu.js → loops-SbkOdciY.js} +0 -0
  273. /package/client/dist/assets/{lua-B6AOaJSi.js → lua-ClKCZMmP.js} +0 -0
  274. /package/client/dist/assets/{m3-VnMkHJcy.js → m3-25hKFWMb.js} +0 -0
  275. /package/client/dist/assets/{markdown-8vKNdvIM.js → markdown-BGAj9q0K.js} +0 -0
  276. /package/client/dist/assets/{mips-DoEcuzan.js → mips-BrVgY2Pf.js} +0 -0
  277. /package/client/dist/assets/{msdax-CNzvHyEp.js → msdax-7EhcRsm8.js} +0 -0
  278. /package/client/dist/assets/{mysql-Buk3vUtL.js → mysql-B5_atCBH.js} +0 -0
  279. /package/client/dist/assets/{nav-_0vAgZ_k.js → nav-B2Cv1vjz.js} +0 -0
  280. /package/client/dist/assets/{nav-Cw3_40fA.js → nav-Br2AivTc.js} +0 -0
  281. /package/client/dist/assets/{nav-DNDJ3H-_.js → nav-CFofO7QO.js} +0 -0
  282. /package/client/dist/assets/{nav-CCz4krPP.js → nav-CyHKTZxn.js} +0 -0
  283. /package/client/dist/assets/{nav-B5W9IMnf.js → nav-DqyLGJmF.js} +0 -0
  284. /package/client/dist/assets/{nav-CrG_mYRr.js → nav-_-siCrRv.js} +0 -0
  285. /package/client/dist/assets/{nav-DbAbG5_k.js → nav-rO4Nqnh-.js} +0 -0
  286. /package/client/dist/assets/{nav-DVp1nEsi.js → nav-zyBhf29M.js} +0 -0
  287. /package/client/dist/assets/{objective-c-DfOmda-5.js → objective-c-CLUvUl9T.js} +0 -0
  288. /package/client/dist/assets/{pascal-DoAA2yjy.js → pascal-BnU1HU42.js} +0 -0
  289. /package/client/dist/assets/{pascaligo-C65Vn1fu.js → pascaligo-dsKvjFzi.js} +0 -0
  290. /package/client/dist/assets/{perl-INlfQ_ro.js → perl-CZne1GYG.js} +0 -0
  291. /package/client/dist/assets/{pgsql-DtwRzglx.js → pgsql-CMa5W_iF.js} +0 -0
  292. /package/client/dist/assets/{php-DfHqVNet.js → php-Cu4mS35J.js} +0 -0
  293. /package/client/dist/assets/{pla-D3dNVRYk.js → pla-B7COwnnm.js} +0 -0
  294. /package/client/dist/assets/{postiats-UKXD1rM4.js → postiats-GLeNtnBQ.js} +0 -0
  295. /package/client/dist/assets/{powerquery-zE3E3O7s.js → powerquery-BqPf3R1W.js} +0 -0
  296. /package/client/dist/assets/{powershell-Df9b3zQl.js → powershell-D9btb5su.js} +0 -0
  297. /package/client/dist/assets/{protobuf-BF0nUVrW.js → protobuf-6GHSuaNm.js} +0 -0
  298. /package/client/dist/assets/{pug-Bj6Yikv_.js → pug-ct6rYKQd.js} +0 -0
  299. /package/client/dist/assets/{qsharp-BI4h-raZ.js → qsharp-CIrAQNPy.js} +0 -0
  300. /package/client/dist/assets/{r-DhpnmaXx.js → r-Bk-a0sON.js} +0 -0
  301. /package/client/dist/assets/{redis-DwYYPr4d.js → redis-C9yfaWYh.js} +0 -0
  302. /package/client/dist/assets/{redshift-D2f3Bc-4.js → redshift-DaOT1jRU.js} +0 -0
  303. /package/client/dist/assets/{restructuredtext-Dkiif6fe.js → restructuredtext-C1t9LQfS.js} +0 -0
  304. /package/client/dist/assets/{ruby-C6hLmHy0.js → ruby-COiPZJjc.js} +0 -0
  305. /package/client/dist/assets/{rust-X8WAGtxB.js → rust--gZOJZzj.js} +0 -0
  306. /package/client/dist/assets/{sb-4M2la0Kr.js → sb-NHf3iazF.js} +0 -0
  307. /package/client/dist/assets/{scala-CaCXz58E.js → scala-D1nO1TBd.js} +0 -0
  308. /package/client/dist/assets/{scheme-CMdjpmP7.js → scheme-Bref42s5.js} +0 -0
  309. /package/client/dist/assets/{scss-QopmvPyp.js → scss-BS9CCLr3.js} +0 -0
  310. /package/client/dist/assets/{settings-DyBxunCh.js → settings-BN4dufu6.js} +0 -0
  311. /package/client/dist/assets/{settings-BN7OusER.js → settings-Bap_q3rt.js} +0 -0
  312. /package/client/dist/assets/{settings-Bi5FFkIw.js → settings-BlYjWMy5.js} +0 -0
  313. /package/client/dist/assets/{settings-iQe5Dim-.js → settings-C7t_uUz4.js} +0 -0
  314. /package/client/dist/assets/{settings-fk-WlnUt.js → settings-CIFrUsKt.js} +0 -0
  315. /package/client/dist/assets/{settings-BA1V6KdK.js → settings-Cbj9VWmI.js} +0 -0
  316. /package/client/dist/assets/{settings-CRJxyTNN.js → settings-D7saHMU8.js} +0 -0
  317. /package/client/dist/assets/{settings-0m2iuTzd.js → settings-DrRjM5e8.js} +0 -0
  318. /package/client/dist/assets/{shell-CDBchS00.js → shell-DT3joMBB.js} +0 -0
  319. /package/client/dist/assets/{solidity-DvBfi5mC.js → solidity-o2Fm9dvg.js} +0 -0
  320. /package/client/dist/assets/{sophia-HSnXR17u.js → sophia-Dj1N6Xqb.js} +0 -0
  321. /package/client/dist/assets/{sparql-DhG_ppup.js → sparql-D2fjpTWm.js} +0 -0
  322. /package/client/dist/assets/{specs-BvsFNKTs.js → specs-C-WXGBqy.js} +0 -0
  323. /package/client/dist/assets/{specs-D4ORogcT.js → specs-C57koADY.js} +0 -0
  324. /package/client/dist/assets/{specs-CnH7dOiF.js → specs-CCXV-eSF.js} +0 -0
  325. /package/client/dist/assets/{specs-CUE3xSFM.js → specs-CYA5Bv7Q.js} +0 -0
  326. /package/client/dist/assets/{specs-C2wW5bq8.js → specs-DFCFg51O.js} +0 -0
  327. /package/client/dist/assets/{specs-C_8j4ELZ.js → specs-Dslng_yW.js} +0 -0
  328. /package/client/dist/assets/{specs-D6Y76Bgi.js → specs-DwRPiJTc.js} +0 -0
  329. /package/client/dist/assets/{specs-Bku8SypT.js → specs-DzlROLy7.js} +0 -0
  330. /package/client/dist/assets/{sql-DHeIS-tf.js → sql-BArhsPUz.js} +0 -0
  331. /package/client/dist/assets/{st-CMWchiRU.js → st-Bd2-tALj.js} +0 -0
  332. /package/client/dist/assets/{swift-CDXvBefj.js → swift-DvEpXBKj.js} +0 -0
  333. /package/client/dist/assets/{systemverilog-0RTukYUE.js → systemverilog-mHEbsnVH.js} +0 -0
  334. /package/client/dist/assets/{tcl-CbBF_Ttl.js → tcl-DePutp1e.js} +0 -0
  335. /package/client/dist/assets/{terminal-CB33IsO1.js → terminal-2S-Wsk6L.js} +0 -0
  336. /package/client/dist/assets/{terminal-Cz_Puz0q.js → terminal-BRQMrU74.js} +0 -0
  337. /package/client/dist/assets/{terminal-DFEH9XTQ.js → terminal-BTiemy98.js} +0 -0
  338. /package/client/dist/assets/{terminal-BTanJIt_.js → terminal-CjQeWfpp.js} +0 -0
  339. /package/client/dist/assets/{terminal-CY_sPfdD.js → terminal-CmP5riTU.js} +0 -0
  340. /package/client/dist/assets/{terminal-BLh00ouM.js → terminal-CnObBCAh.js} +0 -0
  341. /package/client/dist/assets/{terminal-CR6t-Oey.js → terminal-DcPKgKMN.js} +0 -0
  342. /package/client/dist/assets/{terminal-Cj4HzP3p.js → terminal-XciDq6VV.js} +0 -0
  343. /package/client/dist/assets/{tickets-OrJwUxJR.js → tickets-7kl_0jgM.js} +0 -0
  344. /package/client/dist/assets/{tickets-68LH1xp6.js → tickets-BSyaZI8d.js} +0 -0
  345. /package/client/dist/assets/{tickets-blQnNA4N.js → tickets-CcTcvwKS.js} +0 -0
  346. /package/client/dist/assets/{tickets-D6f3GSYn.js → tickets-D75vyZJj.js} +0 -0
  347. /package/client/dist/assets/{tickets-PtHNxQo5.js → tickets-D79ZT2SZ.js} +0 -0
  348. /package/client/dist/assets/{tickets-DBQXMYYA.js → tickets-DbcMWq5L.js} +0 -0
  349. /package/client/dist/assets/{tickets-jxsTrApR.js → tickets-ZA_2iPd1.js} +0 -0
  350. /package/client/dist/assets/{tickets-REr-EQx9.js → tickets-mxd23fWX.js} +0 -0
  351. /package/client/dist/assets/{twig-DCcGd8FE.js → twig-DQ2zIX0b.js} +0 -0
  352. /package/client/dist/assets/{typespec-HTphp-Uh.js → typespec-DPoaiGTJ.js} +0 -0
  353. /package/client/dist/assets/{vb-Cb_yUcVd.js → vb-Jo98wdMr.js} +0 -0
  354. /package/client/dist/assets/{wgsl-DrKU3YXj.js → wgsl-DZc4h_eS.js} +0 -0
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.analyticsTools = analyticsTools;
4
+ const zod_1 = require("zod");
5
+ const types_1 = require("./types");
6
+ /**
7
+ * Build a `?a=b&c=d` query string from a flat record, skipping undefined/null/''
8
+ * values. Arrays are joined with commas (the spending router parses CSV for
9
+ * surface/model/modelProvider/provider). Used by the read actions below.
10
+ */
11
+ function buildQuery(params) {
12
+ const parts = [];
13
+ for (const [k, v] of Object.entries(params)) {
14
+ if (v === undefined || v === null || v === '')
15
+ continue;
16
+ const value = Array.isArray(v) ? v.join(',') : String(v);
17
+ if (value === '')
18
+ continue;
19
+ parts.push(`${encodeURIComponent(k)}=${encodeURIComponent(value)}`);
20
+ }
21
+ return parts.length ? `?${parts.join('&')}` : '';
22
+ }
23
+ function analyticsTools() {
24
+ return [
25
+ {
26
+ name: 'specrails_analytics',
27
+ title: 'Analytics & Spending',
28
+ description: 'Per-project cost analytics over billable AI-CLI invocations (jobs, quick-spec, explore-spec, ai-edit, smash, file-summary, loop). ' +
29
+ 'All read-only except set_budget. Actions: ' +
30
+ 'spending (full dashboard: cost summary with prev-period delta, by-surface/model/mode/provider breakdowns, daily timeline, cost-vs-turns scatter, top tickets), ' +
31
+ 'invocations (paginated raw invocation table), ' +
32
+ 'ticket_summary (per-ticket cost aggregate across all surfaces), ' +
33
+ 'export (download summary/raw analytics as CSV or JSON — file download, returns a note + headers), ' +
34
+ 'budget_get (daily budget, per-job threshold, cost-today, utilization %), ' +
35
+ 'budget_set (write — set/clear daily budget cap + per-job cost threshold; a too-low budget pauses the job queue). ' +
36
+ 'Prefer spending over invocations/export-raw for token economy. ' +
37
+ 'Filters: period(7d|30d|90d|all|custom), from/to (ISO, required for custom), surface[], model[], modelProvider[] (index-aligned to model), provider[], status(success|failed|aborted), minCostUsd, ticketId, tzOffsetMinutes(±840 — pass the user local offset so "today" lines up), sortBy.',
38
+ hintTier: 'read',
39
+ tier: (a) => (a.action === 'budget_set' ? 'write' : 'read'),
40
+ inputSchema: {
41
+ action: zod_1.z
42
+ .enum(['spending', 'invocations', 'ticket_summary', 'export', 'budget_get', 'budget_set'])
43
+ .describe('Operation to perform'),
44
+ projectId: zod_1.z.string().optional().describe('Project id (defaults to the active project)'),
45
+ // ─── Filters shared by spending / invocations / export ────────────────
46
+ period: zod_1.z
47
+ .enum(['7d', '30d', '90d', 'all', 'custom'])
48
+ .optional()
49
+ .describe('Time window (default 30d). "custom" requires from + to.'),
50
+ from: zod_1.z.string().optional().describe('ISO start date (required when period=custom)'),
51
+ to: zod_1.z.string().optional().describe('ISO end date (required when period=custom)'),
52
+ surface: zod_1.z
53
+ .array(zod_1.z.enum(['job', 'quick-spec', 'explore-spec', 'ai-edit', 'smash', 'file-summary', 'loop']))
54
+ .optional()
55
+ .describe('Filter to these surfaces (CSV)'),
56
+ model: zod_1.z.array(zod_1.z.string()).optional().describe('Filter to these model ids (CSV)'),
57
+ modelProvider: zod_1.z
58
+ .array(zod_1.z.string())
59
+ .optional()
60
+ .describe('Providers index-aligned to model[] (scopes each model id to its provider so codex/gemini estimated cost does not merge into a claude bar)'),
61
+ provider: zod_1.z
62
+ .array(zod_1.z.string())
63
+ .optional()
64
+ .describe('Filter to these providers (e.g. claude, codex, gemini) (CSV)'),
65
+ status: zod_1.z.enum(['success', 'failed', 'aborted']).optional().describe('Filter by invocation status'),
66
+ minCostUsd: zod_1.z.number().optional().describe('Only invocations costing at least this many USD'),
67
+ ticketId: zod_1.z.number().int().optional().describe('Scope to a single ticket id'),
68
+ tzOffsetMinutes: zod_1.z
69
+ .number()
70
+ .int()
71
+ .optional()
72
+ .describe('Local UTC offset in minutes (±840) for daily-timeline calendar-day bucketing (default 0 = UTC)'),
73
+ sortBy: zod_1.z.enum(['recency', 'cost']).optional().describe('Sort order'),
74
+ // ─── invocations pagination ───────────────────────────────────────────
75
+ limit: zod_1.z
76
+ .number()
77
+ .int()
78
+ .optional()
79
+ .describe('invocations: max rows (clamped server-side to [1, 10000])'),
80
+ offset: zod_1.z.number().int().optional().describe('invocations: row offset for pagination'),
81
+ // ─── ticket_summary ───────────────────────────────────────────────────
82
+ id: zod_1.z.number().int().optional().describe('ticket_summary: the ticket id to aggregate'),
83
+ // ─── export ───────────────────────────────────────────────────────────
84
+ format: zod_1.z.enum(['csv', 'json']).optional().describe('export: output format (default json)'),
85
+ mode: zod_1.z
86
+ .enum(['summary', 'raw'])
87
+ .optional()
88
+ .describe('export: summary (aggregated dashboard) or raw (up to 10000 invocation rows). Default summary.'),
89
+ // ─── budget_set ───────────────────────────────────────────────────────
90
+ dailyBudgetUsd: zod_1.z
91
+ .number()
92
+ .nullable()
93
+ .optional()
94
+ .describe('budget_set: daily budget cap USD (>0); null clears it'),
95
+ jobCostThresholdUsd: zod_1.z
96
+ .number()
97
+ .nullable()
98
+ .optional()
99
+ .describe('budget_set: per-job cost alert threshold USD (>0); null clears it'),
100
+ },
101
+ async handler(ctx, args) {
102
+ const base = (0, types_1.projectPath)(ctx, args.projectId);
103
+ const action = args.action;
104
+ const filters = {
105
+ period: args.period,
106
+ from: args.from,
107
+ to: args.to,
108
+ surface: args.surface,
109
+ model: args.model,
110
+ modelProvider: args.modelProvider,
111
+ provider: args.provider,
112
+ status: args.status,
113
+ minCostUsd: args.minCostUsd,
114
+ ticketId: args.ticketId,
115
+ tzOffsetMinutes: args.tzOffsetMinutes,
116
+ sortBy: args.sortBy,
117
+ };
118
+ switch (action) {
119
+ case 'spending':
120
+ return (0, types_1.apiCall)(ctx, 'GET', `${base}/spending${buildQuery(filters)}`);
121
+ case 'invocations':
122
+ return (0, types_1.apiCall)(ctx, 'GET', `${base}/invocations${buildQuery({
123
+ ...filters,
124
+ limit: args.limit,
125
+ offset: args.offset,
126
+ })}`);
127
+ case 'ticket_summary': {
128
+ const id = args.id;
129
+ if (id === undefined || id === null) {
130
+ throw new Error('ticket_summary requires an "id" (ticket id).');
131
+ }
132
+ return (0, types_1.apiCall)(ctx, 'GET', `${base}/tickets/${id}/spending-summary`);
133
+ }
134
+ case 'export': {
135
+ // GET /analytics/export streams a file download (Content-Disposition).
136
+ // apiCall returns the body text/JSON; for CSV it is the raw CSV string,
137
+ // for JSON the parsed dashboard/invocations object. We surface it
138
+ // inline with a note since there is no file sink over MCP.
139
+ const format = args.format ?? 'json';
140
+ const mode = args.mode ?? 'summary';
141
+ const data = await (0, types_1.apiCall)(ctx, 'GET', `${base}/analytics/export${buildQuery({ ...filters, format, mode })}`);
142
+ return {
143
+ note: `Analytics export (mode=${mode}, format=${format}). This endpoint is normally a file download; the content is returned inline below. Raw mode caps at 10000 rows. Prefer the "spending" action for already-aggregated, bounded data.`,
144
+ format,
145
+ mode,
146
+ data,
147
+ };
148
+ }
149
+ case 'budget_get':
150
+ return (0, types_1.apiCall)(ctx, 'GET', `${base}/budget`);
151
+ case 'budget_set': {
152
+ const body = {};
153
+ if ('dailyBudgetUsd' in args)
154
+ body.dailyBudgetUsd = args.dailyBudgetUsd;
155
+ if ('jobCostThresholdUsd' in args)
156
+ body.jobCostThresholdUsd = args.jobCostThresholdUsd;
157
+ if (Object.keys(body).length === 0) {
158
+ throw new Error('budget_set requires dailyBudgetUsd and/or jobCostThresholdUsd (number>0 to set, null to clear).');
159
+ }
160
+ return (0, types_1.apiCall)(ctx, 'PATCH', `${base}/budget`, body);
161
+ }
162
+ default:
163
+ throw new Error(`Unknown action "${action}".`);
164
+ }
165
+ },
166
+ },
167
+ ];
168
+ }
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.appTools = appTools;
4
+ const zod_1 = require("zod");
5
+ const desktop_db_1 = require("../../desktop-db");
6
+ const mcp_tiers_1 = require("../mcp-tiers");
7
+ // App-level settings the MCP may read/write. NOTE: the MCP enable flag and the
8
+ // permission-tier toggles are intentionally NOT writable here — an external LLM
9
+ // must never be able to escalate its own permissions. Those are user-only,
10
+ // changed in the Settings ▸ MCP panel.
11
+ const WRITABLE_THEMES = ['specrails', 'dracula', 'aurora-light', 'obsidian-dark', 'matrix'];
12
+ const WRITABLE_LANGS = ['en', 'es', 'fr', 'de', 'pt', 'it', 'zh', 'ja'];
13
+ function appTools() {
14
+ return [
15
+ {
16
+ name: 'specrails_settings',
17
+ title: 'App settings',
18
+ description: 'Read or update app-level Specrails settings (theme, language, daily budget, cost-alert threshold). ' +
19
+ 'Actions: get, set. The MCP enable flag and permission tiers are read-only here (user-controlled in the app).',
20
+ hintTier: 'read',
21
+ tier: (args) => (args.action === 'set' ? 'write' : 'read'),
22
+ inputSchema: {
23
+ action: zod_1.z.enum(['get', 'set']).describe('Operation'),
24
+ theme: zod_1.z.enum(WRITABLE_THEMES).optional(),
25
+ language: zod_1.z.enum(WRITABLE_LANGS).optional(),
26
+ dailyBudgetUsd: zod_1.z.number().min(0).nullable().optional(),
27
+ costAlertThresholdUsd: zod_1.z.number().min(0).nullable().optional(),
28
+ },
29
+ handler: (ctx, args) => {
30
+ const db = ctx.desktopDb;
31
+ if (args.action === 'get') {
32
+ return {
33
+ theme: (0, desktop_db_1.getDesktopSetting)(db, 'ui_theme') ?? 'specrails',
34
+ language: (0, desktop_db_1.getDesktopSetting)(db, 'ui_language') ?? null,
35
+ dailyBudgetUsd: num((0, desktop_db_1.getDesktopSetting)(db, 'desktop_daily_budget_usd')),
36
+ costAlertThresholdUsd: num((0, desktop_db_1.getDesktopSetting)(db, 'cost_alert_threshold_usd')),
37
+ mcp: {
38
+ enabled: (0, mcp_tiers_1.isMcpEnabled)(db),
39
+ tierWrite: (0, mcp_tiers_1.isTierEnabled)(db, 'write'),
40
+ tierAiSpawn: (0, mcp_tiers_1.isTierEnabled)(db, 'ai-spawn'),
41
+ tierDestructive: (0, mcp_tiers_1.isTierEnabled)(db, 'destructive'),
42
+ },
43
+ };
44
+ }
45
+ // set
46
+ const changed = [];
47
+ if (args.theme !== undefined) {
48
+ (0, desktop_db_1.setDesktopSetting)(db, 'ui_theme', String(args.theme));
49
+ changed.push('theme');
50
+ }
51
+ if (args.language !== undefined) {
52
+ (0, desktop_db_1.setDesktopSetting)(db, 'ui_language', String(args.language));
53
+ changed.push('language');
54
+ }
55
+ if (args.dailyBudgetUsd !== undefined) {
56
+ writeNumOrClear(db, 'desktop_daily_budget_usd', args.dailyBudgetUsd);
57
+ changed.push('dailyBudgetUsd');
58
+ }
59
+ if (args.costAlertThresholdUsd !== undefined) {
60
+ writeNumOrClear(db, 'cost_alert_threshold_usd', args.costAlertThresholdUsd);
61
+ changed.push('costAlertThresholdUsd');
62
+ }
63
+ if (!changed.length)
64
+ throw new Error('set requires at least one field (theme, language, dailyBudgetUsd, costAlertThresholdUsd).');
65
+ return { ok: true, changed };
66
+ },
67
+ },
68
+ ];
69
+ }
70
+ function num(v) {
71
+ if (v === undefined)
72
+ return null;
73
+ const n = Number(v);
74
+ return Number.isFinite(n) ? n : null;
75
+ }
76
+ function writeNumOrClear(db, key, value) {
77
+ if (value === null)
78
+ (0, desktop_db_1.setDesktopSetting)(db, key, '');
79
+ else
80
+ (0, desktop_db_1.setDesktopSetting)(db, key, String(value));
81
+ }
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildToolSpecs = buildToolSpecs;
4
+ const projects_1 = require("./projects");
5
+ const app_settings_1 = require("./app-settings");
6
+ const watch_1 = require("./watch");
7
+ const meta_1 = require("./meta");
8
+ const specs_1 = require("./specs");
9
+ const rails_1 = require("./rails");
10
+ const jobs_1 = require("./jobs");
11
+ const chat_1 = require("./chat");
12
+ const agents_1 = require("./agents");
13
+ const plugins_1 = require("./plugins");
14
+ const jira_1 = require("./jira");
15
+ const loops_1 = require("./loops");
16
+ const code_1 = require("./code");
17
+ const setup_1 = require("./setup");
18
+ const analytics_1 = require("./analytics");
19
+ /**
20
+ * The full MCP tool catalog. Domain-facade tools each expose an `action` enum
21
+ * and call the app's REST API over loopback (see apiCall). Meta tools receive a
22
+ * lazy getter so `search`/`describe` can see the whole list.
23
+ */
24
+ function buildToolSpecs() {
25
+ const specs = [];
26
+ // App-level + meta + watch
27
+ specs.push(...(0, projects_1.projectsTools)());
28
+ specs.push(...(0, app_settings_1.appTools)());
29
+ specs.push((0, watch_1.watchTool)());
30
+ // Per-project domains
31
+ specs.push(...(0, specs_1.specsTools)());
32
+ specs.push(...(0, rails_1.railsTools)());
33
+ specs.push(...(0, jobs_1.jobsTools)());
34
+ specs.push(...(0, chat_1.chatTools)());
35
+ specs.push(...(0, agents_1.agentsTools)());
36
+ specs.push(...(0, plugins_1.pluginsTools)());
37
+ specs.push(...(0, jira_1.jiraTools)());
38
+ specs.push(...(0, loops_1.loopsTools)());
39
+ specs.push(...(0, code_1.codeTools)());
40
+ specs.push(...(0, setup_1.setupTools)());
41
+ specs.push(...(0, analytics_1.analyticsTools)());
42
+ // Meta last (needs the full list for search/describe)
43
+ specs.push(...(0, meta_1.metaTools)(() => specs));
44
+ return specs;
45
+ }
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.chatTools = chatTools;
4
+ const zod_1 = require("zod");
5
+ const types_1 = require("./types");
6
+ /**
7
+ * Chat / Explore conversations for a project. A domain-facade tool over the
8
+ * per-project chat routes in `server/project-router-chat.ts`. The agent-refine
9
+ * (AI-edit) routes under `/profiles/catalog/:agentId/refine` are intentionally
10
+ * NOT here — they belong to the agents domain.
11
+ *
12
+ * `send` is the only cost-incurring action: it 202-accepts and streams the
13
+ * assistant reply over WebSocket, so it returns a watch hint keyed on the
14
+ * conversation id.
15
+ */
16
+ function chatTools() {
17
+ return [
18
+ {
19
+ name: 'specrails_chat',
20
+ title: 'Chat / Explore',
21
+ description: 'Manage a project\'s chat & Explore-Spec conversations and drive their AI turns. ' +
22
+ 'Actions: list_conversations, get (conversation + messages), create (kind sidebar|explore, optional provider/model/contextScope), ' +
23
+ 'send (cost-incurring — spawns the AI CLI and streams the reply async over WS), abort (interrupt the in-flight turn), ' +
24
+ 'delete (destructive — removes the conversation, its messages, and clears linked draft origin), minimize (arm Explore idle-kill timer), ' +
25
+ 'restore (cancel the idle-kill timer), spec_draft (read the in-memory Explore spec-draft state), messages (persisted history only).',
26
+ hintTier: 'read',
27
+ tier: (a) => {
28
+ const action = a.action;
29
+ if (action === 'delete')
30
+ return 'destructive';
31
+ if (action === 'send')
32
+ return 'ai-spawn';
33
+ if (action === 'create' || action === 'update' || action === 'abort' || action === 'minimize' || action === 'restore')
34
+ return 'write';
35
+ return 'read';
36
+ },
37
+ inputSchema: {
38
+ action: zod_1.z
39
+ .enum([
40
+ 'list_conversations',
41
+ 'get',
42
+ 'create',
43
+ 'update',
44
+ 'send',
45
+ 'abort',
46
+ 'delete',
47
+ 'minimize',
48
+ 'restore',
49
+ 'spec_draft',
50
+ 'messages',
51
+ ])
52
+ .describe('Operation to perform'),
53
+ projectId: zod_1.z.string().optional().describe('Project id (defaults to the active project)'),
54
+ conversationId: zod_1.z.string().optional().describe('Conversation id (required for get/update/send/abort/delete/minimize/restore/spec_draft/messages)'),
55
+ // create params
56
+ kind: zod_1.z.enum(['sidebar', 'explore']).optional().describe('Conversation kind for create (default sidebar)'),
57
+ provider: zod_1.z.string().optional().describe('AI engine for create — must be installed on the project (alias of aiEngine); defaults to the primary provider'),
58
+ model: zod_1.z.string().optional().describe('Model for create/update — must be valid for the conversation\'s provider'),
59
+ contextScope: zod_1.z
60
+ .record(zod_1.z.unknown())
61
+ .optional()
62
+ .describe('Explore-only context scope flags for create (mcp/userMcp/full/specrails/openspec/contractRefine)'),
63
+ // update params
64
+ title: zod_1.z.string().optional().describe('New title for update'),
65
+ // send params
66
+ text: zod_1.z.string().optional().describe('User message text for send (required)'),
67
+ lightweight: zod_1.z.boolean().optional().describe('Use the lightweight system prompt for send'),
68
+ maxTurns: zod_1.z.number().optional().describe('Max agent turns for send'),
69
+ attachments: zod_1.z
70
+ .object({
71
+ ticketKey: zod_1.z.string().describe('Ticket key the attachments belong to'),
72
+ ids: zod_1.z.array(zod_1.z.string()).describe('Uploaded attachment ids'),
73
+ })
74
+ .optional()
75
+ .describe('Attachment references for send'),
76
+ },
77
+ async handler(ctx, args) {
78
+ const base = (0, types_1.projectPath)(ctx, args.projectId);
79
+ const action = args.action;
80
+ const convId = args.conversationId;
81
+ const requireConv = () => {
82
+ if (!convId)
83
+ throw new Error(`Action "${action}" requires a "conversationId".`);
84
+ return convId;
85
+ };
86
+ switch (action) {
87
+ case 'list_conversations':
88
+ return (0, types_1.apiCall)(ctx, 'GET', `${base}/chat/conversations`);
89
+ case 'get':
90
+ return (0, types_1.apiCall)(ctx, 'GET', `${base}/chat/conversations/${requireConv()}`);
91
+ case 'messages':
92
+ return (0, types_1.apiCall)(ctx, 'GET', `${base}/chat/conversations/${requireConv()}/messages`);
93
+ case 'spec_draft':
94
+ return (0, types_1.apiCall)(ctx, 'GET', `${base}/chat/conversations/${requireConv()}/spec-draft`);
95
+ case 'create': {
96
+ const body = {};
97
+ if (args.kind !== undefined)
98
+ body.kind = args.kind;
99
+ if (args.provider !== undefined)
100
+ body.aiEngine = args.provider;
101
+ if (args.model !== undefined)
102
+ body.model = args.model;
103
+ if (args.contextScope !== undefined)
104
+ body.contextScope = args.contextScope;
105
+ return (0, types_1.apiCall)(ctx, 'POST', `${base}/chat/conversations`, body);
106
+ }
107
+ case 'update': {
108
+ const body = {};
109
+ if (args.title !== undefined)
110
+ body.title = args.title;
111
+ if (args.model !== undefined)
112
+ body.model = args.model;
113
+ return (0, types_1.apiCall)(ctx, 'PATCH', `${base}/chat/conversations/${requireConv()}`, body);
114
+ }
115
+ case 'send': {
116
+ const text = args.text;
117
+ if (!text || !text.trim())
118
+ throw new Error('send requires non-empty "text".');
119
+ const body = { text: text.trim() };
120
+ if (args.lightweight !== undefined)
121
+ body.lightweight = args.lightweight;
122
+ if (args.maxTurns !== undefined)
123
+ body.maxTurns = args.maxTurns;
124
+ if (args.attachments !== undefined)
125
+ body.attachments = args.attachments;
126
+ const r = (await (0, types_1.apiCall)(ctx, 'POST', `${base}/chat/conversations/${requireConv()}/messages`, body));
127
+ return {
128
+ ...r,
129
+ conversationId: requireConv(),
130
+ hint: `Turn accepted (202). The assistant reply streams over WebSocket — use specrails_watch with conversationId "${requireConv()}" to await completion (chat_done / chat_error).`,
131
+ };
132
+ }
133
+ case 'abort':
134
+ return (0, types_1.apiCall)(ctx, 'DELETE', `${base}/chat/conversations/${requireConv()}/messages/stream`);
135
+ case 'delete':
136
+ return (0, types_1.apiCall)(ctx, 'DELETE', `${base}/chat/conversations/${requireConv()}`);
137
+ case 'minimize':
138
+ return (0, types_1.apiCall)(ctx, 'POST', `${base}/chat/conversations/${requireConv()}/minimize`);
139
+ case 'restore':
140
+ return (0, types_1.apiCall)(ctx, 'POST', `${base}/chat/conversations/${requireConv()}/restore`);
141
+ default:
142
+ throw new Error(`Unknown action "${action}".`);
143
+ }
144
+ },
145
+ },
146
+ ];
147
+ }
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.codeTools = codeTools;
4
+ const zod_1 = require("zod");
5
+ const types_1 = require("./types");
6
+ /**
7
+ * Read-only Code Explorer surface for a project: the AI-touched file tree,
8
+ * file contents + plain-language AI summaries, "touched by AI" provenance, and
9
+ * stored per-file diffs — plus the one cost-incurring action, regenerating a
10
+ * file's AI summary (async, fire-and-forget over WS).
11
+ *
12
+ * Every op is per-project under `/api/projects/:projectId/code/*`. The v1 edit
13
+ * path (PUT /code/file) is intentionally NOT exposed — Code Explorer is
14
+ * read-only here. The app-level GET/PATCH /api/code-explorer-settings ops are
15
+ * app-scoped settings, surfaced by the settings domain, not here.
16
+ *
17
+ * Encode query strings explicitly so file paths with spaces/`#`/`?` survive.
18
+ */
19
+ function codeTools() {
20
+ return [
21
+ {
22
+ name: 'specrails_code',
23
+ title: 'Code Explorer',
24
+ description: 'Read-only browse a project\'s source through the Code Explorer: list the file tree ' +
25
+ '(default scoped to AI-touched files, optional provenance rollup), read a file with its ' +
26
+ 'AI summary + staleness + provenance, fetch a stored summary alone, regenerate a file\'s ' +
27
+ 'AI summary (cost-incurring, async), list "touched by AI" provenance rows, and fetch the ' +
28
+ 'stored unified-diff a job applied to a file. ' +
29
+ 'Actions: tree, read_file, summary, regenerate_summary (ai-spawn — spawns an AI CLI, ' +
30
+ 'incurs cost, returns 202 then completes over WS), provenance, diff. ' +
31
+ 'Requires SPECRAILS_CODE_EXPLORER (default on); the /code prefix 404s when disabled.',
32
+ hintTier: 'read',
33
+ tier: (a) => (a.action === 'regenerate_summary' ? 'ai-spawn' : 'read'),
34
+ inputSchema: {
35
+ action: zod_1.z
36
+ .enum(['tree', 'read_file', 'summary', 'regenerate_summary', 'provenance', 'diff'])
37
+ .describe('Operation to perform'),
38
+ projectId: zod_1.z.string().optional().describe('Project id (defaults to the active project)'),
39
+ path: zod_1.z
40
+ .string()
41
+ .optional()
42
+ .describe('Project-relative file path. Required for read_file/summary/regenerate_summary/diff; ' +
43
+ 'optional narrowing filter for provenance.'),
44
+ filter: zod_1.z
45
+ .enum(['touched-by-ai', 'all'])
46
+ .optional()
47
+ .describe('tree only: scope to AI-touched files (default) or the whole repo'),
48
+ withProvenance: zod_1.z
49
+ .boolean()
50
+ .optional()
51
+ .describe('tree only: include per-file/dir provenance rollup (created-by / modified-by chips)'),
52
+ cursor: zod_1.z
53
+ .string()
54
+ .optional()
55
+ .describe('tree only: opaque pagination cursor from a prior response\'s nextCursor'),
56
+ ticketId: zod_1.z
57
+ .number()
58
+ .int()
59
+ .positive()
60
+ .optional()
61
+ .describe('tree/provenance: narrow to files touched by this ticket'),
62
+ jobId: zod_1.z
63
+ .string()
64
+ .optional()
65
+ .describe('tree/provenance/diff: narrow to a job; required for diff'),
66
+ overrideBudget: zod_1.z
67
+ .boolean()
68
+ .optional()
69
+ .describe('regenerate_summary only: bypass the monthly summary budget cap. Privileged — ' +
70
+ 'incurs cost beyond the configured limit.'),
71
+ },
72
+ async handler(ctx, args) {
73
+ const base = (0, types_1.projectPath)(ctx, args.projectId);
74
+ const action = args.action;
75
+ const requirePath = () => {
76
+ const p = args.path;
77
+ if (!p || p.trim() === '')
78
+ throw new Error(`Action "${action}" requires a "path".`);
79
+ return p;
80
+ };
81
+ switch (action) {
82
+ case 'tree': {
83
+ const qs = new URLSearchParams();
84
+ if (args.filter)
85
+ qs.set('filter', args.filter);
86
+ if (args.withProvenance === true)
87
+ qs.set('withProvenance', '1');
88
+ if (args.cursor)
89
+ qs.set('cursor', args.cursor);
90
+ if (typeof args.ticketId === 'number')
91
+ qs.set('ticketId', String(args.ticketId));
92
+ if (args.jobId)
93
+ qs.set('jobId', args.jobId);
94
+ const suffix = qs.toString() ? `?${qs.toString()}` : '';
95
+ return (0, types_1.apiCall)(ctx, 'GET', `${base}/code/tree${suffix}`);
96
+ }
97
+ case 'read_file': {
98
+ const qs = new URLSearchParams({ path: requirePath() });
99
+ return (0, types_1.apiCall)(ctx, 'GET', `${base}/code/file?${qs.toString()}`);
100
+ }
101
+ case 'summary': {
102
+ const qs = new URLSearchParams({ path: requirePath() });
103
+ return (0, types_1.apiCall)(ctx, 'GET', `${base}/code/summary?${qs.toString()}`);
104
+ }
105
+ case 'regenerate_summary': {
106
+ const qs = new URLSearchParams({ path: requirePath() });
107
+ const r = (await (0, types_1.apiCall)(ctx, 'POST', `${base}/code/file/regenerate-summary?${qs.toString()}`, { overrideBudget: args.overrideBudget === true }));
108
+ // 202 → enqueued; 200 → { skipped: '...' }. Either way the real
109
+ // outcome (summary ready / failed / skipped) arrives over WS, not in
110
+ // this response, so always point the caller at the live channel.
111
+ return {
112
+ ...r,
113
+ hint: 'Summary generation is async and cost-incurring. The outcome arrives over the ' +
114
+ 'WS channel as file.summary_updated / file.summary_failed / file.summary_skipped ' +
115
+ "(reason: 'budget'|'per-job-cap'|'ttl'|'not-found'), NOT in this response. A 202 " +
116
+ '{ enqueued: true } only means it was queued; a 200 { skipped } means it never ran.',
117
+ };
118
+ }
119
+ case 'provenance': {
120
+ const qs = new URLSearchParams();
121
+ if (typeof args.ticketId === 'number')
122
+ qs.set('ticketId', String(args.ticketId));
123
+ if (args.jobId)
124
+ qs.set('jobId', args.jobId);
125
+ if (args.path)
126
+ qs.set('path', args.path);
127
+ if (![...qs.keys()].length) {
128
+ throw new Error('Action "provenance" requires at least one of: ticketId, jobId, path.');
129
+ }
130
+ return (0, types_1.apiCall)(ctx, 'GET', `${base}/code/provenance?${qs.toString()}`);
131
+ }
132
+ case 'diff': {
133
+ const jobId = args.jobId;
134
+ if (!jobId)
135
+ throw new Error('Action "diff" requires a "jobId".');
136
+ const qs = new URLSearchParams({ jobId, path: requirePath() });
137
+ return (0, types_1.apiCall)(ctx, 'GET', `${base}/code/diff?${qs.toString()}`);
138
+ }
139
+ default:
140
+ throw new Error(`Unknown action "${action}".`);
141
+ }
142
+ },
143
+ },
144
+ ];
145
+ }