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
|
@@ -26,6 +26,22 @@ const path_resolver_1 = require("./path-resolver");
|
|
|
26
26
|
function nodeInterpreter() {
|
|
27
27
|
return (0, path_resolver_1.resolveBundledNodeExe)() ?? process.execPath;
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolve symlinks in the CLI path we pass as the child's argv[1]. Core's
|
|
31
|
+
* cli.js auto-run guard compares import.meta.url (realpathed by Node's ESM
|
|
32
|
+
* loader) against pathToFileURL(process.argv[1]) — a symlinked argv[1] (e.g.
|
|
33
|
+
* a staging dir under macOS /var/folders) makes them differ, so main() never
|
|
34
|
+
* runs and the child exits 0 as a silent no-op. Realpathing here keeps the
|
|
35
|
+
* guard true regardless of where the core package lives.
|
|
36
|
+
*/
|
|
37
|
+
function realpathOrSelf(p) {
|
|
38
|
+
try {
|
|
39
|
+
return fs_1.default.realpathSync(p);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return p;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
29
45
|
/** `~/.specrails/framework` — same home as the registry. */
|
|
30
46
|
function frameworkRoot(home) {
|
|
31
47
|
return path_1.default.join((0, artifact_registry_1.resolveHome)(home), '.specrails', 'framework');
|
|
@@ -121,9 +137,10 @@ class FrameworkManager {
|
|
|
121
137
|
resolveCli() {
|
|
122
138
|
if (this.coreRoot) {
|
|
123
139
|
const cli = path_1.default.join(this.coreRoot, 'dist', 'installer', 'cli.js');
|
|
124
|
-
return fs_1.default.existsSync(cli) ? cli : null;
|
|
140
|
+
return fs_1.default.existsSync(cli) ? realpathOrSelf(cli) : null;
|
|
125
141
|
}
|
|
126
|
-
|
|
142
|
+
const bundled = (0, bundled_core_1.getBundledCoreCli)();
|
|
143
|
+
return bundled ? realpathOrSelf(bundled) : null;
|
|
127
144
|
}
|
|
128
145
|
/** True when a usable core (override or bundled) is present (else methods no-op). */
|
|
129
146
|
isAvailable() {
|
|
@@ -11,16 +11,30 @@ const path_1 = __importDefault(require("path"));
|
|
|
11
11
|
const framework_manager_1 = require("./framework-manager");
|
|
12
12
|
const workspace_manager_1 = require("./workspace-manager");
|
|
13
13
|
const artifact_registry_1 = require("./artifact-registry");
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
const providers_1 = require("./providers");
|
|
15
|
+
/** Whole-directory shared subtrees for the legacy providers. `agent-memory` is
|
|
16
|
+
* intentionally absent — it is real per-workspace state, never compared/linked. */
|
|
16
17
|
const SHARED_SUBTREES = ['commands', 'agents', 'skills', 'rules'];
|
|
18
|
+
/**
|
|
19
|
+
* Roots that core assembles as whole-directory framework links.
|
|
20
|
+
*
|
|
21
|
+
* Kimi is intentionally special: `.kimi-code/skills` remains a REAL directory
|
|
22
|
+
* and core links only the framework-owned children within it. That merged layout
|
|
23
|
+
* is what lets Kimi keep OpenSpec skills and desktop-authored `custom-*` roles
|
|
24
|
+
* as direct children. Treating the root as a copied shared subtree would back it up,
|
|
25
|
+
* expect a root symlink that core will never create, then revert every launch.
|
|
26
|
+
*/
|
|
27
|
+
function sharedSubtreesFor(provider) {
|
|
28
|
+
return provider === 'kimi' ? ['rules'] : SHARED_SUBTREES;
|
|
29
|
+
}
|
|
17
30
|
/** Map a provider id to its providerDir name (mirrors core). */
|
|
18
31
|
function providerDirFor(provider) {
|
|
19
|
-
|
|
20
|
-
return
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
32
|
+
try {
|
|
33
|
+
return (0, providers_1.getAdapter)(provider).projectDirName;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return '.claude';
|
|
37
|
+
}
|
|
24
38
|
}
|
|
25
39
|
/** sha256 of a file's bytes, or null when unreadable. */
|
|
26
40
|
function hashFile(p) {
|
|
@@ -83,9 +97,9 @@ function isCustomAgent(rel) {
|
|
|
83
97
|
* from (or is missing in) `current` — excluding `custom-*` agents — counts as
|
|
84
98
|
* local divergence.
|
|
85
99
|
*/
|
|
86
|
-
function compareSharedSubtrees(workspaceProviderDir, fwProviderDir) {
|
|
100
|
+
function compareSharedSubtrees(workspaceProviderDir, fwProviderDir, subtrees) {
|
|
87
101
|
let hadSharedSubtree = false;
|
|
88
|
-
for (const sub of
|
|
102
|
+
for (const sub of subtrees) {
|
|
89
103
|
const copyDir = path_1.default.join(workspaceProviderDir, sub);
|
|
90
104
|
if (!isRealDir(copyDir))
|
|
91
105
|
continue;
|
|
@@ -154,15 +168,16 @@ function runMigration(slug, projectPath, provider, fwCurrent, fm, opts) {
|
|
|
154
168
|
const ws = (0, workspace_manager_1.workspacePathFor)(slug, opts.home);
|
|
155
169
|
const wsProviderDir = path_1.default.join(ws, providerDir);
|
|
156
170
|
const fwProviderDir = path_1.default.join(fwCurrent, providerDir);
|
|
171
|
+
const sharedSubtrees = sharedSubtreesFor(provider);
|
|
157
172
|
// Idempotent: if any shared subtree is already a symlink into `current`, the
|
|
158
173
|
// workspace is migrated — no-op.
|
|
159
|
-
for (const sub of
|
|
174
|
+
for (const sub of sharedSubtrees) {
|
|
160
175
|
if (linkResolvesIntoFramework(path_1.default.join(wsProviderDir, sub), fwCurrent)) {
|
|
161
176
|
return { outcome: 'already-symlinked' };
|
|
162
177
|
}
|
|
163
178
|
}
|
|
164
179
|
// Detect the migratable real-copy layout + the local-divergence guard.
|
|
165
|
-
const cmp = compareSharedSubtrees(wsProviderDir, fwProviderDir);
|
|
180
|
+
const cmp = compareSharedSubtrees(wsProviderDir, fwProviderDir, sharedSubtrees);
|
|
166
181
|
if (!cmp.hadSharedSubtree) {
|
|
167
182
|
return { outcome: 'not-a-copy' };
|
|
168
183
|
}
|
|
@@ -172,7 +187,7 @@ function runMigration(slug, projectPath, provider, fwCurrent, fm, opts) {
|
|
|
172
187
|
}
|
|
173
188
|
// ── Backup the copied shared subtrees (never delete). ──────────────────────
|
|
174
189
|
const backedUp = [];
|
|
175
|
-
for (const sub of
|
|
190
|
+
for (const sub of sharedSubtrees) {
|
|
176
191
|
const live = path_1.default.join(wsProviderDir, sub);
|
|
177
192
|
if (!isRealDir(live))
|
|
178
193
|
continue;
|
|
@@ -48,7 +48,7 @@ function isSafeSlug(slug) {
|
|
|
48
48
|
!slug.includes('..'));
|
|
49
49
|
}
|
|
50
50
|
/** True when a provider id is a safe filename segment (registry ids are
|
|
51
|
-
* lowercase-kebab — `claude` / `codex` / `gemini`). */
|
|
51
|
+
* lowercase-kebab — `claude` / `codex` / `gemini` / `kimi`). */
|
|
52
52
|
function isSafeProvider(provider) {
|
|
53
53
|
return typeof provider === 'string' && /^[a-z0-9][a-z0-9-]*$/.test(provider);
|
|
54
54
|
}
|
|
@@ -39,6 +39,7 @@ const explore_stdin_session_1 = require("./explore-stdin-session");
|
|
|
39
39
|
const result_event_1 = require("./result-event");
|
|
40
40
|
const db_1 = require("./db");
|
|
41
41
|
const stream_display_1 = require("./util/stream-display");
|
|
42
|
+
const runtime_1 = require("./providers/runtime");
|
|
42
43
|
/** Claude's stream-json result frames do not carry a turn id. Hash a canonical
|
|
43
44
|
* representation of the real frame instead: an exact/semantic retransmission
|
|
44
45
|
* remains identifiable even after the next stdin turn has been armed, while a
|
|
@@ -443,10 +444,10 @@ class InteractiveJobSession {
|
|
|
443
444
|
if (this._acceptedResultSignatures.has(signature))
|
|
444
445
|
return;
|
|
445
446
|
}
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
-
this._turnEvents.push(
|
|
449
|
-
if (!this._sawModelWork && isModelWorkEvent(
|
|
447
|
+
const adapterEvents = (0, runtime_1.parseStreamEvents)(this._adapter, line);
|
|
448
|
+
for (const adapterEvent of adapterEvents) {
|
|
449
|
+
this._turnEvents.push(adapterEvent);
|
|
450
|
+
if (!this._sawModelWork && isModelWorkEvent(adapterEvent))
|
|
450
451
|
this._sawModelWork = true;
|
|
451
452
|
}
|
|
452
453
|
if (parsed) {
|
|
@@ -476,8 +477,9 @@ class InteractiveJobSession {
|
|
|
476
477
|
}
|
|
477
478
|
else {
|
|
478
479
|
this._persistLog('stdout', line);
|
|
479
|
-
|
|
480
|
-
|
|
480
|
+
const textEvent = adapterEvents.find((event) => event.kind === 'text-delta');
|
|
481
|
+
if (textEvent?.kind === 'text-delta') {
|
|
482
|
+
this._emitLog('stdout', textEvent.text);
|
|
481
483
|
}
|
|
482
484
|
else {
|
|
483
485
|
this._emitLog('stdout', line);
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
* claude `/specrails:<name>`, codex `$<name>` (skill), gemini `/specrails:<name>`.
|
|
9
9
|
* Mirrors QueueManager's rail invocation (`/specrails:implement #1 #2 --yes`).
|
|
10
10
|
* - `template`: a provider-invariant curated prompt (no core coupling).
|
|
11
|
-
* - `native`: a raw autonomous Freestyle command —
|
|
12
|
-
* command; it expands to a self-contained
|
|
11
|
+
* - `native`: a raw autonomous Freestyle command — gated by the provider's
|
|
12
|
+
* Freestyle capability, NOT a slash command; it expands to a self-contained
|
|
13
|
+
* autonomous prompt.
|
|
13
14
|
*
|
|
14
15
|
* Each command declares its TICKET SCOPE:
|
|
15
16
|
* - `all` → one run over ALL the rail's tickets (`#1 #2 #3`). implement, batch.
|
|
@@ -24,6 +25,8 @@ exports.getLoopCommand = getLoopCommand;
|
|
|
24
25
|
exports.expandCommands = expandCommands;
|
|
25
26
|
exports.dominantTicketScope = dominantTicketScope;
|
|
26
27
|
exports.referencesClaudeOnlyCommand = referencesClaudeOnlyCommand;
|
|
28
|
+
exports.referencesUnsupportedProviderCommand = referencesUnsupportedProviderCommand;
|
|
29
|
+
const registry_1 = require("./providers/registry");
|
|
27
30
|
/** The autonomous prompt a `native` command (Freestyle) expands to for the
|
|
28
31
|
* LoopRunManager path. Factory Freestyle loops route to QueueManager's real
|
|
29
32
|
* `_buildFreestylePrompt` instead (phase A); this is the custom-loop fallback. */
|
|
@@ -70,9 +73,9 @@ exports.LOOP_COMMANDS = [
|
|
|
70
73
|
{
|
|
71
74
|
name: 'freestyle',
|
|
72
75
|
label: 'Freestyle',
|
|
73
|
-
description: 'Free-form autonomous per-ticket implementation —
|
|
76
|
+
description: 'Free-form autonomous per-ticket implementation — the selected capable provider receives the spec as a prompt and works it end-to-end with no pipeline. Internal token: {{cmd:freestyle}}.',
|
|
74
77
|
native: true,
|
|
75
|
-
|
|
78
|
+
requiredCapability: 'freestyle',
|
|
76
79
|
ticketScope: 'per-ticket',
|
|
77
80
|
},
|
|
78
81
|
{
|
|
@@ -134,19 +137,19 @@ exports.LOOP_COMMANDS = [
|
|
|
134
137
|
{
|
|
135
138
|
name: 'opsx:ff', label: 'opsx:ff', ticketScope: 'per-ticket',
|
|
136
139
|
description: 'OpenSpec fast-forward: create (or continue) a change and generate all its artifacts (proposal, specs, design, tasks). Native /opsx:ff (claude/gemini) or $opsx:ff (codex).',
|
|
137
|
-
providerNative: { claude: '/opsx:ff', gemini: '/opsx:ff', codex: '$opsx:ff' },
|
|
140
|
+
providerNative: { claude: '/opsx:ff', gemini: '/opsx:ff', codex: '$opsx:ff', kimi: '/skill:openspec-ff-change' },
|
|
138
141
|
template: 'Create or continue an OpenSpec change for the work described next and generate all of its artifacts (proposal, specs, design, and tasks) so it is ready to implement.',
|
|
139
142
|
},
|
|
140
143
|
{
|
|
141
144
|
name: 'opsx:apply', label: 'opsx:apply', ticketScope: 'per-ticket',
|
|
142
145
|
description: 'OpenSpec apply: implement all pending tasks of the active change. Native /opsx:apply (claude/gemini) or $opsx:apply (codex).',
|
|
143
|
-
providerNative: { claude: '/opsx:apply', gemini: '/opsx:apply', codex: '$opsx:apply' },
|
|
146
|
+
providerNative: { claude: '/opsx:apply', gemini: '/opsx:apply', codex: '$opsx:apply', kimi: '/skill:openspec-apply-change' },
|
|
144
147
|
template: 'Implement every pending task of the active OpenSpec change, editing the code as needed and marking each task complete as you finish it.',
|
|
145
148
|
},
|
|
146
149
|
{
|
|
147
150
|
name: 'opsx:verify', label: 'opsx:verify', ticketScope: 'per-ticket',
|
|
148
151
|
description: "OpenSpec verify: check the active change's implementation against its specs/tasks; ends with VERIFICATION: PASS|FAIL. Native /opsx:verify (claude/gemini) or $opsx:verify (codex).",
|
|
149
|
-
providerNative: { claude: '/opsx:verify', gemini: '/opsx:verify', codex: '$opsx:verify' },
|
|
152
|
+
providerNative: { claude: '/opsx:verify', gemini: '/opsx:verify', codex: '$opsx:verify', kimi: '/skill:openspec-verify-change' },
|
|
150
153
|
template: 'Verify the active OpenSpec change: inspect the REAL implementation against its specs, design, and tasks. Finish with exactly `VERIFICATION: PASS` when nothing required is missing, or `VERIFICATION: FAIL — <what is still missing>` otherwise.',
|
|
151
154
|
},
|
|
152
155
|
// ── Merge-resolver (parallel rails: integrate worktree branches back) ───────
|
|
@@ -225,7 +228,11 @@ const CMD_TOKEN_RE = /\{\{\s*cmd:([\w:-]+)\s*\}\}/g;
|
|
|
225
228
|
* identical in shape to the rail's `/specrails:implement #1 #2 --yes`. Codex has
|
|
226
229
|
* no `/namespace:cmd` parser, so it invokes the equivalent `$<name>` skill. */
|
|
227
230
|
function nativeInvocation(coreCommand, provider, ids) {
|
|
228
|
-
const head = provider === 'codex'
|
|
231
|
+
const head = provider === 'codex'
|
|
232
|
+
? `$${coreCommand}`
|
|
233
|
+
: provider === 'kimi'
|
|
234
|
+
? `/skill:specrails-${coreCommand}`
|
|
235
|
+
: `/specrails:${coreCommand}`;
|
|
229
236
|
const tickets = ids.length ? ' ' + ids.map((id) => `#${id}`).join(' ') : '';
|
|
230
237
|
return `${head}${tickets} --yes`;
|
|
231
238
|
}
|
|
@@ -267,10 +274,20 @@ function dominantTicketScope(text) {
|
|
|
267
274
|
}
|
|
268
275
|
return sawPerTicket ? 'per-ticket' : 'per-ticket';
|
|
269
276
|
}
|
|
270
|
-
/**
|
|
277
|
+
/** Legacy helper retained for API compatibility. */
|
|
271
278
|
function referencesClaudeOnlyCommand(text) {
|
|
272
279
|
for (const m of text.matchAll(CMD_TOKEN_RE)) {
|
|
273
|
-
if (COMMANDS_BY_NAME.get(m[1])?.
|
|
280
|
+
if (COMMANDS_BY_NAME.get(m[1])?.requiredCapability === 'freestyle')
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
/** True when a prompt uses a command the selected provider cannot execute. */
|
|
286
|
+
function referencesUnsupportedProviderCommand(text, provider) {
|
|
287
|
+
const capabilities = (0, registry_1.getAdapter)(provider).capabilities;
|
|
288
|
+
for (const m of text.matchAll(CMD_TOKEN_RE)) {
|
|
289
|
+
const required = COMMANDS_BY_NAME.get(m[1])?.requiredCapability;
|
|
290
|
+
if (required && capabilities[required] !== true)
|
|
274
291
|
return true;
|
|
275
292
|
}
|
|
276
293
|
return false;
|
|
@@ -23,6 +23,7 @@ const result_event_1 = require("./result-event");
|
|
|
23
23
|
const loop_decider_1 = require("./loop-decider");
|
|
24
24
|
const rail_isolation_1 = require("./rail-isolation");
|
|
25
25
|
const feature_flags_1 = require("./feature-flags");
|
|
26
|
+
const runtime_1 = require("./providers/runtime");
|
|
26
27
|
// Per-step wall-clock caps so a single hung step can't block the engine's
|
|
27
28
|
// overall deadline check (which only runs between nodes).
|
|
28
29
|
const AI_STEP_TIMEOUT_MS = 15 * 60_000;
|
|
@@ -109,13 +110,10 @@ function aiStepEnv(env, repoDir) {
|
|
|
109
110
|
* no-op under danger-full-access on iteration 1.
|
|
110
111
|
*/
|
|
111
112
|
function aiStepExtraArgs(adapter, cwd, repoDir) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
: adapter.id === 'codex'
|
|
117
|
-
? ['-c', `sandbox_workspace_write.writable_roots=[${JSON.stringify(repoDir)}, ${JSON.stringify(cwd)}]`]
|
|
118
|
-
: undefined;
|
|
113
|
+
if (!repoDir)
|
|
114
|
+
return undefined;
|
|
115
|
+
const args = (0, runtime_1.buildProviderRepoAccessArgs)(adapter, [repoDir, ...(adapter.id === 'codex' ? [cwd] : [])]);
|
|
116
|
+
return args.length > 0 ? args : undefined;
|
|
119
117
|
}
|
|
120
118
|
function createLoopExecutors(opts = {}) {
|
|
121
119
|
const resolveEnv = () => typeof opts.env === 'function' ? opts.env() : opts.env ?? process.env;
|
|
@@ -150,6 +148,14 @@ function createLoopExecutors(opts = {}) {
|
|
|
150
148
|
// agent self-heal on Windows.
|
|
151
149
|
const stepEnv = aiStepEnv(resolveEnv(), repoDir);
|
|
152
150
|
const extraArgs = aiStepExtraArgs(adapter, cwd, repoDir);
|
|
151
|
+
const effectivePrompt = (0, runtime_1.formatProviderCommand)(adapter, prompt, cwd, sessionId ?? undefined);
|
|
152
|
+
const buildOpts = {
|
|
153
|
+
prompt: effectivePrompt,
|
|
154
|
+
model,
|
|
155
|
+
sessionId: sessionId ?? undefined,
|
|
156
|
+
reasoning_effort: effort,
|
|
157
|
+
extraArgs,
|
|
158
|
+
};
|
|
153
159
|
if (repoDir) {
|
|
154
160
|
try {
|
|
155
161
|
(0, workspace_manager_1.ensureFrameworkAgents)(cwd, adapter.projectDirName);
|
|
@@ -169,12 +175,13 @@ function createLoopExecutors(opts = {}) {
|
|
|
169
175
|
// surface the REAL reason (e.g. "You've hit your usage limit") instead of
|
|
170
176
|
// the `stderrTail`, which often holds only an informational line.
|
|
171
177
|
let errorText;
|
|
178
|
+
const wallStartedAt = Date.now();
|
|
172
179
|
const res = await (0, spawn_lifecycle_1.runAiCliInvocation)({
|
|
173
180
|
adapter,
|
|
174
181
|
action,
|
|
175
|
-
buildOpts
|
|
182
|
+
buildOpts,
|
|
176
183
|
cwd,
|
|
177
|
-
env: stepEnv,
|
|
184
|
+
env: (0, runtime_1.buildProviderEnv)(adapter, buildOpts, stepEnv),
|
|
178
185
|
timeoutMs: aiStepTimeoutMs ?? AI_STEP_TIMEOUT_MS,
|
|
179
186
|
onSpawn,
|
|
180
187
|
// Two complementary streams, mirroring QueueManager's contract:
|
|
@@ -194,7 +201,10 @@ function createLoopExecutors(opts = {}) {
|
|
|
194
201
|
errorText = ev.message;
|
|
195
202
|
},
|
|
196
203
|
});
|
|
197
|
-
const failed = res.spawnFailed ||
|
|
204
|
+
const failed = res.spawnFailed ||
|
|
205
|
+
res.timedOut ||
|
|
206
|
+
(res.code != null && res.code !== 0) ||
|
|
207
|
+
errorText !== undefined;
|
|
198
208
|
if (res.spawnFailed) {
|
|
199
209
|
errorText = errorText ?? `failed to spawn "${adapter.binary}" (on PATH?)`;
|
|
200
210
|
const msg = `AI step: ${errorText}`;
|
|
@@ -219,11 +229,24 @@ function createLoopExecutors(opts = {}) {
|
|
|
219
229
|
console.error(`[loop] ${msg}`);
|
|
220
230
|
onLine?.(msg, 'stderr');
|
|
221
231
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
232
|
+
else if (errorText) {
|
|
233
|
+
// A normalized provider error is terminal even if an upstream CLI
|
|
234
|
+
// anomalously reports a clean process exit.
|
|
235
|
+
const msg = `AI step: ${adapter.binary} reported an error — ${errorText}`;
|
|
236
|
+
console.error(`[loop] ${msg}`);
|
|
237
|
+
onLine?.(msg, 'stderr');
|
|
238
|
+
}
|
|
239
|
+
const { result, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, res.events, {
|
|
240
|
+
fallbackModel: model,
|
|
241
|
+
durationMs: Math.max(0, Date.now() - wallStartedAt),
|
|
242
|
+
});
|
|
243
|
+
const tokensIn = result.tokens_in;
|
|
244
|
+
const tokensOut = result.tokens_out;
|
|
245
|
+
const tokensCacheRead = result.tokens_cache_read;
|
|
246
|
+
const tokensCacheCreate = result.tokens_cache_create;
|
|
247
|
+
const tokens = tokensIn === undefined && tokensOut === undefined
|
|
248
|
+
? undefined
|
|
249
|
+
: (tokensIn ?? 0) + (tokensOut ?? 0);
|
|
227
250
|
return {
|
|
228
251
|
text,
|
|
229
252
|
sessionId: res.sessionId ?? undefined,
|
|
@@ -234,7 +257,7 @@ function createLoopExecutors(opts = {}) {
|
|
|
234
257
|
// cache tokens or the claude loop-job token display would inflate. The
|
|
235
258
|
// full cache breakdown is persisted to the ai_invocations row via the
|
|
236
259
|
// structured tokensCacheRead/tokensCacheCreate fields below.
|
|
237
|
-
tokens
|
|
260
|
+
tokens,
|
|
238
261
|
tokensIn,
|
|
239
262
|
tokensOut,
|
|
240
263
|
tokensCacheRead,
|
|
@@ -280,7 +303,7 @@ function createLoopExecutors(opts = {}) {
|
|
|
280
303
|
(0, claude_trust_1.ensureClaudeTrusted)(adapter.id, [cwd, repoDir]);
|
|
281
304
|
}
|
|
282
305
|
catch { /* best-effort */ }
|
|
283
|
-
const
|
|
306
|
+
const buildOpts = {
|
|
284
307
|
// chat-stream feeds the prompt over stdin per-turn, so the argv `prompt`
|
|
285
308
|
// is unused — pass empty to satisfy the shared SpawnOptions shape.
|
|
286
309
|
prompt: '',
|
|
@@ -291,10 +314,11 @@ function createLoopExecutors(opts = {}) {
|
|
|
291
314
|
sessionId: sessionId ?? undefined,
|
|
292
315
|
reasoning_effort: effort,
|
|
293
316
|
extraArgs,
|
|
294
|
-
}
|
|
317
|
+
};
|
|
318
|
+
const args = adapter.buildArgs('chat-stream', buildOpts);
|
|
295
319
|
return {
|
|
296
320
|
adapter,
|
|
297
|
-
spec: { binary: adapter.binary, args, cwd, env: stepEnv },
|
|
321
|
+
spec: { binary: adapter.binary, args, cwd, env: (0, runtime_1.buildProviderEnv)(adapter, buildOpts, stepEnv) },
|
|
298
322
|
// The loop's ai-step timeout bounds the WHOLE step, interactive included.
|
|
299
323
|
stepTimeoutMs: aiStepTimeoutMs ?? AI_STEP_TIMEOUT_MS,
|
|
300
324
|
};
|
|
@@ -309,12 +333,14 @@ function createLoopExecutors(opts = {}) {
|
|
|
309
333
|
const decEnv = repoDir ? { ...baseEnv, SPECRAILS_REPO_DIR: repoDir } : baseEnv;
|
|
310
334
|
// spec-gen is a one-shot, system-prompted invocation (workspace-write on
|
|
311
335
|
// codex, not full-access) — appropriate for a read-only judgment.
|
|
336
|
+
const buildOpts = { prompt: userPrompt, systemPrompt, model, maxTurns: 1, reasoning_effort: effort, toolPolicy: 'read-only' };
|
|
337
|
+
const wallStartedAt = Date.now();
|
|
312
338
|
const res = await (0, spawn_lifecycle_1.runAiCliInvocation)({
|
|
313
339
|
adapter,
|
|
314
340
|
action: 'spec-gen',
|
|
315
|
-
buildOpts
|
|
341
|
+
buildOpts,
|
|
316
342
|
cwd,
|
|
317
|
-
env: decEnv,
|
|
343
|
+
env: (0, runtime_1.buildProviderEnv)(adapter, buildOpts, decEnv),
|
|
318
344
|
timeoutMs: DECIDER_TIMEOUT_MS,
|
|
319
345
|
onSpawn,
|
|
320
346
|
onStdoutLine: onRawLine,
|
|
@@ -322,11 +348,17 @@ function createLoopExecutors(opts = {}) {
|
|
|
322
348
|
text += ev.text; },
|
|
323
349
|
});
|
|
324
350
|
const decision = (0, loop_decider_1.parseDeciderDecision)(text);
|
|
325
|
-
const { result, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, res.events, {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
const
|
|
351
|
+
const { result, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, res.events, {
|
|
352
|
+
fallbackModel: model,
|
|
353
|
+
durationMs: Math.max(0, Date.now() - wallStartedAt),
|
|
354
|
+
});
|
|
355
|
+
const tokensIn = result.tokens_in;
|
|
356
|
+
const tokensOut = result.tokens_out;
|
|
357
|
+
const tokensCacheRead = result.tokens_cache_read;
|
|
358
|
+
const tokensCacheCreate = result.tokens_cache_create;
|
|
359
|
+
const tokens = tokensIn === undefined && tokensOut === undefined
|
|
360
|
+
? undefined
|
|
361
|
+
: (tokensIn ?? 0) + (tokensOut ?? 0);
|
|
330
362
|
return {
|
|
331
363
|
...decision,
|
|
332
364
|
cost: result.total_cost_usd,
|
|
@@ -336,7 +368,7 @@ function createLoopExecutors(opts = {}) {
|
|
|
336
368
|
// cache tokens or the claude loop-job token display would inflate. The
|
|
337
369
|
// full cache breakdown is persisted to the ai_invocations row via the
|
|
338
370
|
// structured tokensCacheRead/tokensCacheCreate fields below.
|
|
339
|
-
tokens
|
|
371
|
+
tokens,
|
|
340
372
|
tokensIn,
|
|
341
373
|
tokensOut,
|
|
342
374
|
tokensCacheRead,
|
|
@@ -42,9 +42,9 @@ exports.FACTORY_LOOPS = [
|
|
|
42
42
|
// with full freedom — no pipeline, it works like a regular coding agent.
|
|
43
43
|
// The id/mode strings are the canonical rail contract.
|
|
44
44
|
name: 'Freestyle',
|
|
45
|
-
description: 'Hands the spec straight to the model with full freedom — no pipeline, it works like a regular coding agent, then verify + refine until green.
|
|
45
|
+
description: 'Hands the spec straight to the model with full freedom — no pipeline, it works like a regular coding agent, then verify + refine until green.',
|
|
46
46
|
mode: 'freestyle',
|
|
47
|
-
|
|
47
|
+
requiredCapability: 'freestyle',
|
|
48
48
|
graph: (0, loop_templates_1.fixLoopGraph)(['{{cmd:freestyle}}'], GREEN_GOAL, FACTORY_MAX_ITERATIONS, FACTORY_LOOP_TIMEOUT_MIN, FACTORY_AI_STEP_TIMEOUT_MIN),
|
|
49
49
|
},
|
|
50
50
|
SDD_QUICK_OPENSPEC_FACTORY,
|