specrails-desktop 2.18.2 → 2.19.1
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.
- package/README.md +1 -1
- package/client/dist/assets/{ActivityFeedPage-mGnv5SOe.js → ActivityFeedPage-C0_k6n5T.js} +1 -1
- package/client/dist/assets/AgentBrowserCapture-NHUCEnTh.js +1 -0
- package/client/dist/assets/AgentModeCodePane-jddXrhPY.js +2 -0
- package/client/dist/assets/AgentsPage-BPjf6bId.js +86 -0
- package/client/dist/assets/AnalyticsPage-BaJjj5mO.js +1 -0
- package/client/dist/assets/{BarChart-BqHUOnl9.js → BarChart-HPiao--v.js} +1 -1
- package/client/dist/assets/CodePage-CAD4KfkC.js +2 -0
- package/client/dist/assets/{DesktopAnalyticsPage-CR-m97Ui.js → DesktopAnalyticsPage-B2RBxIvj.js} +1 -1
- package/client/dist/assets/DocsDialog-BJDvUEGj.js +11 -0
- package/client/dist/assets/DocsPage-B6H-DBs8.js +11 -0
- package/client/dist/assets/{ExportDropdown-C-o1Q4ef.js → ExportDropdown-CYMcbLTD.js} +1 -1
- package/client/dist/assets/IntegrationsPage-Dx_UpQVk.js +3 -0
- package/client/dist/assets/JobDetailPage-BlTnsRAN.js +16 -0
- package/client/dist/assets/JobsPage-EB0PbXOk.js +1 -0
- package/client/dist/assets/LoopBuilderPage-DfWfhhJY.js +7 -0
- package/client/dist/assets/LoopsPage-DCVATTv5.js +1 -0
- package/client/dist/assets/{addspec-B9dY_F5T.js → addspec-BXV6sx5l.js} +1 -1
- package/client/dist/assets/{addspec-tbxr3sHa.js → addspec-CS895X6A.js} +1 -1
- package/client/dist/assets/{addspec-W0r16BOC2.js → addspec-CXfEOrD42.js} +1 -1
- package/client/dist/assets/{addspec-D43TlMVp2.js → addspec-D28kw9ow2.js} +1 -1
- package/client/dist/assets/{addspec-B9nhMikb.js → addspec-D39EEg02.js} +1 -1
- package/client/dist/assets/{addspec-DfgIZ5lO.js → addspec-DC1tgsFG.js} +1 -1
- package/client/dist/assets/{addspec-BtNaJHu2.js → addspec-DcHALPEp.js} +1 -1
- package/client/dist/assets/{addspec-BloGn_ey.js → addspec-DxW6oPsk.js} +1 -1
- package/client/dist/assets/{agent-Bm2tPrdr.js → agent-B5Ycau5M.js} +1 -1
- package/client/dist/assets/{agent-DMUrz9ZS2.js → agent-BEz08l4_2.js} +1 -1
- package/client/dist/assets/{agent-C4bO1l_v.js → agent-BIX51CEA.js} +1 -1
- package/client/dist/assets/{agent-9WdSxPU5.js → agent-Bc9Kwf65.js} +1 -1
- package/client/dist/assets/{agent-pO8x4jbR.js → agent-BiM7puyn.js} +1 -1
- package/client/dist/assets/{agent-CgKsh88Z2.js → agent-C0kYSv3m2.js} +1 -1
- package/client/dist/assets/agent-CCzWlfqs.js +1 -0
- package/client/dist/assets/{agent-ASIyVcg0.js → agent-DiCSo31C.js} +1 -1
- package/client/dist/assets/{agents-DfGvYtpq2.js → agents-BFrHy5d-2.js} +1 -1
- package/client/dist/assets/{agents-Dli56gr82.js → agents-BFy2Kq_k2.js} +1 -1
- package/client/dist/assets/{agents-C07al8rI.js → agents-BXDCFJQa.js} +1 -1
- package/client/dist/assets/{agents-BAxAwHy-.js → agents-BySH0Gvw.js} +1 -1
- package/client/dist/assets/{agents-Eqw_AQ6H.js → agents-CTdwacTO.js} +1 -1
- package/client/dist/assets/{agents-BjT_xLjv.js → agents-Cev2oFfX.js} +1 -1
- package/client/dist/assets/{agents-BUYBb825.js → agents-CsDEv4Fj.js} +1 -1
- package/client/dist/assets/{agents-52t8NVpS.js → agents-z0kA-y0Q.js} +1 -1
- package/client/dist/assets/dashboard-Bl2_Yjs6.js +1 -0
- package/client/dist/assets/dashboard-C_vS9RaM2.js +1 -0
- package/client/dist/assets/dashboard-CcEpALV_.js +1 -0
- package/client/dist/assets/dashboard-CfltY66K.js +1 -0
- package/client/dist/assets/dashboard-CoED_41r.js +1 -0
- package/client/dist/assets/dashboard-DLeC5ziO.js +1 -0
- package/client/dist/assets/dashboard-DxEPkALo2.js +1 -0
- package/client/dist/assets/dashboard-MgDVmaYS2.js +1 -0
- package/client/dist/assets/{dist-js-CUegfF6k.js → dist-js-ClEfL6Bo.js} +1 -1
- package/client/dist/assets/{dist-js-BHhtSerX.js → dist-js-b2_z7zAi.js} +1 -1
- package/client/dist/assets/index-9yNUBwEi.css +2 -0
- package/client/dist/assets/{index-B7vB20Jw.js → index-BeujshsU.js} +57 -57
- package/client/dist/assets/{lib-PQoHlR5u.js → lib-CfphudAm.js} +1 -1
- package/client/dist/assets/loops-BEUiCzEI.js +1 -0
- package/client/dist/assets/loops-BlrQiK122.js +1 -0
- package/client/dist/assets/loops-Bs0ectZ32.js +1 -0
- package/client/dist/assets/loops-CLZV8HHY2.js +1 -0
- package/client/dist/assets/loops-CQuuMlyZ.js +1 -0
- package/client/dist/assets/loops-DuuWQWTI.js +1 -0
- package/client/dist/assets/loops-KOTryzk5.js +1 -0
- package/client/dist/assets/loops-t1mUZtf0.js +1 -0
- package/client/dist/assets/nav--1ErXZrS.js +1 -0
- package/client/dist/assets/nav-18nqSJ8h.js +1 -0
- package/client/dist/assets/nav-BuonHb17.js +1 -0
- package/client/dist/assets/nav-C-sCoOLY2.js +1 -0
- package/client/dist/assets/nav-ClXz_3Ic2.js +1 -0
- package/client/dist/assets/nav-CtqgSQeE2.js +1 -0
- package/client/dist/assets/nav-S3YvCaVv.js +1 -0
- package/client/dist/assets/nav-czg8NkN-.js +1 -0
- package/client/dist/assets/settings-BOZBX-Vq.js +1 -0
- package/client/dist/assets/settings-CX29QcQW.js +1 -0
- package/client/dist/assets/settings-CfOWHPzc2.js +1 -0
- package/client/dist/assets/settings-DaXhxNug2.js +1 -0
- package/client/dist/assets/settings-DmyDpuzu.js +1 -0
- package/client/dist/assets/settings-DwPRLcxr2.js +1 -0
- package/client/dist/assets/settings-MjYVJvDE.js +1 -0
- package/client/dist/assets/settings-zJFdTzKE.js +1 -0
- package/client/dist/assets/{setup-BYoDYoPY2.js → setup-BmXfxlzA2.js} +1 -1
- package/client/dist/assets/{setup-faMApo0U2.js → setup-BxVydxbl2.js} +1 -1
- package/client/dist/assets/{setup-C5UbM0RP.js → setup-DIRZ1Lf-.js} +1 -1
- package/client/dist/assets/{setup-Bf9eLKxU.js → setup-DwbKSnKQ.js} +1 -1
- package/client/dist/assets/{setup-JFkWWZnR.js → setup-Dx13pESZ.js} +1 -1
- package/client/dist/assets/{setup-CqGrWb6G.js → setup-G4ZvDKxX.js} +1 -1
- package/client/dist/assets/{setup-tloaTobG2.js → setup-SLAi4xxQ2.js} +1 -1
- package/client/dist/assets/{setup-4us-Bz3H.js → setup-Z01j3st4.js} +1 -1
- package/client/dist/assets/{upload-PnJDPHZH.js → upload-Ox9jUq1X.js} +1 -1
- package/client/dist/assets/{value-BTDefcOV.js → value-BeQVX5gN.js} +1 -1
- package/client/dist/index.html +10 -10
- package/docs/codex.md +5 -5
- package/docs/customizing.md +4 -4
- package/docs/gemini.md +2 -2
- package/docs/getting-started.md +1 -1
- package/docs/guide/de/integrations/1-ai-providers.md +2 -2
- package/docs/guide/de/integrations/5-mcp-server.md +20 -1
- package/docs/guide/de/pipeline/1-rails-and-jobs.md +4 -4
- package/docs/guide/de/pipeline/2-the-job-detail-view.md +1 -1
- package/docs/guide/de/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/de/pipeline/5-the-loop-builder.md +2 -2
- package/docs/guide/en/integrations/1-ai-providers.md +2 -2
- package/docs/guide/en/integrations/5-mcp-server.md +20 -1
- package/docs/guide/en/pipeline/1-rails-and-jobs.md +4 -4
- package/docs/guide/en/pipeline/2-the-job-detail-view.md +1 -1
- package/docs/guide/en/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/en/pipeline/5-the-loop-builder.md +2 -2
- package/docs/guide/es/integrations/1-ai-providers.md +2 -2
- package/docs/guide/es/integrations/5-mcp-server.md +20 -1
- package/docs/guide/es/pipeline/1-rails-and-jobs.md +4 -4
- package/docs/guide/es/pipeline/2-the-job-detail-view.md +1 -1
- package/docs/guide/es/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/es/pipeline/5-the-loop-builder.md +2 -2
- package/docs/guide/fr/integrations/1-ai-providers.md +2 -2
- package/docs/guide/fr/integrations/5-mcp-server.md +20 -1
- package/docs/guide/fr/pipeline/1-rails-and-jobs.md +4 -4
- package/docs/guide/fr/pipeline/2-the-job-detail-view.md +1 -1
- package/docs/guide/fr/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/fr/pipeline/5-the-loop-builder.md +2 -2
- package/docs/guide/it/integrations/1-ai-providers.md +2 -2
- package/docs/guide/it/integrations/5-mcp-server.md +20 -1
- package/docs/guide/it/pipeline/1-rails-and-jobs.md +4 -4
- package/docs/guide/it/pipeline/2-the-job-detail-view.md +1 -1
- package/docs/guide/it/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/it/pipeline/5-the-loop-builder.md +2 -2
- package/docs/guide/ja/integrations/1-ai-providers.md +2 -2
- package/docs/guide/ja/integrations/5-mcp-server.md +20 -1
- package/docs/guide/ja/pipeline/1-rails-and-jobs.md +4 -4
- package/docs/guide/ja/pipeline/2-the-job-detail-view.md +1 -1
- package/docs/guide/ja/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/ja/pipeline/5-the-loop-builder.md +2 -2
- package/docs/guide/pt/integrations/1-ai-providers.md +2 -2
- package/docs/guide/pt/integrations/5-mcp-server.md +20 -1
- package/docs/guide/pt/pipeline/1-rails-and-jobs.md +4 -4
- package/docs/guide/pt/pipeline/2-the-job-detail-view.md +1 -1
- package/docs/guide/pt/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/pt/pipeline/5-the-loop-builder.md +2 -2
- package/docs/guide/zh/integrations/1-ai-providers.md +2 -2
- package/docs/guide/zh/integrations/5-mcp-server.md +20 -1
- package/docs/guide/zh/pipeline/1-rails-and-jobs.md +4 -4
- package/docs/guide/zh/pipeline/2-the-job-detail-view.md +1 -1
- package/docs/guide/zh/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/zh/pipeline/5-the-loop-builder.md +2 -2
- package/docs/internals/switch-to-agent-mode-design.md +301 -0
- package/docs/internals/visual-design-audit.md +184 -0
- package/docs/mcp.md +26 -1
- package/docs/running-pipelines.md +10 -10
- package/docs/tracking-cost.md +1 -1
- package/package.json +1 -1
- package/server/dist/agent-chat-manager.js +107 -33
- package/server/dist/agent-chat-router.js +170 -8
- package/server/dist/agent-cwd-manager.js +2 -47
- package/server/dist/agent-operator-prompt.js +277 -0
- package/server/dist/agent-store.js +27 -5
- package/server/dist/attachment-manager.js +138 -0
- package/server/dist/desktop-db.js +15 -0
- package/server/dist/loop-factory.js +12 -2
- package/server/dist/mcp/guide.js +186 -51
- package/server/dist/mcp/tools/analytics.js +1 -1
- package/server/dist/mcp/tools/app-settings.js +45 -5
- package/server/dist/mcp/tools/chat.js +9 -2
- package/server/dist/mcp/tools/code.js +3 -2
- package/server/dist/mcp/tools/jobs.js +18 -6
- package/server/dist/mcp/tools/loops.js +57 -5
- package/server/dist/mcp/tools/meta.js +43 -3
- package/server/dist/mcp/tools/rails.js +6 -6
- package/server/dist/mcp/tools/setup.js +2 -1
- package/server/dist/mcp/tools/specs.js +60 -38
- package/server/dist/mcp/tools/types.js +17 -8
- package/server/dist/mcp/tools/watch.js +71 -8
- package/server/dist/project-router-helpers.js +1 -1
- package/server/dist/project-router-tickets.js +43 -4
- package/server/dist/providers/claude-adapter.js +6 -0
- package/server/dist/providers/codex-adapter.js +10 -0
- package/server/dist/providers/gemini-adapter.js +3 -0
- package/server/dist/rails-router.js +8 -17
- package/server/dist/spec-models.js +1 -0
- package/client/dist/assets/AgentsPage-BH1isg5j.js +0 -86
- package/client/dist/assets/AnalyticsPage-ByyshYRI.js +0 -1
- package/client/dist/assets/CodePage-CU7T_HYs.js +0 -2
- package/client/dist/assets/DocsDialog-CEmZp_8V.js +0 -11
- package/client/dist/assets/DocsPage-DYbAQ1AT.js +0 -11
- package/client/dist/assets/IntegrationsPage-C6fKdwVH.js +0 -3
- package/client/dist/assets/JobDetailPage-CKfIfBgE.js +0 -16
- package/client/dist/assets/JobsPage-nBng0riZ.js +0 -1
- package/client/dist/assets/LoopBuilderPage-Co_TYqYk.js +0 -7
- package/client/dist/assets/LoopsPage-a2hd37Ya.js +0 -1
- package/client/dist/assets/agent-Dwkz5mPS.js +0 -1
- package/client/dist/assets/dashboard-BTiH361F.js +0 -1
- package/client/dist/assets/dashboard-COSm_14E.js +0 -1
- package/client/dist/assets/dashboard-CfOs70FN2.js +0 -1
- package/client/dist/assets/dashboard-Cyzp4ox9.js +0 -1
- package/client/dist/assets/dashboard-CzHDp14_2.js +0 -1
- package/client/dist/assets/dashboard-D6Woy2B5.js +0 -1
- package/client/dist/assets/dashboard-DwbH4oVH.js +0 -1
- package/client/dist/assets/dashboard-cWhU3krA2.js +0 -1
- package/client/dist/assets/index-B0FxQALR.css +0 -2
- package/client/dist/assets/loops-BDhEfnx82.js +0 -1
- package/client/dist/assets/loops-BM5QggwH.js +0 -1
- package/client/dist/assets/loops-CPjLAAxj.js +0 -1
- package/client/dist/assets/loops-D8Iu6Jss.js +0 -1
- package/client/dist/assets/loops-DKnk79TB2.js +0 -1
- package/client/dist/assets/loops-DLW0aFMm.js +0 -1
- package/client/dist/assets/loops-Dcv3dFy_2.js +0 -1
- package/client/dist/assets/loops-y7wFRx6M.js +0 -1
- package/client/dist/assets/nav-1hj2izqB2.js +0 -1
- package/client/dist/assets/nav-BBUKMAu-2.js +0 -1
- package/client/dist/assets/nav-CLqkP-26.js +0 -1
- package/client/dist/assets/nav-Cv46L837.js +0 -1
- package/client/dist/assets/nav-DE3yWQw6.js +0 -1
- package/client/dist/assets/nav-DgA-rjLk2.js +0 -1
- package/client/dist/assets/nav-EG2pr6vN.js +0 -1
- package/client/dist/assets/nav-r3mIJVfU.js +0 -1
- package/client/dist/assets/settings-BKmORxlB2.js +0 -1
- package/client/dist/assets/settings-BVv2JgQ8.js +0 -1
- package/client/dist/assets/settings-Bghm3pAV.js +0 -1
- package/client/dist/assets/settings-BuC_aplX.js +0 -1
- package/client/dist/assets/settings-Bw_Qk8E32.js +0 -1
- package/client/dist/assets/settings-CAKgJv7p.js +0 -1
- package/client/dist/assets/settings-CEUgk1Ck.js +0 -1
- package/client/dist/assets/settings-C_PDE20s2.js +0 -1
- /package/client/dist/assets/{activity-Uj576ckT.js → activity-BlvN5rhP.js} +0 -0
- /package/client/dist/assets/{activity-w1qMFwxh.js → activity-C5SeKbom.js} +0 -0
- /package/client/dist/assets/{activity-BySXFT2J2.js → activity-DIJexk6v2.js} +0 -0
- /package/client/dist/assets/{activity-B82z3Pna.js → activity-DLdwUYv7.js} +0 -0
- /package/client/dist/assets/{activity-BVpZrs0J.js → activity-DOKV_Wyf.js} +0 -0
- /package/client/dist/assets/{activity-BId0pwuS2.js → activity-DVuiy8TI2.js} +0 -0
- /package/client/dist/assets/{activity-DIWnV0Pl.js → activity-Dsf3J7iW.js} +0 -0
- /package/client/dist/assets/{agentstudio-C7xxqVWn.js → agentstudio-B8H2H4Db2.js} +0 -0
- /package/client/dist/assets/{agentstudio-D-UoNAIA.js → agentstudio-B9zthaTJ.js} +0 -0
- /package/client/dist/assets/{agentstudio-0o3XKrcy.js → agentstudio-BDMpU01s.js} +0 -0
- /package/client/dist/assets/{agentstudio-Bu8m5jDw.js → agentstudio-CSZo7p8K.js} +0 -0
- /package/client/dist/assets/{agentstudio-ObTpVbBP.js → agentstudio-CdD6J23W.js} +0 -0
- /package/client/dist/assets/{agentstudio-PzFB3vfh2.js → agentstudio-D80fZu_M2.js} +0 -0
- /package/client/dist/assets/{agentstudio-OJjjz6Uf2.js → agentstudio-EuKglkaF2.js} +0 -0
- /package/client/dist/assets/{aiedit-DRrNiaB4.js → aiedit-B_VOTUo42.js} +0 -0
- /package/client/dist/assets/{aiedit-sP_iao2j.js → aiedit-Cxoe_0wv.js} +0 -0
- /package/client/dist/assets/{aiedit-DAM_WRAl2.js → aiedit-D59sPapq2.js} +0 -0
- /package/client/dist/assets/{aiedit-BaLZalLa.js → aiedit-DX3BBpXF.js} +0 -0
- /package/client/dist/assets/{aiedit-BIQqv2XM2.js → aiedit-GYOYWCHJ2.js} +0 -0
- /package/client/dist/assets/{aiedit-BjlUzasF.js → aiedit-TON-4N9S.js} +0 -0
- /package/client/dist/assets/{aiedit-BmDufyGU.js → aiedit-ybQmdsST.js} +0 -0
- /package/client/dist/assets/{analytics-MVJRjcY52.js → analytics-B2jjXLCP2.js} +0 -0
- /package/client/dist/assets/{analytics-C4z_NgJZ.js → analytics-BTkXLTfa.js} +0 -0
- /package/client/dist/assets/{analytics-DL2vJCbq.js → analytics-BotqRU_R.js} +0 -0
- /package/client/dist/assets/{analytics-e1mkNTgy2.js → analytics-Ck3vl2Qo2.js} +0 -0
- /package/client/dist/assets/{analytics-Ds_PNxtO2.js → analytics-CqMJQb7N.js} +0 -0
- /package/client/dist/assets/{analytics-B_rxNC9X.js → analytics-DGOoMkaZ.js} +0 -0
- /package/client/dist/assets/{analytics-BDqqCzN9.js → analytics-DL7uwNAI2.js} +0 -0
- /package/client/dist/assets/{attachments-BP0Ac1yt.js → attachments-7w-BR2V2.js} +0 -0
- /package/client/dist/assets/{attachments-CPBVeHX72.js → attachments-B5QX1Xfa2.js} +0 -0
- /package/client/dist/assets/{attachments-Db7JfA8a.js → attachments-BcE7kZG-2.js} +0 -0
- /package/client/dist/assets/{attachments-CJaO1vCH.js → attachments-BsJJXFzT.js} +0 -0
- /package/client/dist/assets/{attachments-8QCKHCEF2.js → attachments-Cbh4AwjP.js} +0 -0
- /package/client/dist/assets/{attachments-CV2uaTGE.js → attachments-D0fGlFve.js} +0 -0
- /package/client/dist/assets/{attachments-CaOjdN332.js → attachments-D3DJpd3e2.js} +0 -0
- /package/client/dist/assets/{browser-C9rUUxo4.js → browser-9GR11iTi.js} +0 -0
- /package/client/dist/assets/{browser-CEqx11iy.js → browser-BOxg0p3n.js} +0 -0
- /package/client/dist/assets/{browser-543jbxE4.js → browser-BSh8xUWV.js} +0 -0
- /package/client/dist/assets/{browser-CLC0etB_2.js → browser-CaV3BJNY2.js} +0 -0
- /package/client/dist/assets/{browser-0xeW8fUa2.js → browser-CmWGMRGf2.js} +0 -0
- /package/client/dist/assets/{browser-ExmELH702.js → browser-D6wbpBOL2.js} +0 -0
- /package/client/dist/assets/{browser-DyG2l9Wa.js → browser-dsgDU1HB.js} +0 -0
- /package/client/dist/assets/{chat-DagUyoVA.js → chat-B90iLDI4.js} +0 -0
- /package/client/dist/assets/{chat-Cu6F3d6g2.js → chat-CAo0jCnj2.js} +0 -0
- /package/client/dist/assets/{chat-CN8BMAMc.js → chat-CW54IP3u.js} +0 -0
- /package/client/dist/assets/{chat-NQPCBQo72.js → chat-CYHUUW0p2.js} +0 -0
- /package/client/dist/assets/{chat-CCytD3P8.js → chat-D1PXX_p2.js} +0 -0
- /package/client/dist/assets/{chat-IjutwlBg.js → chat-DhpcWjOf.js} +0 -0
- /package/client/dist/assets/{chat-vVpwkOp52.js → chat-cFG-UfRA2.js} +0 -0
- /package/client/dist/assets/{code-Dhb6jbAU.js → code--qUk_yn-.js} +0 -0
- /package/client/dist/assets/{code-Ce-nBIwj.js → code-B1aOMCVV.js} +0 -0
- /package/client/dist/assets/{code-BaG05zK62.js → code-B5UrmjaE2.js} +0 -0
- /package/client/dist/assets/{code-Dap54vOb.js → code-CjBHU0nw.js} +0 -0
- /package/client/dist/assets/{code-_NOCo-Ol2.js → code-Cjv4_HkK2.js} +0 -0
- /package/client/dist/assets/{code-32l6Naxu2.js → code-D7GLAjrz2.js} +0 -0
- /package/client/dist/assets/{code-C5cibF2F.js → code-DZKjfzBN.js} +0 -0
- /package/client/dist/assets/{commands-Cc2WpuXa.js → commands-B9XaopQC.js} +0 -0
- /package/client/dist/assets/{commands-k9wbNYoi.js → commands-BCx1uDIE.js} +0 -0
- /package/client/dist/assets/{commands-CM99Upsz2.js → commands-Bhw9Hqsa2.js} +0 -0
- /package/client/dist/assets/{commands-Bc8y9eNo2.js → commands-D0RnooQF2.js} +0 -0
- /package/client/dist/assets/{commands-Bl3-KVfj.js → commands-DuaQT-it.js} +0 -0
- /package/client/dist/assets/{commands-DASXJD-l.js → commands-MqNuGGO4.js} +0 -0
- /package/client/dist/assets/{commands-C5WQ9blx2.js → commands-oB9q2vy_2.js} +0 -0
- /package/client/dist/assets/{common-CHARW6MZ2.js → common-BXzqeuiC2.js} +0 -0
- /package/client/dist/assets/{common-0aY9HQBP.js → common-BaJ6MF7T.js} +0 -0
- /package/client/dist/assets/{common-CQCJzAQq2.js → common-C-jaOdxz2.js} +0 -0
- /package/client/dist/assets/{common-DNhhqjlJ.js → common-CKjy-R8-.js} +0 -0
- /package/client/dist/assets/{common-YdyZtmaI2.js → common-CRd-Ge5u2.js} +0 -0
- /package/client/dist/assets/{common-5jScBJqt.js → common-DPGR3Tfo.js} +0 -0
- /package/client/dist/assets/{common-BdaRciTu.js → common-wEB9RBdf.js} +0 -0
- /package/client/dist/assets/{explore-ChtxIiSM.js → explore-B_79NLR5.js} +0 -0
- /package/client/dist/assets/{explore-BzdMEpuf.js → explore-D-htKul_.js} +0 -0
- /package/client/dist/assets/{explore-B82VMUJ_.js → explore-D5b2jgvR.js} +0 -0
- /package/client/dist/assets/{explore-DfcUfiPw2.js → explore-Dvp-5qOw2.js} +0 -0
- /package/client/dist/assets/{explore-CbW0381i2.js → explore-FaKfWCr72.js} +0 -0
- /package/client/dist/assets/{explore-BGz1rvQE.js → explore-IS8VyaSZ.js} +0 -0
- /package/client/dist/assets/{explore-yRF7wFSp2.js → explore-OZhWV0Eb2.js} +0 -0
- /package/client/dist/assets/{format-command-D96da4fZ.js → format-command-CHImQv6W.js} +0 -0
- /package/client/dist/assets/{integrations-CnrX7vqw2.js → integrations-B97cGWfo2.js} +0 -0
- /package/client/dist/assets/{integrations-BJvrlcc7.js → integrations-Bp3leAh3.js} +0 -0
- /package/client/dist/assets/{integrations-CPKYkG36.js → integrations-C3Ma3GdM.js} +0 -0
- /package/client/dist/assets/{integrations-BA5pM05t.js → integrations-C5MUA-0-.js} +0 -0
- /package/client/dist/assets/{integrations-B0OBPU9_.js → integrations-CiQbCn_W.js} +0 -0
- /package/client/dist/assets/{integrations-DeJFRyXz2.js → integrations-Du_0rDfi2.js} +0 -0
- /package/client/dist/assets/{integrations-DBou159M2.js → integrations-t4X5UVcx2.js} +0 -0
- /package/client/dist/assets/{jira-mi37H4Kt.js → jira-B1XaR6fj.js} +0 -0
- /package/client/dist/assets/{jira-Srx2P5zS.js → jira-BCHx9zUF.js} +0 -0
- /package/client/dist/assets/{jira-DeotPx6P2.js → jira-BqXyykbt2.js} +0 -0
- /package/client/dist/assets/{jira-BwLBgmfI2.js → jira-BzFvFn7t2.js} +0 -0
- /package/client/dist/assets/{jira-BDgxAFTF2.js → jira-D6IDTIsc2.js} +0 -0
- /package/client/dist/assets/{jira-NwlUCcQD.js → jira-DSZ5xFRl.js} +0 -0
- /package/client/dist/assets/{jira-D3GGzXOI.js → jira-DdEKW9Pu.js} +0 -0
- /package/client/dist/assets/{jobs-D8adm2BX.js → jobs-BX9dP3Qn.js} +0 -0
- /package/client/dist/assets/{jobs-B56vQEkh2.js → jobs-BgHEgCWk2.js} +0 -0
- /package/client/dist/assets/{jobs-K_Y8KAZ2.js → jobs-CU-khJTt.js} +0 -0
- /package/client/dist/assets/{jobs-BYIk6Tg_.js → jobs-Ce0SE81t.js} +0 -0
- /package/client/dist/assets/{jobs-C-lM-iax2.js → jobs-CeOcGHd_2.js} +0 -0
- /package/client/dist/assets/{jobs-CYdevGgT.js → jobs-Ct5v2p6T.js} +0 -0
- /package/client/dist/assets/{jobs-OwM0ZWhI2.js → jobs-m7L0K9uC2.js} +0 -0
- /package/client/dist/assets/{mcp-D3E4_Mmk2.js → mcp-4QbfLPa4.js} +0 -0
- /package/client/dist/assets/{mcp-B6nwJJmR.js → mcp-CXy61khH.js} +0 -0
- /package/client/dist/assets/{mcp-CNgFiTEh.js → mcp-CmOBPDjE.js} +0 -0
- /package/client/dist/assets/{mcp-mupPuPDO2.js → mcp-NlLc9T8u2.js} +0 -0
- /package/client/dist/assets/{mcp-B4irfLJ2.js → mcp-_DUUXTHB2.js} +0 -0
- /package/client/dist/assets/{mcp-BP7PpbDr2.js → mcp-dlOyUQQy2.js} +0 -0
- /package/client/dist/assets/{mcp-BOoEGTSQ.js → mcp-zqSVP7nA.js} +0 -0
- /package/client/dist/assets/{specs-D4z5d8uq.js → specs-57pue7UQ.js} +0 -0
- /package/client/dist/assets/{specs-CWNKAScX2.js → specs-BWQ-0EXt2.js} +0 -0
- /package/client/dist/assets/{specs-B8mwScoM2.js → specs-BYSOlQRw2.js} +0 -0
- /package/client/dist/assets/{specs-B5XOoH-02.js → specs-CkP0B28v2.js} +0 -0
- /package/client/dist/assets/{specs-DgvIRZtM.js → specs-RSYuLgF4.js} +0 -0
- /package/client/dist/assets/{specs-DuRzE5wE.js → specs-d-zU7_3Q.js} +0 -0
- /package/client/dist/assets/{specs-Bj_3fDrQ.js → specs-nM5Cpcqe.js} +0 -0
- /package/client/dist/assets/{terminal-DoMTHedv2.js → terminal-Adi3W-GZ2.js} +0 -0
- /package/client/dist/assets/{terminal-DOwfkxqa2.js → terminal-BA6FCZna2.js} +0 -0
- /package/client/dist/assets/{terminal-CH0fdHvP.js → terminal-BCIUSkrg.js} +0 -0
- /package/client/dist/assets/{terminal-B2sExUis.js → terminal-C8KlD61D.js} +0 -0
- /package/client/dist/assets/{terminal-DjSSa5qP.js → terminal-D3RTuBwy.js} +0 -0
- /package/client/dist/assets/{terminal-w0i-OCp32.js → terminal-DCkOEjSj2.js} +0 -0
- /package/client/dist/assets/{terminal-CPMigUX7.js → terminal-DOuNm2BI.js} +0 -0
- /package/client/dist/assets/{tickets-D00mSt832.js → tickets-B2q36GlQ2.js} +0 -0
- /package/client/dist/assets/{tickets-CQTana1u.js → tickets-Bsyv_znj.js} +0 -0
- /package/client/dist/assets/{tickets-D7CSuWjO.js → tickets-C_UPra_1.js} +0 -0
- /package/client/dist/assets/{tickets-heDAaj8C2.js → tickets-D72LbUtU2.js} +0 -0
- /package/client/dist/assets/{tickets-DvbFg_-c2.js → tickets-DDjU7UfE2.js} +0 -0
- /package/client/dist/assets/{tickets-onKZz6Dd.js → tickets-DR4ZrPMf.js} +0 -0
- /package/client/dist/assets/{tickets-Dq7HDy8n.js → tickets-DiUA3rXq.js} +0 -0
package/server/dist/mcp/guide.js
CHANGED
|
@@ -10,73 +10,208 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.SPECRAILS_GUIDE = void 0;
|
|
11
11
|
exports.SPECRAILS_GUIDE = `# Specrails Desktop — Agent Guide
|
|
12
12
|
|
|
13
|
-
You are operating Specrails Desktop through its MCP server
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
You are operating Specrails Desktop through its MCP server — either as an
|
|
14
|
+
EXTERNAL MCP client (Claude Desktop, Cursor, a custom agent) or as the app's own
|
|
15
|
+
embedded agent chat. Everything here applies to both, except Permissions, which
|
|
16
|
+
differs by client kind (see below).
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
Specrails is a local dashboard + pipeline runner that manages multiple software
|
|
19
|
+
projects (registered repositories) and drives AI coding agents (Claude Code,
|
|
20
|
+
Codex, Gemini) to implement specs.
|
|
21
|
+
|
|
22
|
+
## The object model
|
|
18
23
|
|
|
19
24
|
- **Project**: a registered repository. Almost every tool is project-scoped and
|
|
20
|
-
takes a \`projectId\`.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
\`
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
- **
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
25
|
+
takes a \`projectId\`. \`specrails_select_project\` sets a sticky active project
|
|
26
|
+
so later calls can omit it; an explicit \`projectId\` overrides.
|
|
27
|
+
\`specrails_projects(get)\` includes the repo's absolute path.
|
|
28
|
+
- **Spec / ticket**: a unit of work in a project's backlog. Statuses \`draft\`,
|
|
29
|
+
\`todo\`, \`in_progress\`, \`done\`, \`cancelled\`, plus a \`needs_review\` boolean FLAG
|
|
30
|
+
set on \`done\` specs when the pipeline ships with partial confidence (it is
|
|
31
|
+
not a status). Priorities \`critical|high|medium|low\`. INVARIANT: priority may
|
|
32
|
+
be null ONLY when status is \`draft\`. Specs can be epics with children (see
|
|
33
|
+
SMASH) and can be Jira-backed (\`source: 'jira'\`).
|
|
34
|
+
- **Rail**: a persistent numbered launch slot that runs the AI pipeline over its
|
|
35
|
+
assigned tickets. A rail REMEMBERS its config across launches: ticket ids,
|
|
36
|
+
mode, profile, engine, name. Launching spawns AI CLI processes that write
|
|
37
|
+
code, run tests and commit — it costs money and runs for minutes.
|
|
38
|
+
- **Job**: one spawned pipeline run. Jobs stream events over the app's bus and
|
|
39
|
+
settle (completed/failed/canceled). Job outcome mutates spec status
|
|
40
|
+
AUTOMATICALLY: launch → \`in_progress\`; success → \`done\`; revert → \`todo\`;
|
|
41
|
+
partial confidence → \`done\` + \`needs_review\`. Do not patch statuses the
|
|
42
|
+
pipeline manages.
|
|
43
|
+
- **Loop**: an APP-LEVEL saved workflow graph (not project-scoped). Author with
|
|
44
|
+
\`specrails_loops\`; RUN it with \`specrails_rails(launch, mode:'loop', loopId)\`.
|
|
45
|
+
- **Profile**: per-project agent configuration (which agents, which models,
|
|
46
|
+
routing). CLAUDE-ONLY; forced to null for codex/gemini rails.
|
|
47
|
+
- **Provider / engine**: claude, codex or gemini. A project installs one or
|
|
48
|
+
more; a requested engine must be one of the installed set.
|
|
37
49
|
- **Plugin**: an MCP-based integration installed per project (e.g. serena).
|
|
38
50
|
|
|
51
|
+
## Creating specs — three paths, one decision rule
|
|
52
|
+
|
|
53
|
+
1. **Quick (AI-generated)** — \`specrails_specs(action:'generate', idea, …)\`, or
|
|
54
|
+
the simpler \`create\` with title/description: routes through the app's Quick
|
|
55
|
+
Add Spec — an AI pass structures the request into a complete spec, so
|
|
56
|
+
MCP-created specs are indistinguishable from UI-created ones. \`generate\`
|
|
57
|
+
additionally accepts \`contextScope\`, \`attachmentIds\`, \`createLocal\`. Async
|
|
58
|
+
(202): watch the returned ref. Use for clear, well-scoped requests.
|
|
59
|
+
2. **Explore (multi-turn refinement)** — when requirements are fuzzy:
|
|
60
|
+
- \`specrails_chat(create, kind:'explore', contextScope)\` → keep the
|
|
61
|
+
conversation id.
|
|
62
|
+
- First \`send\`: text \`/specrails:explore-spec\` + blank line + the idea, with
|
|
63
|
+
\`lightweight: true\`, \`maxTurns: 20\`. Watch each turn by conversationId
|
|
64
|
+
(\`chat_done\` / \`chat_error\` are terminal).
|
|
65
|
+
- \`specrails_chat(spec_draft)\` reads the live structured draft the Explore
|
|
66
|
+
assistant maintains (title, description, labels, priority,
|
|
67
|
+
acceptanceCriteria, ready).
|
|
68
|
+
- When converged: \`specrails_specs(save_draft, conversationId)\` parks a
|
|
69
|
+
resumable draft ticket; \`specrails_specs(commit_draft, conversationId,
|
|
70
|
+
title, …)\` creates the real spec. Passing the conversationId preserves the
|
|
71
|
+
origin link ("Continue Explore", Contract Refine eligibility).
|
|
72
|
+
- \`contextScope\` flags: \`specrails\` (pipeline context), \`openspec\` (spec
|
|
73
|
+
history), \`full\` (whole-repo access), \`mcp\` (project .mcp.json servers),
|
|
74
|
+
\`userMcp\` (the user's own approved MCP servers), \`contractRefine\` (append
|
|
75
|
+
a Contract Layer after commit).
|
|
76
|
+
An EMBEDDED agent may instead run the refinement conversation ITSELF (no
|
|
77
|
+
nested AI spawn, no extra cost) and persist via path 3 — use the app's
|
|
78
|
+
Explore when the user wants the draft visible and resumable in the UI.
|
|
79
|
+
3. **Direct insert (no AI)** — for a COMPLETE spec you already hold:
|
|
80
|
+
- \`specrails_specs(commit_draft)\` with NO \`conversationId\`/\`draftTicketId\`
|
|
81
|
+
is the canonical rich insert: \`title\` (required), \`description\`,
|
|
82
|
+
\`acceptanceCriteria\` (folded into an \`## Acceptance Criteria\` section),
|
|
83
|
+
\`priority\`, \`labels\`, \`shortSummary\` (max 240 chars). One write call.
|
|
84
|
+
- \`specrails_specs(from_prompt)\` stores a description verbatim but CANNOT
|
|
85
|
+
set acceptanceCriteria or shortSummary — prefer \`commit_draft\` for
|
|
86
|
+
structured specs.
|
|
87
|
+
- Follow with \`update\` for assignee/prerequisites/metadata when needed.
|
|
88
|
+
- Never route an already-refined spec through \`create\`/\`generate\` — they
|
|
89
|
+
REGENERATE the content with AI.
|
|
90
|
+
|
|
91
|
+
A complete spec matches the app-generated shape: short imperative English
|
|
92
|
+
\`title\`; one-sentence \`shortSummary\`; a \`description\` with the sections
|
|
93
|
+
\`## Problem Statement\`, \`## Proposed Solution\`, \`## Out of Scope\`,
|
|
94
|
+
\`## Technical Considerations\`, \`## Estimated Complexity\`; a separate
|
|
95
|
+
\`acceptanceCriteria\` array (never duplicated inside the description; no title
|
|
96
|
+
heading inside the description); \`labels\`; \`priority\`. Spec content is English.
|
|
97
|
+
|
|
98
|
+
## Running the pipeline (rails)
|
|
99
|
+
|
|
100
|
+
- Configure: \`set_tickets\` (replaces the assigned set), \`set_profile\` (null =
|
|
101
|
+
legacy), \`set_engine\` (null = project primary), \`set_name\`.
|
|
102
|
+
- Launch modes:
|
|
103
|
+
- \`implement\`: one pipeline job (Architect → Developer → Reviewer → Ship)
|
|
104
|
+
over the rail's tickets.
|
|
105
|
+
- \`batch-implement\`: dependency-aware waves across many tickets.
|
|
106
|
+
- Freestyle (wire value \`ultracode\`): hands the spec straight to the model —
|
|
107
|
+
one job per ticket; Claude-only; \`model\` picker; optional
|
|
108
|
+
\`interactive\` in-job chat (settle with \`specrails_jobs(finalize)\`).
|
|
109
|
+
- \`loop\`: runs a published loop graph per ticket (\`loopId\`,
|
|
110
|
+
\`reasoning_effort\`).
|
|
111
|
+
- Profiles are Claude-only: a profile set on a rail that is then pointed at
|
|
112
|
+
codex/gemini is force-nulled.
|
|
113
|
+
- \`stop\` kills the rail's process tree AND cancels its queued jobs
|
|
114
|
+
(destructive).
|
|
115
|
+
- \`specrails_jobs(spawn, command)\` bypasses rails and enqueues an arbitrary
|
|
116
|
+
slash-command job (e.g. \`/specrails:implement #5 --yes\`); \`queue\`, \`pause\`,
|
|
117
|
+
\`resume\`, \`reorder\`, \`priority\` manage the queue.
|
|
118
|
+
|
|
39
119
|
## Async results (IMPORTANT)
|
|
40
120
|
|
|
41
121
|
Cost-incurring / streaming actions (launch a rail, generate a spec, send a chat
|
|
42
|
-
turn, refine an agent, SMASH) return immediately with a
|
|
43
|
-
requestId) and emit
|
|
44
|
-
|
|
45
|
-
operation to settle
|
|
46
|
-
|
|
122
|
+
turn, refine an agent, SMASH, install a plugin) return 202 immediately with a
|
|
123
|
+
reference (jobId / conversationId / requestId) and emit the REAL result over
|
|
124
|
+
the app's event bus. \`specrails_watch(projectId, ref, untilMs)\` waits for the
|
|
125
|
+
operation to settle. Rules:
|
|
126
|
+
|
|
127
|
+
- \`projectId\` is REQUIRED on watch — it does not default to the active project.
|
|
128
|
+
- Default \`untilMs\` is 120000 (max 600000); rails routinely run longer.
|
|
129
|
+
- \`settled:false\` means TIMEOUT, not failure: the operation may still be
|
|
130
|
+
running, or may have finished without a watch-terminal event. Re-watch with a
|
|
131
|
+
larger window or poll the domain read to confirm: \`specrails_jobs(get)\`,
|
|
132
|
+
\`specrails_specs(get)\`, \`specrails_plugins(health)\`.
|
|
133
|
+
- Chat turns are watched by conversationId (\`chat_done\` / \`chat_error\`).
|
|
134
|
+
|
|
135
|
+
Never assume success from the 202 acceptance alone.
|
|
136
|
+
|
|
137
|
+
## Permissions — two regimes
|
|
138
|
+
|
|
139
|
+
- **External MCP clients** (Claude Desktop, Cursor, …): four INDEPENDENT opt-in
|
|
140
|
+
tiers configured by the user in the app's Settings ▸ MCP — Read (always on),
|
|
141
|
+
Write, AI-spawn (costs money), Destructive. On refusal, tell the user to
|
|
142
|
+
enable the named tier in Settings ▸ MCP.
|
|
143
|
+
- **The in-app agent chat**: a CUMULATIVE ladder the user steers live with
|
|
144
|
+
Shift+Tab — observe (read) ▸ edit (+write) ▸ operate (+ai-spawn) ▸ autonomous
|
|
145
|
+
(+destructive). It overrides the Settings checkboxes for that chat. On
|
|
146
|
+
refusal, tell the user to raise the level with Shift+Tab.
|
|
47
147
|
|
|
48
|
-
|
|
148
|
+
Tools cannot raise their own permissions in either regime. Common tiers:
|
|
149
|
+
list/get/spending/watch = read; commit_draft, from_prompt, update, set_tickets,
|
|
150
|
+
plugin install, Jira connect = write; spec create/generate, rail launch, chat
|
|
151
|
+
send, job spawn = ai-spawn; spec delete, rail stop, job purge, plugin
|
|
152
|
+
uninstall, Jira disconnect, project unregister = destructive. Note the
|
|
153
|
+
embedded spec-refinement happy path (investigate + commit_draft) needs only
|
|
154
|
+
read + write — ai-spawn is required only to launch work or spawn a nested AI.
|
|
49
155
|
|
|
50
|
-
|
|
51
|
-
- **Read** (always on): queries + resources.
|
|
52
|
-
- **Write**: create/edit specs, settings, rail config.
|
|
53
|
-
- **AI-spawn**: actions that spawn an AI CLI and cost money.
|
|
54
|
-
- **Destructive**: delete data, kill processes, mutate external systems.
|
|
156
|
+
## Providers & Claude-only surface
|
|
55
157
|
|
|
56
|
-
|
|
57
|
-
|
|
158
|
+
- Installed providers are per-project; AI-spawning calls may pick any installed
|
|
159
|
+
one (\`aiEngine\`); rails carry a per-rail engine.
|
|
160
|
+
- CLAUDE-ONLY: agent profiles, Contract Refine, SMASH, Freestyle mode
|
|
161
|
+
(\`ultracode\`), interactive jobs. They are rejected or inert when the
|
|
162
|
+
effective engine is codex or gemini.
|
|
163
|
+
- Cost figures are authoritative for claude and estimated for codex/gemini
|
|
164
|
+
(flagged as estimated in analytics).
|
|
58
165
|
|
|
59
|
-
##
|
|
166
|
+
## Domain cheat-sheet
|
|
60
167
|
|
|
61
|
-
|
|
62
|
-
(
|
|
168
|
+
- **Epics / SMASH** (\`specrails_specs\`): \`smash\` splits a large spec into child
|
|
169
|
+
specs (Claude-only); \`smash_undo\` restores (needs the \`smashedAt\` stamp);
|
|
170
|
+
\`delete_epic_children\` removes a whole family.
|
|
171
|
+
- **Attachments**: \`list_attachments\` / \`get_attachment\` read files the user
|
|
172
|
+
attached in the app UI; \`generate\` / \`ai_edit\` accept \`attachmentIds\`.
|
|
173
|
+
Uploading new attachments is not available over MCP.
|
|
174
|
+
- **Jira** (\`specrails_jira\`): per-project connection (the token stays
|
|
175
|
+
on-device). Jira-backed specs carry a LOCAL numeric id — never a \`PROJ-123\`
|
|
176
|
+
key; map via \`links\`. Status write-back flows through a durable outbox
|
|
177
|
+
(\`outbox\`, \`retry_outbox\`).
|
|
178
|
+
- **Code explorer** (\`specrails_code\`): read-only repo browsing — \`tree\`
|
|
179
|
+
(provenance: which specs/jobs touched each file), \`read_file\`, \`summary\`,
|
|
180
|
+
\`provenance\`, \`diff\`. There is no MCP write path to files.
|
|
181
|
+
- **Analytics** (\`specrails_analytics\`): \`spending\` aggregates by surface
|
|
182
|
+
(\`job\`, \`quick-spec\`, \`explore-spec\`, \`ai-edit\`, \`file-summary\`), model,
|
|
183
|
+
ticket, day. Prefer \`spending\` over raw \`invocations\`/\`export\` for token
|
|
184
|
+
economy. TWO budget knobs exist: \`specrails_analytics(budget_set,
|
|
185
|
+
dailyBudgetUsd)\` is PER-PROJECT and pauses that project's queue when
|
|
186
|
+
exceeded; \`specrails_settings(set, dailyBudgetUsd)\` is the APP-WIDE budget.
|
|
187
|
+
- **Plugins** (\`specrails_plugins\`): per-project MCP integrations; \`preview\`
|
|
188
|
+
the diff before \`install\`; a degraded plugin never blocks rail launches.
|
|
189
|
+
- **Profiles** (\`specrails_agents\`): per-project agent chains; the baseline
|
|
190
|
+
trio \`sr-architect\`/\`sr-developer\`/\`sr-reviewer\` is required; routing rules
|
|
191
|
+
end in a single terminal \`default: true\` rule; requires specrails-core
|
|
192
|
+
4.1.0 or newer.
|
|
193
|
+
- **Setup** (\`specrails_setup\`): \`prerequisites\` → \`add_project\` →
|
|
194
|
+
\`install_config\` per provider → ONE \`install\` (provisions all chosen
|
|
195
|
+
providers; quick-only, offline) → poll \`checkpoints\` until
|
|
196
|
+
\`isInstalling === false\`.
|
|
197
|
+
- **Loops lifecycle** (\`specrails_loops\`): Draft → \`publish\` (graph-validated)
|
|
198
|
+
→ runnable; \`update\` reverts to Draft and returns 409 while running;
|
|
199
|
+
\`preview\` dry-runs token resolution without spawning; constants are shared
|
|
200
|
+
values graphs reference.
|
|
63
201
|
|
|
64
|
-
##
|
|
202
|
+
## Operating discipline
|
|
65
203
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
3. \`specrails_rails(set_tickets)\` then \`specrails_rails(launch)\` → run the pipeline;
|
|
74
|
-
\`specrails_watch\` the returned jobId.
|
|
75
|
-
4. \`specrails_analytics(spending)\` → review cost.
|
|
204
|
+
- Do not mutate statuses the pipeline manages (\`in_progress\`/\`done\` transitions
|
|
205
|
+
ride job outcomes).
|
|
206
|
+
- Confirm cost-incurring (ai-spawn) and destructive actions with the user
|
|
207
|
+
first, with cost/risk framing.
|
|
208
|
+
- Report ids and results verbatim; never fabricate outcomes.
|
|
209
|
+
- Use \`specrails_search\` / \`specrails_describe\` to discover the exact action
|
|
210
|
+
and arguments instead of guessing.
|
|
76
211
|
|
|
77
212
|
## Resources
|
|
78
213
|
|
|
79
|
-
Read-only state is also exposed as MCP resources: \`specrails://
|
|
80
|
-
\`specrails://projects
|
|
81
|
-
\`specrails://projects/{
|
|
214
|
+
Read-only state is also exposed as MCP resources: \`specrails://guide\` (this
|
|
215
|
+
document), \`specrails://projects\` (all registered projects), and
|
|
216
|
+
\`specrails://projects/{projectId}\` (one project by id).
|
|
82
217
|
`;
|
|
@@ -91,7 +91,7 @@ function analyticsTools() {
|
|
|
91
91
|
.number()
|
|
92
92
|
.nullable()
|
|
93
93
|
.optional()
|
|
94
|
-
.describe('budget_set: daily budget cap USD (>0); null clears it'),
|
|
94
|
+
.describe('budget_set: daily budget cap USD (>0); null clears it. PER-PROJECT daily cap — pauses this project\'s queue when exceeded. For the app-wide budget across all projects use specrails_settings.'),
|
|
95
95
|
jobCostThresholdUsd: zod_1.z
|
|
96
96
|
.number()
|
|
97
97
|
.nullable()
|
|
@@ -15,16 +15,31 @@ function appTools() {
|
|
|
15
15
|
{
|
|
16
16
|
name: 'specrails_settings',
|
|
17
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).'
|
|
18
|
+
description: 'Read or update app-level Specrails settings (theme, language, daily budget, cost-alert threshold, Code Explorer summary language + monthly summary budget). ' +
|
|
19
|
+
'Actions: get, set. The MCP enable flag and permission tiers are read-only here (user-controlled in the app). ' +
|
|
20
|
+
'dailyBudgetUsd here is APP-WIDE (all projects combined); per-project caps live in specrails_analytics(budget_set).',
|
|
20
21
|
hintTier: 'read',
|
|
21
22
|
tier: (args) => (args.action === 'set' ? 'write' : 'read'),
|
|
22
23
|
inputSchema: {
|
|
23
24
|
action: zod_1.z.enum(['get', 'set']).describe('Operation'),
|
|
24
25
|
theme: zod_1.z.enum(WRITABLE_THEMES).optional(),
|
|
25
26
|
language: zod_1.z.enum(WRITABLE_LANGS).optional(),
|
|
26
|
-
dailyBudgetUsd: zod_1.z
|
|
27
|
+
dailyBudgetUsd: zod_1.z
|
|
28
|
+
.number()
|
|
29
|
+
.min(0)
|
|
30
|
+
.nullable()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe('APP-WIDE daily budget cap USD across all projects; null clears it. Per-project caps live in specrails_analytics(budget_set).'),
|
|
27
33
|
costAlertThresholdUsd: zod_1.z.number().min(0).nullable().optional(),
|
|
34
|
+
summaryLanguage: zod_1.z
|
|
35
|
+
.enum(['en', 'es'])
|
|
36
|
+
.optional()
|
|
37
|
+
.describe('Code Explorer file-summary language (app-wide)'),
|
|
38
|
+
summaryMonthlyBudgetUsd: zod_1.z
|
|
39
|
+
.number()
|
|
40
|
+
.min(0)
|
|
41
|
+
.optional()
|
|
42
|
+
.describe('Code Explorer monthly AI file-summary budget in USD (app-wide, default 5)'),
|
|
28
43
|
},
|
|
29
44
|
handler: (ctx, args) => {
|
|
30
45
|
const db = ctx.desktopDb;
|
|
@@ -34,6 +49,9 @@ function appTools() {
|
|
|
34
49
|
language: (0, desktop_db_1.getDesktopSetting)(db, 'ui_language') ?? null,
|
|
35
50
|
dailyBudgetUsd: num((0, desktop_db_1.getDesktopSetting)(db, 'desktop_daily_budget_usd')),
|
|
36
51
|
costAlertThresholdUsd: num((0, desktop_db_1.getDesktopSetting)(db, 'cost_alert_threshold_usd')),
|
|
52
|
+
// Code Explorer settings (same keys + defaults as GET /api/code-explorer-settings)
|
|
53
|
+
summaryLanguage: (0, desktop_db_1.getDesktopSetting)(db, 'summary_language') === 'es' ? 'es' : 'en',
|
|
54
|
+
summaryMonthlyBudgetUsd: nonNegNum((0, desktop_db_1.getDesktopSetting)(db, 'summary_monthly_budget_usd')) ?? 5.0,
|
|
37
55
|
mcp: {
|
|
38
56
|
enabled: (0, mcp_tiers_1.isMcpEnabled)(db),
|
|
39
57
|
tierWrite: (0, mcp_tiers_1.isTierEnabled)(db, 'write'),
|
|
@@ -60,8 +78,25 @@ function appTools() {
|
|
|
60
78
|
writeNumOrClear(db, 'cost_alert_threshold_usd', args.costAlertThresholdUsd);
|
|
61
79
|
changed.push('costAlertThresholdUsd');
|
|
62
80
|
}
|
|
63
|
-
|
|
64
|
-
|
|
81
|
+
// Code Explorer settings — same validation as PATCH /api/code-explorer-settings.
|
|
82
|
+
if (args.summaryLanguage !== undefined) {
|
|
83
|
+
if (args.summaryLanguage !== 'en' && args.summaryLanguage !== 'es') {
|
|
84
|
+
throw new Error("summaryLanguage must be one of: 'en', 'es'.");
|
|
85
|
+
}
|
|
86
|
+
(0, desktop_db_1.setDesktopSetting)(db, 'summary_language', args.summaryLanguage);
|
|
87
|
+
changed.push('summaryLanguage');
|
|
88
|
+
}
|
|
89
|
+
if (args.summaryMonthlyBudgetUsd !== undefined) {
|
|
90
|
+
const v = args.summaryMonthlyBudgetUsd;
|
|
91
|
+
if (typeof v !== 'number' || !Number.isFinite(v) || v < 0) {
|
|
92
|
+
throw new Error('summaryMonthlyBudgetUsd must be a non-negative number.');
|
|
93
|
+
}
|
|
94
|
+
(0, desktop_db_1.setDesktopSetting)(db, 'summary_monthly_budget_usd', String(v));
|
|
95
|
+
changed.push('summaryMonthlyBudgetUsd');
|
|
96
|
+
}
|
|
97
|
+
if (!changed.length) {
|
|
98
|
+
throw new Error('set requires at least one field (theme, language, dailyBudgetUsd, costAlertThresholdUsd, summaryLanguage, summaryMonthlyBudgetUsd).');
|
|
99
|
+
}
|
|
65
100
|
return { ok: true, changed };
|
|
66
101
|
},
|
|
67
102
|
},
|
|
@@ -73,6 +108,11 @@ function num(v) {
|
|
|
73
108
|
const n = Number(v);
|
|
74
109
|
return Number.isFinite(n) ? n : null;
|
|
75
110
|
}
|
|
111
|
+
/** Mirror of the code-explorer-settings route parsing: finite AND >= 0, else null. */
|
|
112
|
+
function nonNegNum(v) {
|
|
113
|
+
const n = num(v);
|
|
114
|
+
return n !== null && n >= 0 ? n : null;
|
|
115
|
+
}
|
|
76
116
|
function writeNumOrClear(db, key, value) {
|
|
77
117
|
if (value === null)
|
|
78
118
|
(0, desktop_db_1.setDesktopSetting)(db, key, '');
|
|
@@ -19,7 +19,12 @@ function chatTools() {
|
|
|
19
19
|
name: 'specrails_chat',
|
|
20
20
|
title: 'Chat / Explore',
|
|
21
21
|
description: 'Manage a project\'s chat & Explore-Spec conversations and drive their AI turns. ' +
|
|
22
|
+
'EXPLORE RECIPE: create(kind:\'explore\', contextScope) → send the bootstrap text "/specrails:explore-spec\\n\\n<idea>" ' +
|
|
23
|
+
'with {lightweight:true, maxTurns:20} → watch chat_done per turn → spec_draft to read the accumulated draft → ' +
|
|
24
|
+
'persist via specrails_specs(commit_draft, conversationId=<this conversation>) which preserves origin linkage, ' +
|
|
25
|
+
'Contract Refine and "Continue Explore". NOTE: spec_draft state is in-memory; it returns {draft:null} after a server restart. ' +
|
|
22
26
|
'Actions: list_conversations, get (conversation + messages), create (kind sidebar|explore, optional provider/model/contextScope), ' +
|
|
27
|
+
'update (rename title / change model), ' +
|
|
23
28
|
'send (cost-incurring — spawns the AI CLI and streams the reply async over WS), abort (interrupt the in-flight turn), ' +
|
|
24
29
|
'delete (destructive — removes the conversation, its messages, and clears linked draft origin), minimize (arm Explore idle-kill timer), ' +
|
|
25
30
|
'restore (cancel the idle-kill timer), spec_draft (read the in-memory Explore spec-draft state), messages (persisted history only).',
|
|
@@ -59,7 +64,9 @@ function chatTools() {
|
|
|
59
64
|
contextScope: zod_1.z
|
|
60
65
|
.record(zod_1.z.unknown())
|
|
61
66
|
.optional()
|
|
62
|
-
.describe('Explore-only context scope flags for create
|
|
67
|
+
.describe('Explore-only context scope flags for create: {full: repo-wide investigation, specrails: specs context, ' +
|
|
68
|
+
'openspec: openspec context, mcp: load project .mcp.json (spawns from repo cwd, slower), ' +
|
|
69
|
+
"userMcp: user's approved MCP servers, contractRefine: append Contract Layer on commit}"),
|
|
63
70
|
// update params
|
|
64
71
|
title: zod_1.z.string().optional().describe('New title for update'),
|
|
65
72
|
// send params
|
|
@@ -127,7 +134,7 @@ function chatTools() {
|
|
|
127
134
|
return {
|
|
128
135
|
...r,
|
|
129
136
|
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).`,
|
|
137
|
+
hint: `Turn accepted (202). The assistant reply streams over WebSocket — use specrails_watch with conversationId "${requireConv()}" to await completion (chat_done / chat_error). Each send spawns a fresh AI CLI turn (cost); Explore turns accumulate the spec_draft.`,
|
|
131
138
|
};
|
|
132
139
|
}
|
|
133
140
|
case 'abort':
|
|
@@ -11,8 +11,9 @@ const types_1 = require("./types");
|
|
|
11
11
|
*
|
|
12
12
|
* Every op is per-project under `/api/projects/:projectId/code/*`. The v1 edit
|
|
13
13
|
* path (PUT /code/file) is intentionally NOT exposed — Code Explorer is
|
|
14
|
-
* read-only here. The app-level
|
|
15
|
-
*
|
|
14
|
+
* read-only here. The app-level code-explorer settings (summary language +
|
|
15
|
+
* monthly summary budget) are surfaced by specrails_settings
|
|
16
|
+
* (summaryLanguage / summaryMonthlyBudgetUsd), not here.
|
|
16
17
|
*
|
|
17
18
|
* Encode query strings explicitly so file paths with spaces/`#`/`?` survive.
|
|
18
19
|
*/
|
|
@@ -23,10 +23,11 @@ function jobsTools() {
|
|
|
23
23
|
'cancel (destructive — cancels a running/queued job or deletes a terminal one), ' +
|
|
24
24
|
'purge (destructive — bulk-delete persisted job rows in a date range), ' +
|
|
25
25
|
'pause / resume (queue), reorder (queued-job order), priority (change a queued job\'s priority), ' +
|
|
26
|
-
'compare (two jobs side-by-side), export (up to 10k rows as JSON/CSV), ' +
|
|
26
|
+
'compare (two jobs side-by-side), export (up to 10k rows as JSON/CSV — inlines everything; prefer list/stats for token economy), ' +
|
|
27
27
|
'diagnostic (binary ZIP — returns a note, not the bytes), run_state (project run state), ' +
|
|
28
|
+
'pipeline (read a pipeline\'s jobs + statuses — use after composing dependent spawns), ' +
|
|
28
29
|
'activity (recent activity feed), stats, metrics, default_spec_model, ' +
|
|
29
|
-
'interactive_turn (ai-spawn — send one more prompt to a running interactive ultracode job), ' +
|
|
30
|
+
'interactive_turn (ai-spawn — send one more prompt to a running interactive Freestyle/ultracode job), ' +
|
|
30
31
|
'finalize (finalize a running interactive job).',
|
|
31
32
|
hintTier: 'read',
|
|
32
33
|
tier: (a) => {
|
|
@@ -56,6 +57,7 @@ function jobsTools() {
|
|
|
56
57
|
'export',
|
|
57
58
|
'diagnostic',
|
|
58
59
|
'run_state',
|
|
60
|
+
'pipeline',
|
|
59
61
|
'activity',
|
|
60
62
|
'stats',
|
|
61
63
|
'metrics',
|
|
@@ -84,7 +86,7 @@ function jobsTools() {
|
|
|
84
86
|
.optional()
|
|
85
87
|
.describe('Priority for spawn / priority action'),
|
|
86
88
|
dependsOnJobId: zod_1.z.string().optional().describe('Make the spawned job depend on this job id'),
|
|
87
|
-
pipelineId: zod_1.z.string().optional().describe('
|
|
89
|
+
pipelineId: zod_1.z.string().optional().describe('Pipeline id: group the spawned job into this pipeline (spawn) / pipeline to read (pipeline)'),
|
|
88
90
|
profileName: zod_1.z
|
|
89
91
|
.string()
|
|
90
92
|
.optional()
|
|
@@ -143,7 +145,7 @@ function jobsTools() {
|
|
|
143
145
|
});
|
|
144
146
|
return {
|
|
145
147
|
...r,
|
|
146
|
-
hint: 'Spawned an AI CLI job (incurs token cost). Use specrails_watch
|
|
148
|
+
hint: 'Spawned an AI CLI job (incurs token cost). Use specrails_jobs(get, jobId) to poll status; specrails_watch settles for this jobId via its 5s job-status poll fallback (terminal events stream only for rail-launched or interactive jobs).',
|
|
147
149
|
};
|
|
148
150
|
}
|
|
149
151
|
case 'cancel': {
|
|
@@ -191,7 +193,11 @@ function jobsTools() {
|
|
|
191
193
|
qs.set('from', args.from);
|
|
192
194
|
if (args.to)
|
|
193
195
|
qs.set('to', args.to);
|
|
194
|
-
|
|
196
|
+
const data = await (0, types_1.apiCall)(ctx, 'GET', `${base}/jobs/export?${qs.toString()}`);
|
|
197
|
+
return {
|
|
198
|
+
note: 'Inlines up to 10k rows — prefer list/stats for token economy.',
|
|
199
|
+
data,
|
|
200
|
+
};
|
|
195
201
|
}
|
|
196
202
|
case 'diagnostic': {
|
|
197
203
|
const id = args.jobId;
|
|
@@ -210,6 +216,12 @@ function jobsTools() {
|
|
|
210
216
|
}
|
|
211
217
|
case 'run_state':
|
|
212
218
|
return (0, types_1.apiCall)(ctx, 'GET', `${base}/state`);
|
|
219
|
+
case 'pipeline': {
|
|
220
|
+
const id = args.pipelineId;
|
|
221
|
+
if (!id)
|
|
222
|
+
throw new Error('pipeline requires a "pipelineId".');
|
|
223
|
+
return (0, types_1.apiCall)(ctx, 'GET', `${base}/pipelines/${encodeURIComponent(id)}`);
|
|
224
|
+
}
|
|
213
225
|
case 'activity': {
|
|
214
226
|
const qs = new URLSearchParams();
|
|
215
227
|
if (args.limit !== undefined)
|
|
@@ -240,7 +252,7 @@ function jobsTools() {
|
|
|
240
252
|
const r = await (0, types_1.apiCall)(ctx, 'POST', `${base}/jobs/${encodeURIComponent(id)}/messages`, { text });
|
|
241
253
|
return {
|
|
242
254
|
...r,
|
|
243
|
-
hint: 'Queued an additional interactive turn (incurs token cost).
|
|
255
|
+
hint: 'Queued an additional interactive turn (incurs token cost). specrails_watch settles when the whole job finalizes; a single turn\'s completion arrives as job.turn_done in the events array.',
|
|
244
256
|
};
|
|
245
257
|
}
|
|
246
258
|
case 'finalize': {
|
|
@@ -7,11 +7,16 @@ const types_1 = require("./types");
|
|
|
7
7
|
* Loops — the GLOBAL (cross-project) visual loop-builder library. Routes live at
|
|
8
8
|
* `/api/loops*` and `/api/loop-templates` (NOT under `/projects` — no projectId).
|
|
9
9
|
* Gated server-side by SPECRAILS_LOOPS_SECTION (every route 404s when off).
|
|
10
|
+
* Exception: the standalone run actions (`run` / `run_get`) ARE project-scoped
|
|
11
|
+
* (`/api/projects/:projectId/loop-runs*`) — a ticket-less loop runs directly
|
|
12
|
+
* against a project with no rail and no ticket.
|
|
10
13
|
*
|
|
11
14
|
* A single domain-facade tool with an `action` enum and a dynamic tier:
|
|
12
|
-
* - read: list, get, templates, factory, commands, constants_list,
|
|
15
|
+
* - read: list, get, templates, factory, commands, constants_list,
|
|
16
|
+
* preview, run_get
|
|
13
17
|
* - write: constant_create, constant_update, import, create, from_template,
|
|
14
18
|
* fork, update, publish, unpublish, duplicate
|
|
19
|
+
* - ai-spawn: run (spawns an AI CLI, incurs cost, async 202)
|
|
15
20
|
* - destructive: constant_delete, delete
|
|
16
21
|
*/
|
|
17
22
|
function loopsTools() {
|
|
@@ -20,7 +25,9 @@ function loopsTools() {
|
|
|
20
25
|
name: 'specrails_loops',
|
|
21
26
|
title: 'Loops',
|
|
22
27
|
description: 'Manage the global (cross-project) loop library and its templates/factory/constants. ' +
|
|
23
|
-
'Loops are visual builder graphs reused across projects; this is an APP-LEVEL domain (no projectId). ' +
|
|
28
|
+
'Loops are visual builder graphs reused across projects; this is an APP-LEVEL domain (no projectId, except the run actions). ' +
|
|
29
|
+
'To RUN a loop on a project\'s tickets: publish it, then specrails_rails(launch, mode:\'loop\', loopId=…). ' +
|
|
30
|
+
'For a standalone ticket-less run use the run action. ' +
|
|
24
31
|
'Actions: ' +
|
|
25
32
|
'list (all saved loops), ' +
|
|
26
33
|
'get (one loop by id), ' +
|
|
@@ -37,12 +44,16 @@ function loopsTools() {
|
|
|
37
44
|
'update (name/description/graph — reverts to Draft, 409 while running), ' +
|
|
38
45
|
'publish (graph-validated), unpublish (409 while running), ' +
|
|
39
46
|
'duplicate (copy a loop), ' +
|
|
40
|
-
'delete (destructive — 409 while running)
|
|
47
|
+
'delete (destructive — 409 while running), ' +
|
|
48
|
+
'run (ai-spawn — standalone ticket-less run of a Published loop against a project: spawns an AI CLI, incurs token cost, returns 202 with loopRunId), ' +
|
|
49
|
+
'run_get (read one loop run\'s live/terminal state — the post-timeout recovery read).',
|
|
41
50
|
hintTier: 'read',
|
|
42
51
|
tier: (a) => {
|
|
43
52
|
const action = a.action;
|
|
44
53
|
if (action === 'delete' || action === 'constant_delete')
|
|
45
54
|
return 'destructive';
|
|
55
|
+
if (action === 'run')
|
|
56
|
+
return 'ai-spawn';
|
|
46
57
|
if ([
|
|
47
58
|
'constant_create',
|
|
48
59
|
'constant_update',
|
|
@@ -81,9 +92,16 @@ function loopsTools() {
|
|
|
81
92
|
'unpublish',
|
|
82
93
|
'duplicate',
|
|
83
94
|
'delete',
|
|
95
|
+
'run',
|
|
96
|
+
'run_get',
|
|
84
97
|
])
|
|
85
98
|
.describe('Operation to perform'),
|
|
86
|
-
|
|
99
|
+
projectId: zod_1.z
|
|
100
|
+
.string()
|
|
101
|
+
.optional()
|
|
102
|
+
.describe('Project id (run / run_get only — defaults to the active project; ignored by every other action)'),
|
|
103
|
+
loopId: zod_1.z.string().optional().describe('Loop id (for get / update / publish / unpublish / duplicate / delete / run — must be Published for run)'),
|
|
104
|
+
loopRunId: zod_1.z.string().optional().describe('Loop run id (for run_get — returned by run)'),
|
|
87
105
|
constantId: zod_1.z.string().optional().describe('Constant id (for constant_update / constant_delete)'),
|
|
88
106
|
templateId: zod_1.z.string().optional().describe('Template id (for from_template)'),
|
|
89
107
|
factoryId: zod_1.z.string().optional().describe('Factory loop id (for fork)'),
|
|
@@ -97,7 +115,18 @@ function loopsTools() {
|
|
|
97
115
|
.optional()
|
|
98
116
|
.describe('Loop graph object { nodes, edges, ... } (for create / update; required for preview)'),
|
|
99
117
|
value: zod_1.z.string().optional().describe('Constant value (for constant_create / constant_update)'),
|
|
100
|
-
provider: zod_1.z
|
|
118
|
+
provider: zod_1.z
|
|
119
|
+
.string()
|
|
120
|
+
.optional()
|
|
121
|
+
.describe('Provider for token resolution in preview (default "claude") / AI engine for run (must be installed on the project; default = project primary)'),
|
|
122
|
+
model: zod_1.z
|
|
123
|
+
.string()
|
|
124
|
+
.optional()
|
|
125
|
+
.describe('Model for run — validated against the chosen provider\'s catalog; omit for the provider default'),
|
|
126
|
+
reasoning_effort: zod_1.z
|
|
127
|
+
.enum(['low', 'medium', 'high'])
|
|
128
|
+
.optional()
|
|
129
|
+
.describe('Reasoning-effort tier for run'),
|
|
101
130
|
loops: zod_1.z.array(zod_1.z.unknown()).optional().describe('Array of loop export envelopes (for import)'),
|
|
102
131
|
},
|
|
103
132
|
async handler(ctx, args) {
|
|
@@ -214,6 +243,29 @@ function loopsTools() {
|
|
|
214
243
|
...(args.name !== undefined ? { name: args.name } : {}),
|
|
215
244
|
});
|
|
216
245
|
}
|
|
246
|
+
// ── Standalone runs (project-scoped) ────────────────────────────────
|
|
247
|
+
case 'run': {
|
|
248
|
+
if (!loopId)
|
|
249
|
+
throw new Error('run requires a "loopId" (the loop must be Published).');
|
|
250
|
+
const base = (0, types_1.projectPath)(ctx, args.projectId);
|
|
251
|
+
const r = await (0, types_1.apiCall)(ctx, 'POST', `${base}/loop-runs`, {
|
|
252
|
+
loopId,
|
|
253
|
+
...(args.provider !== undefined ? { provider: args.provider } : {}),
|
|
254
|
+
...(args.model !== undefined ? { model: args.model } : {}),
|
|
255
|
+
...(args.reasoning_effort !== undefined ? { reasoning_effort: args.reasoning_effort } : {}),
|
|
256
|
+
});
|
|
257
|
+
return {
|
|
258
|
+
...r,
|
|
259
|
+
hint: 'Run accepted (202). Use specrails_watch with the returned loopRunId (loop.run_completed / loop.run_stopped are terminal), or poll specrails_loops(run_get, loopRunId) after a timeout.',
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
case 'run_get': {
|
|
263
|
+
const loopRunId = args.loopRunId;
|
|
264
|
+
if (!loopRunId)
|
|
265
|
+
throw new Error('run_get requires a "loopRunId".');
|
|
266
|
+
const base = (0, types_1.projectPath)(ctx, args.projectId);
|
|
267
|
+
return (0, types_1.apiCall)(ctx, 'GET', `${base}/loop-runs/${encodeURIComponent(loopRunId)}`);
|
|
268
|
+
}
|
|
217
269
|
// ── Destructive ─────────────────────────────────────────────────────
|
|
218
270
|
case 'delete': {
|
|
219
271
|
if (!loopId)
|