specrails-desktop 2.58.0 → 2.59.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 (425) hide show
  1. package/README.md +2 -5
  2. package/client/dist/assets/{ActivityFeedPage-BQGppIR0.js → ActivityFeedPage-DBFt8ZHP.js} +1 -1
  3. package/client/dist/assets/AgentBrowserCapture-DiQx0W67.js +1 -0
  4. package/client/dist/assets/AgentModeAnalyticsPane-BmDSXp_J.js +2 -0
  5. package/client/dist/assets/AgentModeCodePane-BLQLPSwr.js +2 -0
  6. package/client/dist/assets/{AgentModeJobsPane-DR_06oqH.js → AgentModeJobsPane-BbTXdKUa.js} +1 -1
  7. package/client/dist/assets/{AgentsPage-BKIKjm_1.js → AgentsPage-Dei1jGR8.js} +3 -3
  8. package/client/dist/assets/{AnalyticsPage-069npRVo.js → AnalyticsPage-BhkeGIGn.js} +1 -1
  9. package/client/dist/assets/CodePage-B_9yYWUx.js +3 -0
  10. package/client/dist/assets/{DesktopAnalyticsPage-qtWAPM47.js → DesktopAnalyticsPage-DAcfEJac.js} +1 -1
  11. package/client/dist/assets/DocsDialog-WCuiYgsc.js +11 -0
  12. package/client/dist/assets/DocsPage-bGVYTMTU.js +11 -0
  13. package/client/dist/assets/{ExportDropdown-BcMpvV89.js → ExportDropdown-CsodZ-yb.js} +1 -1
  14. package/client/dist/assets/InteractiveJobComposer-D5fh_eVL.js +19 -0
  15. package/client/dist/assets/JobDetailModal-DlpXF61O.js +1 -0
  16. package/client/dist/assets/JobDetailPage-2yR19_Lb.js +1 -0
  17. package/client/dist/assets/JobsPage-CS9IR6Dq.js +1 -0
  18. package/client/dist/assets/LoopBuilderPage-BwiAtmOr.js +1 -0
  19. package/client/dist/assets/{LoopPreviewModal-je5pSCf-.js → LoopPreviewModal--upwvgTv.js} +1 -1
  20. package/client/dist/assets/LoopWindowSurface-DRnUixtl.js +1 -0
  21. package/client/dist/assets/LoopsPage-Xm3nRToQ.js +2 -0
  22. package/client/dist/assets/MinimizedChatsContext-D_8L4EWZ.js +1 -0
  23. package/client/dist/assets/PluginsPage-CAFQ1B4Q.js +2 -0
  24. package/client/dist/assets/ProjectSettingsDialog-DYSO4v90.js +1 -0
  25. package/client/dist/assets/{RepositoryDeliveries-BiwJuS8r.js → RepositoryDeliveries-CbQmW7Qx.js} +1 -1
  26. package/client/dist/assets/RepositoryScopeSelector-DKzvIGSZ.js +2 -0
  27. package/client/dist/assets/ReviewPacketPage-SDBhYdQB.js +4 -0
  28. package/client/dist/assets/TemplatePreviewModal-DHBUds51.js +1 -0
  29. package/client/dist/assets/TicketDetailModalContext-UAeNm7BB.js +16 -0
  30. package/client/dist/assets/{Trans-D3AfDylf.js → Trans-DExd3Z00.js} +1 -1
  31. package/client/dist/assets/agent-BElLtdKP.js +1 -0
  32. package/client/dist/assets/agent-C-m9VugX.js +1 -0
  33. package/client/dist/assets/agent-CGSKxfZk.js +1 -0
  34. package/client/dist/assets/agent-CW74ODDP.js +1 -0
  35. package/client/dist/assets/agent-DeCAZDhL.js +1 -0
  36. package/client/dist/assets/agent-DrM4qned.js +1 -0
  37. package/client/dist/assets/agent-KdIXq3w5.js +1 -0
  38. package/client/dist/assets/agent-jK8mCisM.js +1 -0
  39. package/client/dist/assets/{agentRuntime-DGz_IqKW.js → agentRuntime-15Pkk6we.js} +1 -1
  40. package/client/dist/assets/agentRuntime-Bpx3yWHK.js +1 -0
  41. package/client/dist/assets/{agentRuntime-Bg9tbmqm.js → agentRuntime-C78n13To.js} +1 -1
  42. package/client/dist/assets/{agentRuntime-D-GJVGkj.js → agentRuntime-CCI7XF4c.js} +1 -1
  43. package/client/dist/assets/{agentRuntime-D2__CVI_.js → agentRuntime-CKDHe2-a.js} +1 -1
  44. package/client/dist/assets/{agentRuntime-D35dGVOP.js → agentRuntime-Ddqvp2bP.js} +1 -1
  45. package/client/dist/assets/{agentRuntime-hInH9Fzj.js → agentRuntime-TXPQowKJ.js} +1 -1
  46. package/client/dist/assets/{agentRuntime-O1liDt6G.js → agentRuntime-hqZRy08E.js} +1 -1
  47. package/client/dist/assets/{builder-DGETbtZj.js → builder-B9gorTnT.js} +1 -1
  48. package/client/dist/assets/{builder-DyQperXU.js → builder-Bvw5s3Mi.js} +1 -1
  49. package/client/dist/assets/{builder-C1neIYGR.js → builder-CL5l4dU3.js} +1 -1
  50. package/client/dist/assets/{builder-DXEJUlC0.js → builder-CVDTVrQX.js} +1 -1
  51. package/client/dist/assets/{builder-CzW5ovyI.js → builder-CpS9liE9.js} +1 -1
  52. package/client/dist/assets/{builder-CvnFm0im.js → builder-DNctIL9Q.js} +1 -1
  53. package/client/dist/assets/{builder-D06L7iPy.js → builder-De2NxX6o.js} +1 -1
  54. package/client/dist/assets/{builder-C0FyvM83.js → builder-DeYT7Y-m.js} +1 -1
  55. package/client/dist/assets/{button-Ccc9Dc-D.js → button-D1xExSTF.js} +1 -1
  56. package/client/dist/assets/{common-DmsclwjP.js → common-Bdi0qN4S.js} +1 -1
  57. package/client/dist/assets/{common-C4Yvvhp6.js → common-Bhb9zN1P.js} +1 -1
  58. package/client/dist/assets/{common-od8WThlf.js → common-BykKlZg1.js} +1 -1
  59. package/client/dist/assets/{common-C0BOdeNi.js → common-CvnNNSJA.js} +1 -1
  60. package/client/dist/assets/{common-BCK7c9Pv.js → common-D5zk_mqq.js} +1 -1
  61. package/client/dist/assets/{common-DpLWwgI1.js → common-DQNO_al5.js} +1 -1
  62. package/client/dist/assets/{common-OCvl3c8t.js → common-Dax30Vmp.js} +1 -1
  63. package/client/dist/assets/{common-c0aujEZC.js → common-DkllpVSb.js} +1 -1
  64. package/client/dist/assets/{dialog-xXB2q5HJ.js → dialog-CMgps2MY.js} +1 -1
  65. package/client/dist/assets/external-link-D6XxC_Cu.js +1 -0
  66. package/client/dist/assets/file-text-BcLCfcWZ.js +1 -0
  67. package/client/dist/assets/{formatDistanceToNow-aBss1Nai.js → formatDistanceToNow-aw7H5ORC.js} +1 -1
  68. package/client/dist/assets/{getTimezoneOffsetInMilliseconds-DOGj1Mfz.js → getTimezoneOffsetInMilliseconds-NyC7gZJX.js} +1 -1
  69. package/client/dist/assets/index-CahchzS5.css +2 -0
  70. package/client/dist/assets/index-JSTZVJfe.js +83 -0
  71. package/client/dist/assets/integrations-BkpRUbvp.js +1 -0
  72. package/client/dist/assets/integrations-Bo8qbJf4.js +1 -0
  73. package/client/dist/assets/integrations-CmSrKzZb.js +1 -0
  74. package/client/dist/assets/integrations-DGtq26Rr.js +1 -0
  75. package/client/dist/assets/integrations-De38GFnQ.js +1 -0
  76. package/client/dist/assets/integrations-Dw6zdtb-.js +1 -0
  77. package/client/dist/assets/integrations-Dwl9KQp0.js +1 -0
  78. package/client/dist/assets/integrations-Refg_d2I.js +1 -0
  79. package/client/dist/assets/jira-api-DlXaRwA3.js +1 -0
  80. package/client/dist/assets/{jobs-KG4Sn12X.js → jobs-1G3wodhl.js} +1 -1
  81. package/client/dist/assets/{jobs-6_-r75yC.js → jobs-B4pu8TdF.js} +1 -1
  82. package/client/dist/assets/{jobs-pPv4KWjb.js → jobs-BD47Ov11.js} +1 -1
  83. package/client/dist/assets/{jobs-B1yqyId5.js → jobs-BLOoVRRl.js} +1 -1
  84. package/client/dist/assets/{jobs-BKiK-ZWh.js → jobs-CSrRx5lD.js} +1 -1
  85. package/client/dist/assets/{jobs-BFuV7ttH.js → jobs-DZAbh1m2.js} +1 -1
  86. package/client/dist/assets/{jobs-DmKV7b7d.js → jobs-epP7gt8W.js} +1 -1
  87. package/client/dist/assets/{jobs-BKa8LuwA.js → jobs-tWjcDF_6.js} +1 -1
  88. package/client/dist/assets/loops--KWr0X-w.js +1 -0
  89. package/client/dist/assets/{loops-BO3V8244.js → loops-3IutojWt.js} +1 -1
  90. package/client/dist/assets/{loops-C-hZK8pf.js → loops-BAosWtXE.js} +1 -1
  91. package/client/dist/assets/{loops-eUnCfLjC.js → loops-BISDssL5.js} +1 -1
  92. package/client/dist/assets/{loops-Dv849ckF.js → loops-Cm55CXJ4.js} +1 -1
  93. package/client/dist/assets/{loops-CDOWZ0ci.js → loops-D7tL_Saw.js} +1 -1
  94. package/client/dist/assets/{loops-BJDY9FTh.js → loops-DHQtnfze.js} +1 -1
  95. package/client/dist/assets/{loops-Q9LIgGkq.js → loops-kIJJkaxf.js} +1 -1
  96. package/client/dist/assets/nav--u7iPYlS.js +1 -0
  97. package/client/dist/assets/nav-C5Jgfaby.js +1 -0
  98. package/client/dist/assets/nav-CAna_Wpt.js +1 -0
  99. package/client/dist/assets/nav-CCLqeyHo.js +1 -0
  100. package/client/dist/assets/nav-Cf3c90Jk.js +1 -0
  101. package/client/dist/assets/nav-DMYQaQjR.js +1 -0
  102. package/client/dist/assets/nav-Df_PkZ9F.js +1 -0
  103. package/client/dist/assets/nav-VyNGBJwj.js +1 -0
  104. package/client/dist/assets/{project-repositories-CSnfzUpg.js → project-repositories-DXhb9FP4.js} +1 -1
  105. package/client/dist/assets/provider-capabilities-lePfeT_Y.js +1 -0
  106. package/client/dist/assets/save-OsUqVn99.js +1 -0
  107. package/client/dist/assets/settings-B5Hy_Kol.js +1 -0
  108. package/client/dist/assets/settings-BBj_kZaD.js +1 -0
  109. package/client/dist/assets/settings-ByVE7jdZ.js +1 -0
  110. package/client/dist/assets/settings-COlH_P33.js +1 -0
  111. package/client/dist/assets/settings-D77mC_Lb.js +1 -0
  112. package/client/dist/assets/settings-DZKy7MqN.js +1 -0
  113. package/client/dist/assets/settings-Dbyd6gmj.js +1 -0
  114. package/client/dist/assets/settings-Dn-pXukr.js +1 -0
  115. package/client/dist/assets/setup-Be485n2u.js +1 -0
  116. package/client/dist/assets/setup-CKGUxKr-.js +1 -0
  117. package/client/dist/assets/setup-Ck1Uwd7_.js +1 -0
  118. package/client/dist/assets/setup-Cm774a6v.js +1 -0
  119. package/client/dist/assets/setup-DIqMQpxt.js +1 -0
  120. package/client/dist/assets/setup-DfCsoNFL.js +1 -0
  121. package/client/dist/assets/setup-DkeE8mP0.js +1 -0
  122. package/client/dist/assets/setup-xVntVaz1.js +1 -0
  123. package/client/dist/assets/{spending-HBSk-6jv.js → spending-BdcyVkcd.js} +1 -1
  124. package/client/dist/assets/subscriptionUsage-Cf87DeS_.js +1 -0
  125. package/client/dist/assets/subscriptionUsage-D6u7VBdz.js +1 -0
  126. package/client/dist/assets/subscriptionUsage-DQ02J25O.js +1 -0
  127. package/client/dist/assets/subscriptionUsage-DWF3zKp4.js +1 -0
  128. package/client/dist/assets/subscriptionUsage-DkIf6Zuh.js +1 -0
  129. package/client/dist/assets/subscriptionUsage-DoWQv7l1.js +1 -0
  130. package/client/dist/assets/subscriptionUsage-N9hB-ARf.js +1 -0
  131. package/client/dist/assets/subscriptionUsage-zRcRPHkP.js +1 -0
  132. package/client/dist/assets/tauri-shell-DE6LfGPw.js +2 -0
  133. package/client/dist/assets/{useDesktop-0unHDBJJ.js → useDesktop-D07TvesS.js} +1 -1
  134. package/client/dist/assets/{useRuntimeRuns-BN1rhyEm.js → useRuntimeRuns-pGLmtAC6.js} +1 -1
  135. package/client/dist/assets/useSharedWebSocket-TzKtPRp9.js +2 -0
  136. package/client/dist/index.html +33 -32
  137. package/docs/README.md +1 -9
  138. package/docs/agent-live-steering.md +0 -6
  139. package/docs/agents/README.md +0 -2
  140. package/docs/agents/mcp.md +1 -14
  141. package/docs/cli.md +0 -13
  142. package/docs/codex.md +2 -75
  143. package/docs/creating-specs.md +0 -39
  144. package/docs/customizing.md +1 -15
  145. package/docs/getting-started.md +0 -23
  146. package/docs/guide/de/agents/2-profiles-and-the-balanced-default.md +0 -8
  147. package/docs/guide/de/agents/4-custom-agents-catalog.md +0 -15
  148. package/docs/guide/de/getting-started/1-what-is-specrails.md +0 -2
  149. package/docs/guide/de/getting-started/2-installing-and-first-run.md +0 -2
  150. package/docs/guide/de/getting-started/3-adding-your-first-project.md +0 -4
  151. package/docs/guide/de/getting-started/4-the-dashboard-tour.md +0 -5
  152. package/docs/guide/de/integrations/1-ai-providers.md +2 -50
  153. package/docs/guide/de/integrations/2-plugins.md +0 -8
  154. package/docs/guide/de/integrations/5-mcp-server.md +1 -14
  155. package/docs/guide/de/integrations/6-agent-chat.md +0 -11
  156. package/docs/guide/de/integrations/7-local-engines.md +0 -4
  157. package/docs/guide/de/pipeline/1-rails-and-jobs.md +0 -13
  158. package/docs/guide/de/pipeline/2-the-job-detail-view.md +0 -3
  159. package/docs/guide/de/pipeline/4-picking-an-engine-per-rail.md +0 -20
  160. package/docs/guide/de/pipeline/5-the-loop-builder.md +0 -6
  161. package/docs/guide/de/specs/2-add-spec-quick-mode.md +0 -7
  162. package/docs/guide/en/agents/2-profiles-and-the-balanced-default.md +0 -10
  163. package/docs/guide/en/agents/4-custom-agents-catalog.md +0 -25
  164. package/docs/guide/en/getting-started/1-what-is-specrails.md +0 -2
  165. package/docs/guide/en/getting-started/2-installing-and-first-run.md +0 -2
  166. package/docs/guide/en/getting-started/3-adding-your-first-project.md +0 -4
  167. package/docs/guide/en/getting-started/4-the-dashboard-tour.md +0 -5
  168. package/docs/guide/en/insights/3-code-explorer.md +0 -5
  169. package/docs/guide/en/integrations/1-ai-providers.md +10 -99
  170. package/docs/guide/en/integrations/2-plugins.md +0 -8
  171. package/docs/guide/en/integrations/5-mcp-server.md +1 -1
  172. package/docs/guide/en/integrations/6-agent-chat.md +0 -17
  173. package/docs/guide/en/integrations/7-local-engines.md +0 -4
  174. package/docs/guide/en/pipeline/1-rails-and-jobs.md +2 -24
  175. package/docs/guide/en/pipeline/2-the-job-detail-view.md +0 -3
  176. package/docs/guide/en/pipeline/4-picking-an-engine-per-rail.md +10 -65
  177. package/docs/guide/en/pipeline/5-the-loop-builder.md +0 -7
  178. package/docs/guide/en/specs/2-add-spec-quick-mode.md +0 -11
  179. package/docs/guide/es/agents/2-profiles-and-the-balanced-default.md +0 -8
  180. package/docs/guide/es/agents/4-custom-agents-catalog.md +0 -15
  181. package/docs/guide/es/getting-started/1-what-is-specrails.md +0 -2
  182. package/docs/guide/es/getting-started/2-installing-and-first-run.md +0 -2
  183. package/docs/guide/es/getting-started/3-adding-your-first-project.md +0 -4
  184. package/docs/guide/es/getting-started/4-the-dashboard-tour.md +0 -5
  185. package/docs/guide/es/integrations/1-ai-providers.md +10 -75
  186. package/docs/guide/es/integrations/2-plugins.md +0 -8
  187. package/docs/guide/es/integrations/5-mcp-server.md +1 -1
  188. package/docs/guide/es/integrations/6-agent-chat.md +0 -11
  189. package/docs/guide/es/integrations/7-local-engines.md +0 -4
  190. package/docs/guide/es/pipeline/1-rails-and-jobs.md +3 -13
  191. package/docs/guide/es/pipeline/2-the-job-detail-view.md +0 -3
  192. package/docs/guide/es/pipeline/4-picking-an-engine-per-rail.md +10 -53
  193. package/docs/guide/es/pipeline/5-the-loop-builder.md +1 -6
  194. package/docs/guide/es/specs/2-add-spec-quick-mode.md +0 -7
  195. package/docs/guide/fr/agents/2-profiles-and-the-balanced-default.md +0 -8
  196. package/docs/guide/fr/agents/4-custom-agents-catalog.md +0 -15
  197. package/docs/guide/fr/getting-started/1-what-is-specrails.md +0 -2
  198. package/docs/guide/fr/getting-started/2-installing-and-first-run.md +0 -2
  199. package/docs/guide/fr/getting-started/3-adding-your-first-project.md +0 -4
  200. package/docs/guide/fr/getting-started/4-the-dashboard-tour.md +0 -5
  201. package/docs/guide/fr/integrations/1-ai-providers.md +2 -50
  202. package/docs/guide/fr/integrations/2-plugins.md +0 -8
  203. package/docs/guide/fr/integrations/5-mcp-server.md +1 -14
  204. package/docs/guide/fr/integrations/6-agent-chat.md +0 -11
  205. package/docs/guide/fr/integrations/7-local-engines.md +0 -4
  206. package/docs/guide/fr/pipeline/1-rails-and-jobs.md +0 -13
  207. package/docs/guide/fr/pipeline/2-the-job-detail-view.md +0 -3
  208. package/docs/guide/fr/pipeline/4-picking-an-engine-per-rail.md +0 -22
  209. package/docs/guide/fr/pipeline/5-the-loop-builder.md +0 -6
  210. package/docs/guide/fr/specs/2-add-spec-quick-mode.md +0 -7
  211. package/docs/guide/it/agents/2-profiles-and-the-balanced-default.md +0 -8
  212. package/docs/guide/it/agents/4-custom-agents-catalog.md +0 -15
  213. package/docs/guide/it/getting-started/1-what-is-specrails.md +0 -2
  214. package/docs/guide/it/getting-started/2-installing-and-first-run.md +0 -2
  215. package/docs/guide/it/getting-started/3-adding-your-first-project.md +0 -4
  216. package/docs/guide/it/getting-started/4-the-dashboard-tour.md +0 -5
  217. package/docs/guide/it/integrations/1-ai-providers.md +2 -48
  218. package/docs/guide/it/integrations/2-plugins.md +0 -8
  219. package/docs/guide/it/integrations/5-mcp-server.md +1 -14
  220. package/docs/guide/it/integrations/6-agent-chat.md +0 -11
  221. package/docs/guide/it/integrations/7-local-engines.md +0 -4
  222. package/docs/guide/it/pipeline/1-rails-and-jobs.md +2 -13
  223. package/docs/guide/it/pipeline/2-the-job-detail-view.md +0 -3
  224. package/docs/guide/it/pipeline/4-picking-an-engine-per-rail.md +0 -20
  225. package/docs/guide/it/pipeline/5-the-loop-builder.md +1 -6
  226. package/docs/guide/it/specs/2-add-spec-quick-mode.md +0 -7
  227. package/docs/guide/ja/agents/2-profiles-and-the-balanced-default.md +0 -9
  228. package/docs/guide/ja/agents/4-custom-agents-catalog.md +0 -15
  229. package/docs/guide/ja/getting-started/1-what-is-specrails.md +0 -2
  230. package/docs/guide/ja/getting-started/2-installing-and-first-run.md +0 -2
  231. package/docs/guide/ja/getting-started/3-adding-your-first-project.md +0 -4
  232. package/docs/guide/ja/getting-started/4-the-dashboard-tour.md +0 -5
  233. package/docs/guide/ja/integrations/1-ai-providers.md +1 -69
  234. package/docs/guide/ja/integrations/2-plugins.md +0 -8
  235. package/docs/guide/ja/integrations/5-mcp-server.md +1 -14
  236. package/docs/guide/ja/integrations/6-agent-chat.md +0 -10
  237. package/docs/guide/ja/integrations/7-local-engines.md +0 -4
  238. package/docs/guide/ja/pipeline/1-rails-and-jobs.md +0 -13
  239. package/docs/guide/ja/pipeline/2-the-job-detail-view.md +0 -3
  240. package/docs/guide/ja/pipeline/4-picking-an-engine-per-rail.md +0 -21
  241. package/docs/guide/ja/pipeline/5-the-loop-builder.md +0 -6
  242. package/docs/guide/ja/specs/2-add-spec-quick-mode.md +0 -7
  243. package/docs/guide/pt/agents/2-profiles-and-the-balanced-default.md +0 -8
  244. package/docs/guide/pt/agents/4-custom-agents-catalog.md +0 -15
  245. package/docs/guide/pt/getting-started/1-what-is-specrails.md +0 -2
  246. package/docs/guide/pt/getting-started/2-installing-and-first-run.md +0 -2
  247. package/docs/guide/pt/getting-started/3-adding-your-first-project.md +0 -4
  248. package/docs/guide/pt/getting-started/4-the-dashboard-tour.md +0 -5
  249. package/docs/guide/pt/integrations/1-ai-providers.md +2 -48
  250. package/docs/guide/pt/integrations/2-plugins.md +0 -8
  251. package/docs/guide/pt/integrations/5-mcp-server.md +1 -14
  252. package/docs/guide/pt/integrations/6-agent-chat.md +0 -10
  253. package/docs/guide/pt/integrations/7-local-engines.md +0 -4
  254. package/docs/guide/pt/pipeline/1-rails-and-jobs.md +0 -13
  255. package/docs/guide/pt/pipeline/2-the-job-detail-view.md +0 -2
  256. package/docs/guide/pt/pipeline/4-picking-an-engine-per-rail.md +0 -21
  257. package/docs/guide/pt/pipeline/5-the-loop-builder.md +0 -6
  258. package/docs/guide/pt/specs/2-add-spec-quick-mode.md +0 -7
  259. package/docs/guide/zh/agents/2-profiles-and-the-balanced-default.md +0 -7
  260. package/docs/guide/zh/agents/4-custom-agents-catalog.md +0 -15
  261. package/docs/guide/zh/getting-started/1-what-is-specrails.md +0 -2
  262. package/docs/guide/zh/getting-started/2-installing-and-first-run.md +0 -2
  263. package/docs/guide/zh/getting-started/3-adding-your-first-project.md +0 -4
  264. package/docs/guide/zh/getting-started/4-the-dashboard-tour.md +0 -5
  265. package/docs/guide/zh/integrations/1-ai-providers.md +1 -67
  266. package/docs/guide/zh/integrations/2-plugins.md +0 -8
  267. package/docs/guide/zh/integrations/5-mcp-server.md +1 -14
  268. package/docs/guide/zh/integrations/6-agent-chat.md +0 -9
  269. package/docs/guide/zh/integrations/7-local-engines.md +0 -4
  270. package/docs/guide/zh/pipeline/1-rails-and-jobs.md +0 -13
  271. package/docs/guide/zh/pipeline/2-the-job-detail-view.md +0 -2
  272. package/docs/guide/zh/pipeline/4-picking-an-engine-per-rail.md +0 -20
  273. package/docs/guide/zh/pipeline/5-the-loop-builder.md +0 -6
  274. package/docs/guide/zh/specs/2-add-spec-quick-mode.md +0 -7
  275. package/docs/internals/adding-a-provider.md +7 -0
  276. package/docs/internals/desktop-owned-workflows.md +121 -0
  277. package/docs/internals/operations-runbook.md +20 -0
  278. package/docs/internals/programmatic-agent-runtime.md +34 -28
  279. package/docs/internals/project-builder.md +34 -11
  280. package/docs/internals/source-map.md +51 -3
  281. package/docs/internals/spec-addenda.md +11 -5
  282. package/docs/local-providers.md +8 -13
  283. package/docs/mcp.md +1 -17
  284. package/docs/platforms/macos.md +0 -40
  285. package/docs/platforms/windows-parity.md +1 -1
  286. package/docs/platforms/windows.md +0 -8
  287. package/docs/running-pipelines.md +1 -46
  288. package/docs/subscription-usage.md +19 -0
  289. package/docs/terminal.md +0 -2
  290. package/docs/tracking-cost.md +2 -33
  291. package/package.json +1 -1
  292. package/server/dist/core-execution.js +24 -15
  293. package/server/dist/desktop-db.js +23 -10
  294. package/server/dist/desktop-router.js +8 -4
  295. package/server/dist/index.js +10 -5
  296. package/server/dist/mcp/guide.js +1 -0
  297. package/server/dist/mcp/tools/jobs.js +1 -1
  298. package/server/dist/mcp/tools/loops.js +2 -0
  299. package/server/dist/mcp/tools/meta.js +6 -7
  300. package/server/dist/mcp/tools/projects.js +31 -6
  301. package/server/dist/mcp/tools/rails.js +6 -3
  302. package/server/dist/mcp/tools/setup.js +10 -0
  303. package/server/dist/mcp/tools/specs.js +1 -1
  304. package/server/dist/modules/accounting/runtime/pricing.js +6 -1
  305. package/server/dist/modules/agent-runtime/runtime/agent-runtime-bridge.js +55 -12
  306. package/server/dist/modules/agent-runtime/runtime/agent-runtime-metrics.js +1 -1
  307. package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings-router.js +1 -1
  308. package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings.js +42 -0
  309. package/server/dist/modules/agent-runtime/runtime/agent-runtime-verification-suggestions.js +10 -4
  310. package/server/dist/modules/builder/runtime/milestone-chain.js +76 -10
  311. package/server/dist/modules/delivery/runtime/delivery-evidence.js +3 -2
  312. package/server/dist/modules/delivery/runtime/multi-repo-execution.js +3 -0
  313. package/server/dist/modules/delivery/runtime/rail-isolated-launch.js +1 -0
  314. package/server/dist/modules/delivery/runtime/rail-launch-parser.js +8 -0
  315. package/server/dist/modules/delivery/runtime/rails-router.js +48 -26
  316. package/server/dist/modules/delivery/runtime/review-packet.js +1 -1
  317. package/server/dist/modules/loops/runtime/loop-agent-defaults.json +6 -0
  318. package/server/dist/modules/loops/runtime/loop-agents.js +21 -0
  319. package/server/dist/modules/loops/runtime/loop-command-catalog.js +1 -1
  320. package/server/dist/modules/loops/runtime/loop-core-factory.js +19 -3
  321. package/server/dist/modules/loops/runtime/loop-definition.js +79 -12
  322. package/server/dist/modules/loops/runtime/loop-effect.js +1 -1
  323. package/server/dist/modules/loops/runtime/loop-executors.js +24 -9
  324. package/server/dist/modules/loops/runtime/loop-factory.js +1 -1
  325. package/server/dist/modules/loops/runtime/loop-graph.js +5 -14
  326. package/server/dist/modules/loops/runtime/loop-implement-recipe.js +49 -0
  327. package/server/dist/modules/loops/runtime/loop-run-manager.js +3 -3
  328. package/server/dist/modules/loops/runtime/loop-templates.js +29 -5
  329. package/server/dist/modules/loops/runtime/loops-router.js +17 -0
  330. package/server/dist/modules/missions/runtime/agent-context-resolver.js +1 -1
  331. package/server/dist/modules/missions/runtime/agent-operator-prompt.js +17 -8
  332. package/server/dist/modules/specs/runtime/spec-models.js +4 -7
  333. package/server/dist/modules/subscription-usage/adapters/claude.js +113 -0
  334. package/server/dist/modules/subscription-usage/adapters/codex.js +164 -0
  335. package/server/dist/modules/subscription-usage/adapters/errors.js +15 -0
  336. package/server/dist/modules/subscription-usage/adapters/http.js +20 -0
  337. package/server/dist/modules/subscription-usage/adapters/local-auth.js +61 -0
  338. package/server/dist/modules/subscription-usage/application.js +11 -0
  339. package/server/dist/modules/subscription-usage/domain.js +70 -0
  340. package/server/dist/modules/subscription-usage/index.js +2 -0
  341. package/server/dist/modules/subscription-usage/ports.js +2 -0
  342. package/server/dist/modules/subscription-usage/runtime/composition.js +20 -0
  343. package/server/dist/modules/subscription-usage/runtime/usage-service.js +111 -0
  344. package/server/dist/project-registry.js +16 -1
  345. package/server/dist/project-repositories.js +51 -2
  346. package/server/dist/project-router-helpers.js +1 -1
  347. package/server/dist/project-router-loop-runs.js +4 -1
  348. package/server/dist/providers/claude-adapter.js +6 -4
  349. package/server/dist/providers/codex-adapter.js +4 -5
  350. package/server/dist/schemas/workflow-definition.schema.json +2 -0
  351. package/client/dist/assets/AgentBrowserCapture-PI-cxyxi.js +0 -1
  352. package/client/dist/assets/AgentModeAnalyticsPane-mQsOqdXx.js +0 -2
  353. package/client/dist/assets/AgentModeCodePane-BL-vpmlY.js +0 -2
  354. package/client/dist/assets/CodePage-Alitorrv.js +0 -3
  355. package/client/dist/assets/DocsDialog-DwL6rgcT.js +0 -11
  356. package/client/dist/assets/DocsPage-BA1hiJZ-.js +0 -11
  357. package/client/dist/assets/InteractiveJobComposer-B3H1YHr6.js +0 -19
  358. package/client/dist/assets/JobDetailModal-XZQ9eAAy.js +0 -1
  359. package/client/dist/assets/JobDetailPage-B-SIaq_q.js +0 -1
  360. package/client/dist/assets/JobsPage-iQXAv2mx.js +0 -1
  361. package/client/dist/assets/LoopBuilderPage-B_gbFAHn.js +0 -1
  362. package/client/dist/assets/LoopsPage-BZwcY5cu.js +0 -2
  363. package/client/dist/assets/MinimizedChatsContext-CNx_0bZu.js +0 -1
  364. package/client/dist/assets/PluginsPage-DFocnoHX.js +0 -2
  365. package/client/dist/assets/ProjectSettingsDialog-Bh3S6EBB.js +0 -1
  366. package/client/dist/assets/RepositoryScopeSelector-C2mvWBQ6.js +0 -1
  367. package/client/dist/assets/ReviewPacketPage-CrAf-WDy.js +0 -4
  368. package/client/dist/assets/TemplatePreviewModal-C7DordpN.js +0 -1
  369. package/client/dist/assets/TicketDetailModalContext-B-DySpKL.js +0 -16
  370. package/client/dist/assets/agent-BaG10AN6.js +0 -1
  371. package/client/dist/assets/agent-CH4aJ884.js +0 -1
  372. package/client/dist/assets/agent-CLc9fA7v.js +0 -1
  373. package/client/dist/assets/agent-DHh9-AdL.js +0 -1
  374. package/client/dist/assets/agent-DkKnd6Wv.js +0 -1
  375. package/client/dist/assets/agent-aiVhqFW1.js +0 -1
  376. package/client/dist/assets/agent-dbznD3eO.js +0 -1
  377. package/client/dist/assets/agent-sMVFcPwL.js +0 -1
  378. package/client/dist/assets/agentRuntime-BeUb3g9g.js +0 -1
  379. package/client/dist/assets/file-text-CFT-xXKN.js +0 -1
  380. package/client/dist/assets/index-BS7KCWkV.css +0 -2
  381. package/client/dist/assets/index-C4Mv6tV6.js +0 -80
  382. package/client/dist/assets/integrations-CH0zy1Mw.js +0 -1
  383. package/client/dist/assets/integrations-CIAjhd7L.js +0 -1
  384. package/client/dist/assets/integrations-CZdwOe8A.js +0 -1
  385. package/client/dist/assets/integrations-Ct7omMld.js +0 -1
  386. package/client/dist/assets/integrations-D6MSxy3-.js +0 -1
  387. package/client/dist/assets/integrations-DbZa-Zyc.js +0 -1
  388. package/client/dist/assets/integrations-b8pH-vfl.js +0 -1
  389. package/client/dist/assets/integrations-mB-7zoyT.js +0 -1
  390. package/client/dist/assets/jira-api-BYbEPlkr.js +0 -1
  391. package/client/dist/assets/layers-eDMjG41I.js +0 -1
  392. package/client/dist/assets/loops-B4_D-nbg.js +0 -1
  393. package/client/dist/assets/nav-B-tpjyc2.js +0 -1
  394. package/client/dist/assets/nav-BJNXGg29.js +0 -1
  395. package/client/dist/assets/nav-BdhtRLP7.js +0 -1
  396. package/client/dist/assets/nav-ByYgyN5T.js +0 -1
  397. package/client/dist/assets/nav-DA0Mva2c.js +0 -1
  398. package/client/dist/assets/nav-DcJm_Jg_.js +0 -1
  399. package/client/dist/assets/nav-DhMPtAXc.js +0 -1
  400. package/client/dist/assets/nav-DhPb-Isc.js +0 -1
  401. package/client/dist/assets/provider-capabilities-Vi1ZGvAK.js +0 -1
  402. package/client/dist/assets/save-B6wGWwBR.js +0 -1
  403. package/client/dist/assets/settings-3o4Ntzi5.js +0 -1
  404. package/client/dist/assets/settings-B97jlkwD.js +0 -1
  405. package/client/dist/assets/settings-BTaT_bsS.js +0 -1
  406. package/client/dist/assets/settings-CT8w7WiC.js +0 -1
  407. package/client/dist/assets/settings-Cvr8_tvh.js +0 -1
  408. package/client/dist/assets/settings-Dn1qgAC8.js +0 -1
  409. package/client/dist/assets/settings-EShDdg4J.js +0 -1
  410. package/client/dist/assets/settings-tfLhQZRN.js +0 -1
  411. package/client/dist/assets/setup-CBMu3tqH.js +0 -1
  412. package/client/dist/assets/setup-CPh-e6J2.js +0 -1
  413. package/client/dist/assets/setup-CRKLp_ke.js +0 -1
  414. package/client/dist/assets/setup-Cy302v4J.js +0 -1
  415. package/client/dist/assets/setup-D681vTPf.js +0 -1
  416. package/client/dist/assets/setup-DYK0VBkE.js +0 -1
  417. package/client/dist/assets/setup-KAuiIiVs.js +0 -1
  418. package/client/dist/assets/setup-OGX-oCfI.js +0 -1
  419. package/client/dist/assets/useSharedWebSocket-BZMrX4jr.js +0 -2
  420. package/client/dist/assets/wrench-BfmNO9Vw.js +0 -1
  421. package/docs/agy-cli-provider-study.md +0 -257
  422. package/docs/gemini-cli-provider-study.md +0 -301
  423. package/docs/gemini-core-support-evaluation.md +0 -160
  424. package/docs/gemini.md +0 -257
  425. package/docs/kimi.md +0 -291
@@ -1,14 +1,4 @@
1
1
  "use strict";
2
- /**
3
- * Loop graph model + validation — the pure core shared by the canvas builder
4
- * (`loop-builder-canvas`) and the publish gate (`loops-store.publishLoop`).
5
- *
6
- * A loop is a directed graph of typed nodes connected by edges. Cycles are
7
- * allowed (a loop routes back to an earlier node); the run is bounded by the
8
- * graph's `config.maxIterations` + `timeoutMinutes`. This module has NO I/O and
9
- * NO provider knowledge — it only describes and validates the shape, so it is
10
- * trivially unit-testable and reused verbatim by both the store and the engine.
11
- */
12
2
  Object.defineProperty(exports, "__esModule", { value: true });
13
3
  exports.CORE_NODE_KINDS = void 0;
14
4
  exports.isDefinitionReviewerPath = isDefinitionReviewerPath;
@@ -24,8 +14,8 @@ exports.successors = successors;
24
14
  exports.loopNeedsTicket = loopNeedsTicket;
25
15
  exports.interpolateSpec = interpolateSpec;
26
16
  exports.CORE_NODE_KINDS = ['prompt', 'role-turn', 'decider', 'condition', 'assign', 'verify', 'shell',
27
- 'openspec-validate', 'openspec-archive', 'approval', 'question', 'gate', 'map', 'join',
28
- 'component', 'implementation', 'end'];
17
+ 'artifact-contract', 'openspec-validate', 'openspec-archive', 'approval', 'question', 'gate', 'map', 'join',
18
+ 'component', 'implementation', 'implementation-step', 'end'];
29
19
  function isDefinitionReviewerPath(graph, value) {
30
20
  if (typeof value !== 'string' || !value || value.length > 2048)
31
21
  return false;
@@ -38,7 +28,7 @@ function isDefinitionReviewerPath(graph, value) {
38
28
  if (!node || node.type !== 'core')
39
29
  return false;
40
30
  if (index === segments.length - 1)
41
- return node.data?.kind === 'role-turn';
31
+ return node.data?.kind === 'role-turn' || node.data?.kind === 'implementation-step' && node.data.params?.phase === 'reviewer';
42
32
  const ref = node.data?.kind === 'component' ? node.data.params?.ref : node.data?.kind === 'map' ? node.data.params?.body : undefined;
43
33
  body = typeof ref === 'string' ? graph.components?.[ref] : undefined;
44
34
  }
@@ -176,6 +166,7 @@ function validateLoopGraph(graph, catalog) {
176
166
  (cfg.maxCostUsd !== undefined && !Number.isFinite(cfg.maxCostUsd)) ||
177
167
  (cfg.maxTransitions !== undefined && (!Number.isInteger(cfg.maxTransitions) || cfg.maxTransitions < 1 || cfg.maxTransitions > 10000)) ||
178
168
  (cfg.maxTokens !== undefined && (!Number.isInteger(cfg.maxTokens) || cfg.maxTokens < 1)) ||
169
+ (cfg.ticketScope !== undefined && !['all', 'per-ticket'].includes(cfg.ticketScope)) ||
179
170
  (cfg.reviewerStepId !== undefined && !isDefinitionReviewerPath(graph, cfg.reviewerStepId))) {
180
171
  errors.push({
181
172
  code: 'INVALID_CONFIG',
@@ -300,7 +291,7 @@ function loopNeedsTicket(graph) {
300
291
  if (!graph)
301
292
  return false;
302
293
  for (const node of graph.nodes) {
303
- if (node.type === 'core' && node.data?.kind === 'implementation')
294
+ if (node.type === 'core' && ['implementation', 'implementation-step'].includes(node.data?.kind ?? ''))
304
295
  return true;
305
296
  const text = [node.data?.prompt, node.data?.command, node.data?.goal,
306
297
  node.type === 'core' ? JSON.stringify(node.data?.params) : undefined]
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.configurableImplementGraph = configurableImplementGraph;
4
+ const loop_agents_1 = require("./loop-agents");
5
+ const objectSchema = (properties, required = Object.keys(properties)) => ({ type: 'object', properties, required, additionalProperties: false });
6
+ const string = { type: 'string' };
7
+ const strings = { type: 'array', items: string, maxItems: 100 };
8
+ const score = { type: 'number', minimum: 0, maximum: 100 };
9
+ const aspects = { type_correctness: 60, pattern_adherence: 60, test_coverage: 60, security: 75, architectural_alignment: 60 };
10
+ /** The recipe, roles, schemas and decisions are Desktop data, never Core phases. */
11
+ function configurableImplementGraph() {
12
+ const agents = (0, loop_agents_1.defaultLoopAgents)();
13
+ agents.roles = {
14
+ plan: { ...agents.agents.architect, access: 'read', artifacts: 'all', openspecSkill: 'openspec-ff-change', prompt: agents.rolePrompts?.architect },
15
+ build: { ...agents.agents.developer, access: 'write', artifacts: 'tasks-checkboxes', openspecSkill: 'openspec-apply-change', prompt: agents.rolePrompts?.developer },
16
+ assess: { ...agents.agents.reviewer, access: 'read', artifacts: 'none', openspecSkill: 'openspec-verify-change', prompt: agents.rolePrompts?.reviewer },
17
+ correct: { ...agents.fixer, access: 'write', artifacts: 'tasks-checkboxes', openspecSkill: 'openspec-apply-change', prompt: agents.rolePrompts?.fixer },
18
+ };
19
+ const nodes = [{ id: 'start', type: 'start', position: { x: 0, y: 0 } }], edges = [];
20
+ const node = (id, label, kind, params, outcomes) => {
21
+ nodes.push({ id, type: 'core', position: { x: 0, y: nodes.length * 140 }, data: { kind, label, params } });
22
+ for (const [outcome, target] of Object.entries(outcomes))
23
+ edges.push({ id: `e-${id}-${outcome}`, source: id, target, label: outcome });
24
+ };
25
+ const turn = (id, label, roleId, prompt, schema, next) => node(id, label, 'role-turn', { roleId, prompt, structuredOutput: schema, sessionContinuity: 'none' }, { next, invalid: 'failed', failed: 'failed' });
26
+ const change = '{{run.changeId}}';
27
+ turn('architect', 'Architect', 'plan', `Plan the frozen ticket requirements for OpenSpec change ${change}. Use the bound official fast-forward skill. Author complete proposal, design, delta specs and actionable tasks. Propose existing repository verification commands for repositories with no configured checks. Return confidence, question (empty when none), and verification [{repositoryId,command,args,cwd?}]. When revisiting low confidence, investigate the missing repository evidence before asking again. Context and human answers: {{history.text}}`, objectSchema({ confidence: { enum: ['high', 'medium', 'low'] }, question: string, verification: { type: 'array', maxItems: 20, items: objectSchema({ repositoryId: string, command: string, args: strings, cwd: string }, ['repositoryId', 'command', 'args']) } }), 'confidence');
28
+ node('confidence', 'Planning confidence', 'condition', { expr: '$outputs.architect.structured.confidence != "low"' }, { true: 'validate', false: 'investigate' });
29
+ node('investigate', 'Investigate low confidence once', 'condition', { expr: '!exists($vars.planInvestigated) || $vars.planInvestigated == false' }, { true: 'mark-investigated', false: 'clarify' });
30
+ node('mark-investigated', 'Mark confidence investigation', 'assign', { set: { planInvestigated: true } }, { next: 'architect', failed: 'failed' });
31
+ node('clarify', 'Clarify plan', 'question', { text: '{{outputs.architect.structured.question}}' }, { next: 'reset-confidence' });
32
+ node('reset-confidence', 'Reset confidence after answer', 'assign', { set: { planInvestigated: false } }, { next: 'architect', failed: 'failed' });
33
+ node('validate', 'Validate OpenSpec', 'openspec-validate', { change }, { pass: 'freeze', fail: 'architect', failed: 'failed' });
34
+ node('freeze', 'Freeze approved artifacts', 'artifact-contract', { change, contractId: 'plan', action: 'freeze' }, { pass: 'developer', fail: 'architect', failed: 'failed' });
35
+ const implementation = objectSchema({ summary: string, incomplete: strings });
36
+ turn('developer', 'Developer', 'build', `Implement every approved task for change ${change} using the bound official apply skill. Preserve proposal, design and specs; only tick tasks you completed. Report summary and incomplete task descriptions. Prior execution evidence and human answers: {{history.text}}`, implementation, 'tasks');
37
+ node('tasks', 'Check artifacts and completed tasks', 'artifact-contract', { change, contractId: 'plan', action: 'check', requireCompletedTasks: true }, { pass: 'verify', fail: 'developer', failed: 'failed' });
38
+ node('verify', 'Verify candidate', 'verify', { commands: 'configured', additionalCommandsFrom: 'architect' }, { pass: 'reviewer', fail: 'fixer', failed: 'failed' });
39
+ turn('reviewer', 'Reviewer', 'assess', `Review change ${change} read-only against all approved artifacts and frozen ticket acceptance criteria. Inspect real code and the host verification evidence: {{outputs.verify}}. Return approved, summary, issues, score (0-100), and aspects. Prior execution: {{history.text}}`, objectSchema({ approved: { type: 'boolean' }, summary: string, issues: strings, score, aspects: objectSchema(Object.fromEntries(Object.keys(aspects).map(aspect => [aspect, score]))) }), 'review-policy');
40
+ node('review-policy', 'Review acceptance policy', 'condition', { expr: ['$outputs.reviewer.structured.approved == true', '$outputs.reviewer.structured.issues.length == 0', '$outputs.reviewer.structured.score >= 70', ...Object.entries(aspects).map(([aspect, threshold]) => `$outputs.reviewer.structured.aspects.${aspect} >= ${threshold}`)].join(' && ') }, { true: 'approve', false: 'fixer' });
41
+ turn('fixer', 'Fixer', 'correct', `Correct only failures in change ${change}, using the bound apply skill and preserving approved artifacts. Report summary and incomplete tasks. Host verification: {{outputs.verify}}. Prior execution: {{history.text}}`, implementation, 'tasks');
42
+ node('approve', 'Approve archive', 'approval', { reason: `Approve archiving the reviewed and verified candidate for change ${change}.`, bindCandidate: true, enabled: agents.approvalBeforeArchive === true }, { next: 'approval-policy' });
43
+ node('approval-policy', 'Approval decision', 'condition', { expr: '$outputs.approve.response.approved == true' }, { true: 'archive', false: 'failed' });
44
+ node('archive', 'Archive OpenSpec', 'openspec-archive', { change, allowArchived: true, requiresVerified: true, reviewedCandidate: '{{outputs.reviewer.candidateHash}}', approvedCandidate: '{{outputs.approve.candidateHash}}' }, { next: 'verify-archive', failed: 'verify' });
45
+ node('verify-archive', 'Verify archived candidate', 'verify', { commands: 'configured', additionalCommandsFrom: 'architect' }, { pass: 'done', fail: 'failed', failed: 'failed' });
46
+ nodes.push({ id: 'done', type: 'end', position: { x: 0, y: nodes.length * 140 }, data: { outcome: 'success', requiresVerified: true } }, { id: 'failed', type: 'end', position: { x: 360, y: nodes.length * 140 }, data: { outcome: 'failure' } });
47
+ edges.unshift({ id: 'e-start', source: 'start', target: 'architect' });
48
+ return { nodes, edges, config: { maxIterations: 12, maxTransitions: 200, timeoutMinutes: 0, aiStepTimeoutMinutes: 0, change: 'new', journal: 'ledger-only', ticketScope: 'all', agents, reviewerStepId: 'reviewer' } };
49
+ }
@@ -498,7 +498,7 @@ class LoopRunManager {
498
498
  if ((0, loop_graph_1.isDefinitionGraph)(graph)) {
499
499
  if (!this.executors.runDefinition)
500
500
  throw new Error('engine_unsupported: Core workflow execution is unavailable');
501
- await this.executors.assertDefinitionSupport?.();
501
+ await this.executors.assertDefinitionSupport?.(graph);
502
502
  }
503
503
  else
504
504
  await this.executors.assertLegacyEngineSupport?.();
@@ -1422,7 +1422,7 @@ class LoopRunManager {
1422
1422
  const effectiveTimeoutMs = Number.isFinite(remainingMs)
1423
1423
  ? Math.max(1, Math.min(aiStepTimeoutMs === 0 ? Infinity : (aiStepTimeoutMs ?? 15 * 60_000), remainingMs))
1424
1424
  : aiStepTimeoutMs;
1425
- const coreRun = { runId, implementation: requiresCoreCompletion, spec: req.spec, goal: req.spec ? undefined : JSON.stringify({ loop: req.loopName, graph: req.graph }), repositoryId: req.repositoryId, verificationStep: node.data?.requireVerificationPass === true || /\{\{\s*cmd:(?:verify|revision-verify|opsx:verify)\s*\}\}/.test(rawTemplate) };
1425
+ const coreRun = { runId, implementation: requiresCoreCompletion, spec: req.spec, goal: req.spec ? undefined : JSON.stringify({ loop: req.loopName, graph: req.graph }), repositoryId: req.repositoryId, workspacePaths: req.workspacePaths, verificationStep: node.data?.requireVerificationPass === true || /\{\{\s*cmd:(?:verify|revision-verify|opsx:verify)\s*\}\}/.test(rawTemplate) };
1426
1426
  const interactivePlan = this.executors.planInteractiveAiStep?.({
1427
1427
  coreRun,
1428
1428
  provider: nodeProvider,
@@ -1552,7 +1552,7 @@ class LoopRunManager {
1552
1552
  && requiresCoreCompletion
1553
1553
  && this.executors.validateCoreCompletion) {
1554
1554
  const completion = this.executors.validateCoreCompletion({
1555
- coreRun: { runId, spec: req.spec, goal: req.spec ? undefined : JSON.stringify({ loop: req.loopName, graph: req.graph }), repositoryId: req.repositoryId },
1555
+ coreRun: { runId, spec: req.spec, goal: req.spec ? undefined : JSON.stringify({ loop: req.loopName, graph: req.graph }), repositoryId: req.repositoryId, workspacePaths: req.workspacePaths },
1556
1556
  provider: nodeProvider, model: nodeModel, effort: nodeEffort, profileName: req.profileName,
1557
1557
  cwd: req.cwd, repoDir: req.repoDir, executionManifest: req.executionManifest,
1558
1558
  });
@@ -8,6 +8,8 @@ exports.coreStarterGraph = coreStarterGraph;
8
8
  exports.supportsCoreTemplates = supportsCoreTemplates;
9
9
  exports.loopTemplatesForCapabilities = loopTemplatesForCapabilities;
10
10
  exports.getLoopTemplate = getLoopTemplate;
11
+ const loop_core_factory_1 = require("./loop-core-factory");
12
+ const loop_agents_1 = require("./loop-agents");
11
13
  /** Closed taxonomy a template's `category` must belong to. Single source of truth
12
14
  * for the gallery's category chips (the client derives its chip list from the
13
15
  * categories actually present in the served catalog). */
@@ -303,7 +305,8 @@ exports.LEGACY_LOOP_TEMPLATES = exports.LOOP_TEMPLATES;
303
305
  // - every mutating starter runs the real `verify` piece over the project's
304
306
  // configured checks and ends with `requiresVerified: true` — a passing sentinel
305
307
  // alone never reaches a success end;
306
- // - ship-and-green = native `implementation` → verify → decider → prompt(fix) loop;
308
+ // - ship-and-green expands implementation operations when supported, then
309
+ // verify → decider → prompt(fix); old Core retains the compatibility wrapper;
307
310
  // - prompts, goals and iteration caps come from STARTER_TEXT (legacy parity).
308
311
  /** Fix step shared by every mutating Core starter. Reuses the tuned `{{cmd:fix}}`
309
312
  * contract and covers the verify→fix edge, where no Decider verdict precedes it. */
@@ -324,7 +327,7 @@ function watcherVerdict(goal) {
324
327
  const CORE_GOAL_EVIDENCE = 'The configured host verification already passed on the current candidate before this decision. Judge only from concrete evidence in the history (commands run, their output, files changed); green baseline checks, setup or planning alone do not prove the goal.';
325
328
  const SHIP_AND_GREEN_GOAL = 'Stop only when the history proves the spec is implemented: every acceptance criterion maps to real code and behavioral evidence across every selected ticket and repository, and the configured host verification passed on the current candidate. Setup, planning, a launched subagent or green baseline checks alone are insufficient; continue when work is missing or incomplete.';
326
329
  /** Wall-clock cap for starters (legacy default). ship-and-green is untimed like the
327
- * Implement factory: the native implementation piece runs the whole pipeline. */
330
+ * Implement factory: implementation operations retain their own execution limits. */
328
331
  const STARTER_TIMEOUT_MIN = 30;
329
332
  const CORE_STARTER_SHAPES = {
330
333
  'ship-and-green': 'ship',
@@ -338,8 +341,10 @@ const CORE_STARTER_SHAPES = {
338
341
  };
339
342
  /** Core definition graph for one of the eight starters. Deterministic: same id ⇒
340
343
  * structurally identical graph (positions included). */
341
- function coreStarterGraph(id) {
344
+ function coreStarterGraph(id, independent = false, configurable = false) {
342
345
  const shape = CORE_STARTER_SHAPES[id];
346
+ if (shape === 'ship' && configurable)
347
+ return (0, loop_core_factory_1.coreFactoryGraph)('implement', true, true);
343
348
  const { prompt, goal, maxIterations } = STARTER_TEXT[id];
344
349
  const nodes = [{ id: 'start', type: 'start', position: { x: COL_X, y: 0 } }];
345
350
  const edges = [];
@@ -381,10 +386,29 @@ function coreStarterGraph(id) {
381
386
  }
382
387
  edges.unshift({ id: 'e-start', source: 'start', target: entry });
383
388
  nodes.push({ id: 'done', type: 'end', position: { x: COL_X, y: ROW_GAP * nodes.length }, data: successEnd }, { id: 'failed', type: 'end', position: { x: COL_RIGHT_X, y: ROW_GAP * nodes.length }, data: { outcome: 'failure' } });
389
+ if (independent) {
390
+ config.agents = (0, loop_agents_1.defaultLoopAgents)(shape === 'ship' ? 'implementation' : 'free');
391
+ if (shape === 'ship') {
392
+ const operations = (0, loop_core_factory_1.coreFactoryGraph)('implement', true);
393
+ const path = (id) => id === 'done' ? 'verify' : id === 'failed' ? 'failed' : `implementation-${id}`;
394
+ nodes.splice(nodes.findIndex(node => node.id === 'implement'), 1);
395
+ const remove = new Set(edges.filter(edge => edge.source === 'implement').map(edge => edge.id));
396
+ for (let i = edges.length - 1; i >= 0; i--)
397
+ if (remove.has(edges[i].id))
398
+ edges.splice(i, 1);
399
+ for (const edge of edges)
400
+ if (edge.target === 'implement')
401
+ edge.target = path('architect');
402
+ for (const node of operations.nodes.filter(node => node.type === 'core'))
403
+ nodes.push({ ...node, id: path(node.id) });
404
+ for (const edge of operations.edges.filter(edge => edge.source !== 'start'))
405
+ edges.push({ ...edge, id: 'implementation-' + edge.id, source: path(edge.source), target: path(edge.target) });
406
+ }
407
+ }
384
408
  return { nodes, edges, config };
385
409
  }
386
410
  const CORE_STARTER_DESCRIPTIONS = {
387
- 'ship-and-green': 'Fully autonomous: run Core\'s native implementation pipeline for the spec, then verify with the project\'s configured checks and refine (fix) on failure — verify → decide → fix until green. Success requires a verified candidate; no human intervention.',
411
+ 'ship-and-green': 'Fully autonomous: run the loop\'s implementation steps for the spec, then verify with the project\'s configured checks and refine (fix) on failure — verify → decide → fix until green. Success requires a verified candidate; no human intervention.',
388
412
  'verify-pass': 'Autonomous verify-and-fix: run the project\'s configured build/lint/tests through Core\'s verify piece, then refine on failure — verify → fix → verify until green.',
389
413
  'ci-watch': 'Poll CI checks on the open PR (the agent uses the repo\'s CI tooling) until every check is green. Read-only: the watcher never edits the repository.',
390
414
  'lint-and-fix': 'The agent detects and runs the project\'s linter and fixes every issue, iterating until the codebase is clean. Every pass is confirmed by the project\'s configured verification before the loop can succeed.',
@@ -414,7 +438,7 @@ function loopTemplatesForCapabilities(capabilities) {
414
438
  ...template,
415
439
  description: CORE_STARTER_DESCRIPTIONS[template.id],
416
440
  ...(readOnly ? { readOnly: true } : {}),
417
- graph: coreStarterGraph(template.id),
441
+ graph: coreStarterGraph(template.id, capabilities?.implementationSteps === 1, capabilities?.workflowAgentSteps === 1),
418
442
  };
419
443
  });
420
444
  }
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.registerLoopsRoutes = registerLoopsRoutes;
4
+ const loop_agents_1 = require("./loop-agents");
5
+ const agent_runtime_settings_1 = require("../../agent-runtime/runtime/agent-runtime-settings");
4
6
  const ids_1 = require("../../../ids");
5
7
  const feature_flags_1 = require("../../../feature-flags");
6
8
  const loops_store_1 = require("./loops-store");
@@ -57,6 +59,12 @@ function registerLoopsRoutes(router, deps) {
57
59
  }
58
60
  return true;
59
61
  }
62
+ router.get('/loop-agent-defaults', async (_req, res) => {
63
+ if (!guard(res))
64
+ return;
65
+ const runtime = await (0, agent_runtime_loader_1.loadCoreAgentRuntime)().catch(() => null);
66
+ res.json({ agents: (0, loop_agents_1.defaultLoopAgents)(), guardrails: { supported: runtime?.api?.capabilities?.configurableGuardrails === 1, catalog: runtime?.api?.guardrails ?? [] } });
67
+ });
60
68
  // ── Templates ──────────────────────────────────────────────────────────────
61
69
  router.get('/loop-templates', async (_req, res) => {
62
70
  if (!guard(res))
@@ -410,6 +418,15 @@ function registerLoopsRoutes(router, deps) {
410
418
  res.status(409).json({ error: 'engine_unsupported', message: 'Update Core to publish executable workflows.' });
411
419
  return;
412
420
  }
421
+ if (current.graph.config.agents) {
422
+ try {
423
+ (0, agent_runtime_settings_1.validateLoopRuntimeSettings)(current.graph.config.agents);
424
+ }
425
+ catch (error) {
426
+ res.status(422).json({ error: 'invalid_loop_agents', message: error instanceof Error ? error.message : 'Invalid loop agent settings' });
427
+ return;
428
+ }
429
+ }
413
430
  let draft;
414
431
  try {
415
432
  draft = (0, loop_definition_1.compileLoopToDefinition)(current.graph, { id: current.id, title: current.name, constants: (0, loop_constants_1.loadConstantMap)(db), provider: 'claude', spec: { id: 1, title: 'Sample spec', description: 'Publication preview' } });
@@ -149,7 +149,7 @@ function formatProjectOverview(ref, index, deps) {
149
149
  lines.push('resolution: unresolved project');
150
150
  return lines.join('\n');
151
151
  }
152
- lines.push(`project.id: ${project.id}`, `project.name: ${safe(project.name, 180)}`, `project.slug: ${safe(project.slug, 120)}`, `project.path: ${project.path}`, `project.provider: ${safe(project.provider, 80)}`, `project.providers: ${(project.providers ?? [project.provider]).join(', ')}`, `project.runtime: ${context ? 'available' : 'unavailable; do not interpret this as a deleted project'}`, `project.repositories: ${JSON.stringify((0, project_repositories_1.getProjectRepositories)(project).map(repository => ({ id: repository.id, name: repository.name, path: repository.path, isPrimary: repository.isPrimary, kind: repository.kind, available: repository.available })))}`, 'repository.scope: One shared project backlog. Files and Git operations require repositoryId when more than one member exists; find/search can discover across members. Reading context does not grant implementation write access. Historical specs without repositoryIds target only the primary.');
152
+ lines.push(`project.id: ${project.id}`, `project.name: ${safe(project.name, 180)}`, `project.slug: ${safe(project.slug, 120)}`, `project.path: ${project.path}`, `project.provider: ${safe(project.provider, 80)}`, `project.providers: ${(project.providers ?? [project.provider]).join(', ')}`, `project.runtime: ${context ? 'available' : 'unavailable; do not interpret this as a deleted project'}`, `project.repositories: ${JSON.stringify((0, project_repositories_1.getProjectRepositories)(project).map(repository => ({ id: repository.id, name: repository.name, path: repository.path, workspacePaths: repository.workspacePaths ?? [repository.workspacePath ?? repository.path], isPrimary: repository.isPrimary, kind: repository.kind, available: repository.available })))}`, 'repository.scope: One shared project backlog. Files and Git operations require repositoryId when more than one member exists; find/search can discover across members. Reading context does not grant implementation write access. Historical specs without repositoryIds target only the primary.');
153
153
  try {
154
154
  const tickets = Object.values((0, ticket_store_1.readStore)(ticketFileFor(project)).tickets);
155
155
  const counts = tickets.reduce((acc, ticket) => {
@@ -628,6 +628,13 @@ summary later.
628
628
  N-1. When talking to the user ALWAYS use the 1-based label (tool results
629
629
  include \`railLabel\`, e.g. railIndex 3 → "Rail 4") or the rail's custom name;
630
630
  never quote the raw railIndex as the rail's name.
631
+ - Code workspace selection: discover \`workspacePaths\` in the project context. A
632
+ project folder can contain several code workspaces; tests must run in the
633
+ workspace being changed. Include \`workspaceSelection\` (repository ID → array
634
+ of registered workspace paths) in rail-launch cards and direct launch calls to
635
+ target a subset. Preserve \`repositoryIds\` for affected Git memberships. Do not
636
+ invent paths or substitute the parent folder. Omission uses every configured
637
+ workspace for each affected membership.
631
638
  - Configure then launch: \`specrails_rails(set_tickets, railIndex, ticketIds)\` →
632
639
  \`specrails_rails(launch, railIndex, mode, …)\`. Setting a profile and then
633
640
  switching the rail's engine to a provider without profile support
@@ -657,15 +664,15 @@ summary later.
657
664
  relaunch strategy even when \`main\` did not have that spec before the PR. If
658
665
  asked why a strategy was chosen, verify against active PR contents before
659
666
  answering.
660
- - **"Change something about work already delivered" = a Quick SDD continuation.** When
667
+ - **"Change something about work already delivered" = a delivery continuation.** When
661
668
  the user asks for a modification to a delivery that is awaiting their decision
662
669
  (any non-terminal card: \`on_review\`, \`pr_draft\`, \`pr_ready\`, \`no_changes\`,
663
670
  \`implementation_failed\`), call \`specrails_rails(launch)\` with
664
671
  \`revisionOfDeliveryId\` = that card's \`prDeliveryId\` and \`revisionNote\` = what
665
672
  they asked for, in their own words. Do NOT tell them to publish, discard or
666
- merge first, and do NOT relaunch the ordinary implement mode: a revision
667
- always uses Quick SDD: pass \`loopId:'factory:sdd-quick-openspec'\` alongside the delivery
668
- target. The server preserves the branch while running Quick SDD. The rail must still carry exactly that delivery's
673
+ merge first. Respect the user's explicit loop selection, including Implement:
674
+ pass that loopId alongside the delivery target. Without a preference, use
675
+ \`loopId:'factory:sdd-quick-openspec'\`. The server preserves the branch. The rail must still carry exactly that delivery's
669
676
  specs; a mismatch returns \`invalid_revision_target\`, which means re-check the
670
677
  rail's spec assignment rather than retrying blindly.
671
678
  - **"Resolve / fix the review comments on this PR" = a FOLLOW-UP launch, never a
@@ -706,9 +713,9 @@ summary later.
706
713
  \`dismiss_addendum\` withdraws it. Prefer an addendum + normal launch over a
707
714
  \`revisionNote\` when the change should stay attached to the spec for later
708
715
  runs; the two combine freely.
709
- **Addenda on an existing branch/open PR ALWAYS run Quick SDD**, never Revision.
710
- Use \`loopId:'factory:sdd-quick-openspec'\`; the server routes addenda there
711
- even if the rail stores a different loop. A same-spec pending delivery is
716
+ **Respect explicit loop selection for addenda**, including Implement.
717
+ Recommend Quick SDD when no preference was given; never silently replace
718
+ Implement with Quick SDD after agreeing to use Implement. A same-spec pending delivery is
712
719
  continued without requiring publish/discard first. Keep the exact ticket and
713
720
  repository scope; pass the delivery id when known. The runtime assigns a NEW
714
721
  run-specific OpenSpec change for the frozen addenda, so NEVER edit
@@ -889,6 +896,8 @@ never as a launch):
889
896
  \`null\` means "the rail's / project's default".
890
897
  - \`targetPrNumber\` / \`baseBranch\`: only when the user named an existing PR
891
898
  or a branch to stack on.
899
+ - \`repositoryIds\`: selected registered repository memberships, consistent with the specs.
900
+ - \`workspaceSelection\`: optional object mapping each selected repository id to a non-empty array of registered workspace paths. Discover paths from project context; never invent them. Omission uses every configured workspace. The card lets the user edit this choice before Play.
892
901
  - \`rationale\`: ONE sentence — why this grouping / engine.
893
902
 
894
903
  Prose around the block: say what you propose in one or two lines and stop —
@@ -916,7 +925,7 @@ investigate and fix. Read runtime_diagnose before recommending a retry.
916
925
  function buildOperatorInstructions() {
917
926
  return (0, feature_flags_1.isMissionRailCardsEnabled)() ? `${exports.OPERATOR_INSTRUCTIONS}\n${exports.RAIL_LAUNCH_CARD_SECTION}` : exports.OPERATOR_INSTRUCTIONS;
918
927
  }
919
- exports.RAIL_LAUNCH_CARD_SYSTEM_CLAUSE = ' When the user asks to assign, prepare or launch specs on a rail WITHOUT explicitly saying to launch now, do not call specrails_rails launch — emit one fenced rail-launch JSON block per rail (ticketIds, railIndex or newRail, mode, loopId, aiEngine, model, reasoningEffort, profileName, rationale) so the app renders an editable launch card the user plays; never propose a rail whose availability is not free. A message starting with "[Specrails run-failure briefing" is app-posted: answer in ≤ 6 lines with the failure and ONE recommended next action, and never resume, recover, relaunch or discard in that turn.';
928
+ exports.RAIL_LAUNCH_CARD_SYSTEM_CLAUSE = ' When the user asks to assign, prepare or launch specs on a rail WITHOUT explicitly saying to launch now, do not call specrails_rails launch — emit one fenced rail-launch JSON block per rail (ticketIds, railIndex or newRail, mode, loopId, aiEngine, model, reasoningEffort, profileName, repositoryIds, workspaceSelection, rationale) so the app renders an editable launch card the user plays; never propose a rail whose availability is not free. A message starting with "[Specrails run-failure briefing" is app-posted: answer in ≤ 6 lines with the failure and ONE recommended next action, and never resume, recover, relaunch or discard in that turn.';
920
929
  /** The per-turn system prompt (flag-aware). */
921
930
  function buildOperatorSystemPrompt() {
922
931
  return (0, feature_flags_1.isMissionRailCardsEnabled)() ? `${exports.OPERATOR_SYSTEM_PROMPT}${exports.RAIL_LAUNCH_CARD_SYSTEM_CLAUSE}` : exports.OPERATOR_SYSTEM_PROMPT;
@@ -6,20 +6,17 @@ exports.isValidModelForProvider = isValidModelForProvider;
6
6
  exports.getProviderDefault = getProviderDefault;
7
7
  const providers_1 = require("../../../providers");
8
8
  exports.CLAUDE_MODELS = [
9
- { value: 'sonnet', label: 'Claude Sonnet' },
10
- { value: 'fable', label: 'Claude Fable' },
9
+ { value: 'sonnet', label: 'Sonnet 5.5' },
10
+ { value: 'fable', label: 'Fable 5.1' },
11
11
  { value: 'opus', label: 'Claude Opus' },
12
12
  { value: 'haiku', label: 'Claude Haiku' },
13
13
  ];
14
14
  exports.CODEX_MODELS = [
15
+ { value: 'gpt-6.1-sol', label: 'GPT-6.1 Sol' },
15
16
  { value: 'gpt-6-astra', label: 'GPT-6 Astra' },
16
17
  { value: 'gpt-5.6-sol', label: 'GPT-5.6 Sol' },
17
18
  { value: 'gpt-5.6-terra', label: 'GPT-5.6 Terra' },
18
19
  { value: 'gpt-5.6-luna', label: 'GPT-5.6 Luna' },
19
- { value: 'gpt-5.5', label: 'GPT-5.5' },
20
- { value: 'gpt-5.4', label: 'GPT-5.4' },
21
- { value: 'gpt-5.4-mini', label: 'GPT-5.4 Mini' },
22
- { value: 'gpt-5.3-codex', label: 'GPT-5.3 Codex' },
23
20
  ];
24
21
  // Mirrors GEMINI_MODELS in server/providers/gemini-adapter.ts.
25
22
  exports.GEMINI_MODELS = [
@@ -43,7 +40,7 @@ const PROVIDER_MODELS = {
43
40
  };
44
41
  exports.PROVIDER_DEFAULT_MODEL = {
45
42
  claude: 'sonnet',
46
- codex: 'gpt-5.5',
43
+ codex: 'gpt-6.1-sol',
47
44
  gemini: 'gemini-3.5-flash',
48
45
  kimi: 'k3',
49
46
  };
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createClaudeReader = createClaudeReader;
7
+ const node_child_process_1 = require("node:child_process");
8
+ const node_os_1 = require("node:os");
9
+ const promises_1 = require("node:fs/promises");
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const domain_1 = require("../domain");
12
+ const errors_1 = require("./errors");
13
+ const local_auth_1 = require("./local-auth");
14
+ function readKeychain(service, signal) {
15
+ return new Promise((resolve, reject) => {
16
+ let account;
17
+ try {
18
+ account = process.env.USER || process.env.USERNAME || (0, node_os_1.userInfo)().username;
19
+ }
20
+ catch {
21
+ account = 'claude-code-user';
22
+ }
23
+ if (!/^[a-zA-Z0-9._-]+$/.test(account))
24
+ account = 'claude-code-user';
25
+ (0, node_child_process_1.execFile)('/usr/bin/security', ['find-generic-password', '-s', service, '-a', account, '-w'], { timeout: 3000, maxBuffer: 1024 * 1024, signal }, (error, stdout) => {
26
+ if (!error)
27
+ resolve(stdout);
28
+ else if (error.code === 44)
29
+ resolve(null);
30
+ else
31
+ reject(new errors_1.UsageError('credentials-unreadable'));
32
+ });
33
+ });
34
+ }
35
+ function createClaudeReader(options = {}) {
36
+ const configured = options.configDir ?? process.env.CLAUDE_CONFIG_DIR;
37
+ const configDir = configured ?? node_path_1.default.join((0, node_os_1.homedir)(), '.claude');
38
+ async function credentials(signal) {
39
+ if (!node_path_1.default.isAbsolute(configDir))
40
+ throw new errors_1.UsageError('unsupported-platform');
41
+ let keychainFailure = false;
42
+ if ((options.platform ?? process.platform) === 'darwin') {
43
+ const aliases = configured ? [configDir] : [];
44
+ if (configured) {
45
+ try {
46
+ const canonical = await (0, promises_1.realpath)(configDir);
47
+ if (canonical !== configDir)
48
+ aliases.push(canonical);
49
+ }
50
+ catch { /* use the exact resolved context */ }
51
+ }
52
+ const services = configured ? aliases.map(dir => `Claude Code-credentials-${(0, local_auth_1.fingerprint)(dir.normalize('NFC')).slice(0, 8)}`) : ['Claude Code-credentials'];
53
+ for (const service of services) {
54
+ try {
55
+ const raw = await (options.keychain ?? readKeychain)(service, signal);
56
+ if (raw)
57
+ return raw;
58
+ }
59
+ catch {
60
+ keychainFailure = true;
61
+ break;
62
+ }
63
+ }
64
+ }
65
+ const file = await (options.readFile ?? local_auth_1.readAuthFile)(node_path_1.default.join(configDir, '.credentials.json'));
66
+ if (file)
67
+ return file;
68
+ if (keychainFailure)
69
+ throw new errors_1.UsageError('credentials-unreadable');
70
+ return null;
71
+ }
72
+ return {
73
+ async context(signal) { return (0, local_auth_1.fingerprint)(`${configDir}:${await credentials(signal) ?? 'none'}`); },
74
+ async read(signal) {
75
+ const raw = await credentials(signal);
76
+ if (!raw)
77
+ return { availability: 'signed-out', windows: [], plan: null, source: null };
78
+ let data;
79
+ try {
80
+ data = (0, domain_1.record)(JSON.parse(raw));
81
+ }
82
+ catch {
83
+ throw new errors_1.UsageError('credentials-unreadable');
84
+ }
85
+ const oauth = (0, domain_1.record)(data.claudeAiOauth);
86
+ if (typeof oauth.accessToken !== 'string' || !oauth.accessToken)
87
+ return { availability: 'unsupported-auth', windows: [], plan: null, source: null };
88
+ const response = await (options.request ?? fetch)('https://api.anthropic.com/api/oauth/usage', {
89
+ headers: { Authorization: `Bearer ${oauth.accessToken}`, 'anthropic-beta': 'oauth-2025-04-20', 'User-Agent': 'claude-code/2.1.0' },
90
+ signal: AbortSignal.any([signal, AbortSignal.timeout(10_000)]), redirect: 'error',
91
+ });
92
+ if (!response.ok) {
93
+ await response.body?.cancel().catch(() => { });
94
+ if (response.status === 401)
95
+ throw new errors_1.UsageError('signed-out');
96
+ if (response.status === 403)
97
+ throw new errors_1.UsageError('permission-denied');
98
+ if (response.status === 429) {
99
+ const header = response.headers.get('retry-after');
100
+ const seconds = header !== null && header.trim() !== '' ? Number(header) : NaN;
101
+ const date = header ? Date.parse(header) : NaN;
102
+ const retry = Number.isFinite(seconds) ? seconds * 1000 : Number.isFinite(date) ? date - Date.now() : 60_000;
103
+ throw new errors_1.UsageError('rate-limited', true, Math.max(30_000, Math.min(24 * 60 * 60_000, retry)));
104
+ }
105
+ throw new errors_1.UsageError('provider-error', response.status >= 500);
106
+ }
107
+ const payload = await (0, local_auth_1.limitedJson)(response), windows = (0, domain_1.normalizeClaude)(payload);
108
+ if (!windows.length)
109
+ throw new errors_1.UsageError('usage-unavailable');
110
+ return { availability: 'available', windows, plan: null, source: 'oauth' };
111
+ },
112
+ };
113
+ }