specrails-desktop 2.36.0 → 2.42.2
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 +94 -247
- package/client/dist/assets/ActivityFeedPage-DoEMumQS.js +1 -0
- package/client/dist/assets/AgentBrowserCapture-DIh4K0gh.js +1 -0
- package/client/dist/assets/AgentModeAnalyticsPane-mbq4WEoO.js +2 -0
- package/client/dist/assets/AgentModeCodePane-CKh7zuA4.js +2 -0
- package/client/dist/assets/AgentModeJobsPane-BDokPiLJ.js +1 -0
- package/client/dist/assets/AgentsPage-BFVAZbBj.js +87 -0
- package/client/dist/assets/AnalyticsPage-3Y9LuWwz.js +1 -0
- package/client/dist/assets/CodePage-C9KyuV_C.js +3 -0
- package/client/dist/assets/DesktopAnalyticsPage-Bhi54bXQ.js +1 -0
- package/client/dist/assets/{DocsDialog-C76VdBJC.js → DocsDialog-Dj6mt4ga.js} +2 -2
- package/client/dist/assets/{DocsPage-ziMlj6B6.js → DocsPage-24yWglNI.js} +1 -1
- package/client/dist/assets/ExportDropdown-ophapHrT.js +1 -0
- package/client/dist/assets/InteractiveJobComposer-C1ucmxQh.js +19 -0
- package/client/dist/assets/JobDetailModal-DNWmgVHD.js +1 -0
- package/client/dist/assets/JobDetailPage-BcajZyuu.js +1 -0
- package/client/dist/assets/JobsPage-B9nTZw6e.js +1 -0
- package/client/dist/assets/LoopBuilderPage-Oc48iOFW.js +7 -0
- package/client/dist/assets/LoopPreviewModal-ae0Fr6SU.js +1 -0
- package/client/dist/assets/LoopsPage-CUEqzUBI.js +1 -0
- package/client/dist/assets/MinimizedChatsContext-Deg39peL.js +1 -0
- package/client/dist/assets/PluginsPage-C1xtARIx.js +2 -0
- package/client/dist/assets/ProjectSettingsDialog-JZzrXFBN.js +1 -0
- package/client/dist/assets/RepositoryDeliveries-CSDsiVUz.js +5 -0
- package/client/dist/assets/RepositoryScopeSelector-D-RCaknl.js +1 -0
- package/client/dist/assets/ReviewPacketPage-x5EfGTiL.js +1 -0
- package/client/dist/assets/TemplatePreviewModal-BSyuZxGq.js +1 -0
- package/client/dist/assets/TicketDetailModalContext-DqyF0so-.js +14 -0
- package/client/dist/assets/Trans-SnMX4MhW.js +1 -0
- package/client/dist/assets/agent-BdT0SB1D.js +1 -0
- package/client/dist/assets/agent-Bh9K7iEt.js +1 -0
- package/client/dist/assets/agent-C4ibdFk9.js +1 -0
- package/client/dist/assets/agent-CSFY22Zo.js +1 -0
- package/client/dist/assets/agent-DAnqxUn8.js +1 -0
- package/client/dist/assets/agent-DTQiu0Mi.js +1 -0
- package/client/dist/assets/agent-T54WuR_Y.js +1 -0
- package/client/dist/assets/agent-i75WDZOA.js +1 -0
- package/client/dist/assets/browser-05vRDg_y.js +1 -0
- package/client/dist/assets/browser-Bulb-cB1.js +1 -0
- package/client/dist/assets/browser-C7f-Jsg1.js +1 -0
- package/client/dist/assets/browser-CG0PE1j_.js +1 -0
- package/client/dist/assets/browser-CMzaqAjo.js +1 -0
- package/client/dist/assets/browser-DMajYdNX.js +1 -0
- package/client/dist/assets/browser-DxcOHrdP.js +1 -0
- package/client/dist/assets/browser-ObE7xVo3.js +1 -0
- package/client/dist/assets/builder-765NeYTp.js +1 -0
- package/client/dist/assets/builder-8MG3V6ea.js +1 -0
- package/client/dist/assets/builder-B-1UBs5K.js +1 -0
- package/client/dist/assets/builder-BTiGnPT0.js +1 -0
- package/client/dist/assets/builder-Cx9Rz-7u.js +1 -0
- package/client/dist/assets/builder-DKFMELBl.js +1 -0
- package/client/dist/assets/builder-OcmKrC0h.js +1 -0
- package/client/dist/assets/builder-P9qVBXFZ.js +1 -0
- package/client/dist/assets/{button-CJqFnUOL.js → button-DCBqEaZl.js} +1 -1
- package/client/dist/assets/{code-CkUuW4m9.js → code-B37GRg9C.js} +1 -1
- package/client/dist/assets/{code-B0O8-p8k.js → code-BBOEZbf9.js} +1 -1
- package/client/dist/assets/{code-B1VLZDhS.js → code-BRm-jcyx.js} +1 -1
- package/client/dist/assets/{code-Bpj4Ddml.js → code-CF7w62CR.js} +1 -1
- package/client/dist/assets/{code-BykBZ5-e.js → code-CLuvJt2r.js} +1 -1
- package/client/dist/assets/{code-B86IMAfz.js → code-D0RCm59f.js} +1 -1
- package/client/dist/assets/code-DaZ-ZwCT.js +1 -0
- package/client/dist/assets/{code-cAqaqMTx.js → code-iIHkGaCL.js} +1 -1
- package/client/dist/assets/commands-0XjAftla.js +1 -0
- package/client/dist/assets/commands-BAWSYHjQ.js +1 -0
- package/client/dist/assets/commands-BBwowgiE.js +1 -0
- package/client/dist/assets/commands-BacjIZLN.js +1 -0
- package/client/dist/assets/commands-Bs62IAZ3.js +1 -0
- package/client/dist/assets/commands-CLPdh-Hh.js +1 -0
- package/client/dist/assets/commands-DlbFzgrp.js +1 -0
- package/client/dist/assets/commands-LjPSsi5F.js +1 -0
- package/client/dist/assets/common-B5AZNYMH.js +1 -0
- package/client/dist/assets/common-BFZ0c_vN.js +1 -0
- package/client/dist/assets/common-BrlwEnL7.js +1 -0
- package/client/dist/assets/common-BttQx3z4.js +1 -0
- package/client/dist/assets/common-CM65k_-e.js +1 -0
- package/client/dist/assets/common-D4mvFFlu.js +1 -0
- package/client/dist/assets/common-TZ9Ny96S.js +1 -0
- package/client/dist/assets/common-nFpSF4GC.js +1 -0
- package/client/dist/assets/dashboard-B14uYXkG.js +1 -0
- package/client/dist/assets/dashboard-BK_mez-z.js +1 -0
- package/client/dist/assets/dashboard-BfBir_6o.js +1 -0
- package/client/dist/assets/dashboard-Bt0cCzeG.js +1 -0
- package/client/dist/assets/dashboard-BwkjxI6H.js +1 -0
- package/client/dist/assets/{dashboard-C8WOEiPu.js → dashboard-C3bDKf7s.js} +1 -1
- package/client/dist/assets/dashboard-CdvjGfog.js +1 -0
- package/client/dist/assets/dashboard-fRrP0Kv0.js +1 -0
- package/client/dist/assets/dialog-SRw01_QU.js +45 -0
- package/client/dist/assets/dist-js-CJ_2XX1Y.js +1 -0
- package/client/dist/assets/formatDistanceToNow-DSj5DprF.js +1 -0
- package/client/dist/assets/getTimezoneOffsetInMilliseconds-YhD8rIEs.js +1 -0
- package/client/dist/assets/index-DwAmL7m5.css +2 -0
- package/client/dist/assets/index-EzrkUb8B.js +76 -0
- package/client/dist/assets/{jira-api-B1-MUehg.js → jira-api-CSCqGr-Q.js} +1 -1
- package/client/dist/assets/{jobs-CN_zv4Gr.js → jobs-B8rrzfyZ.js} +1 -1
- package/client/dist/assets/{jobs-DUlWSYq2.js → jobs-BS6RTurf.js} +1 -1
- package/client/dist/assets/{jobs-Bpks6doU.js → jobs-BTT0Bsks.js} +1 -1
- package/client/dist/assets/{jobs-Bgq-PZkC.js → jobs-CezU69AE.js} +1 -1
- package/client/dist/assets/{jobs-SwYS2M-B.js → jobs-ClFJae0s.js} +1 -1
- package/client/dist/assets/{jobs-BAls3bWq.js → jobs-DJSFIFVy.js} +1 -1
- package/client/dist/assets/{jobs-DhxKgWFq.js → jobs-DhgGr8vm.js} +1 -1
- package/client/dist/assets/{jobs-B_TeSQxb.js → jobs-DzMjUcaN.js} +1 -1
- package/client/dist/assets/mcp-6rMoZfEO.js +1 -0
- package/client/dist/assets/mcp-BD8sL5mP.js +1 -0
- package/client/dist/assets/mcp-BkcA3I5s.js +1 -0
- package/client/dist/assets/mcp-CCpSelOh.js +1 -0
- package/client/dist/assets/mcp-CUAN6ORK.js +1 -0
- package/client/dist/assets/mcp-CqbRxRTE.js +1 -0
- package/client/dist/assets/mcp-DP2YfVhO.js +1 -0
- package/client/dist/assets/mcp-DUVQamDz.js +1 -0
- package/client/dist/assets/narration-B-ynWTpn.js +1 -0
- package/client/dist/assets/narration-Bj_laZwg.js +1 -0
- package/client/dist/assets/narration-BxHpmMv_.js +1 -0
- package/client/dist/assets/narration-C1Px0-0j.js +1 -0
- package/client/dist/assets/narration-CAXhGbzM.js +1 -0
- package/client/dist/assets/narration-DQ1l_Kq6.js +1 -0
- package/client/dist/assets/narration-XISXwqZd.js +1 -0
- package/client/dist/assets/narration-kwzfglQo.js +1 -0
- package/client/dist/assets/nav-1-Hh2kOz.js +1 -0
- package/client/dist/assets/nav-B34QkESm.js +1 -0
- package/client/dist/assets/nav-Bap_UXAq.js +1 -0
- package/client/dist/assets/{nav-pYuXq7sf.js → nav-BwxXIB24.js} +1 -1
- package/client/dist/assets/nav-Ch-zHBG5.js +1 -0
- package/client/dist/assets/nav-CygC_WN-.js +1 -0
- package/client/dist/assets/{nav-iwjCg5FR.js → nav-KnnLQtOQ.js} +1 -1
- package/client/dist/assets/nav-m00uxYUG.js +1 -0
- package/client/dist/assets/packet-BQ2tXfJI.js +1 -0
- package/client/dist/assets/packet-BdpOJ1Cy.js +1 -0
- package/client/dist/assets/packet-C3Ievb9R.js +1 -0
- package/client/dist/assets/packet-C4zJIG0Y.js +1 -0
- package/client/dist/assets/packet-Cx-zRuWn.js +1 -0
- package/client/dist/assets/packet-DUTGX52M.js +1 -0
- package/client/dist/assets/packet-DhsKtUPB.js +1 -0
- package/client/dist/assets/packet-z3LJ8Zyy.js +1 -0
- package/client/dist/assets/project-repositories-DYhTvwQ1.js +1 -0
- package/client/dist/assets/provider-capabilities-B-wOHfLP.js +1 -0
- package/client/dist/assets/settings-BBt2xtDQ.js +1 -0
- package/client/dist/assets/settings-BJB9RKJj.js +1 -0
- package/client/dist/assets/settings-CHwQR2rB.js +1 -0
- package/client/dist/assets/settings-CrMi3kSi.js +1 -0
- package/client/dist/assets/settings-DKyhDGD1.js +1 -0
- package/client/dist/assets/settings-Deupji9c.js +1 -0
- package/client/dist/assets/settings-DqRMmwAM.js +1 -0
- package/client/dist/assets/settings-J4rj6vo-.js +1 -0
- package/client/dist/assets/setup-2xGgu4Sk.js +1 -0
- package/client/dist/assets/setup-Ba11l2JA.js +1 -0
- package/client/dist/assets/setup-BzW4kMok.js +1 -0
- package/client/dist/assets/setup-COzwYhkJ.js +1 -0
- package/client/dist/assets/setup-CRVULhtF.js +1 -0
- package/client/dist/assets/setup-DgvlxwpE.js +1 -0
- package/client/dist/assets/setup-Dw_wYeEY.js +1 -0
- package/client/dist/assets/setup-ZPtEeJPW.js +1 -0
- package/client/dist/assets/spending-BqbdPm_4.js +1 -0
- package/client/dist/assets/square-Ci-PFcFe.js +1 -0
- package/client/dist/assets/{terminal-BFRZnMPP.js → terminal-BAzpHtpY.js} +1 -1
- package/client/dist/assets/{terminal-IahE4LW9.js → terminal-C7dHeR3x.js} +1 -1
- package/client/dist/assets/{terminal-tITa81iz.js → terminal-CMla5Qsz.js} +1 -1
- package/client/dist/assets/{terminal-BZiIu3rf.js → terminal-CdNXH-n9.js} +1 -1
- package/client/dist/assets/{terminal-ScjyXNxQ.js → terminal-Cw5bZsmV.js} +1 -1
- package/client/dist/assets/{terminal-C2NAd7BW.js → terminal-DFUP4eNv.js} +1 -1
- package/client/dist/assets/{terminal-d7GadXbN.js → terminal-DGqljeK_.js} +1 -1
- package/client/dist/assets/{terminal-QpXZU2Bn.js → terminal-cU70NodO.js} +1 -1
- package/client/dist/assets/useDesktop-RSMTyy7V.js +1 -0
- package/client/dist/assets/useSharedWebSocket-BOdS5_Iz.js +2 -0
- package/client/dist/index.html +34 -35
- package/docs/README.md +3 -0
- package/docs/agent-live-steering.md +57 -0
- package/docs/ci-cd.md +57 -0
- package/docs/code-explorer.md +48 -0
- package/docs/codex.md +12 -1
- package/docs/features/detachable-mission-windows.md +59 -0
- package/docs/guide/de/integrations/5-mcp-server.md +13 -9
- package/docs/guide/de/integrations/6-agent-chat.md +1 -0
- package/docs/guide/en/integrations/5-mcp-server.md +13 -9
- package/docs/guide/en/integrations/6-agent-chat.md +1 -0
- package/docs/guide/es/integrations/5-mcp-server.md +13 -9
- package/docs/guide/es/integrations/6-agent-chat.md +1 -0
- package/docs/guide/fr/integrations/5-mcp-server.md +13 -9
- package/docs/guide/fr/integrations/6-agent-chat.md +1 -0
- package/docs/guide/it/integrations/5-mcp-server.md +13 -9
- package/docs/guide/it/integrations/6-agent-chat.md +1 -0
- package/docs/guide/ja/integrations/5-mcp-server.md +13 -9
- package/docs/guide/ja/integrations/6-agent-chat.md +1 -0
- package/docs/guide/pt/integrations/5-mcp-server.md +13 -9
- package/docs/guide/pt/integrations/6-agent-chat.md +1 -0
- package/docs/guide/zh/integrations/5-mcp-server.md +13 -9
- package/docs/guide/zh/integrations/6-agent-chat.md +1 -0
- package/docs/internals/README.md +1 -0
- package/docs/internals/browser-capture-performance.md +55 -3
- package/docs/internals/browser-login-popups.md +45 -0
- package/docs/internals/browser-native-retina-audit.md +39 -0
- package/docs/internals/ci-cd-audit.md +39 -0
- package/docs/internals/core-runtime-updates.md +68 -0
- package/docs/internals/embedded-browser-native-webview-evaluation.md +2 -0
- package/docs/internals/implementation-reliability-audit.md +93 -0
- package/docs/internals/interactive-jobs.md +110 -6
- package/docs/internals/mcp-mission-audit.md +76 -0
- package/docs/internals/project-builder.md +404 -42
- package/docs/internals/safe-pr-review-flow.md +52 -10
- package/docs/internals/startup-recovery-audit.md +58 -0
- package/docs/mcp.md +74 -41
- package/docs/mission-processes.md +59 -0
- package/docs/multi-repo-projects.md +51 -0
- package/docs/platforms/windows-parity.md +70 -0
- package/docs/platforms/windows.md +13 -11
- package/docs/running-pipelines.md +14 -0
- package/mcp-bridge/dist/specrails-mcp.js +7186 -0
- package/package.json +9 -4
- package/server/dist/agent-chat-manager.js +537 -68
- package/server/dist/agent-chat-router.js +87 -6
- package/server/dist/agent-context-resolver.js +129 -25
- package/server/dist/agent-defaults.js +19 -11
- package/server/dist/agent-input-store.js +206 -0
- package/server/dist/agent-mcp-config.js +54 -15
- package/server/dist/agent-operator-prompt.js +255 -65
- package/server/dist/agent-spec-framing.js +202 -0
- package/server/dist/agent-steering.js +218 -0
- package/server/dist/agent-store.js +153 -0
- package/server/dist/api-not-found.js +8 -0
- package/server/dist/background-process-control.js +164 -0
- package/server/dist/background-process-service.js +61 -0
- package/server/dist/background-process-store.js +242 -0
- package/server/dist/background-windows-bootstrap.js +238 -0
- package/server/dist/blueprint-chat-manager.js +476 -62
- package/server/dist/blueprint-commit.js +21 -1
- package/server/dist/blueprint-draft-parser.js +122 -17
- package/server/dist/blueprint-generation.js +238 -0
- package/server/dist/blueprint-operator-prompt.js +91 -63
- package/server/dist/blueprint-router.js +55 -3
- package/server/dist/blueprint-spec-fixtures.js +85 -0
- package/server/dist/blueprint-spec-quality.js +57 -16
- package/server/dist/blueprint-store.js +92 -1
- package/server/dist/browser-capture-manager.js +86 -30
- package/server/dist/browser-playwright.js +168 -45
- package/server/dist/browser-viewport.js +26 -0
- package/server/dist/chat-manager.js +23 -15
- package/server/dist/chromium-archive.cjs +83 -0
- package/server/dist/chromium-resolver.js +72 -64
- package/server/dist/code-activity.js +145 -0
- package/server/dist/code-explorer-router.js +714 -114
- package/server/dist/core-compat.js +28 -1
- package/server/dist/core-execution.js +111 -0
- package/server/dist/core-package.js +4 -16
- package/server/dist/core-runtime.js +202 -0
- package/server/dist/core-update-manager.js +161 -60
- package/server/dist/core-update-state.js +29 -0
- package/server/dist/db.js +66 -35
- package/server/dist/delivery-evidence.js +142 -39
- package/server/dist/desktop-db.js +239 -43
- package/server/dist/desktop-router.js +109 -9
- package/server/dist/dev-ports.js +8 -3
- package/server/dist/file-provenance.js +34 -22
- package/server/dist/file-story-manager.js +62 -64
- package/server/dist/file-story.js +118 -35
- package/server/dist/file-summary-generator.js +46 -5
- package/server/dist/file-summary-manager.js +355 -106
- package/server/dist/framework-manager.js +98 -110
- package/server/dist/framework-reseed.js +76 -10
- package/server/dist/git-diagnostics.js +2 -2
- package/server/dist/headroom-manager.js +38 -3
- package/server/dist/host-control.js +52 -0
- package/server/dist/index.js +43 -2
- package/server/dist/interactive-job-session.js +149 -16
- package/server/dist/internal-api.js +48 -0
- package/server/dist/jira/jira-materializer.js +1 -0
- package/server/dist/json-tolerant.js +174 -0
- package/server/dist/legacy-migration.js +4 -2
- package/server/dist/loop-command-catalog.js +83 -21
- package/server/dist/loop-constants.js +6 -1
- package/server/dist/loop-decider.js +11 -1
- package/server/dist/loop-executors.js +194 -45
- package/server/dist/loop-factory.js +11 -4
- package/server/dist/loop-graph.js +90 -4
- package/server/dist/loop-run-manager.js +301 -69
- package/server/dist/loop-shell-invocation.js +21 -0
- package/server/dist/loop-step-idle.js +55 -0
- package/server/dist/loop-templates.js +31 -7
- package/server/dist/mcp/agent-capability.js +37 -4
- package/server/dist/mcp/guide.js +149 -36
- package/server/dist/mcp/mcp-admin-router.js +20 -4
- package/server/dist/mcp/mcp-server.js +89 -43
- package/server/dist/mcp/mcp-tiers.js +6 -5
- package/server/dist/mcp/mcp-token.js +3 -1
- package/server/dist/mcp/resources.js +5 -4
- package/server/dist/mcp/tools/catalog.js +4 -0
- package/server/dist/mcp/tools/code.js +125 -14
- package/server/dist/mcp/tools/context.js +153 -0
- package/server/dist/mcp/tools/git.js +15 -5
- package/server/dist/mcp/tools/jobs.js +84 -71
- package/server/dist/mcp/tools/loops.js +17 -6
- package/server/dist/mcp/tools/meta.js +74 -27
- package/server/dist/mcp/tools/mission.js +29 -0
- package/server/dist/mcp/tools/projects.js +22 -6
- package/server/dist/mcp/tools/rails.js +48 -11
- package/server/dist/mcp/tools/specs.js +86 -14
- package/server/dist/mcp/tools/support.js +1 -1
- package/server/dist/mcp/tools/types.js +117 -43
- package/server/dist/mcp/tools/watch.js +144 -51
- package/server/dist/milestone-chain-store.js +164 -0
- package/server/dist/milestone-chain.js +487 -0
- package/server/dist/milestone-progress.js +348 -0
- package/server/dist/mobile/mobile-devices.js +10 -7
- package/server/dist/mobile/mobile-gateway.js +2 -0
- package/server/dist/mobile/mobile-missions.js +214 -0
- package/server/dist/mobile/mobile-redact.js +17 -3
- package/server/dist/mobile/mobile-router.js +46 -4
- package/server/dist/mobile/mobile-ws.js +49 -4
- package/server/dist/multi-repo-bases.js +56 -0
- package/server/dist/multi-repo-checkout.js +101 -0
- package/server/dist/multi-repo-delivery.js +100 -0
- package/server/dist/multi-repo-execution-store.js +65 -0
- package/server/dist/multi-repo-execution.js +453 -0
- package/server/dist/offline-assemble.js +10 -8
- package/server/dist/openspec-runtime-plugin-commands.json +18 -0
- package/server/dist/openspec-runtime-plugin.js +120 -0
- package/server/dist/plugins/codex-spawn.js +49 -0
- package/server/dist/plugins/serena/manifest.js +2 -2
- package/server/dist/plugins/serena/templates/instructions.md +16 -0
- package/server/dist/pr-publisher.js +1 -1
- package/server/dist/profiles-router.js +3 -18
- package/server/dist/project-code-discovery.js +142 -0
- package/server/dist/project-git.js +19 -21
- package/server/dist/project-registry.js +272 -20
- package/server/dist/project-repositories.js +157 -0
- package/server/dist/project-repository-provenance.js +31 -0
- package/server/dist/project-router-background-processes.js +105 -0
- package/server/dist/project-router-git.js +75 -16
- package/server/dist/project-router-jobs.js +2 -126
- package/server/dist/project-router-loop-runs.js +72 -2
- package/server/dist/project-router-tickets.js +53 -8
- package/server/dist/project-router.js +239 -38
- package/server/dist/provider-detection.js +18 -6
- package/server/dist/provider-limit.js +64 -0
- package/server/dist/providers/claude-adapter.js +26 -1
- package/server/dist/providers/claude-background-tasks.js +18 -0
- package/server/dist/providers/claude-live-session.js +383 -0
- package/server/dist/providers/codex-adapter.js +19 -0
- package/server/dist/providers/codex-live-session.js +545 -0
- package/server/dist/providers/gemini-adapter.js +1 -0
- package/server/dist/providers/live-session-types.js +12 -0
- package/server/dist/providers/live-session.js +13 -0
- package/server/dist/providers/terminal-result.js +24 -0
- package/server/dist/queue-manager.js +2 -0
- package/server/dist/rail-isolated-launch.js +141 -16
- package/server/dist/rail-pr-decision.js +364 -99
- package/server/dist/rail-pr-store.js +24 -10
- package/server/dist/rail-worktree-release.js +34 -2
- package/server/dist/rail-worktrees-store.js +4 -4
- package/server/dist/rails-router.js +249 -55
- package/server/dist/repo-lock.js +92 -17
- package/server/dist/review-packet.js +23 -13
- package/server/dist/schemas/file-summary.v1.json +59 -59
- package/server/dist/schemas/profile.v1.json +137 -137
- package/server/dist/setup-manager.js +52 -8
- package/server/dist/shell-integration/bash-shim.bash +45 -0
- package/server/dist/shell-integration/fish-shim.fish +36 -0
- package/server/dist/shell-integration/powershell-shim.ps1 +48 -0
- package/server/dist/shell-integration/zsh-shim.zsh +47 -0
- package/server/dist/smash-runner.js +1 -0
- package/server/dist/spawn-lifecycle.js +44 -27
- package/server/dist/spec-contract-prompt.js +143 -0
- package/server/dist/spec-draft-parser.js +6 -1
- package/server/dist/spec-models.js +1 -0
- package/server/dist/stuck-run-detector.js +1 -0
- package/server/dist/terminal-manager.js +21 -1
- package/server/dist/terminal-shell-integration.js +4 -1
- package/server/dist/transient-children.js +619 -230
- package/server/dist/util/cli-prompt.js +78 -5
- package/server/dist/util/sqlite-migrations.js +20 -0
- package/server/dist/util/win-spawn.js +18 -3
- package/server/dist/util/windows-provider-shell.js +29 -0
- package/server/dist/verification-sentinel.js +14 -0
- package/server/dist/vitest-setup.js +2 -0
- package/server/dist/windows-job-supervisor.js +133 -0
- package/server/dist/workspace-manager.js +9 -30
- package/server/dist/worktree-manager.js +17 -2
- package/server/dist/worktree-overlay.js +3 -1
- package/client/dist/assets/ActivityFeedPage-tAQcWs1R.js +0 -1
- package/client/dist/assets/AgentBrowserCapture-BX8BNae5.js +0 -1
- package/client/dist/assets/AgentModeAnalyticsPane-BVAqCL0K.js +0 -2
- package/client/dist/assets/AgentModeCodePane-9XfqQc9c.js +0 -2
- package/client/dist/assets/AgentModeJobsPane-BCjLsPhc.js +0 -1
- package/client/dist/assets/AgentsPage-C8J_42sm.js +0 -87
- package/client/dist/assets/AnalyticsPage-BtQuyfJm.js +0 -1
- package/client/dist/assets/CodePage-BZ2MwdCu.js +0 -2
- package/client/dist/assets/DesktopAnalyticsPage-Bh_29V4g.js +0 -1
- package/client/dist/assets/ExportDropdown-BrtfWzEG.js +0 -1
- package/client/dist/assets/InteractiveJobComposer-BCZiSfzc.js +0 -19
- package/client/dist/assets/JobDetailModal-NAJmuYIT.js +0 -1
- package/client/dist/assets/JobDetailPage-fE0ZycUX.js +0 -1
- package/client/dist/assets/JobsPage-z5M_HVJG.js +0 -1
- package/client/dist/assets/LoopBuilderPage-j1FQS47c.js +0 -7
- package/client/dist/assets/LoopPreviewModal-DhDJjdCe.js +0 -1
- package/client/dist/assets/LoopsPage-Ll7zORZb.js +0 -1
- package/client/dist/assets/MinimizedChatsContext-Bd3OqR_S.js +0 -1
- package/client/dist/assets/PluginsPage-DN4kGvJt.js +0 -2
- package/client/dist/assets/ProjectSettingsDialog-OgsgxjzF.js +0 -1
- package/client/dist/assets/ReviewPacketPage-DFog4sXn.js +0 -1
- package/client/dist/assets/TemplatePreviewModal-L2XxqiOD.js +0 -1
- package/client/dist/assets/TicketDetailModal-CsF-AWZX.js +0 -14
- package/client/dist/assets/Trans-Bsz9_gyq.js +0 -1
- package/client/dist/assets/agent-BQgKv_2F.js +0 -1
- package/client/dist/assets/agent-C1NRDJqL.js +0 -1
- package/client/dist/assets/agent-CLNleiy6.js +0 -1
- package/client/dist/assets/agent-CmceArkQ.js +0 -1
- package/client/dist/assets/agent-D3UxQ3SR.js +0 -1
- package/client/dist/assets/agent-DB1JeE64.js +0 -1
- package/client/dist/assets/agent-DXkHcQ-D.js +0 -1
- package/client/dist/assets/agent-DjJJJ2M8.js +0 -1
- package/client/dist/assets/auth-D_5bQv5W.js +0 -1
- package/client/dist/assets/ban-E4EaZe3a.js +0 -1
- package/client/dist/assets/bot-DzuuuC5R.js +0 -1
- package/client/dist/assets/browser-BgqHDMXP.js +0 -1
- package/client/dist/assets/browser-CsKJtrpv.js +0 -1
- package/client/dist/assets/browser-Cu58EpZU.js +0 -1
- package/client/dist/assets/browser-CvXOJm-j.js +0 -1
- package/client/dist/assets/browser-DOrFh1c7.js +0 -1
- package/client/dist/assets/browser-DQv_Jo7x.js +0 -1
- package/client/dist/assets/browser-LPgxvJu2.js +0 -1
- package/client/dist/assets/browser-eL-3MIEI.js +0 -1
- package/client/dist/assets/builder-0IWtosUm.js +0 -1
- package/client/dist/assets/builder-Bf2N6XWn.js +0 -1
- package/client/dist/assets/builder-BnqaaBkT.js +0 -1
- package/client/dist/assets/builder-BxxfGgAO.js +0 -1
- package/client/dist/assets/builder-C5IIgWsq.js +0 -1
- package/client/dist/assets/builder-CHuahItu.js +0 -1
- package/client/dist/assets/builder-CjWosXL_.js +0 -1
- package/client/dist/assets/builder-CpCIOoKj.js +0 -1
- package/client/dist/assets/code-CHPkOkDS.js +0 -1
- package/client/dist/assets/commands-6tYQih5m.js +0 -1
- package/client/dist/assets/commands-BK2QinXN.js +0 -1
- package/client/dist/assets/commands-C2Nca76h.js +0 -1
- package/client/dist/assets/commands-CKdLihNX.js +0 -1
- package/client/dist/assets/commands-CYIBTAlc.js +0 -1
- package/client/dist/assets/commands-CjUtYJIM.js +0 -1
- package/client/dist/assets/commands-Cq_u_8y9.js +0 -1
- package/client/dist/assets/commands-D_ZHYQug.js +0 -1
- package/client/dist/assets/common-6MLbD-jM.js +0 -1
- package/client/dist/assets/common-BKGEu4rm.js +0 -1
- package/client/dist/assets/common-BNbnv8cE.js +0 -1
- package/client/dist/assets/common-BqGWtDbt.js +0 -1
- package/client/dist/assets/common-DBtTzeYm.js +0 -1
- package/client/dist/assets/common-DEW3Nr8n.js +0 -1
- package/client/dist/assets/common-DHsv9N5d.js +0 -1
- package/client/dist/assets/common-mkrEcW-Y.js +0 -1
- package/client/dist/assets/dashboard-B9GhC5ku.js +0 -1
- package/client/dist/assets/dashboard-CBnv6zOI.js +0 -1
- package/client/dist/assets/dashboard-CaP0fU87.js +0 -1
- package/client/dist/assets/dashboard-D4ZZ4x84.js +0 -1
- package/client/dist/assets/dashboard-DmuTQBX8.js +0 -1
- package/client/dist/assets/dashboard-DynLYj3d.js +0 -1
- package/client/dist/assets/dashboard-zj4gGFJ1.js +0 -1
- package/client/dist/assets/dialog-CdWCb02j.js +0 -45
- package/client/dist/assets/dist-bVqfYmby.js +0 -1
- package/client/dist/assets/dist-js-CWeUdf5Z.js +0 -1
- package/client/dist/assets/formatDistanceToNow-DQCvMgUc.js +0 -1
- package/client/dist/assets/getTimezoneOffsetInMilliseconds-C16cxSe1.js +0 -1
- package/client/dist/assets/git-refresh-wTW0rO0Z.js +0 -1
- package/client/dist/assets/i18n-hnX2DPmo.js +0 -2
- package/client/dist/assets/index-DIhMEAVw.js +0 -66
- package/client/dist/assets/index-DwygcU7s.css +0 -2
- package/client/dist/assets/mcp-B8X8wBLu.js +0 -1
- package/client/dist/assets/mcp-C2AojZZN.js +0 -1
- package/client/dist/assets/mcp-D8BT78_L.js +0 -1
- package/client/dist/assets/mcp-Df5RWBNk.js +0 -1
- package/client/dist/assets/mcp-Dj7BgMQW.js +0 -1
- package/client/dist/assets/mcp-Q7iT7rcz.js +0 -1
- package/client/dist/assets/mcp-YlvNvJbW.js +0 -1
- package/client/dist/assets/mcp-mKFpTSRb.js +0 -1
- package/client/dist/assets/narration-4Z2VUhZw.js +0 -1
- package/client/dist/assets/narration-BGuiEDj3.js +0 -1
- package/client/dist/assets/narration-BuSoqRmv.js +0 -1
- package/client/dist/assets/narration-CB9t29fy.js +0 -1
- package/client/dist/assets/narration-CU3x8FHD.js +0 -1
- package/client/dist/assets/narration-CWeXhfP5.js +0 -1
- package/client/dist/assets/narration-DRaDnhT5.js +0 -1
- package/client/dist/assets/narration-DtEbQgCw.js +0 -1
- package/client/dist/assets/nav-ApJVg3xu.js +0 -1
- package/client/dist/assets/nav-BKNky1Bg.js +0 -1
- package/client/dist/assets/nav-C6vWWKYx.js +0 -1
- package/client/dist/assets/nav-CXJ6Aw89.js +0 -1
- package/client/dist/assets/nav-CsmFBIDf.js +0 -1
- package/client/dist/assets/nav-DjkmQJjd.js +0 -1
- package/client/dist/assets/packet-B1IxaL5f.js +0 -1
- package/client/dist/assets/packet-Bh5kkbiB.js +0 -1
- package/client/dist/assets/packet-By8fqYxW.js +0 -1
- package/client/dist/assets/packet-CZdvA44E.js +0 -1
- package/client/dist/assets/packet-CrjHRQCP.js +0 -1
- package/client/dist/assets/packet-Dwi2pTtx.js +0 -1
- package/client/dist/assets/packet-_-ZIa0IR.js +0 -1
- package/client/dist/assets/packet-n0W6E1Hn.js +0 -1
- package/client/dist/assets/play-DNlrawbS.js +0 -1
- package/client/dist/assets/provider-capabilities-Doej9lfa.js +0 -1
- package/client/dist/assets/settings-Bd0x4TBa.js +0 -1
- package/client/dist/assets/settings-C1-7cXzC.js +0 -1
- package/client/dist/assets/settings-CAFaT38b.js +0 -1
- package/client/dist/assets/settings-Ct3v1nW2.js +0 -1
- package/client/dist/assets/settings-DHh7_IF5.js +0 -1
- package/client/dist/assets/settings-DQXAmdcv.js +0 -1
- package/client/dist/assets/settings-guzlhpup.js +0 -1
- package/client/dist/assets/settings-sZfTPMEH.js +0 -1
- package/client/dist/assets/setup-3jWaoVUO.js +0 -1
- package/client/dist/assets/setup-BjgRneb2.js +0 -1
- package/client/dist/assets/setup-BzFIjv-f.js +0 -1
- package/client/dist/assets/setup-C4VfQsxE.js +0 -1
- package/client/dist/assets/setup-DfUkpDbN.js +0 -1
- package/client/dist/assets/setup-ECe90Pmu.js +0 -1
- package/client/dist/assets/setup-dlqC4Jmm.js +0 -1
- package/client/dist/assets/setup-jwfLMiM2.js +0 -1
- package/client/dist/assets/spending-EC9xqio-.js +0 -1
- package/client/dist/assets/useDesktop-BQVt8lFd.js +0 -1
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.metaTools = metaTools;
|
|
4
7
|
const zod_1 = require("zod");
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const zod_json_schema_compat_js_1 = require("@modelcontextprotocol/sdk/server/zod-json-schema-compat.js");
|
|
5
10
|
const guide_1 = require("../guide");
|
|
6
11
|
const types_1 = require("./types");
|
|
7
12
|
/**
|
|
@@ -43,6 +48,32 @@ function describeZodField(name, field) {
|
|
|
43
48
|
out.enumValues = [...current.options];
|
|
44
49
|
return out;
|
|
45
50
|
}
|
|
51
|
+
function permissions(ctx, spec, args) {
|
|
52
|
+
const tier = typeof spec.tier === 'function' ? spec.tier(args) : spec.tier;
|
|
53
|
+
return { tier, allowed: (0, types_1.toolTierAllowed)(ctx, tier) };
|
|
54
|
+
}
|
|
55
|
+
function actions(ctx, spec) {
|
|
56
|
+
const field = spec.inputSchema.action;
|
|
57
|
+
if (!(field instanceof zod_1.z.ZodEnum))
|
|
58
|
+
return [];
|
|
59
|
+
return field.options.map(action => ({ action, ...permissions(ctx, spec, { action }) }));
|
|
60
|
+
}
|
|
61
|
+
const STOP_WORDS = new Set('a an the to for of in and or with how do i my this el la los las un una de del en y o con como que quiero para mi por'.split(' '));
|
|
62
|
+
const INTENTS = {
|
|
63
|
+
proyecto: ['project', 'context'], proyectos: ['projects'], contexto: ['context', 'overview'],
|
|
64
|
+
codigo: ['code', 'search'], buscar: ['search', 'find'], archivo: ['file'], archivos: ['file', 'tree'],
|
|
65
|
+
implementar: ['launch', 'run', 'implement'], implementacion: ['implement', 'run'], lanzar: ['launch', 'run'],
|
|
66
|
+
ejecucion: ['job', 'run'], ejecuciones: ['jobs', 'runs'], fallida: ['failed', 'logs'], error: ['error', 'logs'],
|
|
67
|
+
mision: ['conversation'], conversar: ['chat'], especificaciones: ['specs'], especificacion: ['spec'],
|
|
68
|
+
revisar: ['review', 'packet'], cambios: ['diff', 'git'], rama: ['branch', 'git'], ramas: ['branch'],
|
|
69
|
+
esperar: ['watch', 'wait'], estado: ['status', 'context'], bucle: ['loop'], bucles: ['loops'],
|
|
70
|
+
herramientas: ['tools'], permisos: ['tier', 'permissions'], configurar: ['settings'],
|
|
71
|
+
};
|
|
72
|
+
const normalize = (text) => text.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
|
73
|
+
function intentTerms(query) {
|
|
74
|
+
const words = normalize(query).split(/[^a-z0-9_]+/).filter(word => word.length > 1 && !STOP_WORDS.has(word));
|
|
75
|
+
return [...new Set(words.flatMap(word => [word, ...(INTENTS[word] ?? [])]))];
|
|
76
|
+
}
|
|
46
77
|
/**
|
|
47
78
|
* Meta tools that teach the platform and aid discovery.
|
|
48
79
|
* `getSpecs` returns the full catalog (passed lazily to avoid a cycle).
|
|
@@ -61,20 +92,26 @@ function metaTools(getSpecs) {
|
|
|
61
92
|
{
|
|
62
93
|
name: 'specrails_search',
|
|
63
94
|
title: 'Search tools',
|
|
64
|
-
description: 'Find the right Specrails tool/action for an intent.
|
|
95
|
+
description: 'Find the right Specrails tool/action for an English or Spanish intent. Searches tool descriptions, actions and input fields; returns current permissions. Follow with describe for exact arguments.',
|
|
65
96
|
tier: 'read',
|
|
66
97
|
inputSchema: {
|
|
67
|
-
query: zod_1.z.string().describe('Natural-language intent, e.g. "launch the pipeline for a ticket"'),
|
|
98
|
+
query: zod_1.z.string().trim().min(1).max(500).describe('Natural-language intent, e.g. "launch the pipeline for a ticket" or "buscar código del proyecto"'),
|
|
68
99
|
},
|
|
69
|
-
handler: (
|
|
70
|
-
const
|
|
71
|
-
const terms = q.split(/\s+/).filter(Boolean);
|
|
100
|
+
handler: (ctx, args) => {
|
|
101
|
+
const terms = intentTerms(String(args.query ?? ''));
|
|
72
102
|
const scored = getSpecs()
|
|
73
103
|
.filter((s) => s.name !== 'specrails_search')
|
|
74
104
|
.map((s) => {
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
|
|
105
|
+
const actionList = actions(ctx, s);
|
|
106
|
+
const name = normalize(`${s.name} ${s.title}`);
|
|
107
|
+
const description = normalize(s.description);
|
|
108
|
+
const schema = normalize(JSON.stringify((0, zod_json_schema_compat_js_1.toJsonSchemaCompat)(zod_1.z.object(s.inputSchema))));
|
|
109
|
+
const score = terms.reduce((acc, term) => acc + (name.includes(term) ? 8 : 0) +
|
|
110
|
+
(actionList.some(item => item.action.includes(term)) ? 5 : 0) +
|
|
111
|
+
(description.includes(term) ? 2 : 0) + (schema.includes(term) ? 1 : 0), 0);
|
|
112
|
+
return { name: s.name, title: s.title, description: s.description, score,
|
|
113
|
+
actions: actionList, ...(actionList.length ? {} : permissions(ctx, s, {})),
|
|
114
|
+
permissionNote: 'Action previews use default arguments. Describe with arguments for the exact tier; execution rechecks current permissions.' };
|
|
78
115
|
})
|
|
79
116
|
.filter((r) => r.score > 0)
|
|
80
117
|
.sort((a, b) => b.score - a.score)
|
|
@@ -85,20 +122,30 @@ function metaTools(getSpecs) {
|
|
|
85
122
|
{
|
|
86
123
|
name: 'specrails_describe',
|
|
87
124
|
title: 'Describe a tool',
|
|
88
|
-
description: 'Return
|
|
125
|
+
description: 'Return a tool\'s complete JSON input schema, including nested objects, arrays, required fields, enums and bounds, plus per-action permissions. Optionally validate prospective arguments and preview their tier without executing anything.',
|
|
89
126
|
tier: 'read',
|
|
90
127
|
inputSchema: {
|
|
91
128
|
name: zod_1.z.string().describe('Tool name, e.g. "specrails_rails"'),
|
|
129
|
+
arguments: zod_1.z.record(zod_1.z.unknown()).optional().describe('Optional prospective tool arguments to validate and preview permissions; never executes the tool'),
|
|
92
130
|
},
|
|
93
|
-
handler: (
|
|
131
|
+
handler: (ctx, args) => {
|
|
94
132
|
const name = String(args.name ?? '');
|
|
95
133
|
const spec = getSpecs().find((s) => s.name === name);
|
|
96
134
|
if (!spec)
|
|
97
135
|
throw new Error(`Unknown tool "${name}". Use specrails_search to find one.`);
|
|
136
|
+
const schema = zod_1.z.object(spec.inputSchema);
|
|
137
|
+
const prospective = args.arguments;
|
|
138
|
+
const validation = prospective === undefined ? undefined : schema.safeParse(prospective);
|
|
98
139
|
return {
|
|
99
140
|
name: spec.name,
|
|
100
141
|
title: spec.title,
|
|
101
142
|
description: spec.description,
|
|
143
|
+
inputSchema: (0, zod_json_schema_compat_js_1.toJsonSchemaCompat)(schema),
|
|
144
|
+
actions: actions(ctx, spec),
|
|
145
|
+
permissionNote: 'Action previews use default arguments. Validation checks the shared JSON schema only; action-specific requirements and backend state are checked at execution. No tool is executed here.',
|
|
146
|
+
...(validation ? { validation: validation.success
|
|
147
|
+
? { valid: true, ...permissions(ctx, spec, validation.data) }
|
|
148
|
+
: { valid: false, issues: validation.error.issues.map(issue => ({ path: issue.path, message: issue.message })) } } : {}),
|
|
102
149
|
inputFields: Object.entries(spec.inputSchema).map(([fieldName, field]) => describeZodField(fieldName, field)),
|
|
103
150
|
};
|
|
104
151
|
},
|
|
@@ -106,30 +153,30 @@ function metaTools(getSpecs) {
|
|
|
106
153
|
{
|
|
107
154
|
name: 'specrails_select_project',
|
|
108
155
|
title: 'Select active project',
|
|
109
|
-
description: 'Set
|
|
156
|
+
description: 'Set this MCP session\'s active project so per-project tools may omit projectId. Pass an id or path, or null to clear. A mission\'s project pin is controlled by the conversation UI; this tool cannot override it.',
|
|
110
157
|
tier: 'read',
|
|
111
158
|
inputSchema: {
|
|
112
159
|
projectId: zod_1.z.string().nullable().optional().describe('Project id to make active, or null to clear'),
|
|
113
160
|
path: zod_1.z.string().optional().describe('Resolve+select a project by filesystem path instead of id'),
|
|
114
161
|
},
|
|
115
162
|
handler: (ctx, args) => {
|
|
116
|
-
if (args.path)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (args.projectId
|
|
124
|
-
(
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
const id = args.projectId;
|
|
128
|
-
if (!id)
|
|
163
|
+
if (args.path !== undefined && args.projectId !== undefined)
|
|
164
|
+
throw new Error('Provide either path or projectId, not both.');
|
|
165
|
+
const project = args.path
|
|
166
|
+
? ctx.registry.listProjects().find(p => node_path_1.default.resolve(p.path) === node_path_1.default.resolve(String(args.path)))
|
|
167
|
+
: typeof args.projectId === 'string' ? ctx.registry.getProjectRow(args.projectId) : undefined;
|
|
168
|
+
if (args.path && !project)
|
|
169
|
+
throw new Error(`No project registered at path "${args.path}".`);
|
|
170
|
+
if (args.projectId && !project)
|
|
171
|
+
throw new Error(`Unknown projectId "${args.projectId}".`);
|
|
172
|
+
if (!project && args.projectId !== null)
|
|
129
173
|
throw new Error('Provide a projectId, a path, or null.');
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
174
|
+
const id = project?.id ?? null;
|
|
175
|
+
if (ctx.requestProjectId !== undefined && ctx.requestProjectId !== id) {
|
|
176
|
+
throw new Error('This mission uses its conversation project pin. Change the pin in the mission UI, or pass projectId explicitly for an intentional cross-project operation; selecting a default here cannot change the pin.');
|
|
177
|
+
}
|
|
178
|
+
(0, types_1.setActiveProject)(ctx, id);
|
|
179
|
+
return project ? { active: id, name: project.name, available: !!ctx.registry.getContext(project.id) } : { active: null };
|
|
133
180
|
},
|
|
134
181
|
},
|
|
135
182
|
];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.missionTools = missionTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
function missionTools() {
|
|
6
|
+
return [{
|
|
7
|
+
name: 'specrails_mission',
|
|
8
|
+
title: 'Mission user updates',
|
|
9
|
+
description: 'First-party mission only: acknowledge authenticated user updates received during the current running turn. For MCP mission_user_updates, read every block, replan, and acknowledge_updates with the exact latest revision in a separate call before invoking other tools. For the initial Mission input ID or native user messages carrying queueId, acknowledge_inputs with those inputIds only after reading them; this records a read receipt and does not release the MCP revision gate. Does not execute, retry or undo any action and cannot change permissions, provider or project pin.',
|
|
10
|
+
tier: 'read',
|
|
11
|
+
inputSchema: {
|
|
12
|
+
action: zod_1.z.enum(['acknowledge_updates', 'acknowledge_inputs']),
|
|
13
|
+
revision: zod_1.z.number().int().positive().max(Number.MAX_SAFE_INTEGER).optional().describe('Required for acknowledge_updates: exact latest revision delivered in mission_user_updates. Never guess; an older acknowledgement cannot release newer messages.'),
|
|
14
|
+
inputIds: zod_1.z.array(zod_1.z.string().min(1).max(200)).min(1).max(50).optional().describe('Required for acknowledge_inputs: exact initial Mission input ID or queueId values from native user messages you have read in this invocation.'),
|
|
15
|
+
},
|
|
16
|
+
handler: (ctx, args) => {
|
|
17
|
+
if (args.action === 'acknowledge_inputs') {
|
|
18
|
+
if (!ctx.firstPartyAgent || !ctx.acknowledgeAgentInputsRead)
|
|
19
|
+
throw new Error('This action requires an active first-party mission turn.');
|
|
20
|
+
return ctx.acknowledgeAgentInputsRead(args.inputIds);
|
|
21
|
+
}
|
|
22
|
+
if (args.action !== 'acknowledge_updates')
|
|
23
|
+
throw new Error(`Unknown action: ${String(args.action)}`);
|
|
24
|
+
if (!ctx.firstPartyAgent || !ctx.acknowledgeAgentUpdates)
|
|
25
|
+
throw new Error('This action requires an active first-party mission turn.');
|
|
26
|
+
return ctx.acknowledgeAgentUpdates(args.revision);
|
|
27
|
+
},
|
|
28
|
+
}];
|
|
29
|
+
}
|
|
@@ -4,12 +4,15 @@ exports.serializeProject = serializeProject;
|
|
|
4
4
|
exports.projectsTools = projectsTools;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const types_1 = require("./types");
|
|
7
|
+
const project_repositories_1 = require("../../project-repositories");
|
|
7
8
|
function serializeProject(p) {
|
|
8
9
|
return {
|
|
9
10
|
id: p.id,
|
|
10
11
|
slug: p.slug,
|
|
11
12
|
name: p.name,
|
|
12
13
|
path: p.path,
|
|
14
|
+
primaryRepositoryId: (0, project_repositories_1.getProjectRepositories)(p).find(repository => repository.isPrimary)?.id,
|
|
15
|
+
repositories: (0, project_repositories_1.getProjectRepositories)(p),
|
|
13
16
|
provider: p.provider,
|
|
14
17
|
providers: p.providers,
|
|
15
18
|
addedAt: p.added_at,
|
|
@@ -34,21 +37,34 @@ function projectsTools() {
|
|
|
34
37
|
const action = args.action;
|
|
35
38
|
switch (action) {
|
|
36
39
|
case 'list':
|
|
37
|
-
return ctx.registry.
|
|
38
|
-
case 'get':
|
|
39
|
-
|
|
40
|
+
return ctx.registry.listProjects().map((p) => ({ ...serializeProject(p), available: !!ctx.registry.getContext(p.id) }));
|
|
41
|
+
case 'get': {
|
|
42
|
+
const id = args.projectId ?? (0, types_1.getActiveProject)(ctx);
|
|
43
|
+
if (!id)
|
|
44
|
+
throw new Error('No project selected. Provide projectId or use specrails_select_project.');
|
|
45
|
+
const p = ctx.registry.getProjectRow(id);
|
|
46
|
+
if (!p)
|
|
47
|
+
throw new Error(`Unknown projectId "${id}".`);
|
|
48
|
+
return { ...serializeProject(p), available: !!ctx.registry.getContext(id) };
|
|
49
|
+
}
|
|
40
50
|
case 'resolve': {
|
|
41
51
|
const p = args.path;
|
|
42
52
|
if (!p)
|
|
43
53
|
throw new Error('resolve requires a "path".');
|
|
44
|
-
const
|
|
45
|
-
|
|
54
|
+
const selected = args.projectId;
|
|
55
|
+
const key = (0, project_repositories_1.repositoryPathKey)((0, project_repositories_1.canonicalRepositoryPath)(p));
|
|
56
|
+
const matches = ctx.registry.listProjects().filter(row => !selected || row.id === selected).flatMap(project => (0, project_repositories_1.getProjectRepositories)(project).filter(repository => (0, project_repositories_1.repositoryPathKey)((0, project_repositories_1.canonicalRepositoryPath)(repository.path)) === key)
|
|
57
|
+
.map(repository => ({ project, repository })));
|
|
58
|
+
if (matches.length > 1)
|
|
59
|
+
return { resolved: false, ambiguous: true, matches: matches.map(({ project, repository }) => ({ projectId: project.id, projectName: project.name, repositoryId: repository.id, repositoryName: repository.name })) };
|
|
60
|
+
const match = matches[0];
|
|
61
|
+
return match ? { ...serializeProject(match.project), repositoryId: match.repository.id, available: !!ctx.registry.getContext(match.project.id) } : { resolved: false };
|
|
46
62
|
}
|
|
47
63
|
case 'unregister': {
|
|
48
64
|
const id = args.projectId;
|
|
49
65
|
if (!id)
|
|
50
66
|
throw new Error('unregister requires a "projectId".');
|
|
51
|
-
if (!ctx.registry.
|
|
67
|
+
if (!ctx.registry.getProjectRow(id))
|
|
52
68
|
throw new Error(`Unknown projectId "${id}".`);
|
|
53
69
|
ctx.registry.removeProject(id);
|
|
54
70
|
return { ok: true, unregistered: id };
|
|
@@ -39,14 +39,14 @@ function railsTools() {
|
|
|
39
39
|
title: 'Rails',
|
|
40
40
|
description: 'List and configure a project\'s rail launch slots, then launch or stop the AI pipeline for a rail. ' +
|
|
41
41
|
'A rail holds assigned ticket IDs plus a mode/profile/engine/name. Rails are DYNAMIC: create_rail adds a new slot (up to 12), so when every rail is busy or holds other work, create a fresh one and proceed — never wait for a slot. ' +
|
|
42
|
-
'
|
|
43
|
-
'Actions: list (rails + active jobs/loop runs), create_rail (add a new rail slot; returns its railIndex), set_tickets (assign ticket IDs), set_profile (default agent profile, null=legacy), ' +
|
|
42
|
+
'Parallel launches normally run in isolated git worktrees; verify the returned isolated flag. Legacy or non-git runs may use shared project files and have no delivery card. ' +
|
|
43
|
+
'Actions: list (rails + active jobs/loop runs), pr_candidates (read compatible open PR targets for railIndex), review_packet (read durable evidence, verification and acceptance capability by prDeliveryId), create_rail (add a new rail slot; returns its railIndex), set_tickets (assign ticket IDs), set_profile (default agent profile, null=legacy), ' +
|
|
44
44
|
'set_engine (provider override, null=primary), set_name (display label, null clears), ' +
|
|
45
45
|
'launch (ai-spawn — spawns the selected installed provider CLI job(s), including Kimi when installed, that WRITE CODE, RUN TESTS, COMMIT, and INCUR TOKEN COST; returns 202 with jobId/jobIds/loopRunIds), ' +
|
|
46
46
|
'launch_all (ai-spawn — launches EVERY rail that has tickets and no active run/uncontinuable pending PR decision, in parallel, using each rail\'s stored mode/engine/profile; returns per-rail outcomes with skip reasons), ' +
|
|
47
47
|
'stop (destructive — kills all active jobs and loop runs for the rail). ' +
|
|
48
48
|
'For on_review tickets with an already-open GitHub PR (including a published pr_ready delivery), launch automatically tries to continue that PR head branch; Jira-linked in_progress tickets can do the same when the PR match is explicit; fresh tickets still start from the project integration branch. ' +
|
|
49
|
-
'When launched from the in-app agent chat without an explicit aiEngine, the engine defaults to your conversation\'s provider (pass aiEngine to override; launch_all always uses each rail\'s stored engine). ' +
|
|
49
|
+
'When launched from the in-app agent chat without an explicit aiEngine, the engine defaults to your conversation\'s provider. On that same provider, an omitted model inherits the conversation model; an explicit model wins (pass aiEngine to override; launch_all always uses each rail\'s stored engine). ' +
|
|
50
50
|
'User-facing naming: call the free-form autonomous mode "Freestyle"; use "freestyle" as the canonical API enum value for that same capability. ' +
|
|
51
51
|
'For small OpenSpec-governed work, recommend "SDD Quick (OpenSpec)" and launch with mode "loop" plus loopId "factory:sdd-quick-openspec"; keep Freestyle for ticket-local implementation-only work. ' +
|
|
52
52
|
'NAMING: railIndex is the 0-BASED internal identity; the dashboard shows rails 1-based ("Rail N" = railIndex N-1). When talking to the user, ALWAYS say "Rail <railIndex + 1>" (or the rail\'s custom name) — results include railLabel with the correct user-facing label.',
|
|
@@ -63,15 +63,18 @@ function railsTools() {
|
|
|
63
63
|
},
|
|
64
64
|
inputSchema: {
|
|
65
65
|
action: zod_1.z
|
|
66
|
-
.enum(['list', 'create_rail', 'set_tickets', 'set_profile', 'set_engine', 'set_name', 'launch', 'launch_all', 'stop'])
|
|
66
|
+
.enum(['list', 'pr_candidates', 'review_packet', 'create_rail', 'set_tickets', 'set_profile', 'set_engine', 'set_name', 'launch', 'launch_all', 'stop'])
|
|
67
67
|
.describe('Operation to perform'),
|
|
68
68
|
projectId: zod_1.z.string().optional().describe('Project id (defaults to the active project)'),
|
|
69
|
+
repositoryIds: zod_1.z.array(zod_1.z.string().min(1)).min(1).max(50).optional().describe('launch only: explicit affected repository memberships for the coordinated run; must include every repository required by the assigned specs. Omission uses the assigned specs\' repository selections.'),
|
|
70
|
+
repositoryId: zod_1.z.string().min(1).optional().describe('review_packet only: member of a grouped delivery to inspect; omission returns the public parent with grouped outcomes.'),
|
|
69
71
|
railIndex: zod_1.z
|
|
70
72
|
.number()
|
|
71
73
|
.int()
|
|
72
74
|
.min(0)
|
|
73
75
|
.optional()
|
|
74
|
-
.describe('Rail slot index, 0-BASED (required
|
|
76
|
+
.describe('Rail slot index, 0-BASED (required except list, create_rail, launch_all and review_packet). The dashboard labels rails 1-based: UI "Rail N" = railIndex N-1.'),
|
|
77
|
+
prDeliveryId: zod_1.z.string().optional().describe('Delivery id returned by list/prDeliveries (required for review_packet)'),
|
|
75
78
|
// set_tickets
|
|
76
79
|
ticketIds: zod_1.z
|
|
77
80
|
.array(zod_1.z.number().int())
|
|
@@ -103,7 +106,7 @@ function railsTools() {
|
|
|
103
106
|
model: zod_1.z
|
|
104
107
|
.string()
|
|
105
108
|
.optional()
|
|
106
|
-
.describe('Model for launch. For Freestyle or loop mode, pass a model string valid for the selected installed provider; Kimi preserves configured model aliases. Freestyle availability is capability-gated by provider.'),
|
|
109
|
+
.describe('Model for launch. Defaults to the launching conversation model when the engine matches; an explicit model wins. For Freestyle or loop mode, pass a model string valid for the selected installed provider; Kimi preserves configured model aliases. Freestyle availability is capability-gated by provider.'),
|
|
107
110
|
interactive: zod_1.z
|
|
108
111
|
.boolean()
|
|
109
112
|
.optional()
|
|
@@ -130,6 +133,10 @@ function railsTools() {
|
|
|
130
133
|
.string()
|
|
131
134
|
.optional()
|
|
132
135
|
.describe('What to change, in the user\'s own words (required with revisionOfDeliveryId). It is injected into the revision run and shown on the updated review packet as "what you asked to change".'),
|
|
136
|
+
baseBranch: zod_1.z
|
|
137
|
+
.string()
|
|
138
|
+
.optional()
|
|
139
|
+
.describe('Local branch to base the isolated worktree on instead of the integration branch (launch). Used to STACK work on a previous delivery\'s branch (the milestone launch chain does this automatically for chunk 2+). Must resolve locally and requires worktree isolation; rejected with invalid_base_branch / base_branch_requires_isolation otherwise.'),
|
|
133
140
|
},
|
|
134
141
|
async handler(ctx, args) {
|
|
135
142
|
const base = `${(0, types_1.projectPath)(ctx, args.projectId)}/rails`;
|
|
@@ -144,6 +151,15 @@ function railsTools() {
|
|
|
144
151
|
switch (action) {
|
|
145
152
|
case 'list':
|
|
146
153
|
return (0, types_1.apiCall)(ctx, 'GET', base);
|
|
154
|
+
case 'pr_candidates':
|
|
155
|
+
return (0, types_1.apiCall)(ctx, 'GET', `${base}/${requireRailIndex()}/pr-candidates`);
|
|
156
|
+
case 'review_packet': {
|
|
157
|
+
if (typeof args.prDeliveryId !== 'string' || !args.prDeliveryId.trim()) {
|
|
158
|
+
throw new Error('review_packet requires "prDeliveryId" from list/prDeliveries.');
|
|
159
|
+
}
|
|
160
|
+
const query = args.repositoryId === undefined ? '' : `?${new URLSearchParams({ repositoryId: args.repositoryId })}`;
|
|
161
|
+
return (0, types_1.apiCall)(ctx, 'GET', `${base}/pr-deliveries/${encodeURIComponent(args.prDeliveryId)}/packet${query}`);
|
|
162
|
+
}
|
|
147
163
|
case 'create_rail': {
|
|
148
164
|
const body = {};
|
|
149
165
|
if (typeof args.name === 'string' && args.name.trim())
|
|
@@ -218,6 +234,10 @@ function railsTools() {
|
|
|
218
234
|
body.reasoning_effort = args.reasoning_effort;
|
|
219
235
|
if (args.targetPrNumber !== undefined)
|
|
220
236
|
body.targetPrNumber = args.targetPrNumber;
|
|
237
|
+
if (args.repositoryIds !== undefined)
|
|
238
|
+
body.repositoryIds = args.repositoryIds;
|
|
239
|
+
if (args.baseBranch !== undefined)
|
|
240
|
+
body.baseBranch = args.baseBranch;
|
|
221
241
|
// Revision of a delivery already awaiting the user's decision: the
|
|
222
242
|
// ONE launch allowed against an undecided delivery. The route
|
|
223
243
|
// re-validates the exemption (must be the rail's active delivery and
|
|
@@ -247,10 +267,16 @@ function railsTools() {
|
|
|
247
267
|
if (body.aiEngine === undefined && defaults.provider) {
|
|
248
268
|
body.aiEngine = defaults.provider;
|
|
249
269
|
}
|
|
270
|
+
if (body.model === undefined && defaults.model && body.aiEngine === defaults.provider) {
|
|
271
|
+
body.model = defaults.model;
|
|
272
|
+
}
|
|
250
273
|
if (body.reasoning_effort === undefined &&
|
|
251
274
|
defaults.reasoningEffort &&
|
|
252
275
|
defaults.provider &&
|
|
253
|
-
body.aiEngine === defaults.provider
|
|
276
|
+
body.aiEngine === defaults.provider &&
|
|
277
|
+
// Effort is model-specific (Astra's ultra is not valid for
|
|
278
|
+
// GPT-5.5). An explicit different model gets its own default.
|
|
279
|
+
(!defaults.model || body.model === defaults.model)) {
|
|
254
280
|
body.reasoning_effort = defaults.reasoningEffort;
|
|
255
281
|
}
|
|
256
282
|
const r = await (0, types_1.apiCall)(ctx, 'POST', `${base}/${railIndex}/launch`, body);
|
|
@@ -277,10 +303,17 @@ function railsTools() {
|
|
|
277
303
|
hint: `Launch accepted (202) on ${railLabel}, but WORKTREE ISOLATION IS UNAVAILABLE because ${why}. The run proceeds on the SHARED working tree and writes changes DIRECTLY into the user's files — there is NO PR-decision/implementation card and NO branch. Do NOT tell the user to look for a PR card; tell them the run writes to their files in place, and explain why. ${fix} When it finishes, the spec parks at on_review — the user accepts it by moving it to Done on the board (the changes are already in their files) or reverts the spec's status (which does NOT undo the file changes).`,
|
|
278
304
|
};
|
|
279
305
|
}
|
|
306
|
+
if (r.isolated !== true) {
|
|
307
|
+
return {
|
|
308
|
+
...r,
|
|
309
|
+
railLabel,
|
|
310
|
+
hint: `Launch accepted (202) on ${railLabel}. The server did not report worktree isolation (the legacy/shared checkout path may be enabled); do not promise a separate branch or delivery card. Read the returned jobId/jobIds with specrails_jobs(get) or use specrails_watch(ref:jobId, kind:"job"); for loopRunIds use kind:"loop_run".`,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
280
313
|
return {
|
|
281
314
|
...r,
|
|
282
315
|
railLabel,
|
|
283
|
-
hint: `Launch accepted (202) on ${railLabel} (isolated worktree, PR flow active) — tell the user it runs on "${railLabel}" (UI labels are 1-based). If the assigned spec is on_review with a matching open PR, including an already-published pr_ready PR, or is Jira-linked in_progress with an explicit PR match, Specrails continues that PR branch automatically; otherwise it starts a fresh branch from the integration branch. The PR-decision card will appear here and on the rail header when it settles. Use specrails_watch
|
|
316
|
+
hint: `Launch accepted (202) on ${railLabel} (isolated worktree, PR flow active) — tell the user it runs on "${railLabel}" (UI labels are 1-based). If the assigned spec is on_review with a matching open PR, including an already-published pr_ready PR, or is Jira-linked in_progress with an explicit PR match, Specrails continues that PR branch automatically; otherwise it starts a fresh branch from the integration branch. The PR-decision card will appear here and on the rail header when it settles. Use specrails_watch(ref:loopRunId, kind:"loop_run") for each returned loopRunId to inspect completion. Rails run for minutes; pass untilMs up to 600000 and re-watch on timeout. Settled does not imply successful delivery: read rails(list) and review_packet for verification and blockers.`,
|
|
284
317
|
};
|
|
285
318
|
}
|
|
286
319
|
case 'launch_all': {
|
|
@@ -332,16 +365,20 @@ function railsTools() {
|
|
|
332
365
|
...(typeof data.jobId === 'string' ? { jobId: data.jobId } : {}),
|
|
333
366
|
...(Array.isArray(data.jobIds) ? { jobIds: data.jobIds } : {}),
|
|
334
367
|
...(Array.isArray(data.loopRunIds) ? { loopRunIds: data.loopRunIds } : {}),
|
|
368
|
+
...(typeof data.isolationUnavailable === 'string' ? { isolationUnavailable: data.isolationUnavailable } : {}),
|
|
369
|
+
...(typeof data.isolationUnavailableDetail === 'string' ? { isolationUnavailableDetail: data.isolationUnavailableDetail } : {}),
|
|
370
|
+
...(typeof data.prDeliveryId === 'string' ? { prDeliveryId: data.prDeliveryId } : {}),
|
|
371
|
+
...(typeof data.isolated === 'boolean' ? { isolated: data.isolated } : {}),
|
|
335
372
|
});
|
|
336
373
|
})
|
|
337
374
|
.catch((err) => {
|
|
338
375
|
// Race-safe: a 409 raised between the snapshot and the launch
|
|
339
376
|
// maps back to its skip reason instead of a hard failure.
|
|
340
377
|
const message = err instanceof Error ? err.message : String(err);
|
|
341
|
-
if (
|
|
378
|
+
if (err instanceof types_1.McpApiError && err.status === 409 && err.code === 'pr_decision_pending') {
|
|
342
379
|
results.push({ railIndex: idx, outcome: 'skipped', reason: 'pr-decision-pending', ticketIds });
|
|
343
380
|
}
|
|
344
|
-
else if (
|
|
381
|
+
else if (err instanceof types_1.McpApiError && err.status === 409 && err.code === 'tickets_in_flight') {
|
|
345
382
|
results.push({ railIndex: idx, outcome: 'skipped', reason: 'tickets-in-flight', ticketIds });
|
|
346
383
|
}
|
|
347
384
|
else {
|
|
@@ -359,7 +396,7 @@ function railsTools() {
|
|
|
359
396
|
return {
|
|
360
397
|
launched, skipped, failed, results,
|
|
361
398
|
hint: launched > 0
|
|
362
|
-
? 'Launches accepted (202) and running
|
|
399
|
+
? 'Launches accepted (202) and running in parallel. Check each result: isolationUnavailable means that rail writes directly into project files and has NO delivery card; explain that limitation. Report the per-rail ids verbatim; progress streams live. Use specrails_watch(kind:"loop_run", ref:loopRunId) or specrails_jobs(get) to inspect completion.'
|
|
363
400
|
: 'No rail was launched — see per-rail reasons. Assign tickets with set_tickets (create_rail if no free rail) and retry.',
|
|
364
401
|
};
|
|
365
402
|
}
|