specrails-desktop 2.58.1 → 2.59.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 +2 -5
- package/client/dist/assets/{ActivityFeedPage-BQGppIR0.js → ActivityFeedPage-DBFt8ZHP.js} +1 -1
- package/client/dist/assets/AgentBrowserCapture-DiQx0W67.js +1 -0
- package/client/dist/assets/AgentModeAnalyticsPane-BmDSXp_J.js +2 -0
- package/client/dist/assets/AgentModeCodePane-BLQLPSwr.js +2 -0
- package/client/dist/assets/{AgentModeJobsPane-DR_06oqH.js → AgentModeJobsPane-BbTXdKUa.js} +1 -1
- package/client/dist/assets/{AgentsPage-BKIKjm_1.js → AgentsPage-Dei1jGR8.js} +3 -3
- package/client/dist/assets/{AnalyticsPage-069npRVo.js → AnalyticsPage-BhkeGIGn.js} +1 -1
- package/client/dist/assets/CodePage-B_9yYWUx.js +3 -0
- package/client/dist/assets/{DesktopAnalyticsPage-qtWAPM47.js → DesktopAnalyticsPage-DAcfEJac.js} +1 -1
- package/client/dist/assets/DocsDialog-WCuiYgsc.js +11 -0
- package/client/dist/assets/DocsPage-bGVYTMTU.js +11 -0
- package/client/dist/assets/{ExportDropdown-BcMpvV89.js → ExportDropdown-CsodZ-yb.js} +1 -1
- package/client/dist/assets/InteractiveJobComposer-D5fh_eVL.js +19 -0
- package/client/dist/assets/JobDetailModal-DlpXF61O.js +1 -0
- package/client/dist/assets/JobDetailPage-2yR19_Lb.js +1 -0
- package/client/dist/assets/JobsPage-CS9IR6Dq.js +1 -0
- package/client/dist/assets/LoopBuilderPage-BwiAtmOr.js +1 -0
- package/client/dist/assets/{LoopPreviewModal-je5pSCf-.js → LoopPreviewModal--upwvgTv.js} +1 -1
- package/client/dist/assets/LoopWindowSurface-DRnUixtl.js +1 -0
- package/client/dist/assets/LoopsPage-Xm3nRToQ.js +2 -0
- package/client/dist/assets/MinimizedChatsContext-D_8L4EWZ.js +1 -0
- package/client/dist/assets/PluginsPage-CAFQ1B4Q.js +2 -0
- package/client/dist/assets/ProjectSettingsDialog-DYSO4v90.js +1 -0
- package/client/dist/assets/{RepositoryDeliveries-BiwJuS8r.js → RepositoryDeliveries-CbQmW7Qx.js} +1 -1
- package/client/dist/assets/RepositoryScopeSelector-DKzvIGSZ.js +2 -0
- package/client/dist/assets/ReviewPacketPage-SDBhYdQB.js +4 -0
- package/client/dist/assets/TemplatePreviewModal-DHBUds51.js +1 -0
- package/client/dist/assets/TicketDetailModalContext-UAeNm7BB.js +16 -0
- package/client/dist/assets/{Trans-D3AfDylf.js → Trans-DExd3Z00.js} +1 -1
- package/client/dist/assets/agent-BElLtdKP.js +1 -0
- package/client/dist/assets/agent-C-m9VugX.js +1 -0
- package/client/dist/assets/agent-CGSKxfZk.js +1 -0
- package/client/dist/assets/agent-CW74ODDP.js +1 -0
- package/client/dist/assets/agent-DeCAZDhL.js +1 -0
- package/client/dist/assets/agent-DrM4qned.js +1 -0
- package/client/dist/assets/agent-KdIXq3w5.js +1 -0
- package/client/dist/assets/agent-jK8mCisM.js +1 -0
- package/client/dist/assets/{agentRuntime-DGz_IqKW.js → agentRuntime-15Pkk6we.js} +1 -1
- package/client/dist/assets/agentRuntime-Bpx3yWHK.js +1 -0
- package/client/dist/assets/{agentRuntime-Bg9tbmqm.js → agentRuntime-C78n13To.js} +1 -1
- package/client/dist/assets/{agentRuntime-D-GJVGkj.js → agentRuntime-CCI7XF4c.js} +1 -1
- package/client/dist/assets/{agentRuntime-D2__CVI_.js → agentRuntime-CKDHe2-a.js} +1 -1
- package/client/dist/assets/{agentRuntime-D35dGVOP.js → agentRuntime-Ddqvp2bP.js} +1 -1
- package/client/dist/assets/{agentRuntime-hInH9Fzj.js → agentRuntime-TXPQowKJ.js} +1 -1
- package/client/dist/assets/{agentRuntime-O1liDt6G.js → agentRuntime-hqZRy08E.js} +1 -1
- package/client/dist/assets/{builder-DGETbtZj.js → builder-B9gorTnT.js} +1 -1
- package/client/dist/assets/{builder-DyQperXU.js → builder-Bvw5s3Mi.js} +1 -1
- package/client/dist/assets/{builder-C1neIYGR.js → builder-CL5l4dU3.js} +1 -1
- package/client/dist/assets/{builder-DXEJUlC0.js → builder-CVDTVrQX.js} +1 -1
- package/client/dist/assets/{builder-CzW5ovyI.js → builder-CpS9liE9.js} +1 -1
- package/client/dist/assets/{builder-CvnFm0im.js → builder-DNctIL9Q.js} +1 -1
- package/client/dist/assets/{builder-D06L7iPy.js → builder-De2NxX6o.js} +1 -1
- package/client/dist/assets/{builder-C0FyvM83.js → builder-DeYT7Y-m.js} +1 -1
- package/client/dist/assets/{button-Ccc9Dc-D.js → button-D1xExSTF.js} +1 -1
- package/client/dist/assets/{common-DmsclwjP.js → common-Bdi0qN4S.js} +1 -1
- package/client/dist/assets/{common-C4Yvvhp6.js → common-Bhb9zN1P.js} +1 -1
- package/client/dist/assets/{common-od8WThlf.js → common-BykKlZg1.js} +1 -1
- package/client/dist/assets/{common-C0BOdeNi.js → common-CvnNNSJA.js} +1 -1
- package/client/dist/assets/{common-BCK7c9Pv.js → common-D5zk_mqq.js} +1 -1
- package/client/dist/assets/{common-DpLWwgI1.js → common-DQNO_al5.js} +1 -1
- package/client/dist/assets/{common-OCvl3c8t.js → common-Dax30Vmp.js} +1 -1
- package/client/dist/assets/{common-c0aujEZC.js → common-DkllpVSb.js} +1 -1
- package/client/dist/assets/{dialog-xXB2q5HJ.js → dialog-CMgps2MY.js} +1 -1
- package/client/dist/assets/external-link-D6XxC_Cu.js +1 -0
- package/client/dist/assets/file-text-BcLCfcWZ.js +1 -0
- package/client/dist/assets/{formatDistanceToNow-aBss1Nai.js → formatDistanceToNow-aw7H5ORC.js} +1 -1
- package/client/dist/assets/{getTimezoneOffsetInMilliseconds-DOGj1Mfz.js → getTimezoneOffsetInMilliseconds-NyC7gZJX.js} +1 -1
- package/client/dist/assets/index-CahchzS5.css +2 -0
- package/client/dist/assets/index-JSTZVJfe.js +83 -0
- package/client/dist/assets/integrations-BkpRUbvp.js +1 -0
- package/client/dist/assets/integrations-Bo8qbJf4.js +1 -0
- package/client/dist/assets/integrations-CmSrKzZb.js +1 -0
- package/client/dist/assets/integrations-DGtq26Rr.js +1 -0
- package/client/dist/assets/integrations-De38GFnQ.js +1 -0
- package/client/dist/assets/integrations-Dw6zdtb-.js +1 -0
- package/client/dist/assets/integrations-Dwl9KQp0.js +1 -0
- package/client/dist/assets/integrations-Refg_d2I.js +1 -0
- package/client/dist/assets/jira-api-DlXaRwA3.js +1 -0
- package/client/dist/assets/{jobs-KG4Sn12X.js → jobs-1G3wodhl.js} +1 -1
- package/client/dist/assets/{jobs-6_-r75yC.js → jobs-B4pu8TdF.js} +1 -1
- package/client/dist/assets/{jobs-pPv4KWjb.js → jobs-BD47Ov11.js} +1 -1
- package/client/dist/assets/{jobs-B1yqyId5.js → jobs-BLOoVRRl.js} +1 -1
- package/client/dist/assets/{jobs-BKiK-ZWh.js → jobs-CSrRx5lD.js} +1 -1
- package/client/dist/assets/{jobs-BFuV7ttH.js → jobs-DZAbh1m2.js} +1 -1
- package/client/dist/assets/{jobs-DmKV7b7d.js → jobs-epP7gt8W.js} +1 -1
- package/client/dist/assets/{jobs-BKa8LuwA.js → jobs-tWjcDF_6.js} +1 -1
- package/client/dist/assets/loops--KWr0X-w.js +1 -0
- package/client/dist/assets/{loops-BO3V8244.js → loops-3IutojWt.js} +1 -1
- package/client/dist/assets/{loops-C-hZK8pf.js → loops-BAosWtXE.js} +1 -1
- package/client/dist/assets/{loops-eUnCfLjC.js → loops-BISDssL5.js} +1 -1
- package/client/dist/assets/{loops-Dv849ckF.js → loops-Cm55CXJ4.js} +1 -1
- package/client/dist/assets/{loops-CDOWZ0ci.js → loops-D7tL_Saw.js} +1 -1
- package/client/dist/assets/{loops-BJDY9FTh.js → loops-DHQtnfze.js} +1 -1
- package/client/dist/assets/{loops-Q9LIgGkq.js → loops-kIJJkaxf.js} +1 -1
- package/client/dist/assets/nav--u7iPYlS.js +1 -0
- package/client/dist/assets/nav-C5Jgfaby.js +1 -0
- package/client/dist/assets/nav-CAna_Wpt.js +1 -0
- package/client/dist/assets/nav-CCLqeyHo.js +1 -0
- package/client/dist/assets/nav-Cf3c90Jk.js +1 -0
- package/client/dist/assets/nav-DMYQaQjR.js +1 -0
- package/client/dist/assets/nav-Df_PkZ9F.js +1 -0
- package/client/dist/assets/nav-VyNGBJwj.js +1 -0
- package/client/dist/assets/{project-repositories-CSnfzUpg.js → project-repositories-DXhb9FP4.js} +1 -1
- package/client/dist/assets/provider-capabilities-lePfeT_Y.js +1 -0
- package/client/dist/assets/save-OsUqVn99.js +1 -0
- package/client/dist/assets/settings-B5Hy_Kol.js +1 -0
- package/client/dist/assets/settings-BBj_kZaD.js +1 -0
- package/client/dist/assets/settings-ByVE7jdZ.js +1 -0
- package/client/dist/assets/settings-COlH_P33.js +1 -0
- package/client/dist/assets/settings-D77mC_Lb.js +1 -0
- package/client/dist/assets/settings-DZKy7MqN.js +1 -0
- package/client/dist/assets/settings-Dbyd6gmj.js +1 -0
- package/client/dist/assets/settings-Dn-pXukr.js +1 -0
- package/client/dist/assets/setup-Be485n2u.js +1 -0
- package/client/dist/assets/setup-CKGUxKr-.js +1 -0
- package/client/dist/assets/setup-Ck1Uwd7_.js +1 -0
- package/client/dist/assets/setup-Cm774a6v.js +1 -0
- package/client/dist/assets/setup-DIqMQpxt.js +1 -0
- package/client/dist/assets/setup-DfCsoNFL.js +1 -0
- package/client/dist/assets/setup-DkeE8mP0.js +1 -0
- package/client/dist/assets/setup-xVntVaz1.js +1 -0
- package/client/dist/assets/{spending-HBSk-6jv.js → spending-BdcyVkcd.js} +1 -1
- package/client/dist/assets/subscriptionUsage-Cf87DeS_.js +1 -0
- package/client/dist/assets/subscriptionUsage-D6u7VBdz.js +1 -0
- package/client/dist/assets/subscriptionUsage-DQ02J25O.js +1 -0
- package/client/dist/assets/subscriptionUsage-DWF3zKp4.js +1 -0
- package/client/dist/assets/subscriptionUsage-DkIf6Zuh.js +1 -0
- package/client/dist/assets/subscriptionUsage-DoWQv7l1.js +1 -0
- package/client/dist/assets/subscriptionUsage-N9hB-ARf.js +1 -0
- package/client/dist/assets/subscriptionUsage-zRcRPHkP.js +1 -0
- package/client/dist/assets/tauri-shell-DE6LfGPw.js +2 -0
- package/client/dist/assets/{useDesktop-0unHDBJJ.js → useDesktop-D07TvesS.js} +1 -1
- package/client/dist/assets/{useRuntimeRuns-BN1rhyEm.js → useRuntimeRuns-pGLmtAC6.js} +1 -1
- package/client/dist/assets/useSharedWebSocket-TzKtPRp9.js +2 -0
- package/client/dist/index.html +33 -32
- package/docs/README.md +1 -9
- package/docs/agent-live-steering.md +0 -6
- package/docs/agents/README.md +0 -2
- package/docs/agents/mcp.md +1 -14
- package/docs/cli.md +0 -13
- package/docs/codex.md +2 -75
- package/docs/creating-specs.md +0 -39
- package/docs/customizing.md +1 -15
- package/docs/getting-started.md +0 -23
- package/docs/guide/de/agents/2-profiles-and-the-balanced-default.md +0 -8
- package/docs/guide/de/agents/4-custom-agents-catalog.md +0 -15
- package/docs/guide/de/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/de/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/de/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/de/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/de/integrations/1-ai-providers.md +2 -50
- package/docs/guide/de/integrations/2-plugins.md +0 -8
- package/docs/guide/de/integrations/5-mcp-server.md +1 -14
- package/docs/guide/de/integrations/6-agent-chat.md +0 -11
- package/docs/guide/de/integrations/7-local-engines.md +0 -4
- package/docs/guide/de/pipeline/1-rails-and-jobs.md +0 -13
- package/docs/guide/de/pipeline/2-the-job-detail-view.md +0 -3
- package/docs/guide/de/pipeline/4-picking-an-engine-per-rail.md +0 -20
- package/docs/guide/de/pipeline/5-the-loop-builder.md +0 -6
- package/docs/guide/de/specs/2-add-spec-quick-mode.md +0 -7
- package/docs/guide/en/agents/2-profiles-and-the-balanced-default.md +0 -10
- package/docs/guide/en/agents/4-custom-agents-catalog.md +0 -25
- package/docs/guide/en/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/en/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/en/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/en/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/en/insights/3-code-explorer.md +0 -5
- package/docs/guide/en/integrations/1-ai-providers.md +10 -99
- package/docs/guide/en/integrations/2-plugins.md +0 -8
- package/docs/guide/en/integrations/5-mcp-server.md +1 -1
- package/docs/guide/en/integrations/6-agent-chat.md +0 -17
- package/docs/guide/en/integrations/7-local-engines.md +0 -4
- package/docs/guide/en/pipeline/1-rails-and-jobs.md +2 -24
- package/docs/guide/en/pipeline/2-the-job-detail-view.md +0 -3
- package/docs/guide/en/pipeline/4-picking-an-engine-per-rail.md +10 -65
- package/docs/guide/en/pipeline/5-the-loop-builder.md +0 -7
- package/docs/guide/en/specs/2-add-spec-quick-mode.md +0 -11
- package/docs/guide/es/agents/2-profiles-and-the-balanced-default.md +0 -8
- package/docs/guide/es/agents/4-custom-agents-catalog.md +0 -15
- package/docs/guide/es/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/es/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/es/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/es/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/es/integrations/1-ai-providers.md +10 -75
- package/docs/guide/es/integrations/2-plugins.md +0 -8
- package/docs/guide/es/integrations/5-mcp-server.md +1 -1
- package/docs/guide/es/integrations/6-agent-chat.md +0 -11
- package/docs/guide/es/integrations/7-local-engines.md +0 -4
- package/docs/guide/es/pipeline/1-rails-and-jobs.md +3 -13
- package/docs/guide/es/pipeline/2-the-job-detail-view.md +0 -3
- package/docs/guide/es/pipeline/4-picking-an-engine-per-rail.md +10 -53
- package/docs/guide/es/pipeline/5-the-loop-builder.md +1 -6
- package/docs/guide/es/specs/2-add-spec-quick-mode.md +0 -7
- package/docs/guide/fr/agents/2-profiles-and-the-balanced-default.md +0 -8
- package/docs/guide/fr/agents/4-custom-agents-catalog.md +0 -15
- package/docs/guide/fr/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/fr/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/fr/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/fr/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/fr/integrations/1-ai-providers.md +2 -50
- package/docs/guide/fr/integrations/2-plugins.md +0 -8
- package/docs/guide/fr/integrations/5-mcp-server.md +1 -14
- package/docs/guide/fr/integrations/6-agent-chat.md +0 -11
- package/docs/guide/fr/integrations/7-local-engines.md +0 -4
- package/docs/guide/fr/pipeline/1-rails-and-jobs.md +0 -13
- package/docs/guide/fr/pipeline/2-the-job-detail-view.md +0 -3
- package/docs/guide/fr/pipeline/4-picking-an-engine-per-rail.md +0 -22
- package/docs/guide/fr/pipeline/5-the-loop-builder.md +0 -6
- package/docs/guide/fr/specs/2-add-spec-quick-mode.md +0 -7
- package/docs/guide/it/agents/2-profiles-and-the-balanced-default.md +0 -8
- package/docs/guide/it/agents/4-custom-agents-catalog.md +0 -15
- package/docs/guide/it/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/it/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/it/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/it/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/it/integrations/1-ai-providers.md +2 -48
- package/docs/guide/it/integrations/2-plugins.md +0 -8
- package/docs/guide/it/integrations/5-mcp-server.md +1 -14
- package/docs/guide/it/integrations/6-agent-chat.md +0 -11
- package/docs/guide/it/integrations/7-local-engines.md +0 -4
- package/docs/guide/it/pipeline/1-rails-and-jobs.md +2 -13
- package/docs/guide/it/pipeline/2-the-job-detail-view.md +0 -3
- package/docs/guide/it/pipeline/4-picking-an-engine-per-rail.md +0 -20
- package/docs/guide/it/pipeline/5-the-loop-builder.md +1 -6
- package/docs/guide/it/specs/2-add-spec-quick-mode.md +0 -7
- package/docs/guide/ja/agents/2-profiles-and-the-balanced-default.md +0 -9
- package/docs/guide/ja/agents/4-custom-agents-catalog.md +0 -15
- package/docs/guide/ja/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/ja/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/ja/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/ja/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/ja/integrations/1-ai-providers.md +1 -69
- package/docs/guide/ja/integrations/2-plugins.md +0 -8
- package/docs/guide/ja/integrations/5-mcp-server.md +1 -14
- package/docs/guide/ja/integrations/6-agent-chat.md +0 -10
- package/docs/guide/ja/integrations/7-local-engines.md +0 -4
- package/docs/guide/ja/pipeline/1-rails-and-jobs.md +0 -13
- package/docs/guide/ja/pipeline/2-the-job-detail-view.md +0 -3
- package/docs/guide/ja/pipeline/4-picking-an-engine-per-rail.md +0 -21
- package/docs/guide/ja/pipeline/5-the-loop-builder.md +0 -6
- package/docs/guide/ja/specs/2-add-spec-quick-mode.md +0 -7
- package/docs/guide/pt/agents/2-profiles-and-the-balanced-default.md +0 -8
- package/docs/guide/pt/agents/4-custom-agents-catalog.md +0 -15
- package/docs/guide/pt/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/pt/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/pt/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/pt/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/pt/integrations/1-ai-providers.md +2 -48
- package/docs/guide/pt/integrations/2-plugins.md +0 -8
- package/docs/guide/pt/integrations/5-mcp-server.md +1 -14
- package/docs/guide/pt/integrations/6-agent-chat.md +0 -10
- package/docs/guide/pt/integrations/7-local-engines.md +0 -4
- package/docs/guide/pt/pipeline/1-rails-and-jobs.md +0 -13
- package/docs/guide/pt/pipeline/2-the-job-detail-view.md +0 -2
- package/docs/guide/pt/pipeline/4-picking-an-engine-per-rail.md +0 -21
- package/docs/guide/pt/pipeline/5-the-loop-builder.md +0 -6
- package/docs/guide/pt/specs/2-add-spec-quick-mode.md +0 -7
- package/docs/guide/zh/agents/2-profiles-and-the-balanced-default.md +0 -7
- package/docs/guide/zh/agents/4-custom-agents-catalog.md +0 -15
- package/docs/guide/zh/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/zh/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/zh/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/zh/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/zh/integrations/1-ai-providers.md +1 -67
- package/docs/guide/zh/integrations/2-plugins.md +0 -8
- package/docs/guide/zh/integrations/5-mcp-server.md +1 -14
- package/docs/guide/zh/integrations/6-agent-chat.md +0 -9
- package/docs/guide/zh/integrations/7-local-engines.md +0 -4
- package/docs/guide/zh/pipeline/1-rails-and-jobs.md +0 -13
- package/docs/guide/zh/pipeline/2-the-job-detail-view.md +0 -2
- package/docs/guide/zh/pipeline/4-picking-an-engine-per-rail.md +0 -20
- package/docs/guide/zh/pipeline/5-the-loop-builder.md +0 -6
- package/docs/guide/zh/specs/2-add-spec-quick-mode.md +0 -7
- package/docs/internals/adding-a-provider.md +7 -0
- package/docs/internals/desktop-owned-workflows.md +121 -0
- package/docs/internals/operations-runbook.md +20 -0
- package/docs/internals/programmatic-agent-runtime.md +34 -28
- package/docs/internals/project-builder.md +34 -11
- package/docs/internals/source-map.md +51 -3
- package/docs/internals/spec-addenda.md +11 -5
- package/docs/local-providers.md +8 -13
- package/docs/mcp.md +1 -17
- package/docs/platforms/macos.md +0 -40
- package/docs/platforms/windows-parity.md +1 -1
- package/docs/platforms/windows.md +0 -8
- package/docs/running-pipelines.md +1 -46
- package/docs/subscription-usage.md +19 -0
- package/docs/terminal.md +0 -2
- package/docs/tracking-cost.md +2 -33
- package/package.json +1 -1
- package/server/dist/core-execution.js +24 -15
- package/server/dist/desktop-db.js +23 -10
- package/server/dist/desktop-router.js +8 -4
- package/server/dist/index.js +10 -5
- package/server/dist/mcp/guide.js +1 -0
- package/server/dist/mcp/tools/jobs.js +1 -1
- package/server/dist/mcp/tools/loops.js +2 -0
- package/server/dist/mcp/tools/meta.js +6 -7
- package/server/dist/mcp/tools/projects.js +31 -6
- package/server/dist/mcp/tools/rails.js +6 -3
- package/server/dist/mcp/tools/setup.js +10 -0
- package/server/dist/mcp/tools/specs.js +1 -1
- package/server/dist/modules/accounting/runtime/pricing.js +6 -1
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-bridge.js +55 -12
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-metrics.js +1 -1
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings-router.js +1 -1
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings.js +42 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-verification-suggestions.js +10 -4
- package/server/dist/modules/builder/runtime/milestone-chain.js +76 -10
- package/server/dist/modules/delivery/runtime/delivery-evidence.js +3 -2
- package/server/dist/modules/delivery/runtime/multi-repo-execution.js +3 -0
- package/server/dist/modules/delivery/runtime/rail-isolated-launch.js +1 -0
- package/server/dist/modules/delivery/runtime/rail-launch-parser.js +8 -0
- package/server/dist/modules/delivery/runtime/rails-router.js +48 -26
- package/server/dist/modules/delivery/runtime/review-packet.js +1 -1
- package/server/dist/modules/loops/runtime/loop-agent-defaults.json +6 -0
- package/server/dist/modules/loops/runtime/loop-agents.js +21 -0
- package/server/dist/modules/loops/runtime/loop-command-catalog.js +1 -1
- package/server/dist/modules/loops/runtime/loop-core-factory.js +19 -3
- package/server/dist/modules/loops/runtime/loop-definition.js +79 -12
- package/server/dist/modules/loops/runtime/loop-effect.js +1 -1
- package/server/dist/modules/loops/runtime/loop-executors.js +24 -9
- package/server/dist/modules/loops/runtime/loop-factory.js +1 -1
- package/server/dist/modules/loops/runtime/loop-graph.js +5 -14
- package/server/dist/modules/loops/runtime/loop-implement-recipe.js +49 -0
- package/server/dist/modules/loops/runtime/loop-run-manager.js +3 -3
- package/server/dist/modules/loops/runtime/loop-templates.js +29 -5
- package/server/dist/modules/loops/runtime/loops-router.js +17 -0
- package/server/dist/modules/missions/runtime/agent-context-resolver.js +1 -1
- package/server/dist/modules/missions/runtime/agent-operator-prompt.js +17 -8
- package/server/dist/modules/specs/runtime/spec-models.js +4 -7
- package/server/dist/modules/subscription-usage/adapters/claude.js +113 -0
- package/server/dist/modules/subscription-usage/adapters/codex.js +164 -0
- package/server/dist/modules/subscription-usage/adapters/errors.js +15 -0
- package/server/dist/modules/subscription-usage/adapters/http.js +20 -0
- package/server/dist/modules/subscription-usage/adapters/local-auth.js +61 -0
- package/server/dist/modules/subscription-usage/application.js +11 -0
- package/server/dist/modules/subscription-usage/domain.js +70 -0
- package/server/dist/modules/subscription-usage/index.js +2 -0
- package/server/dist/modules/subscription-usage/ports.js +2 -0
- package/server/dist/modules/subscription-usage/runtime/composition.js +20 -0
- package/server/dist/modules/subscription-usage/runtime/usage-service.js +111 -0
- package/server/dist/project-registry.js +16 -1
- package/server/dist/project-repositories.js +51 -2
- package/server/dist/project-router-helpers.js +1 -1
- package/server/dist/project-router-loop-runs.js +4 -1
- package/server/dist/providers/claude-adapter.js +6 -4
- package/server/dist/providers/codex-adapter.js +4 -5
- package/server/dist/schemas/workflow-definition.schema.json +2 -0
- package/client/dist/assets/AgentBrowserCapture-PI-cxyxi.js +0 -1
- package/client/dist/assets/AgentModeAnalyticsPane-mQsOqdXx.js +0 -2
- package/client/dist/assets/AgentModeCodePane-BL-vpmlY.js +0 -2
- package/client/dist/assets/CodePage-Alitorrv.js +0 -3
- package/client/dist/assets/DocsDialog-DwL6rgcT.js +0 -11
- package/client/dist/assets/DocsPage-BA1hiJZ-.js +0 -11
- package/client/dist/assets/InteractiveJobComposer-B3H1YHr6.js +0 -19
- package/client/dist/assets/JobDetailModal-XZQ9eAAy.js +0 -1
- package/client/dist/assets/JobDetailPage-B-SIaq_q.js +0 -1
- package/client/dist/assets/JobsPage-iQXAv2mx.js +0 -1
- package/client/dist/assets/LoopBuilderPage-B_gbFAHn.js +0 -1
- package/client/dist/assets/LoopsPage-BZwcY5cu.js +0 -2
- package/client/dist/assets/MinimizedChatsContext-CNx_0bZu.js +0 -1
- package/client/dist/assets/PluginsPage-DFocnoHX.js +0 -2
- package/client/dist/assets/ProjectSettingsDialog-Bh3S6EBB.js +0 -1
- package/client/dist/assets/RepositoryScopeSelector-C2mvWBQ6.js +0 -1
- package/client/dist/assets/ReviewPacketPage-CrAf-WDy.js +0 -4
- package/client/dist/assets/TemplatePreviewModal-C7DordpN.js +0 -1
- package/client/dist/assets/TicketDetailModalContext-B-DySpKL.js +0 -16
- package/client/dist/assets/agent-BaG10AN6.js +0 -1
- package/client/dist/assets/agent-CH4aJ884.js +0 -1
- package/client/dist/assets/agent-CLc9fA7v.js +0 -1
- package/client/dist/assets/agent-DHh9-AdL.js +0 -1
- package/client/dist/assets/agent-DkKnd6Wv.js +0 -1
- package/client/dist/assets/agent-aiVhqFW1.js +0 -1
- package/client/dist/assets/agent-dbznD3eO.js +0 -1
- package/client/dist/assets/agent-sMVFcPwL.js +0 -1
- package/client/dist/assets/agentRuntime-BeUb3g9g.js +0 -1
- package/client/dist/assets/file-text-CFT-xXKN.js +0 -1
- package/client/dist/assets/index-BS7KCWkV.css +0 -2
- package/client/dist/assets/index-C4Mv6tV6.js +0 -80
- package/client/dist/assets/integrations-CH0zy1Mw.js +0 -1
- package/client/dist/assets/integrations-CIAjhd7L.js +0 -1
- package/client/dist/assets/integrations-CZdwOe8A.js +0 -1
- package/client/dist/assets/integrations-Ct7omMld.js +0 -1
- package/client/dist/assets/integrations-D6MSxy3-.js +0 -1
- package/client/dist/assets/integrations-DbZa-Zyc.js +0 -1
- package/client/dist/assets/integrations-b8pH-vfl.js +0 -1
- package/client/dist/assets/integrations-mB-7zoyT.js +0 -1
- package/client/dist/assets/jira-api-BYbEPlkr.js +0 -1
- package/client/dist/assets/layers-eDMjG41I.js +0 -1
- package/client/dist/assets/loops-B4_D-nbg.js +0 -1
- package/client/dist/assets/nav-B-tpjyc2.js +0 -1
- package/client/dist/assets/nav-BJNXGg29.js +0 -1
- package/client/dist/assets/nav-BdhtRLP7.js +0 -1
- package/client/dist/assets/nav-ByYgyN5T.js +0 -1
- package/client/dist/assets/nav-DA0Mva2c.js +0 -1
- package/client/dist/assets/nav-DcJm_Jg_.js +0 -1
- package/client/dist/assets/nav-DhMPtAXc.js +0 -1
- package/client/dist/assets/nav-DhPb-Isc.js +0 -1
- package/client/dist/assets/provider-capabilities-Vi1ZGvAK.js +0 -1
- package/client/dist/assets/save-B6wGWwBR.js +0 -1
- package/client/dist/assets/settings-3o4Ntzi5.js +0 -1
- package/client/dist/assets/settings-B97jlkwD.js +0 -1
- package/client/dist/assets/settings-BTaT_bsS.js +0 -1
- package/client/dist/assets/settings-CT8w7WiC.js +0 -1
- package/client/dist/assets/settings-Cvr8_tvh.js +0 -1
- package/client/dist/assets/settings-Dn1qgAC8.js +0 -1
- package/client/dist/assets/settings-EShDdg4J.js +0 -1
- package/client/dist/assets/settings-tfLhQZRN.js +0 -1
- package/client/dist/assets/setup-CBMu3tqH.js +0 -1
- package/client/dist/assets/setup-CPh-e6J2.js +0 -1
- package/client/dist/assets/setup-CRKLp_ke.js +0 -1
- package/client/dist/assets/setup-Cy302v4J.js +0 -1
- package/client/dist/assets/setup-D681vTPf.js +0 -1
- package/client/dist/assets/setup-DYK0VBkE.js +0 -1
- package/client/dist/assets/setup-KAuiIiVs.js +0 -1
- package/client/dist/assets/setup-OGX-oCfI.js +0 -1
- package/client/dist/assets/useSharedWebSocket-BZMrX4jr.js +0 -2
- package/client/dist/assets/wrench-BfmNO9Vw.js +0 -1
- package/docs/agy-cli-provider-study.md +0 -257
- package/docs/gemini-cli-provider-study.md +0 -301
- package/docs/gemini-core-support-evaluation.md +0 -160
- package/docs/gemini.md +0 -257
- package/docs/kimi.md +0 -291
|
@@ -1,14 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Loop graph model + validation — the pure core shared by the canvas builder
|
|
4
|
-
* (`loop-builder-canvas`) and the publish gate (`loops-store.publishLoop`).
|
|
5
|
-
*
|
|
6
|
-
* A loop is a directed graph of typed nodes connected by edges. Cycles are
|
|
7
|
-
* allowed (a loop routes back to an earlier node); the run is bounded by the
|
|
8
|
-
* graph's `config.maxIterations` + `timeoutMinutes`. This module has NO I/O and
|
|
9
|
-
* NO provider knowledge — it only describes and validates the shape, so it is
|
|
10
|
-
* trivially unit-testable and reused verbatim by both the store and the engine.
|
|
11
|
-
*/
|
|
12
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
3
|
exports.CORE_NODE_KINDS = void 0;
|
|
14
4
|
exports.isDefinitionReviewerPath = isDefinitionReviewerPath;
|
|
@@ -24,8 +14,8 @@ exports.successors = successors;
|
|
|
24
14
|
exports.loopNeedsTicket = loopNeedsTicket;
|
|
25
15
|
exports.interpolateSpec = interpolateSpec;
|
|
26
16
|
exports.CORE_NODE_KINDS = ['prompt', 'role-turn', 'decider', 'condition', 'assign', 'verify', 'shell',
|
|
27
|
-
'openspec-validate', 'openspec-archive', 'approval', 'question', 'gate', 'map', 'join',
|
|
28
|
-
'component', 'implementation', 'end'];
|
|
17
|
+
'artifact-contract', 'openspec-validate', 'openspec-archive', 'approval', 'question', 'gate', 'map', 'join',
|
|
18
|
+
'component', 'implementation', 'implementation-step', 'end'];
|
|
29
19
|
function isDefinitionReviewerPath(graph, value) {
|
|
30
20
|
if (typeof value !== 'string' || !value || value.length > 2048)
|
|
31
21
|
return false;
|
|
@@ -38,7 +28,7 @@ function isDefinitionReviewerPath(graph, value) {
|
|
|
38
28
|
if (!node || node.type !== 'core')
|
|
39
29
|
return false;
|
|
40
30
|
if (index === segments.length - 1)
|
|
41
|
-
return node.data?.kind === 'role-turn';
|
|
31
|
+
return node.data?.kind === 'role-turn' || node.data?.kind === 'implementation-step' && node.data.params?.phase === 'reviewer';
|
|
42
32
|
const ref = node.data?.kind === 'component' ? node.data.params?.ref : node.data?.kind === 'map' ? node.data.params?.body : undefined;
|
|
43
33
|
body = typeof ref === 'string' ? graph.components?.[ref] : undefined;
|
|
44
34
|
}
|
|
@@ -176,6 +166,7 @@ function validateLoopGraph(graph, catalog) {
|
|
|
176
166
|
(cfg.maxCostUsd !== undefined && !Number.isFinite(cfg.maxCostUsd)) ||
|
|
177
167
|
(cfg.maxTransitions !== undefined && (!Number.isInteger(cfg.maxTransitions) || cfg.maxTransitions < 1 || cfg.maxTransitions > 10000)) ||
|
|
178
168
|
(cfg.maxTokens !== undefined && (!Number.isInteger(cfg.maxTokens) || cfg.maxTokens < 1)) ||
|
|
169
|
+
(cfg.ticketScope !== undefined && !['all', 'per-ticket'].includes(cfg.ticketScope)) ||
|
|
179
170
|
(cfg.reviewerStepId !== undefined && !isDefinitionReviewerPath(graph, cfg.reviewerStepId))) {
|
|
180
171
|
errors.push({
|
|
181
172
|
code: 'INVALID_CONFIG',
|
|
@@ -300,7 +291,7 @@ function loopNeedsTicket(graph) {
|
|
|
300
291
|
if (!graph)
|
|
301
292
|
return false;
|
|
302
293
|
for (const node of graph.nodes) {
|
|
303
|
-
if (node.type === 'core' && node.data?.kind
|
|
294
|
+
if (node.type === 'core' && ['implementation', 'implementation-step'].includes(node.data?.kind ?? ''))
|
|
304
295
|
return true;
|
|
305
296
|
const text = [node.data?.prompt, node.data?.command, node.data?.goal,
|
|
306
297
|
node.type === 'core' ? JSON.stringify(node.data?.params) : undefined]
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.configurableImplementGraph = configurableImplementGraph;
|
|
4
|
+
const loop_agents_1 = require("./loop-agents");
|
|
5
|
+
const objectSchema = (properties, required = Object.keys(properties)) => ({ type: 'object', properties, required, additionalProperties: false });
|
|
6
|
+
const string = { type: 'string' };
|
|
7
|
+
const strings = { type: 'array', items: string, maxItems: 100 };
|
|
8
|
+
const score = { type: 'number', minimum: 0, maximum: 100 };
|
|
9
|
+
const aspects = { type_correctness: 60, pattern_adherence: 60, test_coverage: 60, security: 75, architectural_alignment: 60 };
|
|
10
|
+
/** The recipe, roles, schemas and decisions are Desktop data, never Core phases. */
|
|
11
|
+
function configurableImplementGraph() {
|
|
12
|
+
const agents = (0, loop_agents_1.defaultLoopAgents)();
|
|
13
|
+
agents.roles = {
|
|
14
|
+
plan: { ...agents.agents.architect, access: 'read', artifacts: 'all', openspecSkill: 'openspec-ff-change', prompt: agents.rolePrompts?.architect },
|
|
15
|
+
build: { ...agents.agents.developer, access: 'write', artifacts: 'tasks-checkboxes', openspecSkill: 'openspec-apply-change', prompt: agents.rolePrompts?.developer },
|
|
16
|
+
assess: { ...agents.agents.reviewer, access: 'read', artifacts: 'none', openspecSkill: 'openspec-verify-change', prompt: agents.rolePrompts?.reviewer },
|
|
17
|
+
correct: { ...agents.fixer, access: 'write', artifacts: 'tasks-checkboxes', openspecSkill: 'openspec-apply-change', prompt: agents.rolePrompts?.fixer },
|
|
18
|
+
};
|
|
19
|
+
const nodes = [{ id: 'start', type: 'start', position: { x: 0, y: 0 } }], edges = [];
|
|
20
|
+
const node = (id, label, kind, params, outcomes) => {
|
|
21
|
+
nodes.push({ id, type: 'core', position: { x: 0, y: nodes.length * 140 }, data: { kind, label, params } });
|
|
22
|
+
for (const [outcome, target] of Object.entries(outcomes))
|
|
23
|
+
edges.push({ id: `e-${id}-${outcome}`, source: id, target, label: outcome });
|
|
24
|
+
};
|
|
25
|
+
const turn = (id, label, roleId, prompt, schema, next) => node(id, label, 'role-turn', { roleId, prompt, structuredOutput: schema, sessionContinuity: 'none' }, { next, invalid: 'failed', failed: 'failed' });
|
|
26
|
+
const change = '{{run.changeId}}';
|
|
27
|
+
turn('architect', 'Architect', 'plan', `Plan the frozen ticket requirements for OpenSpec change ${change}. Use the bound official fast-forward skill. Author complete proposal, design, delta specs and actionable tasks. Propose existing repository verification commands for repositories with no configured checks. Return confidence, question (empty when none), and verification [{repositoryId,command,args,cwd?}]. When revisiting low confidence, investigate the missing repository evidence before asking again. Context and human answers: {{history.text}}`, objectSchema({ confidence: { enum: ['high', 'medium', 'low'] }, question: string, verification: { type: 'array', maxItems: 20, items: objectSchema({ repositoryId: string, command: string, args: strings, cwd: string }, ['repositoryId', 'command', 'args']) } }), 'confidence');
|
|
28
|
+
node('confidence', 'Planning confidence', 'condition', { expr: '$outputs.architect.structured.confidence != "low"' }, { true: 'validate', false: 'investigate' });
|
|
29
|
+
node('investigate', 'Investigate low confidence once', 'condition', { expr: '!exists($vars.planInvestigated) || $vars.planInvestigated == false' }, { true: 'mark-investigated', false: 'clarify' });
|
|
30
|
+
node('mark-investigated', 'Mark confidence investigation', 'assign', { set: { planInvestigated: true } }, { next: 'architect', failed: 'failed' });
|
|
31
|
+
node('clarify', 'Clarify plan', 'question', { text: '{{outputs.architect.structured.question}}' }, { next: 'reset-confidence' });
|
|
32
|
+
node('reset-confidence', 'Reset confidence after answer', 'assign', { set: { planInvestigated: false } }, { next: 'architect', failed: 'failed' });
|
|
33
|
+
node('validate', 'Validate OpenSpec', 'openspec-validate', { change }, { pass: 'freeze', fail: 'architect', failed: 'failed' });
|
|
34
|
+
node('freeze', 'Freeze approved artifacts', 'artifact-contract', { change, contractId: 'plan', action: 'freeze' }, { pass: 'developer', fail: 'architect', failed: 'failed' });
|
|
35
|
+
const implementation = objectSchema({ summary: string, incomplete: strings });
|
|
36
|
+
turn('developer', 'Developer', 'build', `Implement every approved task for change ${change} using the bound official apply skill. Preserve proposal, design and specs; only tick tasks you completed. Report summary and incomplete task descriptions. Prior execution evidence and human answers: {{history.text}}`, implementation, 'tasks');
|
|
37
|
+
node('tasks', 'Check artifacts and completed tasks', 'artifact-contract', { change, contractId: 'plan', action: 'check', requireCompletedTasks: true }, { pass: 'verify', fail: 'developer', failed: 'failed' });
|
|
38
|
+
node('verify', 'Verify candidate', 'verify', { commands: 'configured', additionalCommandsFrom: 'architect' }, { pass: 'reviewer', fail: 'fixer', failed: 'failed' });
|
|
39
|
+
turn('reviewer', 'Reviewer', 'assess', `Review change ${change} read-only against all approved artifacts and frozen ticket acceptance criteria. Inspect real code and the host verification evidence: {{outputs.verify}}. Return approved, summary, issues, score (0-100), and aspects. Prior execution: {{history.text}}`, objectSchema({ approved: { type: 'boolean' }, summary: string, issues: strings, score, aspects: objectSchema(Object.fromEntries(Object.keys(aspects).map(aspect => [aspect, score]))) }), 'review-policy');
|
|
40
|
+
node('review-policy', 'Review acceptance policy', 'condition', { expr: ['$outputs.reviewer.structured.approved == true', '$outputs.reviewer.structured.issues.length == 0', '$outputs.reviewer.structured.score >= 70', ...Object.entries(aspects).map(([aspect, threshold]) => `$outputs.reviewer.structured.aspects.${aspect} >= ${threshold}`)].join(' && ') }, { true: 'approve', false: 'fixer' });
|
|
41
|
+
turn('fixer', 'Fixer', 'correct', `Correct only failures in change ${change}, using the bound apply skill and preserving approved artifacts. Report summary and incomplete tasks. Host verification: {{outputs.verify}}. Prior execution: {{history.text}}`, implementation, 'tasks');
|
|
42
|
+
node('approve', 'Approve archive', 'approval', { reason: `Approve archiving the reviewed and verified candidate for change ${change}.`, bindCandidate: true, enabled: agents.approvalBeforeArchive === true }, { next: 'approval-policy' });
|
|
43
|
+
node('approval-policy', 'Approval decision', 'condition', { expr: '$outputs.approve.response.approved == true' }, { true: 'archive', false: 'failed' });
|
|
44
|
+
node('archive', 'Archive OpenSpec', 'openspec-archive', { change, allowArchived: true, requiresVerified: true, reviewedCandidate: '{{outputs.reviewer.candidateHash}}', approvedCandidate: '{{outputs.approve.candidateHash}}' }, { next: 'verify-archive', failed: 'verify' });
|
|
45
|
+
node('verify-archive', 'Verify archived candidate', 'verify', { commands: 'configured', additionalCommandsFrom: 'architect' }, { pass: 'done', fail: 'failed', failed: 'failed' });
|
|
46
|
+
nodes.push({ id: 'done', type: 'end', position: { x: 0, y: nodes.length * 140 }, data: { outcome: 'success', requiresVerified: true } }, { id: 'failed', type: 'end', position: { x: 360, y: nodes.length * 140 }, data: { outcome: 'failure' } });
|
|
47
|
+
edges.unshift({ id: 'e-start', source: 'start', target: 'architect' });
|
|
48
|
+
return { nodes, edges, config: { maxIterations: 12, maxTransitions: 200, timeoutMinutes: 0, aiStepTimeoutMinutes: 0, change: 'new', journal: 'ledger-only', ticketScope: 'all', agents, reviewerStepId: 'reviewer' } };
|
|
49
|
+
}
|
|
@@ -498,7 +498,7 @@ class LoopRunManager {
|
|
|
498
498
|
if ((0, loop_graph_1.isDefinitionGraph)(graph)) {
|
|
499
499
|
if (!this.executors.runDefinition)
|
|
500
500
|
throw new Error('engine_unsupported: Core workflow execution is unavailable');
|
|
501
|
-
await this.executors.assertDefinitionSupport?.();
|
|
501
|
+
await this.executors.assertDefinitionSupport?.(graph);
|
|
502
502
|
}
|
|
503
503
|
else
|
|
504
504
|
await this.executors.assertLegacyEngineSupport?.();
|
|
@@ -1422,7 +1422,7 @@ class LoopRunManager {
|
|
|
1422
1422
|
const effectiveTimeoutMs = Number.isFinite(remainingMs)
|
|
1423
1423
|
? Math.max(1, Math.min(aiStepTimeoutMs === 0 ? Infinity : (aiStepTimeoutMs ?? 15 * 60_000), remainingMs))
|
|
1424
1424
|
: aiStepTimeoutMs;
|
|
1425
|
-
const coreRun = { runId, implementation: requiresCoreCompletion, spec: req.spec, goal: req.spec ? undefined : JSON.stringify({ loop: req.loopName, graph: req.graph }), repositoryId: req.repositoryId, verificationStep: node.data?.requireVerificationPass === true || /\{\{\s*cmd:(?:verify|revision-verify|opsx:verify)\s*\}\}/.test(rawTemplate) };
|
|
1425
|
+
const coreRun = { runId, implementation: requiresCoreCompletion, spec: req.spec, goal: req.spec ? undefined : JSON.stringify({ loop: req.loopName, graph: req.graph }), repositoryId: req.repositoryId, workspacePaths: req.workspacePaths, verificationStep: node.data?.requireVerificationPass === true || /\{\{\s*cmd:(?:verify|revision-verify|opsx:verify)\s*\}\}/.test(rawTemplate) };
|
|
1426
1426
|
const interactivePlan = this.executors.planInteractiveAiStep?.({
|
|
1427
1427
|
coreRun,
|
|
1428
1428
|
provider: nodeProvider,
|
|
@@ -1552,7 +1552,7 @@ class LoopRunManager {
|
|
|
1552
1552
|
&& requiresCoreCompletion
|
|
1553
1553
|
&& this.executors.validateCoreCompletion) {
|
|
1554
1554
|
const completion = this.executors.validateCoreCompletion({
|
|
1555
|
-
coreRun: { runId, spec: req.spec, goal: req.spec ? undefined : JSON.stringify({ loop: req.loopName, graph: req.graph }), repositoryId: req.repositoryId },
|
|
1555
|
+
coreRun: { runId, spec: req.spec, goal: req.spec ? undefined : JSON.stringify({ loop: req.loopName, graph: req.graph }), repositoryId: req.repositoryId, workspacePaths: req.workspacePaths },
|
|
1556
1556
|
provider: nodeProvider, model: nodeModel, effort: nodeEffort, profileName: req.profileName,
|
|
1557
1557
|
cwd: req.cwd, repoDir: req.repoDir, executionManifest: req.executionManifest,
|
|
1558
1558
|
});
|
|
@@ -8,6 +8,8 @@ exports.coreStarterGraph = coreStarterGraph;
|
|
|
8
8
|
exports.supportsCoreTemplates = supportsCoreTemplates;
|
|
9
9
|
exports.loopTemplatesForCapabilities = loopTemplatesForCapabilities;
|
|
10
10
|
exports.getLoopTemplate = getLoopTemplate;
|
|
11
|
+
const loop_core_factory_1 = require("./loop-core-factory");
|
|
12
|
+
const loop_agents_1 = require("./loop-agents");
|
|
11
13
|
/** Closed taxonomy a template's `category` must belong to. Single source of truth
|
|
12
14
|
* for the gallery's category chips (the client derives its chip list from the
|
|
13
15
|
* categories actually present in the served catalog). */
|
|
@@ -303,7 +305,8 @@ exports.LEGACY_LOOP_TEMPLATES = exports.LOOP_TEMPLATES;
|
|
|
303
305
|
// - every mutating starter runs the real `verify` piece over the project's
|
|
304
306
|
// configured checks and ends with `requiresVerified: true` — a passing sentinel
|
|
305
307
|
// alone never reaches a success end;
|
|
306
|
-
// - ship-and-green
|
|
308
|
+
// - ship-and-green expands implementation operations when supported, then
|
|
309
|
+
// verify → decider → prompt(fix); old Core retains the compatibility wrapper;
|
|
307
310
|
// - prompts, goals and iteration caps come from STARTER_TEXT (legacy parity).
|
|
308
311
|
/** Fix step shared by every mutating Core starter. Reuses the tuned `{{cmd:fix}}`
|
|
309
312
|
* contract and covers the verify→fix edge, where no Decider verdict precedes it. */
|
|
@@ -324,7 +327,7 @@ function watcherVerdict(goal) {
|
|
|
324
327
|
const CORE_GOAL_EVIDENCE = 'The configured host verification already passed on the current candidate before this decision. Judge only from concrete evidence in the history (commands run, their output, files changed); green baseline checks, setup or planning alone do not prove the goal.';
|
|
325
328
|
const SHIP_AND_GREEN_GOAL = 'Stop only when the history proves the spec is implemented: every acceptance criterion maps to real code and behavioral evidence across every selected ticket and repository, and the configured host verification passed on the current candidate. Setup, planning, a launched subagent or green baseline checks alone are insufficient; continue when work is missing or incomplete.';
|
|
326
329
|
/** Wall-clock cap for starters (legacy default). ship-and-green is untimed like the
|
|
327
|
-
* Implement factory:
|
|
330
|
+
* Implement factory: implementation operations retain their own execution limits. */
|
|
328
331
|
const STARTER_TIMEOUT_MIN = 30;
|
|
329
332
|
const CORE_STARTER_SHAPES = {
|
|
330
333
|
'ship-and-green': 'ship',
|
|
@@ -338,8 +341,10 @@ const CORE_STARTER_SHAPES = {
|
|
|
338
341
|
};
|
|
339
342
|
/** Core definition graph for one of the eight starters. Deterministic: same id ⇒
|
|
340
343
|
* structurally identical graph (positions included). */
|
|
341
|
-
function coreStarterGraph(id) {
|
|
344
|
+
function coreStarterGraph(id, independent = false, configurable = false) {
|
|
342
345
|
const shape = CORE_STARTER_SHAPES[id];
|
|
346
|
+
if (shape === 'ship' && configurable)
|
|
347
|
+
return (0, loop_core_factory_1.coreFactoryGraph)('implement', true, true);
|
|
343
348
|
const { prompt, goal, maxIterations } = STARTER_TEXT[id];
|
|
344
349
|
const nodes = [{ id: 'start', type: 'start', position: { x: COL_X, y: 0 } }];
|
|
345
350
|
const edges = [];
|
|
@@ -381,10 +386,29 @@ function coreStarterGraph(id) {
|
|
|
381
386
|
}
|
|
382
387
|
edges.unshift({ id: 'e-start', source: 'start', target: entry });
|
|
383
388
|
nodes.push({ id: 'done', type: 'end', position: { x: COL_X, y: ROW_GAP * nodes.length }, data: successEnd }, { id: 'failed', type: 'end', position: { x: COL_RIGHT_X, y: ROW_GAP * nodes.length }, data: { outcome: 'failure' } });
|
|
389
|
+
if (independent) {
|
|
390
|
+
config.agents = (0, loop_agents_1.defaultLoopAgents)(shape === 'ship' ? 'implementation' : 'free');
|
|
391
|
+
if (shape === 'ship') {
|
|
392
|
+
const operations = (0, loop_core_factory_1.coreFactoryGraph)('implement', true);
|
|
393
|
+
const path = (id) => id === 'done' ? 'verify' : id === 'failed' ? 'failed' : `implementation-${id}`;
|
|
394
|
+
nodes.splice(nodes.findIndex(node => node.id === 'implement'), 1);
|
|
395
|
+
const remove = new Set(edges.filter(edge => edge.source === 'implement').map(edge => edge.id));
|
|
396
|
+
for (let i = edges.length - 1; i >= 0; i--)
|
|
397
|
+
if (remove.has(edges[i].id))
|
|
398
|
+
edges.splice(i, 1);
|
|
399
|
+
for (const edge of edges)
|
|
400
|
+
if (edge.target === 'implement')
|
|
401
|
+
edge.target = path('architect');
|
|
402
|
+
for (const node of operations.nodes.filter(node => node.type === 'core'))
|
|
403
|
+
nodes.push({ ...node, id: path(node.id) });
|
|
404
|
+
for (const edge of operations.edges.filter(edge => edge.source !== 'start'))
|
|
405
|
+
edges.push({ ...edge, id: 'implementation-' + edge.id, source: path(edge.source), target: path(edge.target) });
|
|
406
|
+
}
|
|
407
|
+
}
|
|
384
408
|
return { nodes, edges, config };
|
|
385
409
|
}
|
|
386
410
|
const CORE_STARTER_DESCRIPTIONS = {
|
|
387
|
-
'ship-and-green': 'Fully autonomous: run
|
|
411
|
+
'ship-and-green': 'Fully autonomous: run the loop\'s implementation steps for the spec, then verify with the project\'s configured checks and refine (fix) on failure — verify → decide → fix until green. Success requires a verified candidate; no human intervention.',
|
|
388
412
|
'verify-pass': 'Autonomous verify-and-fix: run the project\'s configured build/lint/tests through Core\'s verify piece, then refine on failure — verify → fix → verify until green.',
|
|
389
413
|
'ci-watch': 'Poll CI checks on the open PR (the agent uses the repo\'s CI tooling) until every check is green. Read-only: the watcher never edits the repository.',
|
|
390
414
|
'lint-and-fix': 'The agent detects and runs the project\'s linter and fixes every issue, iterating until the codebase is clean. Every pass is confirmed by the project\'s configured verification before the loop can succeed.',
|
|
@@ -414,7 +438,7 @@ function loopTemplatesForCapabilities(capabilities) {
|
|
|
414
438
|
...template,
|
|
415
439
|
description: CORE_STARTER_DESCRIPTIONS[template.id],
|
|
416
440
|
...(readOnly ? { readOnly: true } : {}),
|
|
417
|
-
graph: coreStarterGraph(template.id),
|
|
441
|
+
graph: coreStarterGraph(template.id, capabilities?.implementationSteps === 1, capabilities?.workflowAgentSteps === 1),
|
|
418
442
|
};
|
|
419
443
|
});
|
|
420
444
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.registerLoopsRoutes = registerLoopsRoutes;
|
|
4
|
+
const loop_agents_1 = require("./loop-agents");
|
|
5
|
+
const agent_runtime_settings_1 = require("../../agent-runtime/runtime/agent-runtime-settings");
|
|
4
6
|
const ids_1 = require("../../../ids");
|
|
5
7
|
const feature_flags_1 = require("../../../feature-flags");
|
|
6
8
|
const loops_store_1 = require("./loops-store");
|
|
@@ -57,6 +59,12 @@ function registerLoopsRoutes(router, deps) {
|
|
|
57
59
|
}
|
|
58
60
|
return true;
|
|
59
61
|
}
|
|
62
|
+
router.get('/loop-agent-defaults', async (_req, res) => {
|
|
63
|
+
if (!guard(res))
|
|
64
|
+
return;
|
|
65
|
+
const runtime = await (0, agent_runtime_loader_1.loadCoreAgentRuntime)().catch(() => null);
|
|
66
|
+
res.json({ agents: (0, loop_agents_1.defaultLoopAgents)(), guardrails: { supported: runtime?.api?.capabilities?.configurableGuardrails === 1, catalog: runtime?.api?.guardrails ?? [] } });
|
|
67
|
+
});
|
|
60
68
|
// ── Templates ──────────────────────────────────────────────────────────────
|
|
61
69
|
router.get('/loop-templates', async (_req, res) => {
|
|
62
70
|
if (!guard(res))
|
|
@@ -410,6 +418,15 @@ function registerLoopsRoutes(router, deps) {
|
|
|
410
418
|
res.status(409).json({ error: 'engine_unsupported', message: 'Update Core to publish executable workflows.' });
|
|
411
419
|
return;
|
|
412
420
|
}
|
|
421
|
+
if (current.graph.config.agents) {
|
|
422
|
+
try {
|
|
423
|
+
(0, agent_runtime_settings_1.validateLoopRuntimeSettings)(current.graph.config.agents);
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
res.status(422).json({ error: 'invalid_loop_agents', message: error instanceof Error ? error.message : 'Invalid loop agent settings' });
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
413
430
|
let draft;
|
|
414
431
|
try {
|
|
415
432
|
draft = (0, loop_definition_1.compileLoopToDefinition)(current.graph, { id: current.id, title: current.name, constants: (0, loop_constants_1.loadConstantMap)(db), provider: 'claude', spec: { id: 1, title: 'Sample spec', description: 'Publication preview' } });
|
|
@@ -149,7 +149,7 @@ function formatProjectOverview(ref, index, deps) {
|
|
|
149
149
|
lines.push('resolution: unresolved project');
|
|
150
150
|
return lines.join('\n');
|
|
151
151
|
}
|
|
152
|
-
lines.push(`project.id: ${project.id}`, `project.name: ${safe(project.name, 180)}`, `project.slug: ${safe(project.slug, 120)}`, `project.path: ${project.path}`, `project.provider: ${safe(project.provider, 80)}`, `project.providers: ${(project.providers ?? [project.provider]).join(', ')}`, `project.runtime: ${context ? 'available' : 'unavailable; do not interpret this as a deleted project'}`, `project.repositories: ${JSON.stringify((0, project_repositories_1.getProjectRepositories)(project).map(repository => ({ id: repository.id, name: repository.name, path: repository.path, isPrimary: repository.isPrimary, kind: repository.kind, available: repository.available })))}`, 'repository.scope: One shared project backlog. Files and Git operations require repositoryId when more than one member exists; find/search can discover across members. Reading context does not grant implementation write access. Historical specs without repositoryIds target only the primary.');
|
|
152
|
+
lines.push(`project.id: ${project.id}`, `project.name: ${safe(project.name, 180)}`, `project.slug: ${safe(project.slug, 120)}`, `project.path: ${project.path}`, `project.provider: ${safe(project.provider, 80)}`, `project.providers: ${(project.providers ?? [project.provider]).join(', ')}`, `project.runtime: ${context ? 'available' : 'unavailable; do not interpret this as a deleted project'}`, `project.repositories: ${JSON.stringify((0, project_repositories_1.getProjectRepositories)(project).map(repository => ({ id: repository.id, name: repository.name, path: repository.path, workspacePaths: repository.workspacePaths ?? [repository.workspacePath ?? repository.path], isPrimary: repository.isPrimary, kind: repository.kind, available: repository.available })))}`, 'repository.scope: One shared project backlog. Files and Git operations require repositoryId when more than one member exists; find/search can discover across members. Reading context does not grant implementation write access. Historical specs without repositoryIds target only the primary.');
|
|
153
153
|
try {
|
|
154
154
|
const tickets = Object.values((0, ticket_store_1.readStore)(ticketFileFor(project)).tickets);
|
|
155
155
|
const counts = tickets.reduce((acc, ticket) => {
|
|
@@ -628,6 +628,13 @@ summary later.
|
|
|
628
628
|
N-1. When talking to the user ALWAYS use the 1-based label (tool results
|
|
629
629
|
include \`railLabel\`, e.g. railIndex 3 → "Rail 4") or the rail's custom name;
|
|
630
630
|
never quote the raw railIndex as the rail's name.
|
|
631
|
+
- Code workspace selection: discover \`workspacePaths\` in the project context. A
|
|
632
|
+
project folder can contain several code workspaces; tests must run in the
|
|
633
|
+
workspace being changed. Include \`workspaceSelection\` (repository ID → array
|
|
634
|
+
of registered workspace paths) in rail-launch cards and direct launch calls to
|
|
635
|
+
target a subset. Preserve \`repositoryIds\` for affected Git memberships. Do not
|
|
636
|
+
invent paths or substitute the parent folder. Omission uses every configured
|
|
637
|
+
workspace for each affected membership.
|
|
631
638
|
- Configure then launch: \`specrails_rails(set_tickets, railIndex, ticketIds)\` →
|
|
632
639
|
\`specrails_rails(launch, railIndex, mode, …)\`. Setting a profile and then
|
|
633
640
|
switching the rail's engine to a provider without profile support
|
|
@@ -657,15 +664,15 @@ summary later.
|
|
|
657
664
|
relaunch strategy even when \`main\` did not have that spec before the PR. If
|
|
658
665
|
asked why a strategy was chosen, verify against active PR contents before
|
|
659
666
|
answering.
|
|
660
|
-
- **"Change something about work already delivered" = a
|
|
667
|
+
- **"Change something about work already delivered" = a delivery continuation.** When
|
|
661
668
|
the user asks for a modification to a delivery that is awaiting their decision
|
|
662
669
|
(any non-terminal card: \`on_review\`, \`pr_draft\`, \`pr_ready\`, \`no_changes\`,
|
|
663
670
|
\`implementation_failed\`), call \`specrails_rails(launch)\` with
|
|
664
671
|
\`revisionOfDeliveryId\` = that card's \`prDeliveryId\` and \`revisionNote\` = what
|
|
665
672
|
they asked for, in their own words. Do NOT tell them to publish, discard or
|
|
666
|
-
merge first
|
|
667
|
-
|
|
668
|
-
|
|
673
|
+
merge first. Respect the user's explicit loop selection, including Implement:
|
|
674
|
+
pass that loopId alongside the delivery target. Without a preference, use
|
|
675
|
+
\`loopId:'factory:sdd-quick-openspec'\`. The server preserves the branch. The rail must still carry exactly that delivery's
|
|
669
676
|
specs; a mismatch returns \`invalid_revision_target\`, which means re-check the
|
|
670
677
|
rail's spec assignment rather than retrying blindly.
|
|
671
678
|
- **"Resolve / fix the review comments on this PR" = a FOLLOW-UP launch, never a
|
|
@@ -706,9 +713,9 @@ summary later.
|
|
|
706
713
|
\`dismiss_addendum\` withdraws it. Prefer an addendum + normal launch over a
|
|
707
714
|
\`revisionNote\` when the change should stay attached to the spec for later
|
|
708
715
|
runs; the two combine freely.
|
|
709
|
-
**
|
|
710
|
-
|
|
711
|
-
|
|
716
|
+
**Respect explicit loop selection for addenda**, including Implement.
|
|
717
|
+
Recommend Quick SDD when no preference was given; never silently replace
|
|
718
|
+
Implement with Quick SDD after agreeing to use Implement. A same-spec pending delivery is
|
|
712
719
|
continued without requiring publish/discard first. Keep the exact ticket and
|
|
713
720
|
repository scope; pass the delivery id when known. The runtime assigns a NEW
|
|
714
721
|
run-specific OpenSpec change for the frozen addenda, so NEVER edit
|
|
@@ -889,6 +896,8 @@ never as a launch):
|
|
|
889
896
|
\`null\` means "the rail's / project's default".
|
|
890
897
|
- \`targetPrNumber\` / \`baseBranch\`: only when the user named an existing PR
|
|
891
898
|
or a branch to stack on.
|
|
899
|
+
- \`repositoryIds\`: selected registered repository memberships, consistent with the specs.
|
|
900
|
+
- \`workspaceSelection\`: optional object mapping each selected repository id to a non-empty array of registered workspace paths. Discover paths from project context; never invent them. Omission uses every configured workspace. The card lets the user edit this choice before Play.
|
|
892
901
|
- \`rationale\`: ONE sentence — why this grouping / engine.
|
|
893
902
|
|
|
894
903
|
Prose around the block: say what you propose in one or two lines and stop —
|
|
@@ -916,7 +925,7 @@ investigate and fix. Read runtime_diagnose before recommending a retry.
|
|
|
916
925
|
function buildOperatorInstructions() {
|
|
917
926
|
return (0, feature_flags_1.isMissionRailCardsEnabled)() ? `${exports.OPERATOR_INSTRUCTIONS}\n${exports.RAIL_LAUNCH_CARD_SECTION}` : exports.OPERATOR_INSTRUCTIONS;
|
|
918
927
|
}
|
|
919
|
-
exports.RAIL_LAUNCH_CARD_SYSTEM_CLAUSE = ' When the user asks to assign, prepare or launch specs on a rail WITHOUT explicitly saying to launch now, do not call specrails_rails launch — emit one fenced rail-launch JSON block per rail (ticketIds, railIndex or newRail, mode, loopId, aiEngine, model, reasoningEffort, profileName, rationale) so the app renders an editable launch card the user plays; never propose a rail whose availability is not free. A message starting with "[Specrails run-failure briefing" is app-posted: answer in ≤ 6 lines with the failure and ONE recommended next action, and never resume, recover, relaunch or discard in that turn.';
|
|
928
|
+
exports.RAIL_LAUNCH_CARD_SYSTEM_CLAUSE = ' When the user asks to assign, prepare or launch specs on a rail WITHOUT explicitly saying to launch now, do not call specrails_rails launch — emit one fenced rail-launch JSON block per rail (ticketIds, railIndex or newRail, mode, loopId, aiEngine, model, reasoningEffort, profileName, repositoryIds, workspaceSelection, rationale) so the app renders an editable launch card the user plays; never propose a rail whose availability is not free. A message starting with "[Specrails run-failure briefing" is app-posted: answer in ≤ 6 lines with the failure and ONE recommended next action, and never resume, recover, relaunch or discard in that turn.';
|
|
920
929
|
/** The per-turn system prompt (flag-aware). */
|
|
921
930
|
function buildOperatorSystemPrompt() {
|
|
922
931
|
return (0, feature_flags_1.isMissionRailCardsEnabled)() ? `${exports.OPERATOR_SYSTEM_PROMPT}${exports.RAIL_LAUNCH_CARD_SYSTEM_CLAUSE}` : exports.OPERATOR_SYSTEM_PROMPT;
|
|
@@ -6,20 +6,17 @@ exports.isValidModelForProvider = isValidModelForProvider;
|
|
|
6
6
|
exports.getProviderDefault = getProviderDefault;
|
|
7
7
|
const providers_1 = require("../../../providers");
|
|
8
8
|
exports.CLAUDE_MODELS = [
|
|
9
|
-
{ value: 'sonnet', label: '
|
|
10
|
-
{ value: 'fable', label: '
|
|
9
|
+
{ value: 'sonnet', label: 'Sonnet 5.5' },
|
|
10
|
+
{ value: 'fable', label: 'Fable 5.1' },
|
|
11
11
|
{ value: 'opus', label: 'Claude Opus' },
|
|
12
12
|
{ value: 'haiku', label: 'Claude Haiku' },
|
|
13
13
|
];
|
|
14
14
|
exports.CODEX_MODELS = [
|
|
15
|
+
{ value: 'gpt-6.1-sol', label: 'GPT-6.1 Sol' },
|
|
15
16
|
{ value: 'gpt-6-astra', label: 'GPT-6 Astra' },
|
|
16
17
|
{ value: 'gpt-5.6-sol', label: 'GPT-5.6 Sol' },
|
|
17
18
|
{ value: 'gpt-5.6-terra', label: 'GPT-5.6 Terra' },
|
|
18
19
|
{ value: 'gpt-5.6-luna', label: 'GPT-5.6 Luna' },
|
|
19
|
-
{ value: 'gpt-5.5', label: 'GPT-5.5' },
|
|
20
|
-
{ value: 'gpt-5.4', label: 'GPT-5.4' },
|
|
21
|
-
{ value: 'gpt-5.4-mini', label: 'GPT-5.4 Mini' },
|
|
22
|
-
{ value: 'gpt-5.3-codex', label: 'GPT-5.3 Codex' },
|
|
23
20
|
];
|
|
24
21
|
// Mirrors GEMINI_MODELS in server/providers/gemini-adapter.ts.
|
|
25
22
|
exports.GEMINI_MODELS = [
|
|
@@ -43,7 +40,7 @@ const PROVIDER_MODELS = {
|
|
|
43
40
|
};
|
|
44
41
|
exports.PROVIDER_DEFAULT_MODEL = {
|
|
45
42
|
claude: 'sonnet',
|
|
46
|
-
codex: 'gpt-
|
|
43
|
+
codex: 'gpt-6.1-sol',
|
|
47
44
|
gemini: 'gemini-3.5-flash',
|
|
48
45
|
kimi: 'k3',
|
|
49
46
|
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createClaudeReader = createClaudeReader;
|
|
7
|
+
const node_child_process_1 = require("node:child_process");
|
|
8
|
+
const node_os_1 = require("node:os");
|
|
9
|
+
const promises_1 = require("node:fs/promises");
|
|
10
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
+
const domain_1 = require("../domain");
|
|
12
|
+
const errors_1 = require("./errors");
|
|
13
|
+
const local_auth_1 = require("./local-auth");
|
|
14
|
+
function readKeychain(service, signal) {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
let account;
|
|
17
|
+
try {
|
|
18
|
+
account = process.env.USER || process.env.USERNAME || (0, node_os_1.userInfo)().username;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
account = 'claude-code-user';
|
|
22
|
+
}
|
|
23
|
+
if (!/^[a-zA-Z0-9._-]+$/.test(account))
|
|
24
|
+
account = 'claude-code-user';
|
|
25
|
+
(0, node_child_process_1.execFile)('/usr/bin/security', ['find-generic-password', '-s', service, '-a', account, '-w'], { timeout: 3000, maxBuffer: 1024 * 1024, signal }, (error, stdout) => {
|
|
26
|
+
if (!error)
|
|
27
|
+
resolve(stdout);
|
|
28
|
+
else if (error.code === 44)
|
|
29
|
+
resolve(null);
|
|
30
|
+
else
|
|
31
|
+
reject(new errors_1.UsageError('credentials-unreadable'));
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function createClaudeReader(options = {}) {
|
|
36
|
+
const configured = options.configDir ?? process.env.CLAUDE_CONFIG_DIR;
|
|
37
|
+
const configDir = configured ?? node_path_1.default.join((0, node_os_1.homedir)(), '.claude');
|
|
38
|
+
async function credentials(signal) {
|
|
39
|
+
if (!node_path_1.default.isAbsolute(configDir))
|
|
40
|
+
throw new errors_1.UsageError('unsupported-platform');
|
|
41
|
+
let keychainFailure = false;
|
|
42
|
+
if ((options.platform ?? process.platform) === 'darwin') {
|
|
43
|
+
const aliases = configured ? [configDir] : [];
|
|
44
|
+
if (configured) {
|
|
45
|
+
try {
|
|
46
|
+
const canonical = await (0, promises_1.realpath)(configDir);
|
|
47
|
+
if (canonical !== configDir)
|
|
48
|
+
aliases.push(canonical);
|
|
49
|
+
}
|
|
50
|
+
catch { /* use the exact resolved context */ }
|
|
51
|
+
}
|
|
52
|
+
const services = configured ? aliases.map(dir => `Claude Code-credentials-${(0, local_auth_1.fingerprint)(dir.normalize('NFC')).slice(0, 8)}`) : ['Claude Code-credentials'];
|
|
53
|
+
for (const service of services) {
|
|
54
|
+
try {
|
|
55
|
+
const raw = await (options.keychain ?? readKeychain)(service, signal);
|
|
56
|
+
if (raw)
|
|
57
|
+
return raw;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
keychainFailure = true;
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const file = await (options.readFile ?? local_auth_1.readAuthFile)(node_path_1.default.join(configDir, '.credentials.json'));
|
|
66
|
+
if (file)
|
|
67
|
+
return file;
|
|
68
|
+
if (keychainFailure)
|
|
69
|
+
throw new errors_1.UsageError('credentials-unreadable');
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
async context(signal) { return (0, local_auth_1.fingerprint)(`${configDir}:${await credentials(signal) ?? 'none'}`); },
|
|
74
|
+
async read(signal) {
|
|
75
|
+
const raw = await credentials(signal);
|
|
76
|
+
if (!raw)
|
|
77
|
+
return { availability: 'signed-out', windows: [], plan: null, source: null };
|
|
78
|
+
let data;
|
|
79
|
+
try {
|
|
80
|
+
data = (0, domain_1.record)(JSON.parse(raw));
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
throw new errors_1.UsageError('credentials-unreadable');
|
|
84
|
+
}
|
|
85
|
+
const oauth = (0, domain_1.record)(data.claudeAiOauth);
|
|
86
|
+
if (typeof oauth.accessToken !== 'string' || !oauth.accessToken)
|
|
87
|
+
return { availability: 'unsupported-auth', windows: [], plan: null, source: null };
|
|
88
|
+
const response = await (options.request ?? fetch)('https://api.anthropic.com/api/oauth/usage', {
|
|
89
|
+
headers: { Authorization: `Bearer ${oauth.accessToken}`, 'anthropic-beta': 'oauth-2025-04-20', 'User-Agent': 'claude-code/2.1.0' },
|
|
90
|
+
signal: AbortSignal.any([signal, AbortSignal.timeout(10_000)]), redirect: 'error',
|
|
91
|
+
});
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
await response.body?.cancel().catch(() => { });
|
|
94
|
+
if (response.status === 401)
|
|
95
|
+
throw new errors_1.UsageError('signed-out');
|
|
96
|
+
if (response.status === 403)
|
|
97
|
+
throw new errors_1.UsageError('permission-denied');
|
|
98
|
+
if (response.status === 429) {
|
|
99
|
+
const header = response.headers.get('retry-after');
|
|
100
|
+
const seconds = header !== null && header.trim() !== '' ? Number(header) : NaN;
|
|
101
|
+
const date = header ? Date.parse(header) : NaN;
|
|
102
|
+
const retry = Number.isFinite(seconds) ? seconds * 1000 : Number.isFinite(date) ? date - Date.now() : 60_000;
|
|
103
|
+
throw new errors_1.UsageError('rate-limited', true, Math.max(30_000, Math.min(24 * 60 * 60_000, retry)));
|
|
104
|
+
}
|
|
105
|
+
throw new errors_1.UsageError('provider-error', response.status >= 500);
|
|
106
|
+
}
|
|
107
|
+
const payload = await (0, local_auth_1.limitedJson)(response), windows = (0, domain_1.normalizeClaude)(payload);
|
|
108
|
+
if (!windows.length)
|
|
109
|
+
throw new errors_1.UsageError('usage-unavailable');
|
|
110
|
+
return { availability: 'available', windows, plan: null, source: 'oauth' };
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|