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
|
@@ -8,12 +8,12 @@ exports.CORE_PACKAGE_SPEC = void 0;
|
|
|
8
8
|
* minute it is published — adopting a new major is a deliberate one-line
|
|
9
9
|
* bump here, shipped through the app's own release pipeline.
|
|
10
10
|
*
|
|
11
|
-
* Floor bumped to 4.
|
|
12
|
-
* (`.
|
|
11
|
+
* Floor bumped to 4.12.0 — the version that ships the Kimi provider target
|
|
12
|
+
* (`.kimi-code/` skills + roles). It also changes the `npx` package-spec string,
|
|
13
13
|
* which invalidates any stale `_npx` exec cache that npx would otherwise reuse
|
|
14
14
|
* for the old `^4.6.0` range (so users actually resolve the newer core).
|
|
15
15
|
*
|
|
16
16
|
* `SPECRAILS_CORE_BIN` remains the escape hatch for local/linked builds
|
|
17
17
|
* (see getCoreCommand in setup-manager.ts).
|
|
18
18
|
*/
|
|
19
|
-
exports.CORE_PACKAGE_SPEC = 'specrails-core@^4.
|
|
19
|
+
exports.CORE_PACKAGE_SPEC = 'specrails-core@^4.12.0';
|
|
@@ -116,7 +116,13 @@ class CoreUpdateManager {
|
|
|
116
116
|
}
|
|
117
117
|
this.updating = true;
|
|
118
118
|
this.emit('downloading', { version: requested });
|
|
119
|
-
|
|
119
|
+
// realpath the tmp root: on macOS os.tmpdir() is a symlinked path
|
|
120
|
+
// (/var/folders → /private/var/folders). The staged core's cli.js has an
|
|
121
|
+
// auto-run guard comparing import.meta.url (realpathed by Node's ESM
|
|
122
|
+
// loader) against process.argv[1] (the literal spawn arg) — a symlinked
|
|
123
|
+
// staging path makes them differ, so main() never runs and every
|
|
124
|
+
// install-framework/swap-current child exits 0 as a silent no-op.
|
|
125
|
+
const tmp = fs_1.default.mkdtempSync(path_1.default.join(realTmpDir(), 'core-update-'));
|
|
120
126
|
try {
|
|
121
127
|
this.npmInstallFn(`${exports.CORE_PACKAGE}@${requested}`, tmp);
|
|
122
128
|
const coreRoot = path_1.default.join(tmp, 'node_modules', exports.CORE_PACKAGE);
|
|
@@ -187,6 +193,16 @@ function uniqueProviders(values) {
|
|
|
187
193
|
const out = Array.from(new Set(values.filter((v) => typeof v === 'string' && v.length > 0)));
|
|
188
194
|
return out.length > 0 ? out : ['claude'];
|
|
189
195
|
}
|
|
196
|
+
/** os.tmpdir() with symlinks resolved (macOS /var/folders → /private/var/folders). */
|
|
197
|
+
function realTmpDir() {
|
|
198
|
+
const dir = os_1.default.tmpdir();
|
|
199
|
+
try {
|
|
200
|
+
return fs_1.default.realpathSync(dir);
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
return dir;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
190
206
|
/** GET the latest published version from the npm registry (no npm binary needed). */
|
|
191
207
|
async function fetchLatestFromRegistry() {
|
|
192
208
|
const controller = new AbortController();
|
package/server/dist/db.js
CHANGED
|
@@ -1426,6 +1426,44 @@ const MIGRATIONS = [
|
|
|
1426
1426
|
db.exec(`ALTER TABLE rail_pr_deliveries ADD COLUMN safety_archives TEXT NOT NULL DEFAULT '[]'`);
|
|
1427
1427
|
}
|
|
1428
1428
|
},
|
|
1429
|
+
// Migration 55: Agent Studio history belongs to a provider-native role
|
|
1430
|
+
// catalog. The same logical custom role id can validly exist for Claude and
|
|
1431
|
+
// Kimi in one project; keying history only by agent_name mixed bodies and
|
|
1432
|
+
// version counters across those catalogs. Legacy rows predate provider-aware
|
|
1433
|
+
// Studio and therefore belong to Claude.
|
|
1434
|
+
(db) => {
|
|
1435
|
+
const versionCols = new Set(db.prepare(`PRAGMA table_info(agent_versions)`).all()
|
|
1436
|
+
.map((row) => row.name));
|
|
1437
|
+
if (!versionCols.has('provider')) {
|
|
1438
|
+
db.exec(`
|
|
1439
|
+
ALTER TABLE agent_versions RENAME TO agent_versions_v54;
|
|
1440
|
+
CREATE TABLE agent_versions (
|
|
1441
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1442
|
+
provider TEXT NOT NULL DEFAULT 'claude',
|
|
1443
|
+
agent_name TEXT NOT NULL,
|
|
1444
|
+
version INTEGER NOT NULL,
|
|
1445
|
+
body TEXT NOT NULL,
|
|
1446
|
+
created_at INTEGER NOT NULL,
|
|
1447
|
+
UNIQUE (provider, agent_name, version)
|
|
1448
|
+
);
|
|
1449
|
+
INSERT INTO agent_versions (id, provider, agent_name, version, body, created_at)
|
|
1450
|
+
SELECT id, 'claude', agent_name, version, body, created_at
|
|
1451
|
+
FROM agent_versions_v54;
|
|
1452
|
+
DROP TABLE agent_versions_v54;
|
|
1453
|
+
CREATE INDEX idx_agent_versions_provider_name
|
|
1454
|
+
ON agent_versions(provider, agent_name);
|
|
1455
|
+
`);
|
|
1456
|
+
}
|
|
1457
|
+
const testCols = new Set(db.prepare(`PRAGMA table_info(agent_tests)`).all()
|
|
1458
|
+
.map((row) => row.name));
|
|
1459
|
+
if (!testCols.has('provider')) {
|
|
1460
|
+
db.exec(`ALTER TABLE agent_tests ADD COLUMN provider TEXT NOT NULL DEFAULT 'claude'`);
|
|
1461
|
+
}
|
|
1462
|
+
db.exec(`
|
|
1463
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tests_provider_name
|
|
1464
|
+
ON agent_tests(provider, agent_name)
|
|
1465
|
+
`);
|
|
1466
|
+
},
|
|
1429
1467
|
];
|
|
1430
1468
|
function applyMigrations(db) {
|
|
1431
1469
|
// Ensure the migrations table exists (migration 1 creates it, but we need
|
|
@@ -1624,7 +1662,12 @@ function listJobs(db, opts) {
|
|
|
1624
1662
|
}
|
|
1625
1663
|
function getJob(db, jobId) {
|
|
1626
1664
|
return db
|
|
1627
|
-
.prepare(
|
|
1665
|
+
.prepare(`
|
|
1666
|
+
SELECT jobs.*, jp.profile_name AS profile_name
|
|
1667
|
+
FROM jobs
|
|
1668
|
+
LEFT JOIN job_profiles jp ON jp.job_id = jobs.id
|
|
1669
|
+
WHERE jobs.id = ?
|
|
1670
|
+
`)
|
|
1628
1671
|
.get(jobId);
|
|
1629
1672
|
}
|
|
1630
1673
|
function getJobEvents(db, jobId) {
|
|
@@ -1884,11 +1927,19 @@ function getStats(db) {
|
|
|
1884
1927
|
const costSum = `COALESCE(SUM(total_cost_usd), 0)`;
|
|
1885
1928
|
const estSum = `COALESCE(SUM(CASE WHEN total_cost_usd_estimated = 1 THEN total_cost_usd ELSE 0 END), 0)`;
|
|
1886
1929
|
const costRow = db.prepare(`
|
|
1887
|
-
SELECT
|
|
1930
|
+
SELECT
|
|
1931
|
+
${costSum} as totalCostUsd,
|
|
1932
|
+
${estSum} as estimatedCostUsd,
|
|
1933
|
+
COUNT(total_cost_usd) as pricedRuns,
|
|
1934
|
+
SUM(CASE WHEN total_cost_usd IS NULL THEN 1 ELSE 0 END) as unpricedRuns
|
|
1888
1935
|
FROM ai_invocations
|
|
1889
1936
|
`).get();
|
|
1890
1937
|
const costTodayRow = db.prepare(`
|
|
1891
|
-
SELECT
|
|
1938
|
+
SELECT
|
|
1939
|
+
${costSum} as costToday,
|
|
1940
|
+
${estSum} as estimatedCostToday,
|
|
1941
|
+
COUNT(total_cost_usd) as pricedTodayRuns,
|
|
1942
|
+
SUM(CASE WHEN total_cost_usd IS NULL THEN 1 ELSE 0 END) as unpricedTodayRuns
|
|
1892
1943
|
FROM ai_invocations
|
|
1893
1944
|
WHERE strftime('%Y-%m-%d', started_at) = ?
|
|
1894
1945
|
`).get(today);
|
|
@@ -1900,14 +1951,18 @@ function getStats(db) {
|
|
|
1900
1951
|
costToday: costTodayRow.costToday,
|
|
1901
1952
|
estimatedCostUsd: costRow.estimatedCostUsd,
|
|
1902
1953
|
estimatedCostToday: costTodayRow.estimatedCostToday,
|
|
1954
|
+
pricedRuns: costRow.pricedRuns,
|
|
1955
|
+
unpricedRuns: costRow.unpricedRuns ?? 0,
|
|
1956
|
+
pricedTodayRuns: costTodayRow.pricedTodayRuns,
|
|
1957
|
+
unpricedTodayRuns: costTodayRow.unpricedTodayRuns ?? 0,
|
|
1903
1958
|
avgDurationMs: totalRow.avgDurationMs,
|
|
1904
1959
|
};
|
|
1905
1960
|
}
|
|
1906
1961
|
// ─── Project settings ─────────────────────────────────────────────────────────
|
|
1907
1962
|
/**
|
|
1908
|
-
* Default pre-prompt used by Freestyle
|
|
1963
|
+
* Default pre-prompt used by provider-capable Freestyle rails when the project
|
|
1909
1964
|
* has no per-project override. Freestyle skips the OpenSpec pipeline entirely:
|
|
1910
|
-
* it hands
|
|
1965
|
+
* it hands the selected autonomous provider the spec text plus this instruction and lets it work
|
|
1911
1966
|
* autonomously end-to-end.
|
|
1912
1967
|
*/
|
|
1913
1968
|
exports.DEFAULT_FREESTYLE_PRE_PROMPT = [
|
|
@@ -55,7 +55,9 @@ function queryProjectCost(db, clause, params) {
|
|
|
55
55
|
return db.prepare(`
|
|
56
56
|
SELECT
|
|
57
57
|
COALESCE(SUM(total_cost_usd), 0) as totalCostUsd,
|
|
58
|
-
COALESCE(SUM(CASE WHEN total_cost_usd_estimated = 1 THEN total_cost_usd ELSE 0 END), 0) as estimatedCostUsd
|
|
58
|
+
COALESCE(SUM(CASE WHEN total_cost_usd_estimated = 1 THEN total_cost_usd ELSE 0 END), 0) as estimatedCostUsd,
|
|
59
|
+
COUNT(total_cost_usd) as pricedRuns,
|
|
60
|
+
SUM(CASE WHEN total_cost_usd IS NULL THEN 1 ELSE 0 END) as unpricedRuns
|
|
59
61
|
FROM ai_invocations ${clause}
|
|
60
62
|
`).get(...params);
|
|
61
63
|
}
|
|
@@ -76,6 +78,8 @@ function queryProjectKpi(db, clause, params) {
|
|
|
76
78
|
return {
|
|
77
79
|
totalCostUsd: cost.totalCostUsd,
|
|
78
80
|
estimatedCostUsd: cost.estimatedCostUsd,
|
|
81
|
+
pricedRuns: cost.pricedRuns ?? 0,
|
|
82
|
+
unpricedRuns: cost.unpricedRuns ?? 0,
|
|
79
83
|
totalJobs: counts.totalJobs,
|
|
80
84
|
successCount: counts.successCount ?? 0,
|
|
81
85
|
avgDurationMs: counts.avgDurationMs,
|
|
@@ -110,7 +114,8 @@ function queryProjectTimeline(db, clause, params) {
|
|
|
110
114
|
SELECT
|
|
111
115
|
strftime('%Y-%m-%d', started_at) as date,
|
|
112
116
|
COALESCE(SUM(total_cost_usd), 0) as costUsd,
|
|
113
|
-
COALESCE(SUM(CASE WHEN total_cost_usd_estimated = 1 THEN total_cost_usd ELSE 0 END), 0) as estimatedCostUsd
|
|
117
|
+
COALESCE(SUM(CASE WHEN total_cost_usd_estimated = 1 THEN total_cost_usd ELSE 0 END), 0) as estimatedCostUsd,
|
|
118
|
+
SUM(CASE WHEN total_cost_usd IS NULL THEN 1 ELSE 0 END) as unpricedCount
|
|
114
119
|
FROM ai_invocations ${clause}
|
|
115
120
|
GROUP BY date
|
|
116
121
|
ORDER BY date ASC
|
|
@@ -127,10 +132,14 @@ function getDesktopAnalytics(registry, opts) {
|
|
|
127
132
|
const contexts = registry.listContexts();
|
|
128
133
|
let totalCostUsd = 0;
|
|
129
134
|
let estimatedCostUsd = 0;
|
|
135
|
+
let pricedRuns = 0;
|
|
136
|
+
let unpricedRuns = 0;
|
|
130
137
|
let totalJobs = 0;
|
|
131
138
|
let totalSuccess = 0;
|
|
132
139
|
let costToday = 0;
|
|
133
140
|
let estimatedCostToday = 0;
|
|
141
|
+
let pricedTodayRuns = 0;
|
|
142
|
+
let unpricedTodayRuns = 0;
|
|
134
143
|
let jobsToday = 0;
|
|
135
144
|
const projectBreakdown = [];
|
|
136
145
|
const timelineMap = new Map();
|
|
@@ -141,24 +150,31 @@ function getDesktopAnalytics(registry, opts) {
|
|
|
141
150
|
const timeline = queryProjectTimeline(ctx.db, clause, params);
|
|
142
151
|
totalCostUsd += kpi.totalCostUsd;
|
|
143
152
|
estimatedCostUsd += kpi.estimatedCostUsd;
|
|
153
|
+
pricedRuns += kpi.pricedRuns;
|
|
154
|
+
unpricedRuns += kpi.unpricedRuns;
|
|
144
155
|
totalJobs += kpi.totalJobs;
|
|
145
156
|
totalSuccess += kpi.successCount;
|
|
146
157
|
costToday += todayKpi.totalCostUsd;
|
|
147
158
|
estimatedCostToday += todayKpi.estimatedCostUsd;
|
|
159
|
+
pricedTodayRuns += todayKpi.pricedRuns;
|
|
160
|
+
unpricedTodayRuns += todayKpi.unpricedRuns;
|
|
148
161
|
jobsToday += todayKpi.totalJobs;
|
|
149
162
|
projectBreakdown.push({
|
|
150
163
|
projectId: ctx.project.id,
|
|
151
164
|
projectName: ctx.project.name,
|
|
152
165
|
totalCostUsd: kpi.totalCostUsd,
|
|
153
166
|
estimatedCostUsd: kpi.estimatedCostUsd,
|
|
167
|
+
pricedRuns: kpi.pricedRuns,
|
|
168
|
+
unpricedRuns: kpi.unpricedRuns,
|
|
154
169
|
totalJobs: kpi.totalJobs,
|
|
155
170
|
successRate: kpi.totalJobs > 0 ? kpi.successCount / kpi.totalJobs : 0,
|
|
156
171
|
avgDurationMs: kpi.avgDurationMs,
|
|
157
172
|
});
|
|
158
173
|
for (const row of timeline) {
|
|
159
|
-
const acc = timelineMap.get(row.date) ?? { costUsd: 0, estimatedCostUsd: 0 };
|
|
174
|
+
const acc = timelineMap.get(row.date) ?? { costUsd: 0, estimatedCostUsd: 0, unpricedCount: 0 };
|
|
160
175
|
acc.costUsd += row.costUsd;
|
|
161
176
|
acc.estimatedCostUsd += row.estimatedCostUsd;
|
|
177
|
+
acc.unpricedCount += row.unpricedCount ?? 0;
|
|
162
178
|
timelineMap.set(row.date, acc);
|
|
163
179
|
}
|
|
164
180
|
}
|
|
@@ -170,7 +186,12 @@ function getDesktopAnalytics(registry, opts) {
|
|
|
170
186
|
// Build sorted cost timeline
|
|
171
187
|
const costTimeline = Array.from(timelineMap.entries())
|
|
172
188
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
173
|
-
.map(([date, v]) => ({
|
|
189
|
+
.map(([date, v]) => ({
|
|
190
|
+
date,
|
|
191
|
+
costUsd: v.costUsd,
|
|
192
|
+
estimatedCostUsd: v.estimatedCostUsd,
|
|
193
|
+
...(v.unpricedCount > 0 ? { unpricedCount: v.unpricedCount } : {}),
|
|
194
|
+
}));
|
|
174
195
|
// Sort projects by cost descending
|
|
175
196
|
projectBreakdown.sort((a, b) => b.totalCostUsd - a.totalCostUsd);
|
|
176
197
|
return {
|
|
@@ -179,10 +200,14 @@ function getDesktopAnalytics(registry, opts) {
|
|
|
179
200
|
totalCostUsd,
|
|
180
201
|
estimatedCostUsd,
|
|
181
202
|
includesEstimated: estimatedCostUsd > 0,
|
|
203
|
+
pricedRuns,
|
|
204
|
+
unpricedRuns,
|
|
182
205
|
totalJobs,
|
|
183
206
|
successRate: totalJobs > 0 ? totalSuccess / totalJobs : 0,
|
|
184
207
|
costToday,
|
|
185
208
|
estimatedCostToday,
|
|
209
|
+
pricedTodayRuns,
|
|
210
|
+
unpricedTodayRuns,
|
|
186
211
|
jobsToday,
|
|
187
212
|
},
|
|
188
213
|
projectBreakdown,
|
|
@@ -221,11 +246,15 @@ function getDesktopTodayStats(registry) {
|
|
|
221
246
|
let costToday = 0;
|
|
222
247
|
let estimatedCostToday = 0;
|
|
223
248
|
let jobsToday = 0;
|
|
249
|
+
let pricedRuns = 0;
|
|
250
|
+
let unpricedRuns = 0;
|
|
224
251
|
for (const ctx of registry.listContexts()) {
|
|
225
252
|
const costRow = ctx.db.prepare(`
|
|
226
253
|
SELECT
|
|
227
254
|
COALESCE(SUM(total_cost_usd), 0) as costToday,
|
|
228
|
-
COALESCE(SUM(CASE WHEN total_cost_usd_estimated = 1 THEN total_cost_usd ELSE 0 END), 0) as estimatedCostToday
|
|
255
|
+
COALESCE(SUM(CASE WHEN total_cost_usd_estimated = 1 THEN total_cost_usd ELSE 0 END), 0) as estimatedCostToday,
|
|
256
|
+
COUNT(total_cost_usd) as pricedRuns,
|
|
257
|
+
SUM(CASE WHEN total_cost_usd IS NULL THEN 1 ELSE 0 END) as unpricedRuns
|
|
229
258
|
FROM ai_invocations ${clause}
|
|
230
259
|
`).get(...params);
|
|
231
260
|
const jobsRow = ctx.db.prepare(`
|
|
@@ -233,9 +262,18 @@ function getDesktopTodayStats(registry) {
|
|
|
233
262
|
`).get(...params);
|
|
234
263
|
costToday += costRow.costToday;
|
|
235
264
|
estimatedCostToday += costRow.estimatedCostToday;
|
|
265
|
+
pricedRuns += costRow.pricedRuns;
|
|
266
|
+
unpricedRuns += costRow.unpricedRuns ?? 0;
|
|
236
267
|
jobsToday += jobsRow.jobsToday;
|
|
237
268
|
}
|
|
238
269
|
// App-level agent-chat spend (desktop.sqlite), added to the headline figure.
|
|
239
270
|
costToday += agentCostSince(registry, today);
|
|
240
|
-
return {
|
|
271
|
+
return {
|
|
272
|
+
costToday,
|
|
273
|
+
estimatedCostToday,
|
|
274
|
+
includesEstimated: estimatedCostToday > 0,
|
|
275
|
+
jobsToday,
|
|
276
|
+
pricedRuns,
|
|
277
|
+
unpricedRuns,
|
|
278
|
+
};
|
|
241
279
|
}
|
|
@@ -107,9 +107,74 @@ function hasCommandFiles(dir) {
|
|
|
107
107
|
return false;
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
|
+
function hasProviderSkillFiles(dir) {
|
|
111
|
+
try {
|
|
112
|
+
for (const entry of fs_1.default.readdirSync(dir)) {
|
|
113
|
+
if (fs_1.default.existsSync(path_1.default.join(dir, entry, 'SKILL.md')))
|
|
114
|
+
return true;
|
|
115
|
+
if (entry === 'rails') {
|
|
116
|
+
for (const role of fs_1.default.readdirSync(path_1.default.join(dir, entry))) {
|
|
117
|
+
if (fs_1.default.existsSync(path_1.default.join(dir, entry, role, 'SKILL.md')))
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
110
128
|
function hasSpecrails(projectPath) {
|
|
111
129
|
return hasCommandFiles(path_1.default.join(projectPath, '.claude', 'commands', 'sr'))
|
|
112
|
-
|| hasCommandFiles(path_1.default.join(projectPath, '.claude', 'commands', 'specrails'))
|
|
130
|
+
|| hasCommandFiles(path_1.default.join(projectPath, '.claude', 'commands', 'specrails'))
|
|
131
|
+
|| hasProviderSkillFiles(path_1.default.join(projectPath, '.kimi-code', 'skills'));
|
|
132
|
+
}
|
|
133
|
+
function readinessIssue(adapter, detection) {
|
|
134
|
+
if (!detection.installed) {
|
|
135
|
+
return {
|
|
136
|
+
code: 'provider_cli_missing',
|
|
137
|
+
message: `${adapter.displayName} CLI was not found on PATH. Install it, authenticate, then restart Specrails.`,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
if (!detection.executable) {
|
|
141
|
+
return {
|
|
142
|
+
code: 'provider_cli_unusable',
|
|
143
|
+
message: detection.error
|
|
144
|
+
?? `${adapter.displayName} was found but its executable readiness probe failed. Reinstall it, authenticate, then restart Specrails.`,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
// An adapter with a pinned floor is usable only when the probe positively
|
|
148
|
+
// verifies that floor. Treat an unparseable/unknown version as incompatible;
|
|
149
|
+
// otherwise the UI could advertise a binary that cannot honour our contract.
|
|
150
|
+
if (adapter.minCliVersion && detection.meetsMinimum !== true) {
|
|
151
|
+
return {
|
|
152
|
+
code: 'provider_cli_outdated',
|
|
153
|
+
message: detection.error
|
|
154
|
+
?? `${adapter.displayName} ${detection.version ?? '(unknown version)'} does not satisfy the required minimum ${adapter.minCliVersion}.`,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
async function detectProviderReadiness(adapter) {
|
|
160
|
+
try {
|
|
161
|
+
const detection = await adapter.detectInstalled();
|
|
162
|
+
return { detection, issue: readinessIssue(adapter, detection) };
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
const detection = {
|
|
166
|
+
installed: false,
|
|
167
|
+
executable: false,
|
|
168
|
+
error: err instanceof Error ? err.message : String(err),
|
|
169
|
+
};
|
|
170
|
+
return {
|
|
171
|
+
detection,
|
|
172
|
+
issue: {
|
|
173
|
+
code: 'provider_cli_unusable',
|
|
174
|
+
message: `${adapter.displayName} readiness probe failed: ${detection.error}`,
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
}
|
|
113
178
|
}
|
|
114
179
|
function canonicalizePath(resolvedPath) {
|
|
115
180
|
try {
|
|
@@ -293,12 +358,8 @@ function createDesktopRouter(registry, broadcast) {
|
|
|
293
358
|
// the multi-provider work. The `SPECRAILS_CODEX_BETA=0` env var is honoured
|
|
294
359
|
// as an emergency rollback (forces codex back to "unavailable" in the UI
|
|
295
360
|
// without redeploying) — unset or `1` reports the real detection.
|
|
296
|
-
router.get('/available-providers', (_req, res) => {
|
|
361
|
+
router.get('/available-providers', async (_req, res) => {
|
|
297
362
|
const providers = (0, core_compat_1.detectAvailableCLIs)();
|
|
298
|
-
// tiers: quick install is always available (app-driven config); full requires an AI CLI
|
|
299
|
-
const tiers = ['quick'];
|
|
300
|
-
if (Object.values(providers).some(Boolean))
|
|
301
|
-
tiers.push('full');
|
|
302
363
|
// Return the full detected map (registry-driven) so a newly-registered
|
|
303
364
|
// provider surfaces here with no edit. Apply per-provider beta gates: codex
|
|
304
365
|
// is forced unavailable when SPECRAILS_CODEX_BETA=0 (emergency rollback).
|
|
@@ -309,7 +370,34 @@ function createDesktopRouter(registry, broadcast) {
|
|
|
309
370
|
// SPECRAILS_GEMINI_BETA=0 (emergency rollback, parity with codex).
|
|
310
371
|
if (isGeminiBetaDisabled())
|
|
311
372
|
gated.gemini = false;
|
|
312
|
-
|
|
373
|
+
const providerIssues = {};
|
|
374
|
+
if (gated.kimi) {
|
|
375
|
+
const readiness = await detectProviderReadiness((0, providers_1.getAdapter)('kimi'));
|
|
376
|
+
if (readiness.issue) {
|
|
377
|
+
gated.kimi = false;
|
|
378
|
+
providerIssues.kimi = readiness.issue;
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
const core = await (0, core_compat_1.checkCoreCompat)();
|
|
382
|
+
if (!(0, core_compat_1.coreCompatSupportsProvider)(core, 'kimi')) {
|
|
383
|
+
gated.kimi = false;
|
|
384
|
+
providerIssues.kimi = {
|
|
385
|
+
code: 'core_provider_unsupported',
|
|
386
|
+
message: 'This Specrails Core build cannot render Kimi skills. Update or reinstall Specrails, then retry.',
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
// tiers: quick install is always available (app-driven config); full
|
|
392
|
+
// requires a CLI that also survives provider-specific compatibility gates.
|
|
393
|
+
const tiers = ['quick'];
|
|
394
|
+
if (Object.values(gated).some(Boolean))
|
|
395
|
+
tiers.push('full');
|
|
396
|
+
const launchDescriptors = Object.fromEntries((0, providers_1.listAdapters)().map((adapter) => [
|
|
397
|
+
adapter.id,
|
|
398
|
+
{ command: adapter.binary, args: [] },
|
|
399
|
+
]));
|
|
400
|
+
res.json({ ...gated, tiers, providerIssues, launchDescriptors });
|
|
313
401
|
});
|
|
314
402
|
router.get('/setup-prerequisites', (req, res) => {
|
|
315
403
|
const status = (0, setup_prerequisites_1.getSetupPrerequisitesStatus)();
|
|
@@ -335,7 +423,7 @@ function createDesktopRouter(registry, broadcast) {
|
|
|
335
423
|
res.json(status);
|
|
336
424
|
});
|
|
337
425
|
// POST /api/projects — register a new project by path
|
|
338
|
-
router.post('/projects', (req, res) => {
|
|
426
|
+
router.post('/projects', async (req, res) => {
|
|
339
427
|
const { path: projectPath, name, provider, providers: providersRaw } = req.body ?? {};
|
|
340
428
|
if (!projectPath || typeof projectPath !== 'string') {
|
|
341
429
|
res.status(400).json({ error: 'path is required' });
|
|
@@ -382,6 +470,27 @@ function createDesktopRouter(registry, broadcast) {
|
|
|
382
470
|
});
|
|
383
471
|
return;
|
|
384
472
|
}
|
|
473
|
+
if (providers.includes('kimi')) {
|
|
474
|
+
const readiness = await detectProviderReadiness((0, providers_1.getAdapter)('kimi'));
|
|
475
|
+
if (readiness.issue) {
|
|
476
|
+
res.status(409).json({
|
|
477
|
+
code: readiness.issue.code,
|
|
478
|
+
provider: 'kimi',
|
|
479
|
+
error: readiness.issue.message,
|
|
480
|
+
detection: readiness.detection,
|
|
481
|
+
});
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
const core = await (0, core_compat_1.checkCoreCompat)();
|
|
485
|
+
if (!(0, core_compat_1.coreCompatSupportsProvider)(core, 'kimi')) {
|
|
486
|
+
res.status(409).json({
|
|
487
|
+
code: 'core_provider_unsupported',
|
|
488
|
+
provider: 'kimi',
|
|
489
|
+
error: 'This Specrails Core build cannot render Kimi skills. Update or reinstall Specrails, then retry.',
|
|
490
|
+
});
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
385
494
|
const resolvedPath = path_1.default.resolve(projectPath);
|
|
386
495
|
// Validate path exists
|
|
387
496
|
if (!fs_1.default.existsSync(resolvedPath)) {
|
|
@@ -537,11 +646,18 @@ function createDesktopRouter(registry, broadcast) {
|
|
|
537
646
|
const desktopDailyBudgetUsd = desktopDailyBudgetRaw != null ? parseFloat(desktopDailyBudgetRaw) : null;
|
|
538
647
|
const costAlertRaw = (0, desktop_db_1.getDesktopSetting)(registry.desktopDb, 'cost_alert_threshold_usd');
|
|
539
648
|
const costAlertThresholdUsd = costAlertRaw != null ? parseFloat(costAlertRaw) : null;
|
|
540
|
-
const { costToday } = (0, desktop_analytics_1.getDesktopTodayStats)(registry);
|
|
541
|
-
const budgetUtilizationPct = desktopDailyBudgetUsd != null && desktopDailyBudgetUsd > 0
|
|
649
|
+
const { costToday, pricedRuns, unpricedRuns } = (0, desktop_analytics_1.getDesktopTodayStats)(registry);
|
|
650
|
+
const budgetUtilizationPct = desktopDailyBudgetUsd != null && desktopDailyBudgetUsd > 0 && unpricedRuns === 0
|
|
542
651
|
? (costToday / desktopDailyBudgetUsd) * 100
|
|
543
652
|
: null;
|
|
544
|
-
res.json({
|
|
653
|
+
res.json({
|
|
654
|
+
desktopDailyBudgetUsd,
|
|
655
|
+
costAlertThresholdUsd,
|
|
656
|
+
costToday,
|
|
657
|
+
pricedRuns,
|
|
658
|
+
unpricedRuns,
|
|
659
|
+
budgetUtilizationPct,
|
|
660
|
+
});
|
|
545
661
|
});
|
|
546
662
|
// PATCH /api/budget — update app-level budget settings
|
|
547
663
|
router.patch('/budget', (req, res) => {
|
|
@@ -17,8 +17,9 @@ const providers_1 = require("./providers");
|
|
|
17
17
|
* provider CLI for Explore Spec turns. See openspec/changes/accelerate-spec-
|
|
18
18
|
* chat-first-token/design.md decisions D1–D3 + D9, and openspec/changes/
|
|
19
19
|
* add-multi-provider-support/specs/explore-spec/spec.md for the multi-
|
|
20
|
-
* provider behaviour (instructions
|
|
21
|
-
*
|
|
20
|
+
* provider behaviour (the instructions path is adapter-driven: CLAUDE.md for
|
|
21
|
+
* Claude, AGENTS.md for Codex, GEMINI.md for Gemini, and
|
|
22
|
+
* .kimi-code/AGENTS.md for Kimi).
|
|
22
23
|
*
|
|
23
24
|
* Layout under `<specrails-home>/.specrails/projects/<slug>/explore-cwd/`:
|
|
24
25
|
* ├── <adapter.instructionsFilename> — embedded mini-prompt, app-owned
|
|
@@ -115,6 +116,9 @@ function ensureExploreCwd(input, baseDir) {
|
|
|
115
116
|
fs_1.default.mkdirSync(cwd, { recursive: true });
|
|
116
117
|
const adapter = (0, providers_1.getAdapter)(input.provider ?? 'claude');
|
|
117
118
|
const instructionsPath = path_1.default.join(cwd, adapter.instructionsFilename);
|
|
119
|
+
// Provider instruction paths are project-relative, not necessarily
|
|
120
|
+
// top-level filenames (Kimi uses `.kimi-code/AGENTS.md`).
|
|
121
|
+
fs_1.default.mkdirSync(path_1.default.dirname(instructionsPath), { recursive: true });
|
|
118
122
|
const desiredInstructions = renderExploreInstructions(input.projectName);
|
|
119
123
|
let currentInstructions = null;
|
|
120
124
|
try {
|
|
@@ -130,7 +134,12 @@ function ensureExploreCwd(input, baseDir) {
|
|
|
130
134
|
// — provider is immutable post-creation but the lifecycle code MUST handle
|
|
131
135
|
// the edge per spec), remove any stale instructions file authored by a
|
|
132
136
|
// different provider so the explore-cwd doesn't carry both.
|
|
133
|
-
const STALE_INSTRUCTION_FILES = [
|
|
137
|
+
const STALE_INSTRUCTION_FILES = [
|
|
138
|
+
'CLAUDE.md',
|
|
139
|
+
'AGENTS.md',
|
|
140
|
+
'GEMINI.md',
|
|
141
|
+
path_1.default.join('.kimi-code', 'AGENTS.md'),
|
|
142
|
+
];
|
|
134
143
|
for (const stale of STALE_INSTRUCTION_FILES) {
|
|
135
144
|
if (stale === adapter.instructionsFilename)
|
|
136
145
|
continue;
|
|
@@ -140,6 +149,13 @@ function ensureExploreCwd(input, baseDir) {
|
|
|
140
149
|
fs_1.default.unlinkSync(stalePath);
|
|
141
150
|
}
|
|
142
151
|
catch { /* best-effort */ }
|
|
152
|
+
const staleParent = path_1.default.dirname(stalePath);
|
|
153
|
+
if (staleParent !== cwd) {
|
|
154
|
+
try {
|
|
155
|
+
fs_1.default.rmdirSync(staleParent);
|
|
156
|
+
}
|
|
157
|
+
catch { /* non-empty or already gone */ }
|
|
158
|
+
}
|
|
143
159
|
}
|
|
144
160
|
}
|
|
145
161
|
ensureProjectLink(cwd, input.projectPath);
|
|
@@ -30,7 +30,7 @@ function isJiraEnabled() {
|
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* Interactive freestyle jobs: when launched with the rail's "Interactive"
|
|
33
|
-
* toggle,
|
|
33
|
+
* toggle, a Claude Freestyle job becomes a persistent chat session —
|
|
34
34
|
* the user sends multiple prompts across turns, the job stays resident until an
|
|
35
35
|
* explicit "Finalize Job" action, and every turn's real token spend is summed
|
|
36
36
|
* into the single job row. Server-side default ON; set
|
|
@@ -152,9 +152,9 @@ class FileStoryManager {
|
|
|
152
152
|
started_at: startedIso,
|
|
153
153
|
finished_at: new Date((this.deps.now ?? Date.now)()).toISOString(),
|
|
154
154
|
model: out?.model,
|
|
155
|
-
total_cost_usd: out?.costUsd ??
|
|
156
|
-
tokens_in: out?.tokensIn ??
|
|
157
|
-
tokens_out: out?.tokensOut ??
|
|
155
|
+
total_cost_usd: out?.costUsd ?? undefined,
|
|
156
|
+
tokens_in: out?.tokensIn ?? undefined,
|
|
157
|
+
tokens_out: out?.tokensOut ?? undefined,
|
|
158
158
|
tokens_cache_read: out?.tokensCacheRead,
|
|
159
159
|
tokens_cache_create: out?.tokensCacheCreate,
|
|
160
160
|
duration_ms: out?.durationMs ?? 0,
|
|
@@ -9,6 +9,7 @@ const readline_1 = require("readline");
|
|
|
9
9
|
const tree_kill_1 = __importDefault(require("tree-kill"));
|
|
10
10
|
const cli_prompt_1 = require("./util/cli-prompt");
|
|
11
11
|
const result_event_1 = require("./result-event");
|
|
12
|
+
const runtime_1 = require("./providers/runtime");
|
|
12
13
|
const GENERATE_TIMEOUT_MS = 60_000;
|
|
13
14
|
const SYSTEM_PROMPT_EN = 'You are explaining code to a non-developer. Output 2 to 4 sentences in plain language about what the file does. ' +
|
|
14
15
|
'No code, no jargon, no bullet lists. Output only the explanation, nothing else.';
|
|
@@ -54,14 +55,20 @@ function createFileSummaryGenerator(opts) {
|
|
|
54
55
|
const startedAt = Date.now();
|
|
55
56
|
if (signal?.aborted)
|
|
56
57
|
throw new Error('file-summary generator aborted before start');
|
|
57
|
-
const
|
|
58
|
+
const toolPolicy = (0, runtime_1.pureOutputToolPolicy)(adapter);
|
|
59
|
+
if (!toolPolicy) {
|
|
60
|
+
throw new Error(`provider_tool_policy_unsupported:${adapter.id}:pure-output`);
|
|
61
|
+
}
|
|
62
|
+
const spawnOptions = {
|
|
58
63
|
prompt: buildUserPrompt(input, adapter, systemPromptFor),
|
|
59
64
|
systemPrompt: adapter.capabilities.systemPromptArg ? systemPromptFor(input.language) : undefined,
|
|
60
65
|
model,
|
|
61
66
|
maxTurns: 1,
|
|
62
|
-
|
|
67
|
+
toolPolicy,
|
|
68
|
+
};
|
|
69
|
+
const args = adapter.buildArgs('spec-gen', spawnOptions);
|
|
63
70
|
const child = spawn(adapter.binary, args, {
|
|
64
|
-
env:
|
|
71
|
+
env: (0, runtime_1.buildProviderEnv)(adapter, spawnOptions),
|
|
65
72
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
66
73
|
cwd: opts.cwd,
|
|
67
74
|
});
|
|
@@ -81,10 +88,10 @@ function createFileSummaryGenerator(opts) {
|
|
|
81
88
|
return {
|
|
82
89
|
model: result.model ?? model,
|
|
83
90
|
provider: adapter.id,
|
|
84
|
-
costUsd: result.total_cost_usd ??
|
|
91
|
+
costUsd: result.total_cost_usd ?? null,
|
|
85
92
|
costEstimated: estimated,
|
|
86
|
-
tokensIn: result.tokens_in ??
|
|
87
|
-
tokensOut: result.tokens_out ??
|
|
93
|
+
tokensIn: result.tokens_in ?? null,
|
|
94
|
+
tokensOut: result.tokens_out ?? null,
|
|
88
95
|
tokensCacheRead: result.tokens_cache_read,
|
|
89
96
|
tokensCacheCreate: result.tokens_cache_create,
|
|
90
97
|
durationMs: result.duration_ms ?? (Date.now() - startedAt),
|
|
@@ -159,12 +166,11 @@ function createFileSummaryGenerator(opts) {
|
|
|
159
166
|
}
|
|
160
167
|
const reader = (0, readline_1.createInterface)({ input: child.stdout, crlfDelay: Infinity });
|
|
161
168
|
reader.on('line', (line) => {
|
|
162
|
-
const ev
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
fullText += ev.text;
|
|
169
|
+
for (const ev of (0, runtime_1.parseStreamEvents)(adapter, line)) {
|
|
170
|
+
events.push(ev);
|
|
171
|
+
if (ev.kind === 'text-delta')
|
|
172
|
+
fullText += ev.text;
|
|
173
|
+
}
|
|
168
174
|
});
|
|
169
175
|
child.on('error', (err) => {
|
|
170
176
|
clearTimeout(timer);
|
|
@@ -213,10 +219,10 @@ function createFileSummaryGenerator(opts) {
|
|
|
213
219
|
summary,
|
|
214
220
|
model: result.model ?? model,
|
|
215
221
|
provider: adapter.id,
|
|
216
|
-
costUsd: result.total_cost_usd ??
|
|
222
|
+
costUsd: result.total_cost_usd ?? null,
|
|
217
223
|
costEstimated: estimated,
|
|
218
|
-
tokensIn: result.tokens_in ??
|
|
219
|
-
tokensOut: result.tokens_out ??
|
|
224
|
+
tokensIn: result.tokens_in ?? null,
|
|
225
|
+
tokensOut: result.tokens_out ?? null,
|
|
220
226
|
tokensCacheRead: result.tokens_cache_read,
|
|
221
227
|
tokensCacheCreate: result.tokens_cache_create,
|
|
222
228
|
durationMs,
|
|
@@ -554,9 +554,9 @@ class FileSummaryManager {
|
|
|
554
554
|
started_at: startedIso,
|
|
555
555
|
finished_at: new Date((this.deps.now ?? Date.now)()).toISOString(),
|
|
556
556
|
model: out.model,
|
|
557
|
-
total_cost_usd: out.costUsd,
|
|
558
|
-
tokens_in: out.tokensIn,
|
|
559
|
-
tokens_out: out.tokensOut,
|
|
557
|
+
total_cost_usd: out.costUsd ?? undefined,
|
|
558
|
+
tokens_in: out.tokensIn ?? undefined,
|
|
559
|
+
tokens_out: out.tokensOut ?? undefined,
|
|
560
560
|
tokens_cache_read: out.tokensCacheRead,
|
|
561
561
|
tokens_cache_create: out.tokensCacheCreate,
|
|
562
562
|
duration_ms: out.durationMs,
|
|
@@ -598,9 +598,9 @@ class FileSummaryManager {
|
|
|
598
598
|
started_at: startedIso,
|
|
599
599
|
finished_at: new Date((this.deps.now ?? Date.now)()).toISOString(),
|
|
600
600
|
model: partial?.model,
|
|
601
|
-
total_cost_usd: partial?.costUsd ??
|
|
602
|
-
tokens_in: partial?.tokensIn ??
|
|
603
|
-
tokens_out: partial?.tokensOut ??
|
|
601
|
+
total_cost_usd: partial?.costUsd ?? undefined,
|
|
602
|
+
tokens_in: partial?.tokensIn ?? undefined,
|
|
603
|
+
tokens_out: partial?.tokensOut ?? undefined,
|
|
604
604
|
tokens_cache_read: partial?.tokensCacheRead,
|
|
605
605
|
tokens_cache_create: partial?.tokensCacheCreate,
|
|
606
606
|
duration_ms: partial?.durationMs ?? 0,
|