specrails-desktop 2.30.2 → 2.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -24
- package/client/dist/assets/{ActivityFeedPage-9DZOvIcY.js → ActivityFeedPage-CAhFRUO4.js} +1 -1
- package/client/dist/assets/{AgentBrowserCapture-DqyHbzk7.js → AgentBrowserCapture-Ct4G5lsE.js} +1 -1
- package/client/dist/assets/AgentModeCodePane-DQt9WIvu.js +2 -0
- package/client/dist/assets/{AgentModeJobsPane-CTIHMUKN.js → AgentModeJobsPane-podaJVl9.js} +1 -1
- package/client/dist/assets/AgentsPage-DTZdbW80.js +87 -0
- package/client/dist/assets/AnalyticsPage-BskgGPm0.js +1 -0
- package/client/dist/assets/CodePage-CvtYo1DU.js +2 -0
- package/client/dist/assets/{DesktopAnalyticsPage-CkXUFj3F.js → DesktopAnalyticsPage-Dnf99E8e.js} +1 -1
- package/client/dist/assets/{DocsDialog-PhdCJNVj.js → DocsDialog-DHi36rZ4.js} +1 -1
- package/client/dist/assets/{DocsPage-BY-wDthx.js → DocsPage-DIdVrQz1.js} +1 -1
- package/client/dist/assets/{InteractiveJobComposer-C9I0A4KR.js → InteractiveJobComposer-BHeB2inv.js} +1 -1
- package/client/dist/assets/{JobDetailModal-I_RoQJV4.js → JobDetailModal-CF1SKUHH.js} +1 -1
- package/client/dist/assets/JobDetailPage-De3rY18h.js +1 -0
- package/client/dist/assets/{JobsPage-DcllM4Ip.js → JobsPage-CfAqqJTx.js} +1 -1
- package/client/dist/assets/{LoopBuilderPage-DGm_iuff.js → LoopBuilderPage-DSBMuTb3.js} +2 -2
- package/client/dist/assets/{LoopPreviewModal-BC-TeFdD.js → LoopPreviewModal-B-c37kA0.js} +1 -1
- package/client/dist/assets/LoopsPage-DjnNXdmm.js +1 -0
- package/client/dist/assets/{MinimizedChatsContext-Cs34FPTz.js → MinimizedChatsContext-DIsnQMVz.js} +1 -1
- package/client/dist/assets/PluginsPage-DA5pQ_6u.js +2 -0
- package/client/dist/assets/{ProjectSettingsDialog-nEs-ENrE.js → ProjectSettingsDialog-DA23PSi6.js} +1 -1
- package/client/dist/assets/{TemplatePreviewModal-D4qW-J9B.js → TemplatePreviewModal-Cp7IQ-g2.js} +1 -1
- package/client/dist/assets/TicketDetailModal-BPD2i_0R.js +14 -0
- package/client/dist/assets/{Trans-CPISVji8.js → Trans-cWtExGkC.js} +1 -1
- package/client/dist/assets/addspec-4WmLJmBG.js +1 -0
- package/client/dist/assets/addspec-BRlk8jON.js +1 -0
- package/client/dist/assets/addspec-C7XRejU4.js +1 -0
- package/client/dist/assets/addspec-CHW9xf_X.js +1 -0
- package/client/dist/assets/addspec-DTmRrWrF.js +1 -0
- package/client/dist/assets/addspec-DhmnXER8.js +1 -0
- package/client/dist/assets/addspec-Di41DpYV.js +1 -0
- package/client/dist/assets/addspec-x3mizDxc.js +1 -0
- package/client/dist/assets/agent-BKsuIgIT.js +1 -0
- package/client/dist/assets/agent-Bs9NilfI.js +1 -0
- package/client/dist/assets/agent-C23h684q.js +1 -0
- package/client/dist/assets/agent-CqEjy3Z2.js +1 -0
- package/client/dist/assets/agent-D5DZTks1.js +1 -0
- package/client/dist/assets/agent-DE8hUYPl.js +1 -0
- package/client/dist/assets/agent-DsTuJGSc.js +1 -0
- package/client/dist/assets/agent-DwZM05-x.js +1 -0
- package/client/dist/assets/agents-45GbINfh.js +1 -0
- package/client/dist/assets/agents-BHp0_FQt.js +1 -0
- package/client/dist/assets/agents-Bvyi3y6R.js +1 -0
- package/client/dist/assets/agents-DMKFStHL.js +1 -0
- package/client/dist/assets/agents-DaYcxAr1.js +1 -0
- package/client/dist/assets/agents-IUOgqT5t.js +1 -0
- package/client/dist/assets/agents-ms7TwG16.js +1 -0
- package/client/dist/assets/agents-rzPnqoBR.js +1 -0
- package/client/dist/assets/agentstudio-8TQqBenW.js +1 -0
- package/client/dist/assets/agentstudio-B8Z_mmEX.js +1 -0
- package/client/dist/assets/agentstudio-BZR9YmLs.js +1 -0
- package/client/dist/assets/agentstudio-Bge9pAWb.js +1 -0
- package/client/dist/assets/agentstudio-Bz169Vzt.js +1 -0
- package/client/dist/assets/agentstudio-D6L2jpNi.js +1 -0
- package/client/dist/assets/agentstudio-K2-Z7CL0.js +1 -0
- package/client/dist/assets/agentstudio-Zmgzthv8.js +1 -0
- package/client/dist/assets/analytics-B8Qtptbl.js +1 -0
- package/client/dist/assets/analytics-BHqUazhP.js +1 -0
- package/client/dist/assets/analytics-BPptRY4f.js +1 -0
- package/client/dist/assets/analytics-BxDGOIwf.js +1 -0
- package/client/dist/assets/analytics-C9RaQcE3.js +1 -0
- package/client/dist/assets/analytics-CJIwqrEl.js +1 -0
- package/client/dist/assets/analytics-D_OZdQ9O.js +1 -0
- package/client/dist/assets/analytics-We6lUMI8.js +1 -0
- package/client/dist/assets/builder-3bygQtZi.js +1 -0
- package/client/dist/assets/builder-BiUG9Z5K.js +1 -0
- package/client/dist/assets/builder-CGRz_-zP.js +1 -0
- package/client/dist/assets/builder-CWYPw7Cw.js +1 -0
- package/client/dist/assets/builder-CX1437hF.js +1 -0
- package/client/dist/assets/{builder-CwA4T7gP.js → builder-Cowk9jtL.js} +1 -1
- package/client/dist/assets/builder-DwDexYRE.js +1 -0
- package/client/dist/assets/builder-skfnZ1uC.js +1 -0
- package/client/dist/assets/code-B0O8-p8k.js +1 -0
- package/client/dist/assets/code-B1VLZDhS.js +1 -0
- package/client/dist/assets/code-B86IMAfz.js +1 -0
- package/client/dist/assets/code-Bpj4Ddml.js +1 -0
- package/client/dist/assets/code-BykBZ5-e.js +1 -0
- package/client/dist/assets/code-CHPkOkDS.js +1 -0
- package/client/dist/assets/code-CkUuW4m9.js +1 -0
- package/client/dist/assets/code-cAqaqMTx.js +1 -0
- package/client/dist/assets/{dashboard-Dy2Um-US.js → dashboard-BVq6kRJe.js} +1 -1
- package/client/dist/assets/{dashboard-CHCEkds4.js → dashboard-BaKPPmLH.js} +1 -1
- package/client/dist/assets/{dashboard-CrlTV1ms.js → dashboard-Bm8e4zYG.js} +1 -1
- package/client/dist/assets/{dashboard-WhzOQw1S.js → dashboard-Bt6IesnM.js} +1 -1
- package/client/dist/assets/{dashboard-Cslu_GCH.js → dashboard-C_NQZle_.js} +1 -1
- package/client/dist/assets/{dashboard-DweT3Y4R.js → dashboard-CyZKoGoI.js} +1 -1
- package/client/dist/assets/{dashboard-DUU8-_Rg.js → dashboard-HIUdUBQ0.js} +1 -1
- package/client/dist/assets/{dashboard-Cqmmbh3l.js → dashboard-pm4Mr229.js} +1 -1
- package/client/dist/assets/{dist-js-jwoXo0YD.js → dist-js-BaP-xLOy.js} +1 -1
- package/client/dist/assets/{dist-js-Dj72W6qo.js → dist-js-CLlgOa5a.js} +1 -1
- package/client/dist/assets/format-command-C0D9IPmV.js +1 -0
- package/client/dist/assets/{formatDistanceToNow-ByKli7Q_.js → formatDistanceToNow-DUyzS4rr.js} +1 -1
- package/client/dist/assets/{getTimezoneOffsetInMilliseconds-qrcBaLW1.js → getTimezoneOffsetInMilliseconds-BCIwmmTj.js} +1 -1
- package/client/dist/assets/{i18n-Bf9Ckd10.js → i18n-D21Pr8Sj.js} +2 -2
- package/client/dist/assets/index-BdSDUFnA.css +2 -0
- package/client/dist/assets/index-Ci4-JKDr.js +77 -0
- package/client/dist/assets/{jobs-CVFD8rar.js → jobs-BAls3bWq.js} +1 -1
- package/client/dist/assets/{jobs-DoSaFzAa.js → jobs-B_TeSQxb.js} +1 -1
- package/client/dist/assets/jobs-Bgq-PZkC.js +1 -0
- package/client/dist/assets/jobs-Bpks6doU.js +1 -0
- package/client/dist/assets/jobs-CN_zv4Gr.js +1 -0
- package/client/dist/assets/jobs-DUlWSYq2.js +1 -0
- package/client/dist/assets/{jobs-B-sDHEay.js → jobs-DhxKgWFq.js} +1 -1
- package/client/dist/assets/{jobs-lk1_Dq1U.js → jobs-SwYS2M-B.js} +1 -1
- package/client/dist/assets/nav-BHDiSIVu.js +1 -0
- package/client/dist/assets/nav-CMiYAq4i.js +1 -0
- package/client/dist/assets/nav-CqS7NrDW.js +1 -0
- package/client/dist/assets/nav-D-0M7xfv.js +1 -0
- package/client/dist/assets/nav-D65O6u9I.js +1 -0
- package/client/dist/assets/nav-D_LKYvBr.js +1 -0
- package/client/dist/assets/nav-FDTJmU79.js +1 -0
- package/client/dist/assets/nav-VaB-C4k5.js +1 -0
- package/client/dist/assets/provider-capabilities-BvoExILy.js +1 -0
- package/client/dist/assets/settings-BveOJoaI.js +1 -0
- package/client/dist/assets/settings-Cj1C6F5k.js +1 -0
- package/client/dist/assets/settings-CuVwOpe0.js +1 -0
- package/client/dist/assets/settings-D5X4DfRc.js +1 -0
- package/client/dist/assets/settings-DXwxe-BW.js +1 -0
- package/client/dist/assets/settings-Di81Ba_V.js +1 -0
- package/client/dist/assets/settings-jbLjCYC_.js +1 -0
- package/client/dist/assets/settings-wIZNPFnn.js +1 -0
- package/client/dist/assets/setup-BBiHEO7h.js +1 -0
- package/client/dist/assets/setup-BlTWhNIQ.js +1 -0
- package/client/dist/assets/setup-Bp2L_oiP.js +1 -0
- package/client/dist/assets/setup-CInYXp1-.js +1 -0
- package/client/dist/assets/{setup-CITtPjed.js → setup-CYH3bP6K.js} +1 -1
- package/client/dist/assets/setup-DwcQ921P.js +1 -0
- package/client/dist/assets/setup-PBLjuDSs.js +1 -0
- package/client/dist/assets/setup-bx6FtoBp.js +1 -0
- package/client/dist/assets/{spending-DMnCXy84.js → spending-BCyUxoOI.js} +1 -1
- package/client/dist/assets/{tickets-B8BuAaj5.js → tickets-BL9r1G0e.js} +1 -1
- package/client/dist/assets/{tickets-DpmdE8tv.js → tickets-B_NyHJ8f.js} +1 -1
- package/client/dist/assets/{tickets-B_yh4qQk.js → tickets-BarF1wuG.js} +1 -1
- package/client/dist/assets/{tickets-pAUJkDTu.js → tickets-CclVhpQA.js} +1 -1
- package/client/dist/assets/{tickets-D_yDquEw.js → tickets-CqqOHbli.js} +1 -1
- package/client/dist/assets/{tickets-CFk2n2Or.js → tickets-DCkFSiqt.js} +1 -1
- package/client/dist/assets/{tickets-DQp7JS2R.js → tickets-Djn3ccfT.js} +1 -1
- package/client/dist/assets/{tickets-Bs37scwY.js → tickets-MiHBPsy_.js} +1 -1
- package/client/dist/assets/{useBrowserCaptureSession-CkBJShUw.js → useBrowserCaptureSession-CkVCDzer.js} +1 -1
- package/client/dist/assets/{useDesktop-B4pSBIDd.js → useDesktop-DCP_MHp9.js} +1 -1
- package/client/dist/index.html +25 -24
- package/docs/README.md +7 -3
- package/docs/cli.md +3 -3
- package/docs/codex.md +51 -64
- package/docs/creating-specs.md +36 -4
- package/docs/customizing.md +5 -5
- package/docs/gemini.md +35 -47
- package/docs/getting-started.md +15 -9
- package/docs/guide/de/agents/2-profiles-and-the-balanced-default.md +5 -1
- package/docs/guide/de/agents/4-custom-agents-catalog.md +7 -4
- package/docs/guide/de/getting-started/1-what-is-specrails.md +1 -0
- package/docs/guide/de/getting-started/2-installing-and-first-run.md +1 -0
- package/docs/guide/de/getting-started/4-the-dashboard-tour.md +4 -4
- package/docs/guide/de/integrations/1-ai-providers.md +29 -18
- package/docs/guide/de/integrations/2-plugins.md +3 -3
- package/docs/guide/de/integrations/6-agent-chat.md +8 -1
- package/docs/guide/de/pipeline/1-rails-and-jobs.md +9 -6
- package/docs/guide/de/pipeline/2-the-job-detail-view.md +3 -1
- package/docs/guide/de/pipeline/3-batch-implement-and-multi-feature.md +1 -1
- package/docs/guide/de/pipeline/4-picking-an-engine-per-rail.md +13 -13
- package/docs/guide/de/pipeline/5-the-loop-builder.md +6 -2
- package/docs/guide/de/specs/2-add-spec-quick-mode.md +6 -1
- package/docs/guide/en/agents/2-profiles-and-the-balanced-default.md +7 -1
- package/docs/guide/en/agents/4-custom-agents-catalog.md +17 -4
- package/docs/guide/en/getting-started/1-what-is-specrails.md +2 -1
- package/docs/guide/en/getting-started/2-installing-and-first-run.md +2 -1
- package/docs/guide/en/getting-started/4-the-dashboard-tour.md +5 -5
- package/docs/guide/en/insights/3-code-explorer.md +5 -0
- package/docs/guide/en/integrations/1-ai-providers.md +63 -22
- package/docs/guide/en/integrations/2-plugins.md +3 -3
- package/docs/guide/en/integrations/6-agent-chat.md +14 -2
- package/docs/guide/en/pipeline/1-rails-and-jobs.md +19 -7
- package/docs/guide/en/pipeline/2-the-job-detail-view.md +3 -1
- package/docs/guide/en/pipeline/3-batch-implement-and-multi-feature.md +1 -1
- package/docs/guide/en/pipeline/4-picking-an-engine-per-rail.md +25 -11
- package/docs/guide/en/pipeline/5-the-loop-builder.md +7 -2
- package/docs/guide/en/specs/2-add-spec-quick-mode.md +10 -1
- package/docs/guide/es/agents/2-profiles-and-the-balanced-default.md +5 -1
- package/docs/guide/es/agents/4-custom-agents-catalog.md +7 -4
- package/docs/guide/es/getting-started/1-what-is-specrails.md +1 -0
- package/docs/guide/es/getting-started/2-installing-and-first-run.md +1 -0
- package/docs/guide/es/getting-started/4-the-dashboard-tour.md +4 -4
- package/docs/guide/es/integrations/1-ai-providers.md +30 -18
- package/docs/guide/es/integrations/2-plugins.md +3 -3
- package/docs/guide/es/integrations/6-agent-chat.md +8 -1
- package/docs/guide/es/pipeline/1-rails-and-jobs.md +9 -6
- package/docs/guide/es/pipeline/2-the-job-detail-view.md +3 -1
- package/docs/guide/es/pipeline/3-batch-implement-and-multi-feature.md +1 -1
- package/docs/guide/es/pipeline/4-picking-an-engine-per-rail.md +15 -13
- package/docs/guide/es/pipeline/5-the-loop-builder.md +6 -2
- package/docs/guide/es/specs/2-add-spec-quick-mode.md +6 -1
- package/docs/guide/fr/agents/2-profiles-and-the-balanced-default.md +5 -1
- package/docs/guide/fr/agents/4-custom-agents-catalog.md +7 -4
- package/docs/guide/fr/getting-started/1-what-is-specrails.md +1 -0
- package/docs/guide/fr/getting-started/2-installing-and-first-run.md +1 -0
- package/docs/guide/fr/getting-started/4-the-dashboard-tour.md +4 -4
- package/docs/guide/fr/integrations/1-ai-providers.md +29 -18
- package/docs/guide/fr/integrations/2-plugins.md +3 -3
- package/docs/guide/fr/integrations/6-agent-chat.md +8 -1
- package/docs/guide/fr/pipeline/1-rails-and-jobs.md +9 -6
- package/docs/guide/fr/pipeline/2-the-job-detail-view.md +3 -1
- package/docs/guide/fr/pipeline/3-batch-implement-and-multi-feature.md +1 -1
- package/docs/guide/fr/pipeline/4-picking-an-engine-per-rail.md +15 -13
- package/docs/guide/fr/pipeline/5-the-loop-builder.md +6 -2
- package/docs/guide/fr/specs/2-add-spec-quick-mode.md +6 -1
- package/docs/guide/it/agents/2-profiles-and-the-balanced-default.md +5 -1
- package/docs/guide/it/agents/4-custom-agents-catalog.md +7 -4
- package/docs/guide/it/getting-started/1-what-is-specrails.md +1 -0
- package/docs/guide/it/getting-started/2-installing-and-first-run.md +1 -0
- package/docs/guide/it/getting-started/4-the-dashboard-tour.md +4 -4
- package/docs/guide/it/integrations/1-ai-providers.md +28 -18
- package/docs/guide/it/integrations/2-plugins.md +3 -3
- package/docs/guide/it/integrations/6-agent-chat.md +8 -1
- package/docs/guide/it/pipeline/1-rails-and-jobs.md +9 -6
- package/docs/guide/it/pipeline/2-the-job-detail-view.md +3 -1
- package/docs/guide/it/pipeline/3-batch-implement-and-multi-feature.md +1 -1
- package/docs/guide/it/pipeline/4-picking-an-engine-per-rail.md +13 -13
- package/docs/guide/it/pipeline/5-the-loop-builder.md +6 -2
- package/docs/guide/it/specs/2-add-spec-quick-mode.md +6 -1
- package/docs/guide/ja/agents/2-profiles-and-the-balanced-default.md +6 -1
- package/docs/guide/ja/agents/4-custom-agents-catalog.md +7 -4
- package/docs/guide/ja/getting-started/1-what-is-specrails.md +1 -0
- package/docs/guide/ja/getting-started/2-installing-and-first-run.md +1 -0
- package/docs/guide/ja/getting-started/4-the-dashboard-tour.md +4 -4
- package/docs/guide/ja/integrations/1-ai-providers.md +28 -18
- package/docs/guide/ja/integrations/2-plugins.md +3 -3
- package/docs/guide/ja/integrations/6-agent-chat.md +7 -1
- package/docs/guide/ja/pipeline/1-rails-and-jobs.md +9 -6
- package/docs/guide/ja/pipeline/2-the-job-detail-view.md +3 -1
- package/docs/guide/ja/pipeline/3-batch-implement-and-multi-feature.md +1 -1
- package/docs/guide/ja/pipeline/4-picking-an-engine-per-rail.md +14 -13
- package/docs/guide/ja/pipeline/5-the-loop-builder.md +6 -2
- package/docs/guide/ja/specs/2-add-spec-quick-mode.md +6 -1
- package/docs/guide/pt/agents/2-profiles-and-the-balanced-default.md +5 -1
- package/docs/guide/pt/agents/4-custom-agents-catalog.md +7 -4
- package/docs/guide/pt/getting-started/1-what-is-specrails.md +1 -0
- package/docs/guide/pt/getting-started/2-installing-and-first-run.md +1 -0
- package/docs/guide/pt/getting-started/4-the-dashboard-tour.md +4 -4
- package/docs/guide/pt/integrations/1-ai-providers.md +28 -18
- package/docs/guide/pt/integrations/2-plugins.md +3 -3
- package/docs/guide/pt/integrations/6-agent-chat.md +7 -1
- package/docs/guide/pt/pipeline/1-rails-and-jobs.md +9 -6
- package/docs/guide/pt/pipeline/2-the-job-detail-view.md +2 -1
- package/docs/guide/pt/pipeline/3-batch-implement-and-multi-feature.md +1 -1
- package/docs/guide/pt/pipeline/4-picking-an-engine-per-rail.md +14 -13
- package/docs/guide/pt/pipeline/5-the-loop-builder.md +6 -2
- package/docs/guide/pt/specs/2-add-spec-quick-mode.md +6 -1
- package/docs/guide/zh/agents/2-profiles-and-the-balanced-default.md +4 -1
- package/docs/guide/zh/agents/4-custom-agents-catalog.md +7 -4
- package/docs/guide/zh/getting-started/1-what-is-specrails.md +1 -0
- package/docs/guide/zh/getting-started/2-installing-and-first-run.md +1 -0
- package/docs/guide/zh/getting-started/4-the-dashboard-tour.md +4 -4
- package/docs/guide/zh/integrations/1-ai-providers.md +26 -18
- package/docs/guide/zh/integrations/2-plugins.md +3 -3
- package/docs/guide/zh/integrations/6-agent-chat.md +6 -1
- package/docs/guide/zh/pipeline/1-rails-and-jobs.md +9 -6
- package/docs/guide/zh/pipeline/2-the-job-detail-view.md +2 -1
- package/docs/guide/zh/pipeline/3-batch-implement-and-multi-feature.md +1 -1
- package/docs/guide/zh/pipeline/4-picking-an-engine-per-rail.md +12 -12
- package/docs/guide/zh/pipeline/5-the-loop-builder.md +6 -2
- package/docs/guide/zh/specs/2-add-spec-quick-mode.md +6 -1
- package/docs/internals/README.md +4 -1
- package/docs/internals/adding-a-provider.md +32 -28
- package/docs/internals/api-reference.md +37 -13
- package/docs/internals/architecture.md +5 -5
- package/docs/internals/bundled-framework-build-plan.md +3 -3
- package/docs/internals/code-explorer-story.md +4 -0
- package/docs/internals/configuration.md +17 -5
- package/docs/internals/global-artifacts-alignment-contract.md +1 -1
- package/docs/internals/operations-runbook.md +1 -1
- package/docs/internals/profiles.md +37 -45
- package/docs/internals/project-builder.md +16 -0
- package/docs/kimi.md +291 -0
- package/docs/mcp.md +9 -2
- package/docs/platforms/macos.md +17 -7
- package/docs/platforms/windows.md +9 -4
- package/docs/running-pipelines.md +46 -12
- package/docs/terminal.md +1 -1
- package/docs/tracking-cost.md +25 -6
- package/package.json +4 -2
- package/server/dist/agent-chat-manager.js +74 -32
- package/server/dist/agent-chat-router.js +40 -17
- package/server/dist/agent-cwd-manager.js +14 -7
- package/server/dist/agent-generator.js +69 -85
- package/server/dist/agent-mcp-config.js +17 -11
- package/server/dist/agent-operator-prompt.js +29 -20
- package/server/dist/agent-refine-manager.js +58 -38
- package/server/dist/ai-invocations.js +65 -20
- package/server/dist/attachment-manager.js +49 -15
- package/server/dist/blueprint-chat-manager.js +41 -16
- package/server/dist/blueprint-router.js +40 -6
- package/server/dist/chat-manager.js +165 -89
- package/server/dist/code-explorer-router.js +26 -7
- package/server/dist/contract-refine-runner.js +146 -113
- package/server/dist/core-compat.js +57 -2
- package/server/dist/core-package.js +3 -3
- package/server/dist/core-update-manager.js +17 -1
- package/server/dist/db.js +60 -5
- package/server/dist/desktop-analytics.js +44 -6
- package/server/dist/desktop-router.js +127 -11
- package/server/dist/explore-cwd-manager.js +19 -3
- package/server/dist/feature-flags.js +1 -1
- package/server/dist/file-story-manager.js +3 -3
- package/server/dist/file-summary-generator.js +21 -15
- package/server/dist/file-summary-manager.js +6 -6
- package/server/dist/framework-manager.js +19 -2
- package/server/dist/framework-migration.js +27 -12
- package/server/dist/install-config-path.js +1 -1
- package/server/dist/interactive-job-session.js +8 -6
- package/server/dist/loop-command-catalog.js +27 -10
- package/server/dist/loop-executors.js +59 -27
- package/server/dist/loop-factory.js +2 -2
- package/server/dist/loop-run-manager.js +100 -39
- package/server/dist/loops-router.js +1 -1
- package/server/dist/mcp/guide.js +23 -16
- package/server/dist/mcp/tools/agents.js +47 -41
- package/server/dist/mcp/tools/analytics.js +2 -2
- package/server/dist/mcp/tools/loops.js +2 -2
- package/server/dist/mcp/tools/plugins.js +14 -9
- package/server/dist/mcp/tools/rails.js +12 -13
- package/server/dist/mcp/tools/support.js +1 -1
- package/server/dist/mobile/mobile-router.js +5 -1
- package/server/dist/offline-assemble.js +13 -1
- package/server/dist/path-resolver.js +2 -2
- package/server/dist/plugin-manager.js +391 -106
- package/server/dist/plugins/claude-md-mutation.js +5 -4
- package/server/dist/plugins/drift.js +32 -29
- package/server/dist/plugins/rail-integration.js +13 -2
- package/server/dist/plugins/serena/install.js +25 -17
- package/server/dist/plugins/serena/manifest.js +22 -5
- package/server/dist/plugins/serena/verify.js +46 -16
- package/server/dist/plugins-router.js +59 -8
- package/server/dist/profile-manager.js +148 -36
- package/server/dist/profiles-router.js +311 -82
- package/server/dist/project-registry.js +2 -2
- package/server/dist/project-router-chat.js +17 -8
- package/server/dist/project-router-helpers.js +93 -5
- package/server/dist/project-router-jobs.js +76 -12
- package/server/dist/project-router-loop-runs.js +42 -14
- package/server/dist/project-router-settings.js +31 -10
- package/server/dist/project-router-setup.js +4 -5
- package/server/dist/project-router-spending.js +15 -3
- package/server/dist/project-router-tickets.js +187 -181
- package/server/dist/project-router.js +1 -0
- package/server/dist/proposal-manager.js +125 -85
- package/server/dist/providers/claude-adapter.js +14 -0
- package/server/dist/providers/codex-adapter.js +20 -0
- package/server/dist/providers/gemini-adapter.js +14 -0
- package/server/dist/providers/index.js +18 -1
- package/server/dist/providers/kimi-adapter.js +361 -0
- package/server/dist/providers/kimi-skill-prompt.js +332 -0
- package/server/dist/providers/runtime.js +137 -0
- package/server/dist/queue-manager.js +103 -78
- package/server/dist/rail-isolated-launch.js +1 -1
- package/server/dist/rails-router.js +51 -38
- package/server/dist/result-event.js +5 -0
- package/server/dist/schemas/profile.v1.json +3 -4
- package/server/dist/setup-manager.js +222 -101
- package/server/dist/setup-prerequisites.js +7 -1
- package/server/dist/smash-runner.js +104 -57
- package/server/dist/spawn-lifecycle.js +18 -14
- package/server/dist/spec-launcher-manager.js +66 -54
- package/server/dist/spec-models.js +15 -6
- package/server/dist/spending.js +110 -17
- package/server/dist/util/cli-prompt.js +142 -5
- package/server/dist/util/stream-display.js +46 -0
- package/server/dist/workspace-manager.js +100 -37
- package/server/dist/worktree-manager.js +4 -0
- package/server/dist/worktree-overlay.js +12 -3
- package/client/dist/assets/AgentModeCodePane-BAYyFRmY.js +0 -2
- package/client/dist/assets/AgentsPage-DuyJuaFs.js +0 -86
- package/client/dist/assets/AnalyticsPage-BY7gtCx6.js +0 -1
- package/client/dist/assets/CodePage-vyQr40Vl.js +0 -2
- package/client/dist/assets/JobDetailPage-CU4FEnUC.js +0 -1
- package/client/dist/assets/LoopsPage-SqglnXlp.js +0 -1
- package/client/dist/assets/PluginsPage-B89S8o1a.js +0 -2
- package/client/dist/assets/TicketDetailModal-CI47Dq9E.js +0 -14
- package/client/dist/assets/addspec-BXjvkh5q.js +0 -1
- package/client/dist/assets/addspec-C4bwrmpi.js +0 -1
- package/client/dist/assets/addspec-CArHXUDM.js +0 -1
- package/client/dist/assets/addspec-DTKJcXiR.js +0 -1
- package/client/dist/assets/addspec-DbNBbrha.js +0 -1
- package/client/dist/assets/addspec-Rw8uVBC1.js +0 -1
- package/client/dist/assets/addspec-htHGZHOe.js +0 -1
- package/client/dist/assets/addspec-lr_LP6jk.js +0 -1
- package/client/dist/assets/agent-BABjRt0P.js +0 -1
- package/client/dist/assets/agent-BuUpgqVx.js +0 -1
- package/client/dist/assets/agent-CCDZesgU.js +0 -1
- package/client/dist/assets/agent-CVn64zWH.js +0 -1
- package/client/dist/assets/agent-CWeOny0E.js +0 -1
- package/client/dist/assets/agent-DOysmad_.js +0 -1
- package/client/dist/assets/agent-DSsjTBhn.js +0 -1
- package/client/dist/assets/agent-DlZMxfM9.js +0 -1
- package/client/dist/assets/agents-6ZOJXWVk.js +0 -1
- package/client/dist/assets/agents-BZ0XQKjg.js +0 -1
- package/client/dist/assets/agents-BqWklnHR.js +0 -1
- package/client/dist/assets/agents-Bz-thHkB.js +0 -1
- package/client/dist/assets/agents-CJclElx6.js +0 -1
- package/client/dist/assets/agents-D_l9L0VA.js +0 -1
- package/client/dist/assets/agents-DhG7mg6-.js +0 -1
- package/client/dist/assets/agents-u_C0jPB5.js +0 -1
- package/client/dist/assets/agentstudio-BF19hbXj.js +0 -1
- package/client/dist/assets/agentstudio-BIUe1Im2.js +0 -1
- package/client/dist/assets/agentstudio-BLGvxWBx.js +0 -1
- package/client/dist/assets/agentstudio-D9UKiWTj.js +0 -1
- package/client/dist/assets/agentstudio-Drs37nIM.js +0 -1
- package/client/dist/assets/agentstudio-nEnKkcXM.js +0 -1
- package/client/dist/assets/agentstudio-pyFcSBKy.js +0 -1
- package/client/dist/assets/agentstudio-zfTzQh3U.js +0 -1
- package/client/dist/assets/analytics-BC7mwR4s.js +0 -1
- package/client/dist/assets/analytics-BiNg8edP.js +0 -1
- package/client/dist/assets/analytics-C0s_T2GN.js +0 -1
- package/client/dist/assets/analytics-CdsAPAwZ.js +0 -1
- package/client/dist/assets/analytics-Cr1_q-lC.js +0 -1
- package/client/dist/assets/analytics-DZ8Aoq3I.js +0 -1
- package/client/dist/assets/analytics-IEsKZvpW.js +0 -1
- package/client/dist/assets/analytics-SRPf84OT.js +0 -1
- package/client/dist/assets/builder-BH8Fua-g.js +0 -1
- package/client/dist/assets/builder-BoV7DgKd.js +0 -1
- package/client/dist/assets/builder-Cc_Lf79C.js +0 -1
- package/client/dist/assets/builder-CwZ7Bme2.js +0 -1
- package/client/dist/assets/builder-CxW-JFsR.js +0 -1
- package/client/dist/assets/builder-D94lrV7x.js +0 -1
- package/client/dist/assets/builder-cqHpCyGa.js +0 -1
- package/client/dist/assets/code-76gS0IdL.js +0 -1
- package/client/dist/assets/code-BDXEM4ml.js +0 -1
- package/client/dist/assets/code-C1VwxlML.js +0 -1
- package/client/dist/assets/code-CnMZyJpr.js +0 -1
- package/client/dist/assets/code-D20ef9Cf.js +0 -1
- package/client/dist/assets/code-DdOXaWRY.js +0 -1
- package/client/dist/assets/code-Duohuf9l.js +0 -1
- package/client/dist/assets/code-geHmknB9.js +0 -1
- package/client/dist/assets/format-command-Dfa1o2d-.js +0 -1
- package/client/dist/assets/index-Dh9i4CnN.css +0 -2
- package/client/dist/assets/index-F9r8mWP_.js +0 -76
- package/client/dist/assets/jobs-BCtGfgUA.js +0 -1
- package/client/dist/assets/jobs-BHR_EnDI.js +0 -1
- package/client/dist/assets/jobs-BMbZJjJJ.js +0 -1
- package/client/dist/assets/jobs-DzSIR8V6.js +0 -1
- package/client/dist/assets/nav-BRJBxaGt.js +0 -1
- package/client/dist/assets/nav-CAGKv3_F.js +0 -1
- package/client/dist/assets/nav-CNskRJKQ.js +0 -1
- package/client/dist/assets/nav-DY93irBL.js +0 -1
- package/client/dist/assets/nav-DhjvYgqt.js +0 -1
- package/client/dist/assets/nav-Gb-r4wop.js +0 -1
- package/client/dist/assets/nav-TvumAFD2.js +0 -1
- package/client/dist/assets/nav-myFaXRHD.js +0 -1
- package/client/dist/assets/settings-B0ypw9uw.js +0 -1
- package/client/dist/assets/settings-B9ilOSYO.js +0 -1
- package/client/dist/assets/settings-BqlWHRHA.js +0 -1
- package/client/dist/assets/settings-D8dlqt4d.js +0 -1
- package/client/dist/assets/settings-DAZqjX2a.js +0 -1
- package/client/dist/assets/settings-DRh39v1S.js +0 -1
- package/client/dist/assets/settings-Mj1OJbfd.js +0 -1
- package/client/dist/assets/settings-lRReaSYm.js +0 -1
- package/client/dist/assets/setup-3832BJCo.js +0 -1
- package/client/dist/assets/setup-B8J-gECe.js +0 -1
- package/client/dist/assets/setup-BCIOxVsc.js +0 -1
- package/client/dist/assets/setup-BciLj_tU.js +0 -1
- package/client/dist/assets/setup-CTkE3cfh.js +0 -1
- package/client/dist/assets/setup-ajB4rYm-.js +0 -1
- package/client/dist/assets/setup-xFO1wNl0.js +0 -1
|
@@ -10,26 +10,26 @@ const crypto_1 = require("crypto");
|
|
|
10
10
|
const tree_kill_1 = __importDefault(require("tree-kill"));
|
|
11
11
|
const cli_prompt_1 = require("./util/cli-prompt");
|
|
12
12
|
const providers_1 = require("./providers");
|
|
13
|
+
const runtime_1 = require("./providers/runtime");
|
|
13
14
|
const result_event_1 = require("./result-event");
|
|
14
15
|
const ai_invocations_1 = require("./ai-invocations");
|
|
15
16
|
const process_admission_1 = require("./process-admission");
|
|
16
17
|
const transient_children_1 = require("./transient-children");
|
|
17
|
-
const AGENT_STUDIO_ADAPTER = (0, providers_1.getAdapter)('claude');
|
|
18
18
|
/**
|
|
19
19
|
* Finalise the accumulated adapter events (native cost, or pricing-table
|
|
20
20
|
* estimate when the run was killed before its `result` event) and persist one
|
|
21
21
|
* surface='agent-studio' row. Best-effort — a recording failure is logged, never
|
|
22
22
|
* thrown, so it can never break the generate/test flow.
|
|
23
23
|
*/
|
|
24
|
-
function recordAgentStudioInvocation(ctx, events, status, startedAtIso) {
|
|
24
|
+
function recordAgentStudioInvocation(ctx, adapter, events, status, startedAtIso) {
|
|
25
25
|
try {
|
|
26
|
-
const { result, estimated } = (0, result_event_1.finaliseInvocationResult)(
|
|
27
|
-
fallbackModel:
|
|
26
|
+
const { result, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, events, {
|
|
27
|
+
fallbackModel: adapter.defaultModel(),
|
|
28
28
|
});
|
|
29
29
|
(0, ai_invocations_1.recordInvocation)(ctx.db, {
|
|
30
30
|
id: (0, crypto_1.randomUUID)(),
|
|
31
31
|
project_id: ctx.projectId,
|
|
32
|
-
provider:
|
|
32
|
+
provider: adapter.id,
|
|
33
33
|
surface: 'agent-studio',
|
|
34
34
|
surface_ref_id: ctx.surfaceRefId ?? null,
|
|
35
35
|
status,
|
|
@@ -78,23 +78,37 @@ function escalateKill(child) {
|
|
|
78
78
|
catch { /* already gone */ }
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
+
function studioToolPolicy(adapter) {
|
|
82
|
+
const policies = adapter.capabilities.toolPolicies ?? [];
|
|
83
|
+
if (policies.includes('none'))
|
|
84
|
+
return 'none';
|
|
85
|
+
if (policies.includes('read-only'))
|
|
86
|
+
return 'read-only';
|
|
87
|
+
throw new Error(`provider_tool_policy_unsupported:${adapter.id}`);
|
|
88
|
+
}
|
|
81
89
|
async function generateCustomAgent(cwd, opts) {
|
|
82
90
|
const admission = opts.record
|
|
83
91
|
? (0, process_admission_1.captureProcessAdmission)(opts.record.projectId)
|
|
84
92
|
: (0, process_admission_1.captureProcessAdmission)();
|
|
93
|
+
const adapter = (0, providers_1.getAdapter)(opts.providerId ?? 'claude');
|
|
94
|
+
const providerFrontmatter = adapter.id === 'claude'
|
|
95
|
+
? [
|
|
96
|
+
' - model: one of `sonnet`, `opus`, `haiku`',
|
|
97
|
+
' - color: one of `blue`, `green`, `red`, `yellow`, `purple`, `cyan`',
|
|
98
|
+
' - memory: `project`',
|
|
99
|
+
]
|
|
100
|
+
: [];
|
|
85
101
|
const systemPrompt = [
|
|
86
102
|
'You are a specrails agent-authoring assistant.',
|
|
87
103
|
'',
|
|
88
104
|
'Your task: given a short description of what the user wants, produce a COMPLETE',
|
|
89
105
|
'Markdown file for a specrails custom agent. The file MUST be valid input for',
|
|
90
|
-
|
|
106
|
+
`${adapter.displayName}: YAML frontmatter between \`---\` separators, followed by the agent body.`,
|
|
91
107
|
'',
|
|
92
108
|
'Required frontmatter fields:',
|
|
93
109
|
' - name: the exact agent id (starts with `custom-`, lowercase, kebab-case)',
|
|
94
110
|
' - description: one sentence saying when this agent should run (include tag hints in square brackets)',
|
|
95
|
-
|
|
96
|
-
' - color: one of `blue`, `green`, `red`, `yellow`, `purple`, `cyan`',
|
|
97
|
-
' - memory: `project`',
|
|
111
|
+
...providerFrontmatter,
|
|
98
112
|
'',
|
|
99
113
|
'Body sections (use `#` headings): Identity, Mission, Workflow protocol, Personality.',
|
|
100
114
|
'Personality block: bullet list of tone, risk_tolerance, detail_level, focus_areas.',
|
|
@@ -108,22 +122,17 @@ async function generateCustomAgent(cwd, opts) {
|
|
|
108
122
|
'Description of what it should do:',
|
|
109
123
|
opts.description,
|
|
110
124
|
].join('\n');
|
|
125
|
+
const toolPolicy = studioToolPolicy(adapter);
|
|
111
126
|
return new Promise((resolve, reject) => {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
// intentional: an empty tool list is dropped by some Claude versions
|
|
115
|
-
// and silently restores the default toolkit.
|
|
116
|
-
'--tools',
|
|
117
|
-
'__none__',
|
|
118
|
-
'--output-format',
|
|
119
|
-
'stream-json',
|
|
120
|
-
'--verbose',
|
|
121
|
-
'--append-system-prompt',
|
|
127
|
+
const spawnOptions = {
|
|
128
|
+
prompt: userPrompt,
|
|
122
129
|
systemPrompt,
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
130
|
+
model: adapter.defaultModel(),
|
|
131
|
+
toolPolicy,
|
|
132
|
+
};
|
|
133
|
+
const args = adapter.buildArgs('agent-refine', spawnOptions);
|
|
134
|
+
const child = (0, cli_prompt_1.spawnAiCli)(adapter.binary, args, {
|
|
135
|
+
env: (0, runtime_1.buildProviderEnv)(adapter, spawnOptions),
|
|
127
136
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
128
137
|
cwd,
|
|
129
138
|
});
|
|
@@ -142,7 +151,7 @@ async function generateCustomAgent(cwd, opts) {
|
|
|
142
151
|
settled = true;
|
|
143
152
|
clearTimeout(killer);
|
|
144
153
|
if (record && admission.isCurrent()) {
|
|
145
|
-
recordAgentStudioInvocation(record, adapterEvents, status, startedAt);
|
|
154
|
+
recordAgentStudioInvocation(record, adapter, adapterEvents, status, startedAt);
|
|
146
155
|
}
|
|
147
156
|
complete();
|
|
148
157
|
};
|
|
@@ -154,32 +163,11 @@ async function generateCustomAgent(cwd, opts) {
|
|
|
154
163
|
}, 90_000);
|
|
155
164
|
const reader = (0, readline_1.createInterface)({ input: child.stdout, crlfDelay: Infinity });
|
|
156
165
|
reader.on('line', (line) => {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (ev)
|
|
166
|
+
for (const ev of (0, runtime_1.parseStreamEvents)(adapter, line)) {
|
|
167
|
+
if (record)
|
|
160
168
|
adapterEvents.push(ev);
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
try {
|
|
164
|
-
parsed = JSON.parse(line);
|
|
165
|
-
}
|
|
166
|
-
catch {
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
if (!parsed || typeof parsed !== 'object')
|
|
170
|
-
return;
|
|
171
|
-
// Claude stream-json format: {type:"assistant", message:{content:[{type:"text", text:"..."}]}}
|
|
172
|
-
const p = parsed;
|
|
173
|
-
const message = p.message;
|
|
174
|
-
const content = message?.content;
|
|
175
|
-
if (Array.isArray(content)) {
|
|
176
|
-
for (const block of content) {
|
|
177
|
-
if (block && typeof block === 'object' && block.type === 'text') {
|
|
178
|
-
const text = block.text;
|
|
179
|
-
if (typeof text === 'string')
|
|
180
|
-
collected += text;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
169
|
+
if (ev.kind === 'text-delta')
|
|
170
|
+
collected += ev.text;
|
|
183
171
|
}
|
|
184
172
|
});
|
|
185
173
|
let stderr = '';
|
|
@@ -198,11 +186,11 @@ async function generateCustomAgent(cwd, opts) {
|
|
|
198
186
|
const status = code === 0 && trimmed ? 'success' : 'failed';
|
|
199
187
|
settle(status, () => {
|
|
200
188
|
if (code !== 0) {
|
|
201
|
-
reject(new Error(
|
|
189
|
+
reject(new Error(`${adapter.binary} exited with code ${code}${stderr ? `: ${stderr.slice(-500)}` : ''}`));
|
|
202
190
|
return;
|
|
203
191
|
}
|
|
204
192
|
if (!trimmed) {
|
|
205
|
-
reject(new Error(
|
|
193
|
+
reject(new Error(`${adapter.binary} returned empty output`));
|
|
206
194
|
return;
|
|
207
195
|
}
|
|
208
196
|
resolve(trimmed);
|
|
@@ -226,6 +214,7 @@ async function testCustomAgent(cwd, opts) {
|
|
|
226
214
|
? (0, process_admission_1.captureProcessAdmission)(opts.record.projectId)
|
|
227
215
|
: (0, process_admission_1.captureProcessAdmission)();
|
|
228
216
|
const tokenCeiling = opts.tokenCeiling ?? 4000;
|
|
217
|
+
const adapter = (0, providers_1.getAdapter)(opts.providerId ?? 'claude');
|
|
229
218
|
// Strip YAML frontmatter so we feed only the agent's instructions.
|
|
230
219
|
const body = opts.draftBody.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, '').trim();
|
|
231
220
|
if (!body) {
|
|
@@ -242,21 +231,17 @@ async function testCustomAgent(cwd, opts) {
|
|
|
242
231
|
].join('\n');
|
|
243
232
|
const draftHash = (0, crypto_1.createHash)('sha256').update(opts.draftBody).digest('hex').slice(0, 16);
|
|
244
233
|
const started = Date.now();
|
|
234
|
+
const toolPolicy = studioToolPolicy(adapter);
|
|
245
235
|
return new Promise((resolve, reject) => {
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
// text; it never needs authority over the project it is testing in.
|
|
249
|
-
'--tools',
|
|
250
|
-
'__none__',
|
|
251
|
-
'--output-format',
|
|
252
|
-
'stream-json',
|
|
253
|
-
'--verbose',
|
|
254
|
-
'--append-system-prompt',
|
|
236
|
+
const spawnOptions = {
|
|
237
|
+
prompt: opts.sampleTask,
|
|
255
238
|
systemPrompt,
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
239
|
+
model: adapter.defaultModel(),
|
|
240
|
+
toolPolicy,
|
|
241
|
+
};
|
|
242
|
+
const args = adapter.buildArgs('agent-refine', spawnOptions);
|
|
243
|
+
const child = (0, cli_prompt_1.spawnAiCli)(adapter.binary, args, {
|
|
244
|
+
env: (0, runtime_1.buildProviderEnv)(adapter, spawnOptions),
|
|
260
245
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
261
246
|
cwd,
|
|
262
247
|
});
|
|
@@ -275,6 +260,7 @@ async function testCustomAgent(cwd, opts) {
|
|
|
275
260
|
let msgTokensOut = 0;
|
|
276
261
|
let resultTokensIn;
|
|
277
262
|
let resultTokensOut;
|
|
263
|
+
let sawUsage = false;
|
|
278
264
|
let truncated = false;
|
|
279
265
|
// Accumulate adapter events for cost recording (surface='agent-studio', MED-3).
|
|
280
266
|
const adapterEvents = [];
|
|
@@ -290,7 +276,7 @@ async function testCustomAgent(cwd, opts) {
|
|
|
290
276
|
settled = true;
|
|
291
277
|
clearTimeout(killer);
|
|
292
278
|
if (record && admission.isCurrent()) {
|
|
293
|
-
recordAgentStudioInvocation(record, adapterEvents, status, startedAt);
|
|
279
|
+
recordAgentStudioInvocation(record, adapter, adapterEvents, status, startedAt);
|
|
294
280
|
}
|
|
295
281
|
complete();
|
|
296
282
|
};
|
|
@@ -302,10 +288,11 @@ async function testCustomAgent(cwd, opts) {
|
|
|
302
288
|
}, 120_000);
|
|
303
289
|
const reader = (0, readline_1.createInterface)({ input: child.stdout, crlfDelay: Infinity });
|
|
304
290
|
reader.on('line', (line) => {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
if (ev)
|
|
291
|
+
for (const ev of (0, runtime_1.parseStreamEvents)(adapter, line)) {
|
|
292
|
+
if (record)
|
|
308
293
|
adapterEvents.push(ev);
|
|
294
|
+
if (ev.kind === 'text-delta')
|
|
295
|
+
collected += ev.text;
|
|
309
296
|
}
|
|
310
297
|
let parsed;
|
|
311
298
|
try {
|
|
@@ -317,37 +304,34 @@ async function testCustomAgent(cwd, opts) {
|
|
|
317
304
|
if (!parsed || typeof parsed !== 'object')
|
|
318
305
|
return;
|
|
319
306
|
const p = parsed;
|
|
320
|
-
// Text blocks
|
|
321
307
|
const message = p.message;
|
|
322
|
-
const content = message?.content;
|
|
323
|
-
if (Array.isArray(content)) {
|
|
324
|
-
for (const block of content) {
|
|
325
|
-
if (block && typeof block === 'object' && block.type === 'text') {
|
|
326
|
-
const text = block.text;
|
|
327
|
-
if (typeof text === 'string')
|
|
328
|
-
collected += text;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
308
|
// Usage: the terminal `result` frame carries the cumulative total at the
|
|
333
309
|
// top level; assistant frames carry a per-call `message.usage`. Route each
|
|
334
310
|
// to its own accumulator so they are never double-counted.
|
|
335
311
|
if (p.type === 'result') {
|
|
336
312
|
const usage = p.usage;
|
|
337
313
|
if (usage) {
|
|
338
|
-
if (typeof usage.input_tokens === 'number')
|
|
314
|
+
if (typeof usage.input_tokens === 'number') {
|
|
339
315
|
resultTokensIn = usage.input_tokens;
|
|
340
|
-
|
|
316
|
+
sawUsage = true;
|
|
317
|
+
}
|
|
318
|
+
if (typeof usage.output_tokens === 'number') {
|
|
341
319
|
resultTokensOut = usage.output_tokens;
|
|
320
|
+
sawUsage = true;
|
|
321
|
+
}
|
|
342
322
|
}
|
|
343
323
|
}
|
|
344
324
|
else {
|
|
345
325
|
const usage = message?.usage;
|
|
346
326
|
if (usage) {
|
|
347
|
-
if (typeof usage.input_tokens === 'number')
|
|
327
|
+
if (typeof usage.input_tokens === 'number') {
|
|
348
328
|
msgTokensIn += usage.input_tokens;
|
|
349
|
-
|
|
329
|
+
sawUsage = true;
|
|
330
|
+
}
|
|
331
|
+
if (typeof usage.output_tokens === 'number') {
|
|
350
332
|
msgTokensOut += usage.output_tokens;
|
|
333
|
+
sawUsage = true;
|
|
334
|
+
}
|
|
351
335
|
}
|
|
352
336
|
}
|
|
353
337
|
// Enforce token ceiling on the corrected running total.
|
|
@@ -373,14 +357,14 @@ async function testCustomAgent(cwd, opts) {
|
|
|
373
357
|
const status = truncated ? 'aborted' : failedHard ? 'failed' : 'success';
|
|
374
358
|
settle(status, () => {
|
|
375
359
|
if (failedHard) {
|
|
376
|
-
reject(new Error(
|
|
360
|
+
reject(new Error(`${adapter.binary} exited with code ${code}${stderr ? `: ${stderr.slice(-500)}` : ''}`));
|
|
377
361
|
return;
|
|
378
362
|
}
|
|
379
363
|
resolve({
|
|
380
364
|
output: truncated
|
|
381
365
|
? collected + `\n\n[… output truncated after reaching ${tokenCeiling}-token ceiling]`
|
|
382
366
|
: collected,
|
|
383
|
-
tokens: runningTotalTokens(),
|
|
367
|
+
tokens: sawUsage ? runningTotalTokens() : null,
|
|
384
368
|
durationMs,
|
|
385
369
|
draftHash,
|
|
386
370
|
});
|
|
@@ -17,6 +17,7 @@ const crypto_1 = require("crypto");
|
|
|
17
17
|
const path_resolver_1 = require("./path-resolver");
|
|
18
18
|
const win_spawn_1 = require("./util/win-spawn");
|
|
19
19
|
const agent_tier_1 = require("./agent-tier");
|
|
20
|
+
const providers_1 = require("./providers");
|
|
20
21
|
const AGENT_CONVERSATION_ID_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;
|
|
21
22
|
// ─── Agent MCP wiring (design D8 / D1) ────────────────────────────────────────
|
|
22
23
|
//
|
|
@@ -101,11 +102,12 @@ function buildSpecrailsMcpEntry(opts) {
|
|
|
101
102
|
* Additive + idempotent: preserves any existing (e.g. plugin) mcpServers entries,
|
|
102
103
|
* writes atomically (temp + rename), inlines NO token. Returns true when written.
|
|
103
104
|
*/
|
|
104
|
-
function mergeSpecrailsIntoWorkspaceMcp(workspaceDir, port) {
|
|
105
|
+
function mergeSpecrailsIntoWorkspaceMcp(workspaceDir, port, providerId = 'claude') {
|
|
105
106
|
const entry = buildSpecrailsMcpEntry({ port });
|
|
106
107
|
if (!entry)
|
|
107
108
|
return false;
|
|
108
|
-
const
|
|
109
|
+
const adapter = (0, providers_1.getAdapter)(providerId);
|
|
110
|
+
const file = adapter.projectMcpPath?.(workspaceDir) ?? path_1.default.join(workspaceDir, '.mcp.json');
|
|
109
111
|
let current = {};
|
|
110
112
|
try {
|
|
111
113
|
if (fs_1.default.existsSync(file)) {
|
|
@@ -121,7 +123,7 @@ function mergeSpecrailsIntoWorkspaceMcp(workspaceDir, port) {
|
|
|
121
123
|
const mcpServers = { ...(current.mcpServers ?? {}), specrails: entry };
|
|
122
124
|
const next = { ...current, mcpServers };
|
|
123
125
|
const tmp = `${file}.tmp-${process.pid}`;
|
|
124
|
-
fs_1.default.mkdirSync(
|
|
126
|
+
fs_1.default.mkdirSync(path_1.default.dirname(file), { recursive: true });
|
|
125
127
|
fs_1.default.writeFileSync(tmp, JSON.stringify(next, null, 2));
|
|
126
128
|
fs_1.default.renameSync(tmp, file);
|
|
127
129
|
return true;
|
|
@@ -232,20 +234,22 @@ function codexMcpOverrides(entry) {
|
|
|
232
234
|
* (agent then runs tool-less / degraded).
|
|
233
235
|
*/
|
|
234
236
|
function prepareAgentMcp(opts) {
|
|
235
|
-
|
|
237
|
+
const adapter = (0, providers_1.getAdapter)(opts.adapterId);
|
|
238
|
+
if (adapter.id === 'claude') {
|
|
236
239
|
return { extraArgs: buildAgentMcpArgs(opts), env: {} };
|
|
237
240
|
}
|
|
238
241
|
const entry = buildAgentTurnEntry(opts);
|
|
239
242
|
if (!entry)
|
|
240
243
|
return { extraArgs: [], env: {} };
|
|
241
|
-
if (
|
|
244
|
+
if (adapter.mcpRegistration === 'cli-add') {
|
|
242
245
|
// Inline -c overrides contain only the capability FILE PATH, never its secret.
|
|
243
246
|
return { extraArgs: codexMcpOverrides(entry), env: {} };
|
|
244
247
|
}
|
|
245
|
-
//
|
|
246
|
-
|
|
248
|
+
// Project-json providers write only their native project config in the
|
|
249
|
+
// conversation-isolated cwd.
|
|
250
|
+
const file = adapter.projectMcpPath?.(opts.cwd) ?? path_1.default.join(opts.cwd, '.mcp.json');
|
|
247
251
|
mergeServerIntoJsonFile(file, entry);
|
|
248
|
-
if (
|
|
252
|
+
if (adapter.id === 'gemini') {
|
|
249
253
|
// gemini-cli has NEVER read .mcp.json (a Claude convention) — its only MCP
|
|
250
254
|
// surface is `mcpServers` in settings.json (user or <cwd>/.gemini project
|
|
251
255
|
// scope), and an UNTRUSTED cwd suppresses MCP entirely (headless run exits
|
|
@@ -254,9 +258,6 @@ function prepareAgentMcp(opts) {
|
|
|
254
258
|
// via env — the same pattern every other gemini spawn path already uses
|
|
255
259
|
// (chat-manager / queue-manager / cli-prompt). Verified empirically against
|
|
256
260
|
// gemini-cli 0.49.0 (see docs/internals note on FQN tool prefixing).
|
|
257
|
-
const geminiDir = path_1.default.join(opts.cwd, '.gemini');
|
|
258
|
-
fs_1.default.mkdirSync(geminiDir, { recursive: true });
|
|
259
|
-
mergeServerIntoJsonFile(path_1.default.join(geminiDir, 'settings.json'), entry);
|
|
260
261
|
return { extraArgs: [], env: { GEMINI_CLI_TRUST_WORKSPACE: 'true' } };
|
|
261
262
|
}
|
|
262
263
|
return { extraArgs: [], env: {} };
|
|
@@ -278,5 +279,10 @@ function mergeServerIntoJsonFile(file, entry) {
|
|
|
278
279
|
current = {};
|
|
279
280
|
}
|
|
280
281
|
const next = { ...current, mcpServers: { ...(current.mcpServers ?? {}), specrails: entry } };
|
|
282
|
+
fs_1.default.mkdirSync(path_1.default.dirname(file), { recursive: true, mode: 0o700 });
|
|
281
283
|
fs_1.default.writeFileSync(file, JSON.stringify(next, null, 2), { mode: 0o600 });
|
|
284
|
+
try {
|
|
285
|
+
fs_1.default.chmodSync(file, 0o600);
|
|
286
|
+
}
|
|
287
|
+
catch { /* best-effort */ }
|
|
282
288
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// ─── Single source of truth for the in-app operator agent prompts ─────────────
|
|
3
|
-
// OPERATOR_INSTRUCTIONS is the CANONICAL prompt
|
|
4
|
-
// GEMINI.md in ~/.specrails/agent-cwd
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
3
|
+
// OPERATOR_INSTRUCTIONS is the CANONICAL prompt written to CLAUDE.md,
|
|
4
|
+
// AGENTS.md, and GEMINI.md in ~/.specrails/agent-cwd/. Kimi's native
|
|
5
|
+
// instructions path is nested under `.kimi-code`, where its per-conversation
|
|
6
|
+
// MCP config also lives; AgentChatManager therefore folds
|
|
7
|
+
// OPERATOR_SYSTEM_PROMPT into Kimi's effective user turn instead of duplicating
|
|
8
|
+
// the prompt in that native file. Claude receives the compact distillation via
|
|
9
|
+
// --system-prompt (it REPLACES the CLI's default system prompt — keep it), while
|
|
10
|
+
// Codex and Gemini auto-load their app-owned instruction files.
|
|
8
11
|
//
|
|
9
12
|
// BYTE-STABILITY CONTRACT: both constants must stay static (no timestamps, no
|
|
10
13
|
// interpolation, no live data) so Anthropic prompt caching hits on turns 2+.
|
|
@@ -39,10 +42,10 @@ coding pipelines over them.
|
|
|
39
42
|
(one pipeline job — Architect → Developer → Reviewer → Ship — over the rail's
|
|
40
43
|
tickets), \`batch-implement\` (dependency-aware waves), Freestyle (API mode
|
|
41
44
|
value \`freestyle\` only — call it \`Freestyle\` in prose; it sends a free-form
|
|
42
|
-
autonomous prompt straight to
|
|
43
|
-
optional interactive in-job chat), \`loop\` (runs a saved
|
|
44
|
-
ticket). Launching spawns AI CLI processes that WRITE
|
|
45
|
-
COMMIT in the repo — it costs money and runs for minutes.
|
|
45
|
+
autonomous prompt straight to a capable provider, one job per ticket; Claude
|
|
46
|
+
also supports optional interactive in-job chat), \`loop\` (runs a saved
|
|
47
|
+
workflow graph per ticket). Launching spawns AI CLI processes that WRITE
|
|
48
|
+
CODE, RUN TESTS and COMMIT in the repo — it costs money and runs for minutes.
|
|
46
49
|
- **Job** — one spawned run. Outcomes mutate spec status AUTOMATICALLY: launch →
|
|
47
50
|
\`in_progress\`; success → \`done\`; revert → back to \`todo\`; partial confidence →
|
|
48
51
|
\`done\` + \`needs_review\`. NEVER patch a status the pipeline manages; only
|
|
@@ -51,11 +54,13 @@ coding pipelines over them.
|
|
|
51
54
|
publish with \`specrails_loops\`; RUN it with
|
|
52
55
|
\`specrails_rails(launch, mode:'loop', loopId)\`.
|
|
53
56
|
- **Profile** — per-project agent-chain config (which agents, which models,
|
|
54
|
-
routing). Claude
|
|
55
|
-
- **Provider / engine** — claude, codex or
|
|
56
|
-
more; AI-spawning actions may pick any installed one. Claude
|
|
57
|
-
profiles
|
|
58
|
-
|
|
57
|
+
routing). Supported by Claude and Kimi; forced to null on Codex/Gemini rails.
|
|
58
|
+
- **Provider / engine** — claude, codex, gemini or kimi. A project installs one
|
|
59
|
+
or more; AI-spawning actions may pick any installed one. Claude and Kimi
|
|
60
|
+
support profiles and Freestyle; Contract Refine and SMASH require Claude's
|
|
61
|
+
structured-action boundary. Persistent interactive jobs remain Claude-only.
|
|
62
|
+
Cost is authoritative on Claude, estimated (~) on Codex/Gemini, and
|
|
63
|
+
unavailable when Kimi does not report it.
|
|
59
64
|
|
|
60
65
|
## How to work
|
|
61
66
|
|
|
@@ -214,7 +219,8 @@ those through \`specrails_support\` instead.
|
|
|
214
219
|
Only when the user hands you finished text and wants it untouched; otherwise
|
|
215
220
|
prefer \`commit_draft\`.
|
|
216
221
|
- **Big features**: offer SMASH (\`specrails_specs(smash)\`) to split an epic
|
|
217
|
-
into children
|
|
222
|
+
into children when the effective provider supports structured actions
|
|
223
|
+
(currently Claude). **Recurring work**: offer a loop.
|
|
218
224
|
|
|
219
225
|
## Spec refinement mode (super specs)
|
|
220
226
|
|
|
@@ -335,8 +341,9 @@ summary later.
|
|
|
335
341
|
spec lands, one short background AI pass appends a \`## Contract Layer\`
|
|
336
342
|
section (naming contract, data shapes, state machine, invariants, file touch
|
|
337
343
|
list). Pass \`contractRefine: false\` to skip it when the user declined it or
|
|
338
|
-
wants zero AI spend.
|
|
339
|
-
|
|
344
|
+
wants zero AI spend. It requires a structured-action provider (currently
|
|
345
|
+
Claude), respects the app-wide kill switch, and leaves the spec unenriched when
|
|
346
|
+
it cannot run.
|
|
340
347
|
- The enrichment is asynchronous: the commit returns immediately and the
|
|
341
348
|
ticket updates in place when the Contract Layer arrives. To re-fire it
|
|
342
349
|
later, use \`specrails_specs(contract_refine, id)\` — it also works on
|
|
@@ -394,7 +401,8 @@ summary later.
|
|
|
394
401
|
never quote the raw railIndex as the rail's name.
|
|
395
402
|
- Configure then launch: \`specrails_rails(set_tickets, railIndex, ticketIds)\` →
|
|
396
403
|
\`specrails_rails(launch, railIndex, mode, …)\`. Setting a profile and then
|
|
397
|
-
switching the rail's engine to
|
|
404
|
+
switching the rail's engine to a provider without profile support
|
|
405
|
+
(Codex/Gemini) silently drops the profile.
|
|
398
406
|
- When relaunching an \`on_review\` spec that already has an OPEN GitHub PR,
|
|
399
407
|
\`launch\` automatically tries to continue that PR's head branch (matched by
|
|
400
408
|
Jira key / spec id / title) instead of starting from the integration branch.
|
|
@@ -503,8 +511,9 @@ summary later.
|
|
|
503
511
|
spec's status (done / reverted to todo / done with the needs-review flag —
|
|
504
512
|
these are pipeline-managed; do not "fix" them yourself), duration, and cost —
|
|
505
513
|
prefix the cost with \`~\` when the provider reports an estimate
|
|
506
|
-
(
|
|
507
|
-
|
|
514
|
+
(Codex/Gemini); say cost is unavailable when Kimi reports none. Offer the
|
|
515
|
+
Analytics page for detail. On failure, report the failure faithfully and
|
|
516
|
+
offer the diagnostic export.
|
|
508
517
|
|
|
509
518
|
## Stance
|
|
510
519
|
|