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
|
@@ -59,6 +59,8 @@ const node_crypto_1 = require("node:crypto");
|
|
|
59
59
|
const node_readline_1 = require("node:readline");
|
|
60
60
|
const tree_kill_1 = __importDefault(require("tree-kill"));
|
|
61
61
|
const cli_prompt_1 = require("./util/cli-prompt");
|
|
62
|
+
const spawn_lifecycle_1 = require("./spawn-lifecycle");
|
|
63
|
+
const providers_1 = require("./providers");
|
|
62
64
|
const explore_smash_1 = require("./explore-smash");
|
|
63
65
|
const explore_cwd_manager_1 = require("./explore-cwd-manager");
|
|
64
66
|
const workspace_resolution_1 = require("./workspace-resolution");
|
|
@@ -66,6 +68,8 @@ const ai_invocations_1 = require("./ai-invocations");
|
|
|
66
68
|
const result_event_1 = require("./result-event");
|
|
67
69
|
const ticket_store_1 = require("./ticket-store");
|
|
68
70
|
const ticket_store_2 = require("./ticket-store");
|
|
71
|
+
const runtime_1 = require("./providers/runtime");
|
|
72
|
+
const transient_children_1 = require("./transient-children");
|
|
69
73
|
/** Resolve the tickets-store path for a SMASH run: the gated `ticketsPath` when
|
|
70
74
|
* the caller threaded it (relocation-aware), else the legacy repo-relative
|
|
71
75
|
* derivation. */
|
|
@@ -104,21 +108,18 @@ function checkSmashEligibility(store, ticketId) {
|
|
|
104
108
|
return { ok: true, context: { ticket, childCount } };
|
|
105
109
|
}
|
|
106
110
|
// ─── Spawn helpers ───────────────────────────────────────────────────────────
|
|
107
|
-
function buildSmashArgs(model, systemPrompt, userPrompt, mode) {
|
|
108
|
-
// Simple: deny all tools, single turn — fast, no codebase access.
|
|
109
|
-
//
|
|
110
|
-
const disallowed = mode === 'full' ? 'Bash,Edit,Write,NotebookEdit' : 'Read,Grep,Glob,Bash';
|
|
111
|
+
function buildSmashArgs(adapter, model, systemPrompt, userPrompt, mode) {
|
|
112
|
+
// Simple: deny all tools, single turn — fast, no codebase access. Full:
|
|
113
|
+
// request the adapter's verified read-only boundary.
|
|
111
114
|
const maxTurns = mode === 'full' ? SMASH_MAX_TURNS_FULL : SMASH_MAX_TURNS_SIMPLE;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
'
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
'-p', userPrompt,
|
|
121
|
-
];
|
|
115
|
+
const options = {
|
|
116
|
+
prompt: userPrompt,
|
|
117
|
+
model,
|
|
118
|
+
systemPrompt,
|
|
119
|
+
toolPolicy: mode === 'full' ? 'read-only' : 'none',
|
|
120
|
+
maxTurns,
|
|
121
|
+
};
|
|
122
|
+
return { args: adapter.buildArgs('spec-gen', options), options };
|
|
122
123
|
}
|
|
123
124
|
/**
|
|
124
125
|
* Build the spawn argv + cwd. Exported for tests.
|
|
@@ -152,8 +153,10 @@ function prepareSmashSpawn(deps, ticket) {
|
|
|
152
153
|
cwd = deps.projectPath;
|
|
153
154
|
}
|
|
154
155
|
}
|
|
155
|
-
const
|
|
156
|
-
|
|
156
|
+
const adapter = (0, providers_1.getAdapter)(deps.providerId ?? 'claude');
|
|
157
|
+
const model = deps.model ?? adapter.defaultModel();
|
|
158
|
+
const built = buildSmashArgs(adapter, model, systemPrompt, userPrompt, mode);
|
|
159
|
+
return { args: built.args, cwd, env, systemPrompt, userPrompt, mode, options: built.options, adapter };
|
|
157
160
|
}
|
|
158
161
|
/** Grace before SIGKILL-escalating a child that swallowed SIGTERM. */
|
|
159
162
|
const SMASH_SIGKILL_GRACE_MS = 2_000;
|
|
@@ -389,13 +392,16 @@ function applyDeleteEpicChildren(filePath, epicId) {
|
|
|
389
392
|
return { deletedChildren, revision: store.revision };
|
|
390
393
|
}
|
|
391
394
|
// ─── recordInvocation wrapper ────────────────────────────────────────────────
|
|
392
|
-
function recordSafely(deps, ticketId, runId, startedAt, finishedAt, status,
|
|
395
|
+
function recordSafely(deps, adapter, ticketId, runId, startedAt, finishedAt, status, events, model) {
|
|
393
396
|
try {
|
|
394
|
-
const normalised
|
|
397
|
+
const { result: normalised, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, events, {
|
|
398
|
+
fallbackModel: model ?? adapter.defaultModel(),
|
|
399
|
+
durationMs: Math.max(0, Date.parse(finishedAt) - Date.parse(startedAt)),
|
|
400
|
+
});
|
|
395
401
|
(0, ai_invocations_1.recordInvocation)(deps.db, {
|
|
396
402
|
id: (0, node_crypto_1.randomUUID)(),
|
|
397
403
|
project_id: deps.projectId,
|
|
398
|
-
provider:
|
|
404
|
+
provider: adapter.id,
|
|
399
405
|
surface: 'smash',
|
|
400
406
|
surface_ref_id: `smash:${runId}`,
|
|
401
407
|
conversation_id: null,
|
|
@@ -403,8 +409,9 @@ function recordSafely(deps, ticketId, runId, startedAt, finishedAt, status, resu
|
|
|
403
409
|
status,
|
|
404
410
|
started_at: startedAt,
|
|
405
411
|
finished_at: finishedAt,
|
|
412
|
+
total_cost_usd_estimated: estimated,
|
|
406
413
|
...normalised,
|
|
407
|
-
model:
|
|
414
|
+
model: normalised.model ?? model ?? undefined,
|
|
408
415
|
});
|
|
409
416
|
}
|
|
410
417
|
catch (err) {
|
|
@@ -451,10 +458,13 @@ function distributeInt(total, n) {
|
|
|
451
458
|
* are split via largest-remainder so the per-child rows sum EXACTLY back to the
|
|
452
459
|
* spawn total (LOW-9).
|
|
453
460
|
*/
|
|
454
|
-
function recordChildrenInvocations(deps, childrenIds, runId, startedAt, finishedAt,
|
|
455
|
-
if (childrenIds.length === 0
|
|
461
|
+
function recordChildrenInvocations(deps, adapter, childrenIds, runId, startedAt, finishedAt, events, model) {
|
|
462
|
+
if (childrenIds.length === 0)
|
|
456
463
|
return;
|
|
457
|
-
const normalised = (0, result_event_1.
|
|
464
|
+
const { result: normalised, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, events, {
|
|
465
|
+
fallbackModel: model ?? adapter.defaultModel(),
|
|
466
|
+
durationMs: Math.max(0, Date.parse(finishedAt) - Date.parse(startedAt)),
|
|
467
|
+
});
|
|
458
468
|
const n = childrenIds.length;
|
|
459
469
|
const split = (v) => {
|
|
460
470
|
if (v === null || v === undefined)
|
|
@@ -474,7 +484,7 @@ function recordChildrenInvocations(deps, childrenIds, runId, startedAt, finished
|
|
|
474
484
|
(0, ai_invocations_1.recordInvocation)(deps.db, {
|
|
475
485
|
id: (0, node_crypto_1.randomUUID)(),
|
|
476
486
|
project_id: deps.projectId,
|
|
477
|
-
provider:
|
|
487
|
+
provider: adapter.id,
|
|
478
488
|
surface: 'smash',
|
|
479
489
|
surface_ref_id: `smash:${runId}:child:${childId}`,
|
|
480
490
|
conversation_id: null,
|
|
@@ -482,6 +492,7 @@ function recordChildrenInvocations(deps, childrenIds, runId, startedAt, finished
|
|
|
482
492
|
status: 'success',
|
|
483
493
|
started_at: startedAt,
|
|
484
494
|
finished_at: finishedAt,
|
|
495
|
+
total_cost_usd_estimated: estimated,
|
|
485
496
|
duration_ms: split(normalised.duration_ms),
|
|
486
497
|
duration_api_ms: split(normalised.duration_api_ms),
|
|
487
498
|
tokens_in: tokensIn[i],
|
|
@@ -491,7 +502,7 @@ function recordChildrenInvocations(deps, childrenIds, runId, startedAt, finished
|
|
|
491
502
|
total_cost_usd: split(normalised.total_cost_usd),
|
|
492
503
|
num_turns: numTurns[i],
|
|
493
504
|
session_id: normalised.session_id,
|
|
494
|
-
model:
|
|
505
|
+
model: normalised.model ?? model ?? undefined,
|
|
495
506
|
});
|
|
496
507
|
}
|
|
497
508
|
catch (err) {
|
|
@@ -519,6 +530,10 @@ async function runSmash(deps, ticketId) {
|
|
|
519
530
|
if ((0, explore_smash_1.isSpecsSmashKillSwitchActive)()) {
|
|
520
531
|
return { ok: false, reason: 'disabled', ticketId, runId };
|
|
521
532
|
}
|
|
533
|
+
const adapter = (0, providers_1.getAdapter)(deps.providerId ?? 'claude');
|
|
534
|
+
if (adapter.capabilities.structuredActions !== true) {
|
|
535
|
+
return { ok: false, reason: 'provider-unsupported', ticketId, runId };
|
|
536
|
+
}
|
|
522
537
|
// B60: reject a concurrent SMASH of the same ticket. The has-check + add are
|
|
523
538
|
// synchronous (no await between them), so they close the TOCTOU window the
|
|
524
539
|
// pre-flight eligibility check leaves open. Released in the finally below.
|
|
@@ -566,36 +581,14 @@ async function runSmash(deps, ticketId) {
|
|
|
566
581
|
ticketTitle: ticket.title,
|
|
567
582
|
timestamp: startedAt,
|
|
568
583
|
});
|
|
569
|
-
const { args, cwd, env: spawnEnv } = prepareSmashSpawn({
|
|
584
|
+
const { args, cwd, env: spawnEnv, options: spawnOptions } = prepareSmashSpawn({
|
|
570
585
|
projectSlug: deps.projectSlug,
|
|
571
586
|
projectPath: deps.projectPath,
|
|
572
587
|
projectName: deps.projectName,
|
|
573
588
|
model: deps.model,
|
|
574
589
|
mode,
|
|
590
|
+
providerId: adapter.id,
|
|
575
591
|
}, ticket);
|
|
576
|
-
let child;
|
|
577
|
-
try {
|
|
578
|
-
child = spawn('claude', args, {
|
|
579
|
-
env: spawnEnv ? { ...process.env, ...spawnEnv } : process.env,
|
|
580
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
581
|
-
cwd,
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
|
-
catch (err) {
|
|
585
|
-
const finishedAt = now().toISOString();
|
|
586
|
-
recordSafely(deps, ticketId, runId, startedAt, finishedAt, 'failed', null, deps.model);
|
|
587
|
-
deps.broadcast({
|
|
588
|
-
type: 'smash.failed',
|
|
589
|
-
projectId: deps.projectId,
|
|
590
|
-
ticketId,
|
|
591
|
-
runId,
|
|
592
|
-
reason: 'crashed',
|
|
593
|
-
timestamp: finishedAt,
|
|
594
|
-
});
|
|
595
|
-
// LOW-10: a row was recorded — invalidate open dashboards.
|
|
596
|
-
deps.broadcast({ type: 'spending.invalidated', projectId: deps.projectId });
|
|
597
|
-
return { ok: false, reason: 'crashed', ticketId, runId };
|
|
598
|
-
}
|
|
599
592
|
// Synthesize progress pills as the spawn proceeds. The runner uses fixed
|
|
600
593
|
// offsets — cheap and deterministic vs trying to read tool-use events.
|
|
601
594
|
const progressTimers = [];
|
|
@@ -612,12 +605,50 @@ async function runSmash(deps, ticketId) {
|
|
|
612
605
|
});
|
|
613
606
|
}, 200 + i * 1500));
|
|
614
607
|
});
|
|
615
|
-
|
|
608
|
+
let fullText = '';
|
|
609
|
+
let resultEvent = null;
|
|
610
|
+
const run = await (0, spawn_lifecycle_1.runAiCliInvocation)({
|
|
611
|
+
adapter,
|
|
612
|
+
binary: adapter.binary,
|
|
613
|
+
argv: args,
|
|
614
|
+
cwd,
|
|
615
|
+
env: (0, runtime_1.buildProviderEnv)(adapter, spawnOptions, spawnEnv ? { ...process.env, ...spawnEnv } : process.env),
|
|
616
|
+
spawn,
|
|
617
|
+
timeoutMs,
|
|
618
|
+
onSpawn: (child) => (0, transient_children_1.trackTransientChild)(deps.projectId, child),
|
|
619
|
+
onEvent: (event) => {
|
|
620
|
+
if (event.kind === 'text-delta')
|
|
621
|
+
fullText += event.text;
|
|
622
|
+
else if (event.kind === 'result')
|
|
623
|
+
resultEvent = event.payload;
|
|
624
|
+
},
|
|
625
|
+
});
|
|
626
|
+
const result = {
|
|
627
|
+
fullText,
|
|
628
|
+
resultEvent,
|
|
629
|
+
code: run.code,
|
|
630
|
+
timedOut: run.timedOut,
|
|
631
|
+
spawnFailed: run.spawnFailed,
|
|
632
|
+
events: run.events,
|
|
633
|
+
};
|
|
616
634
|
progressTimers.forEach((t) => clearTimeout(t));
|
|
617
635
|
const finishedAt = now().toISOString();
|
|
618
636
|
console.log(`[smash-runner] spawn done code=${result.code} timedOut=${result.timedOut} hasResult=${!!result.resultEvent} textBytes=${result.fullText.length}`);
|
|
637
|
+
if (result.spawnFailed) {
|
|
638
|
+
recordSafely(deps, adapter, ticketId, runId, startedAt, finishedAt, 'failed', result.events, deps.model);
|
|
639
|
+
deps.broadcast({
|
|
640
|
+
type: 'smash.failed',
|
|
641
|
+
projectId: deps.projectId,
|
|
642
|
+
ticketId,
|
|
643
|
+
runId,
|
|
644
|
+
reason: 'crashed',
|
|
645
|
+
timestamp: finishedAt,
|
|
646
|
+
});
|
|
647
|
+
deps.broadcast({ type: 'spending.invalidated', projectId: deps.projectId });
|
|
648
|
+
return { ok: false, reason: 'crashed', ticketId, runId };
|
|
649
|
+
}
|
|
619
650
|
if (result.timedOut) {
|
|
620
|
-
recordSafely(deps, ticketId, runId, startedAt, finishedAt, 'aborted', result.
|
|
651
|
+
recordSafely(deps, adapter, ticketId, runId, startedAt, finishedAt, 'aborted', result.events, deps.model);
|
|
621
652
|
deps.broadcast({
|
|
622
653
|
type: 'smash.failed',
|
|
623
654
|
projectId: deps.projectId,
|
|
@@ -630,9 +661,10 @@ async function runSmash(deps, ticketId) {
|
|
|
630
661
|
deps.broadcast({ type: 'spending.invalidated', projectId: deps.projectId });
|
|
631
662
|
return { ok: false, reason: 'timeout', ticketId, runId };
|
|
632
663
|
}
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
664
|
+
const providerError = result.events.some((event) => event.kind === 'error');
|
|
665
|
+
if (result.code !== 0 || providerError || !result.fullText.trim()) {
|
|
666
|
+
recordSafely(deps, adapter, ticketId, runId, startedAt, finishedAt, 'failed', result.events, deps.model);
|
|
667
|
+
const reason = providerError || result.resultEvent ? 'model_error' : 'crashed';
|
|
636
668
|
deps.broadcast({
|
|
637
669
|
type: 'smash.failed',
|
|
638
670
|
projectId: deps.projectId,
|
|
@@ -648,7 +680,7 @@ async function runSmash(deps, ticketId) {
|
|
|
648
680
|
const parse = (0, explore_smash_1.parseSmashOutput)(result.fullText);
|
|
649
681
|
if (!parse.ok) {
|
|
650
682
|
console.log(`[smash-runner] parse failed reason=${parse.reason} detail=${parse.detail ?? '-'}`);
|
|
651
|
-
recordSafely(deps, ticketId, runId, startedAt, finishedAt, 'failed', result.
|
|
683
|
+
recordSafely(deps, adapter, ticketId, runId, startedAt, finishedAt, 'failed', result.events, deps.model);
|
|
652
684
|
deps.broadcast({
|
|
653
685
|
type: 'smash.failed',
|
|
654
686
|
projectId: deps.projectId,
|
|
@@ -670,7 +702,7 @@ async function runSmash(deps, ticketId) {
|
|
|
670
702
|
}
|
|
671
703
|
catch (err) {
|
|
672
704
|
console.error('[smash-runner] mutation failed:', err);
|
|
673
|
-
recordSafely(deps, ticketId, runId, startedAt, finishedAt, 'failed', result.
|
|
705
|
+
recordSafely(deps, adapter, ticketId, runId, startedAt, finishedAt, 'failed', result.events, deps.model);
|
|
674
706
|
deps.broadcast({
|
|
675
707
|
type: 'smash.failed',
|
|
676
708
|
projectId: deps.projectId,
|
|
@@ -687,7 +719,22 @@ async function runSmash(deps, ticketId) {
|
|
|
687
719
|
// (cost split evenly). The Epic itself does not accrue cost here — the
|
|
688
720
|
// operation logically birthed the Sub-Specs and the cost belongs to them.
|
|
689
721
|
// Total project cost remains the original spawn cost (sum of N × X/N = X).
|
|
690
|
-
|
|
722
|
+
const reported = (0, result_event_1.finaliseInvocationResult)(adapter, result.events, {
|
|
723
|
+
fallbackModel: deps.model ?? adapter.defaultModel(),
|
|
724
|
+
}).result;
|
|
725
|
+
const hasAttributableUsage = reported.total_cost_usd !== undefined ||
|
|
726
|
+
reported.tokens_in !== undefined ||
|
|
727
|
+
reported.tokens_out !== undefined ||
|
|
728
|
+
reported.tokens_cache_read !== undefined ||
|
|
729
|
+
reported.tokens_cache_create !== undefined;
|
|
730
|
+
if (hasAttributableUsage) {
|
|
731
|
+
recordChildrenInvocations(deps, adapter, applied.children.map((c) => c.id), runId, startedAt, finishedAt, result.events, deps.model);
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
// Kimi's stream has no usage/cost envelope. Record the actual process once
|
|
735
|
+
// with null cost instead of fabricating N zero-cost child invocations.
|
|
736
|
+
recordSafely(deps, adapter, ticketId, runId, startedAt, finishedAt, 'success', result.events, deps.model);
|
|
737
|
+
}
|
|
691
738
|
// Broadcast underlying state changes first, then the SMASH-specific event.
|
|
692
739
|
deps.broadcast({
|
|
693
740
|
type: 'ticket_updated',
|
|
@@ -19,6 +19,7 @@ exports.runAiCliInvocation = runAiCliInvocation;
|
|
|
19
19
|
const node_readline_1 = require("node:readline");
|
|
20
20
|
const tree_kill_1 = __importDefault(require("tree-kill"));
|
|
21
21
|
const cli_prompt_1 = require("./util/cli-prompt");
|
|
22
|
+
const runtime_1 = require("./providers/runtime");
|
|
22
23
|
const STDERR_TAIL_CAP = 64 * 1024;
|
|
23
24
|
/**
|
|
24
25
|
* Run one AI-CLI invocation: spawn → stream → settle. Resolves exactly once on
|
|
@@ -31,6 +32,9 @@ function runAiCliInvocation(hooks) {
|
|
|
31
32
|
const binary = hooks.binary ?? hooks.adapter.binary;
|
|
32
33
|
const args = hooks.argv ?? hooks.adapter.buildArgs(hooks.action, hooks.buildOpts);
|
|
33
34
|
const spawn = hooks.spawn ?? cli_prompt_1.spawnAiCli;
|
|
35
|
+
const env = hooks.buildOpts
|
|
36
|
+
? (0, runtime_1.buildProviderEnv)(hooks.adapter, hooks.buildOpts, hooks.env ?? process.env)
|
|
37
|
+
: hooks.env ?? process.env;
|
|
34
38
|
const events = [];
|
|
35
39
|
let lastResultEvent = null;
|
|
36
40
|
let sessionId = null;
|
|
@@ -51,7 +55,7 @@ function runAiCliInvocation(hooks) {
|
|
|
51
55
|
let child;
|
|
52
56
|
try {
|
|
53
57
|
child = spawn(binary, args, {
|
|
54
|
-
env
|
|
58
|
+
env,
|
|
55
59
|
stdio: hooks.stdio ?? ['ignore', 'pipe', 'pipe'],
|
|
56
60
|
cwd: hooks.cwd,
|
|
57
61
|
});
|
|
@@ -100,20 +104,20 @@ function runAiCliInvocation(hooks) {
|
|
|
100
104
|
// uncaught exception that takes the sidecar down.
|
|
101
105
|
try {
|
|
102
106
|
hooks.onStdoutLine?.(line);
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
107
|
+
const parsedEvents = (0, runtime_1.parseStreamEvents)(hooks.adapter, line);
|
|
108
|
+
for (const ev of parsedEvents) {
|
|
109
|
+
events.push(ev);
|
|
110
|
+
if (ev.kind === 'session-started') {
|
|
111
|
+
sessionId = ev.sessionId;
|
|
112
|
+
}
|
|
113
|
+
else if (ev.kind === 'result') {
|
|
114
|
+
lastResultEvent = ev;
|
|
115
|
+
const sid = ev.payload.session_id;
|
|
116
|
+
if (sid)
|
|
117
|
+
sessionId = sid;
|
|
118
|
+
}
|
|
119
|
+
hooks.onEvent?.(ev);
|
|
115
120
|
}
|
|
116
|
-
hooks.onEvent?.(ev);
|
|
117
121
|
}
|
|
118
122
|
catch (err) {
|
|
119
123
|
console.error('[spawn-lifecycle] stdout line handler error (ignored):', err);
|
|
@@ -12,6 +12,9 @@ const cli_prompt_1 = require("./util/cli-prompt");
|
|
|
12
12
|
const providers_1 = require("./providers");
|
|
13
13
|
const result_event_1 = require("./result-event");
|
|
14
14
|
const ai_invocations_1 = require("./ai-invocations");
|
|
15
|
+
const runtime_1 = require("./providers/runtime");
|
|
16
|
+
const loop_command_catalog_1 = require("./loop-command-catalog");
|
|
17
|
+
const workspace_resolution_1 = require("./workspace-resolution");
|
|
15
18
|
// ─── SpecLauncherManager ──────────────────────────────────────────────────────
|
|
16
19
|
class SpecLauncherManager {
|
|
17
20
|
_broadcast;
|
|
@@ -36,21 +39,27 @@ class SpecLauncherManager {
|
|
|
36
39
|
* fires when BOTH are present. */
|
|
37
40
|
_db;
|
|
38
41
|
_projectId;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
_adapter = (0, providers_1.getAdapter)('claude');
|
|
42
|
+
_projectSlug;
|
|
43
|
+
_adapter;
|
|
42
44
|
/** Accumulated adapter events per active launch, drained at close. */
|
|
43
45
|
_events = new Map();
|
|
44
46
|
/** Spawn timestamp per active launch (ISO), for the invocation row. */
|
|
45
47
|
_startedAt = new Map();
|
|
46
|
-
constructor(broadcast, cwd, db, projectId) {
|
|
48
|
+
constructor(broadcast, cwd, db, projectId, providerId = 'claude', projectSlug) {
|
|
47
49
|
this._broadcast = broadcast;
|
|
48
50
|
this._cwd = cwd;
|
|
49
51
|
this._db = db;
|
|
50
52
|
this._projectId = projectId;
|
|
53
|
+
this._projectSlug = projectSlug;
|
|
54
|
+
this._adapter = (0, providers_1.getAdapter)(providerId);
|
|
51
55
|
this._activeProcesses = new Map();
|
|
52
56
|
this._buffers = new Map();
|
|
53
57
|
}
|
|
58
|
+
/** Resolve lazily because Core may populate the relocated workspace after
|
|
59
|
+
* this project-scoped manager was constructed. */
|
|
60
|
+
_execution() {
|
|
61
|
+
return (0, workspace_resolution_1.resolveProjectExecution)({ slug: this._projectSlug, path: this._cwd });
|
|
62
|
+
}
|
|
54
63
|
/**
|
|
55
64
|
* Persist one surface='spec-launcher' ai_invocations row. Cost is the native
|
|
56
65
|
* `total_cost_usd` when the run produced a terminal `result` event, else the
|
|
@@ -66,8 +75,10 @@ class SpecLauncherManager {
|
|
|
66
75
|
if (!db || !projectId)
|
|
67
76
|
return;
|
|
68
77
|
try {
|
|
78
|
+
const finishedAt = new Date().toISOString();
|
|
69
79
|
const { result, estimated } = (0, result_event_1.finaliseInvocationResult)(this._adapter, events, {
|
|
70
80
|
fallbackModel: this._adapter.defaultModel(),
|
|
81
|
+
durationMs: Math.max(0, Date.parse(finishedAt) - Date.parse(startedAt)),
|
|
71
82
|
});
|
|
72
83
|
(0, ai_invocations_1.recordInvocation)(db, {
|
|
73
84
|
id: (0, crypto_1.randomUUID)(),
|
|
@@ -77,7 +88,7 @@ class SpecLauncherManager {
|
|
|
77
88
|
surface_ref_id: launchId,
|
|
78
89
|
status,
|
|
79
90
|
started_at: startedAt,
|
|
80
|
-
finished_at:
|
|
91
|
+
finished_at: finishedAt,
|
|
81
92
|
total_cost_usd_estimated: estimated,
|
|
82
93
|
...result,
|
|
83
94
|
});
|
|
@@ -139,24 +150,42 @@ class SpecLauncherManager {
|
|
|
139
150
|
this._startedAt.clear();
|
|
140
151
|
}
|
|
141
152
|
async launch(launchId, description) {
|
|
153
|
+
const execution = this._execution();
|
|
142
154
|
const rawCommand = `/opsx:ff ${description}`;
|
|
143
|
-
const
|
|
144
|
-
|
|
155
|
+
const resolvedPrompt = this._adapter.capabilities.materializeHeadlessSkills
|
|
156
|
+
? rawCommand
|
|
157
|
+
: (0, command_resolver_1.resolveCommand)(rawCommand, execution.cwd);
|
|
158
|
+
const providerCommand = resolvedPrompt === rawCommand
|
|
159
|
+
? `${(0, loop_command_catalog_1.expandCommands)('{{cmd:opsx:ff}}', { provider: this._adapter.id })} ${description}`
|
|
160
|
+
: resolvedPrompt;
|
|
161
|
+
if (providerCommand === rawCommand) {
|
|
145
162
|
this._broadcastError(launchId, 'This project does not have the /opsx:ff command installed. Run "npx specrails-core@latest" to install it.');
|
|
146
163
|
return;
|
|
147
164
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const
|
|
157
|
-
|
|
165
|
+
let prompt;
|
|
166
|
+
try {
|
|
167
|
+
prompt = (0, runtime_1.formatProviderCommand)(this._adapter, providerCommand, execution.cwd);
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
this._broadcastError(launchId, error instanceof Error ? error.message : String(error));
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const spawnOptions = {
|
|
174
|
+
prompt,
|
|
175
|
+
model: this._adapter.defaultModel(),
|
|
176
|
+
toolPolicy: 'default',
|
|
177
|
+
extraArgs: execution.relocated
|
|
178
|
+
? (0, runtime_1.buildProviderRepoAccessArgs)(this._adapter, [execution.repoDir])
|
|
179
|
+
: [],
|
|
180
|
+
};
|
|
181
|
+
const args = this._adapter.buildArgs('spec-gen', spawnOptions);
|
|
182
|
+
const child = (0, cli_prompt_1.spawnAiCli)(this._adapter.binary, args, {
|
|
183
|
+
env: (0, runtime_1.buildProviderEnv)(this._adapter, spawnOptions, {
|
|
184
|
+
...process.env,
|
|
185
|
+
...execution.env,
|
|
186
|
+
}),
|
|
158
187
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
159
|
-
cwd:
|
|
188
|
+
cwd: execution.cwd,
|
|
160
189
|
});
|
|
161
190
|
this._activeProcesses.set(launchId, child);
|
|
162
191
|
this._buffers.set(launchId, '');
|
|
@@ -178,7 +207,7 @@ class SpecLauncherManager {
|
|
|
178
207
|
type: 'spec_launcher_error',
|
|
179
208
|
projectId: '',
|
|
180
209
|
launchId,
|
|
181
|
-
error: `Failed to launch
|
|
210
|
+
error: `Failed to launch ${this._adapter.binary}: ${err.message}`,
|
|
182
211
|
timestamp: new Date().toISOString(),
|
|
183
212
|
});
|
|
184
213
|
});
|
|
@@ -188,28 +217,12 @@ class SpecLauncherManager {
|
|
|
188
217
|
const stdoutReader = (0, readline_1.createInterface)({ input: child.stdout, crlfDelay: Infinity });
|
|
189
218
|
stdoutReader.on('line', (line) => {
|
|
190
219
|
// Accumulate adapter events so a killed/failed launch is still costed from
|
|
191
|
-
// the per-assistant-event usage snapshots (HIGH-5)
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
let parsed = null;
|
|
198
|
-
try {
|
|
199
|
-
parsed = JSON.parse(line);
|
|
200
|
-
}
|
|
201
|
-
catch { /* skip non-JSON */ }
|
|
202
|
-
if (!parsed)
|
|
203
|
-
return;
|
|
204
|
-
const eventType = parsed.type;
|
|
205
|
-
if (eventType === 'assistant') {
|
|
206
|
-
const msg = parsed.message;
|
|
207
|
-
const blocks = msg?.content ?? [];
|
|
208
|
-
const texts = blocks
|
|
209
|
-
.filter((c) => c.type === 'text')
|
|
210
|
-
.map((c) => c.text ?? '');
|
|
211
|
-
const newText = texts.join('');
|
|
212
|
-
if (newText) {
|
|
220
|
+
// the per-assistant-event usage snapshots (HIGH-5), and so explicit
|
|
221
|
+
// provider failures remain terminal even when a CLI anomalously exits 0.
|
|
222
|
+
for (const event of (0, runtime_1.parseStreamEvents)(this._adapter, line)) {
|
|
223
|
+
this._events.get(launchId)?.push(event);
|
|
224
|
+
if (event.kind === 'text-delta') {
|
|
225
|
+
const newText = event.text;
|
|
213
226
|
// Try to detect change ID from output (look for "openspec/changes/<id>" pattern)
|
|
214
227
|
const changeMatch = newText.match(/openspec\/changes\/([^\s/]+)/);
|
|
215
228
|
if (changeMatch)
|
|
@@ -224,16 +237,14 @@ class SpecLauncherManager {
|
|
|
224
237
|
timestamp: new Date().toISOString(),
|
|
225
238
|
});
|
|
226
239
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
});
|
|
236
|
-
}
|
|
240
|
+
else if (event.kind === 'tool-use') {
|
|
241
|
+
this._broadcast({
|
|
242
|
+
type: 'spec_launcher_stream',
|
|
243
|
+
projectId: '',
|
|
244
|
+
launchId,
|
|
245
|
+
delta: `<!--tool:${event.name}-->`,
|
|
246
|
+
timestamp: new Date().toISOString(),
|
|
247
|
+
});
|
|
237
248
|
}
|
|
238
249
|
}
|
|
239
250
|
});
|
|
@@ -244,13 +255,14 @@ class SpecLauncherManager {
|
|
|
244
255
|
this._activeProcesses.delete(launchId);
|
|
245
256
|
this._buffers.delete(launchId);
|
|
246
257
|
const wasCancelled = this._cancelledIds.delete(launchId);
|
|
258
|
+
const providerError = this._events.get(launchId)?.find((event) => event.kind === 'error')?.message;
|
|
247
259
|
// Record the invocation regardless of cancel/done outcome (the spend is
|
|
248
260
|
// real either way) — but NOT when the project is being torn down, since
|
|
249
261
|
// its DB is closing (recordInvocation would throw). A cancelled/killed
|
|
250
262
|
// launch is 'aborted'; a non-zero exit is 'failed'; a clean exit is
|
|
251
263
|
// 'success' (HIGH-5).
|
|
252
264
|
if (!this._disposed) {
|
|
253
|
-
const status = wasCancelled ? 'aborted' : code === 0 ? 'success' : 'failed';
|
|
265
|
+
const status = wasCancelled ? 'aborted' : code === 0 && !providerError ? 'success' : 'failed';
|
|
254
266
|
this._recordInvocation(launchId, status);
|
|
255
267
|
}
|
|
256
268
|
this._events.delete(launchId);
|
|
@@ -262,7 +274,7 @@ class SpecLauncherManager {
|
|
|
262
274
|
resolve();
|
|
263
275
|
return;
|
|
264
276
|
}
|
|
265
|
-
if (code === 0) {
|
|
277
|
+
if (code === 0 && !providerError) {
|
|
266
278
|
// Also try to extract change ID from full text
|
|
267
279
|
if (!detectedChangeId) {
|
|
268
280
|
const match = fullText.match(/openspec\/changes\/([^\s/]+)/);
|
|
@@ -278,7 +290,7 @@ class SpecLauncherManager {
|
|
|
278
290
|
});
|
|
279
291
|
}
|
|
280
292
|
else {
|
|
281
|
-
this._broadcastError(launchId, 'Spec generation failed');
|
|
293
|
+
this._broadcastError(launchId, providerError ?? 'Spec generation failed');
|
|
282
294
|
}
|
|
283
295
|
resolve();
|
|
284
296
|
});
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PROVIDER_DEFAULT_MODEL = exports.GEMINI_MODELS = exports.CODEX_MODELS = exports.CLAUDE_MODELS = void 0;
|
|
3
|
+
exports.PROVIDER_DEFAULT_MODEL = exports.KIMI_MODELS = exports.GEMINI_MODELS = exports.CODEX_MODELS = exports.CLAUDE_MODELS = void 0;
|
|
4
4
|
exports.getModelsForProvider = getModelsForProvider;
|
|
5
5
|
exports.isValidModelForProvider = isValidModelForProvider;
|
|
6
6
|
exports.getProviderDefault = getProviderDefault;
|
|
7
|
+
const providers_1 = require("./providers");
|
|
7
8
|
exports.CLAUDE_MODELS = [
|
|
8
9
|
{ value: 'sonnet', label: 'Claude Sonnet' },
|
|
9
10
|
{ value: 'fable', label: 'Claude Fable' },
|
|
@@ -26,25 +27,33 @@ exports.GEMINI_MODELS = [
|
|
|
26
27
|
{ value: 'gemini-3.1-flash-lite', label: 'Gemini 3.1 Flash Lite' },
|
|
27
28
|
{ value: 'gemini-2.5-flash-lite', label: 'Gemini 2.5 Flash Lite' },
|
|
28
29
|
];
|
|
29
|
-
|
|
30
|
+
// Mirrors KIMI_MODELS in server/providers/kimi-adapter.ts.
|
|
31
|
+
exports.KIMI_MODELS = [
|
|
32
|
+
{ value: 'k3', label: 'Kimi K3' },
|
|
33
|
+
{ value: 'kimi-for-coding', label: 'Kimi for Coding' },
|
|
34
|
+
{ value: 'kimi-for-coding-highspeed', label: 'Kimi for Coding Highspeed' },
|
|
35
|
+
];
|
|
36
|
+
/** Per-provider model catalog. Unknown providers intentionally return none. */
|
|
30
37
|
const PROVIDER_MODELS = {
|
|
31
38
|
claude: exports.CLAUDE_MODELS,
|
|
32
39
|
codex: exports.CODEX_MODELS,
|
|
33
40
|
gemini: exports.GEMINI_MODELS,
|
|
41
|
+
kimi: exports.KIMI_MODELS,
|
|
34
42
|
};
|
|
35
43
|
exports.PROVIDER_DEFAULT_MODEL = {
|
|
36
44
|
claude: 'sonnet',
|
|
37
45
|
codex: 'gpt-5.5',
|
|
38
46
|
gemini: 'gemini-3.5-flash',
|
|
47
|
+
kimi: 'k3',
|
|
39
48
|
};
|
|
40
49
|
function getModelsForProvider(provider) {
|
|
41
|
-
return PROVIDER_MODELS[provider] ??
|
|
50
|
+
return PROVIDER_MODELS[provider] ?? [];
|
|
42
51
|
}
|
|
43
52
|
function isValidModelForProvider(model, provider) {
|
|
44
|
-
if (
|
|
53
|
+
if (!(0, providers_1.hasAdapter)(provider))
|
|
45
54
|
return false;
|
|
46
|
-
return
|
|
55
|
+
return (0, providers_1.isModelAvailableForAdapter)((0, providers_1.getAdapter)(provider), model);
|
|
47
56
|
}
|
|
48
57
|
function getProviderDefault(provider) {
|
|
49
|
-
return exports.PROVIDER_DEFAULT_MODEL[provider] ??
|
|
58
|
+
return exports.PROVIDER_DEFAULT_MODEL[provider] ?? '';
|
|
50
59
|
}
|