specrails-desktop 2.46.0 → 2.48.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 -0
- package/client/dist/assets/{ActivityFeedPage-CsHQPpvl.js → ActivityFeedPage-CGq6QhP5.js} +1 -1
- package/client/dist/assets/AgentBrowserCapture-C4GZ-kdf.js +1 -0
- package/client/dist/assets/AgentModeAnalyticsPane-_IPmL0ZS.js +2 -0
- package/client/dist/assets/AgentModeCodePane-B5WG5DOP.js +2 -0
- package/client/dist/assets/{AgentModeJobsPane-rnD-EPMd.js → AgentModeJobsPane-w1N_HIXh.js} +1 -1
- package/client/dist/assets/AgentsPage-CmwnnT46.js +87 -0
- package/client/dist/assets/AnalyticsPage-BUMsKtsJ.js +1 -0
- package/client/dist/assets/CodePage-PjgywJPS.js +3 -0
- package/client/dist/assets/DesktopAnalyticsPage-BXY1pH4y.js +1 -0
- package/client/dist/assets/DocsDialog-ccQETHKB.js +11 -0
- package/client/dist/assets/DocsPage-DzEgplB3.js +11 -0
- package/client/dist/assets/{ExportDropdown-pWZGYCv3.js → ExportDropdown-B8bBGopr.js} +1 -1
- package/client/dist/assets/InteractiveJobComposer-CEwGkJ8F.js +19 -0
- package/client/dist/assets/JobDetailModal-BYXmuTDe.js +1 -0
- package/client/dist/assets/JobDetailPage-CWp6MwJj.js +1 -0
- package/client/dist/assets/JobsPage-D1O1uyG8.js +1 -0
- package/client/dist/assets/{LoopBuilderPage-CtmOE4-b.js → LoopBuilderPage-DQE-7Vby.js} +2 -2
- package/client/dist/assets/{LoopPreviewModal-BYeLjQbr.js → LoopPreviewModal-Bk7zIXD5.js} +1 -1
- package/client/dist/assets/LoopsPage-CqG7mx56.js +1 -0
- package/client/dist/assets/MinimizedChatsContext-UpnqccPx.js +1 -0
- package/client/dist/assets/PluginsPage-CjgVvmpW.js +2 -0
- package/client/dist/assets/{ProjectSettingsDialog-DsCRIc4v.js → ProjectSettingsDialog-D6vBCoay.js} +1 -1
- package/client/dist/assets/{RepositoryDeliveries-BQm_3TO8.js → RepositoryDeliveries-C36ipKp_.js} +1 -1
- package/client/dist/assets/{RepositoryScopeSelector-DnAFtjTz.js → RepositoryScopeSelector-0Gz_fR1E.js} +1 -1
- package/client/dist/assets/ReviewPacketPage-Dr9RYs7q.js +1 -0
- package/client/dist/assets/TemplatePreviewModal-sCMHYFJo.js +1 -0
- package/client/dist/assets/TicketDetailModalContext-C5GgJlEt.js +14 -0
- package/client/dist/assets/{Trans-BwLgX6n7.js → Trans-9pHTy2fH.js} +1 -1
- package/client/dist/assets/{addspec-D2YIQ0GU.js → addspec-BOvgmcgk.js} +1 -1
- package/client/dist/assets/{addspec-B_TPJt-R.js → addspec-Clmyfn_R.js} +1 -1
- package/client/dist/assets/{addspec-A1lDQa4M.js → addspec-CsNaBpHp.js} +1 -1
- package/client/dist/assets/{addspec-CQBjzt24.js → addspec-D2tvWmmV.js} +1 -1
- package/client/dist/assets/{addspec-CLYLvaVP.js → addspec-D3nFwvD0.js} +1 -1
- package/client/dist/assets/{addspec-BPpZ_olp.js → addspec-DVLEhK3w.js} +1 -1
- package/client/dist/assets/{addspec-iFdQ6D99.js → addspec-DXbK-tb0.js} +1 -1
- package/client/dist/assets/{addspec-BHZd0N5F.js → addspec-OHG8DFEn.js} +1 -1
- package/client/dist/assets/agentRuntime-BUimiX__.js +1 -0
- package/client/dist/assets/agentRuntime-BcN97sAB.js +1 -0
- package/client/dist/assets/agentRuntime-Ckyg-ahT.js +1 -0
- package/client/dist/assets/agentRuntime-DJCwyX4t.js +1 -0
- package/client/dist/assets/agentRuntime-DVzPJOl0.js +1 -0
- package/client/dist/assets/agentRuntime-V9AZTG3c.js +1 -0
- package/client/dist/assets/agentRuntime-bAAjw1vw.js +1 -0
- package/client/dist/assets/agentRuntime-v4qKAYH-.js +1 -0
- package/client/dist/assets/{agents-45GbINfh.js → agents-CA5eT1d0.js} +1 -1
- package/client/dist/assets/{agents-DMKFStHL.js → agents-CAgy-5uS.js} +1 -1
- package/client/dist/assets/{agents-IUOgqT5t.js → agents-CNm6Qzlv.js} +1 -1
- package/client/dist/assets/{agents-ms7TwG16.js → agents-CTwbx-fb.js} +1 -1
- package/client/dist/assets/{agents-DaYcxAr1.js → agents-DEGV1Vao.js} +1 -1
- package/client/dist/assets/{agents-BHp0_FQt.js → agents-HsDF1aQU.js} +1 -1
- package/client/dist/assets/{agents-Bvyi3y6R.js → agents-IQjdA-z9.js} +1 -1
- package/client/dist/assets/{agents-rzPnqoBR.js → agents-RkGoteXh.js} +1 -1
- package/client/dist/assets/analytics-BNgZ1Nj7.js +1 -0
- package/client/dist/assets/analytics-BlypLLR6.js +1 -0
- package/client/dist/assets/analytics-CoEzWPx4.js +1 -0
- package/client/dist/assets/analytics-DFh5lSOl.js +1 -0
- package/client/dist/assets/analytics-DZp-DS2U.js +1 -0
- package/client/dist/assets/analytics-DjLlE7jS.js +1 -0
- package/client/dist/assets/analytics-jzCkOec3.js +1 -0
- package/client/dist/assets/analytics-nZIjjtCc.js +1 -0
- package/client/dist/assets/{dashboard-BK_mez-z.js → dashboard-C29Qwa-L.js} +1 -1
- package/client/dist/assets/{dashboard-BwkjxI6H.js → dashboard-CSJzf5OT.js} +1 -1
- package/client/dist/assets/{dashboard-C3bDKf7s.js → dashboard-CTfEtkqX.js} +1 -1
- package/client/dist/assets/{dashboard-Bt0cCzeG.js → dashboard-Cr4D8oMn.js} +1 -1
- package/client/dist/assets/{dashboard-fRrP0Kv0.js → dashboard-Csf1yGSN.js} +1 -1
- package/client/dist/assets/{dashboard-CdvjGfog.js → dashboard-D40HP2ks.js} +1 -1
- package/client/dist/assets/dashboard-DBAP2_SQ.js +1 -0
- package/client/dist/assets/{dashboard-B14uYXkG.js → dashboard-DMklepmz.js} +1 -1
- package/client/dist/assets/file-text-CFT-xXKN.js +1 -0
- package/client/dist/assets/{formatDistanceToNow-CeZv93iR.js → formatDistanceToNow-w_2U5pm0.js} +1 -1
- package/client/dist/assets/{getTimezoneOffsetInMilliseconds-DxAkjvJb.js → getTimezoneOffsetInMilliseconds-BRymg1Kk.js} +1 -1
- package/client/dist/assets/index-D0ScFZvR.css +2 -0
- package/client/dist/assets/index-DORCrgbI.js +77 -0
- package/client/dist/assets/jira-api-BqHbSdxK.js +1 -0
- package/client/dist/assets/jobs-C6qmvUAi.js +1 -0
- package/client/dist/assets/jobs-C9j2PuwW.js +1 -0
- package/client/dist/assets/jobs-DLHdDkHc.js +1 -0
- package/client/dist/assets/jobs-DSp9DoD_.js +1 -0
- package/client/dist/assets/jobs-DTQO08nJ.js +1 -0
- package/client/dist/assets/jobs-DoFaEl9g.js +1 -0
- package/client/dist/assets/jobs-Dpw6AEOP.js +1 -0
- package/client/dist/assets/jobs-DrF8Do8s.js +1 -0
- package/client/dist/assets/{narration-BSldQfjd.js → narration--hUhjM5v.js} +1 -1
- package/client/dist/assets/{narration-DKLjXIFI.js → narration-CHI06czm.js} +1 -1
- package/client/dist/assets/{narration-4OSg0b5-.js → narration-DjKB3pQZ.js} +1 -1
- package/client/dist/assets/{narration-BPMOQPFe.js → narration-DtCYvRLM.js} +1 -1
- package/client/dist/assets/{narration-D-e9ssxA.js → narration-DvLQBW9U.js} +1 -1
- package/client/dist/assets/{narration-DnrKC3mF.js → narration-eSx3gR0W.js} +1 -1
- package/client/dist/assets/{narration-Dypjxeel.js → narration-n3hOA7LY.js} +1 -1
- package/client/dist/assets/{narration-CvQdWdR5.js → narration-thJOeT2-.js} +1 -1
- package/client/dist/assets/packet-BNW8ODQw.js +1 -0
- package/client/dist/assets/packet-CXYvfdjy.js +1 -0
- package/client/dist/assets/packet-CtIlB8YE.js +1 -0
- package/client/dist/assets/packet-DA1SJkMH.js +1 -0
- package/client/dist/assets/packet-DYcWfBip.js +1 -0
- package/client/dist/assets/packet-DseX9yKC.js +1 -0
- package/client/dist/assets/packet-_m5aOy_d.js +1 -0
- package/client/dist/assets/packet-qOemUAm3.js +1 -0
- package/client/dist/assets/{project-repositories-BvBj9XH9.js → project-repositories-BsCs1PPA.js} +1 -1
- package/client/dist/assets/provider-capabilities-Vi1ZGvAK.js +1 -0
- package/client/dist/assets/settings-BsehKpty.js +1 -0
- package/client/dist/assets/settings-CQWob3SB.js +1 -0
- package/client/dist/assets/settings-CgCl0hzy.js +1 -0
- package/client/dist/assets/settings-DLRLd22L.js +1 -0
- package/client/dist/assets/settings-Dn5prAFl.js +1 -0
- package/client/dist/assets/settings-HZSu-K4l.js +1 -0
- package/client/dist/assets/{settings-DEgcA0jd.js → settings-p4OVIyRh.js} +1 -1
- package/client/dist/assets/settings-rddaldUp.js +1 -0
- package/client/dist/assets/setup-B5FHuxvB.js +1 -0
- package/client/dist/assets/setup-BihzXadx.js +1 -0
- package/client/dist/assets/setup-BtC6Hg4K.js +1 -0
- package/client/dist/assets/setup-C9Fy9PKQ.js +1 -0
- package/client/dist/assets/setup-CROyqD5N.js +1 -0
- package/client/dist/assets/setup-DpqzaEEA.js +1 -0
- package/client/dist/assets/setup-Dwzt5nO1.js +1 -0
- package/client/dist/assets/setup-zLEDnG7N.js +1 -0
- package/client/dist/assets/{spending-DNM6NAoA.js → spending-hcgxHP4O.js} +1 -1
- package/client/dist/assets/{useDesktop-mxHVQOdx.js → useDesktop-CAisjKWC.js} +1 -1
- package/client/dist/assets/{useSharedWebSocket-DnxHj8jP.js → useSharedWebSocket-BHIfW4QT.js} +2 -2
- package/client/dist/assets/wrench-BfmNO9Vw.js +1 -0
- package/client/dist/index.html +27 -26
- package/docs/guide/de/integrations/7-local-engines.md +37 -0
- package/docs/guide/en/integrations/7-local-engines.md +37 -0
- package/docs/guide/es/integrations/7-local-engines.md +37 -0
- package/docs/guide/fr/integrations/7-local-engines.md +37 -0
- package/docs/guide/it/integrations/7-local-engines.md +37 -0
- package/docs/guide/ja/integrations/7-local-engines.md +37 -0
- package/docs/guide/pt/integrations/7-local-engines.md +37 -0
- package/docs/guide/zh/integrations/7-local-engines.md +37 -0
- package/docs/internals/adding-a-provider.md +12 -0
- package/docs/internals/local-agent-runner.md +153 -0
- package/docs/internals/review-packet.md +8 -0
- package/docs/local-providers.md +215 -0
- package/docs/plans/implementation-efficiency-artifact.json +18 -0
- package/docs/plans/implementation-efficiency-evaluation.json +1817 -0
- package/docs/plans/implementation-efficiency-evaluation.md +41 -0
- package/docs/plans/implementation-efficiency-progress.md +48 -0
- package/docs/plans/implementation-efficiency-release.md +41 -0
- package/docs/plans/implementation-efficiency.md +124 -0
- package/local-runner/dist/specrails-local-runner.js +15815 -0
- package/package.json +7 -5
- package/server/dist/agent-chat-manager.js +8 -1
- package/server/dist/agent-chat-router.js +5 -2
- package/server/dist/agent-fence-promotion.js +53 -0
- package/server/dist/agent-mcp-config.js +4 -1
- package/server/dist/agent-runtime-bridge.js +35 -26
- package/server/dist/agent-runtime-controls-router.js +20 -1
- package/server/dist/agent-runtime-controls.js +94 -12
- package/server/dist/agent-runtime-effective-config.js +53 -0
- package/server/dist/agent-runtime-events.js +46 -0
- package/server/dist/agent-runtime-history.js +47 -0
- package/server/dist/agent-runtime-loader.js +84 -5
- package/server/dist/agent-runtime-metrics.js +77 -1
- package/server/dist/agent-runtime-package.js +205 -0
- package/server/dist/agent-runtime-settings-router.js +96 -5
- package/server/dist/agent-runtime-settings.js +163 -7
- package/server/dist/agent-spec-framing.js +10 -4
- package/server/dist/binary-probe.js +12 -0
- package/server/dist/blueprint-router.js +3 -2
- package/server/dist/chat-manager.js +5 -1
- package/server/dist/desktop-router.js +87 -4
- package/server/dist/index.js +13 -0
- package/server/dist/interactive-job-session.js +3 -1
- package/server/dist/local-engine-detection.js +118 -0
- package/server/dist/loop-executors.js +4 -3
- package/server/dist/loop-role-engines.js +129 -0
- package/server/dist/loop-run-manager.js +14 -6
- package/server/dist/mcp/tools/app-settings.js +30 -4
- package/server/dist/mcp/tools/rails.js +2 -1
- package/server/dist/pr-body.js +11 -2
- package/server/dist/pricing.js +15 -0
- package/server/dist/provider-detection.js +63 -1
- package/server/dist/provider-selection.js +26 -1
- package/server/dist/providers/index.js +4 -1
- package/server/dist/providers/local-adapter-registry.js +56 -0
- package/server/dist/providers/local-adapter.js +426 -0
- package/server/dist/providers/registry.js +39 -4
- package/server/dist/rail-isolated-launch.js +4 -3
- package/server/dist/rails-router.js +90 -8
- package/server/dist/result-event.js +17 -0
- package/server/dist/review-packet.js +1 -0
- package/server/dist/schemas/agent-runtime.schema.json +28 -3
- package/server/dist/schemas/fixtures/runtime-efficiency-summary.v1.json +790 -0
- package/server/dist/setup-manager.js +5 -1
- package/server/dist/spec-models.js +14 -2
- package/server/dist/worktree-node-modules.js +97 -65
- package/client/dist/assets/AgentBrowserCapture-BVcCK7x0.js +0 -1
- package/client/dist/assets/AgentModeAnalyticsPane-C5F3m29G.js +0 -2
- package/client/dist/assets/AgentModeCodePane-C5QuKsu0.js +0 -2
- package/client/dist/assets/AgentsPage-DiyJWZcU.js +0 -87
- package/client/dist/assets/AnalyticsPage-Dkmb0dnd.js +0 -1
- package/client/dist/assets/CodePage-C0dH99-t.js +0 -3
- package/client/dist/assets/DesktopAnalyticsPage-DuTjr2n8.js +0 -1
- package/client/dist/assets/DocsDialog-BVZJZHVR.js +0 -11
- package/client/dist/assets/DocsPage-D6KHTv8V.js +0 -11
- package/client/dist/assets/InteractiveJobComposer-Ck3PQxjN.js +0 -19
- package/client/dist/assets/JobDetailModal-DkoMH3ie.js +0 -1
- package/client/dist/assets/JobDetailPage-CBVivcl2.js +0 -1
- package/client/dist/assets/JobsPage-CzxEeca9.js +0 -1
- package/client/dist/assets/LoopsPage-6iW7g25k.js +0 -1
- package/client/dist/assets/MinimizedChatsContext-B6wVevPq.js +0 -1
- package/client/dist/assets/PluginsPage-Bf1z3WPF.js +0 -2
- package/client/dist/assets/ReviewPacketPage-CaXAwtR7.js +0 -1
- package/client/dist/assets/TemplatePreviewModal-9aRFpJ_J.js +0 -1
- package/client/dist/assets/TicketDetailModalContext-B1X5glzV.js +0 -14
- package/client/dist/assets/agentRuntime-BUagD2I_.js +0 -1
- package/client/dist/assets/agentRuntime-BkL70WtX.js +0 -1
- package/client/dist/assets/agentRuntime-CWXVqgqE.js +0 -1
- package/client/dist/assets/agentRuntime-CvNBdUAe.js +0 -1
- package/client/dist/assets/agentRuntime-D4RmeuNY.js +0 -1
- package/client/dist/assets/agentRuntime-DTidBWKg.js +0 -1
- package/client/dist/assets/agentRuntime-DhKYfyaU.js +0 -1
- package/client/dist/assets/agentRuntime-LL8_GLx9.js +0 -1
- package/client/dist/assets/analytics-47pYygtV.js +0 -1
- package/client/dist/assets/analytics-B0vt1g5U.js +0 -1
- package/client/dist/assets/analytics-BMzCvrCU.js +0 -1
- package/client/dist/assets/analytics-BlFN3Zwx.js +0 -1
- package/client/dist/assets/analytics-CZYzL-nR.js +0 -1
- package/client/dist/assets/analytics-DAsb9MJ8.js +0 -1
- package/client/dist/assets/analytics-FXQlQ2Yt.js +0 -1
- package/client/dist/assets/analytics-RnFCNkah.js +0 -1
- package/client/dist/assets/dashboard-BfBir_6o.js +0 -1
- package/client/dist/assets/file-text-BcLCfcWZ.js +0 -1
- package/client/dist/assets/index-Cfh9aaep.css +0 -2
- package/client/dist/assets/index-DYoyDWim.js +0 -76
- package/client/dist/assets/jira-api-ChjVGJx_.js +0 -1
- package/client/dist/assets/jobs-5PQJbdOf.js +0 -1
- package/client/dist/assets/jobs-B2B08Oy9.js +0 -1
- package/client/dist/assets/jobs-BJZtBbwb.js +0 -1
- package/client/dist/assets/jobs-BlWEsQb7.js +0 -1
- package/client/dist/assets/jobs-ConfD8xD.js +0 -1
- package/client/dist/assets/jobs-DMPU64ms.js +0 -1
- package/client/dist/assets/jobs-DojASiTp.js +0 -1
- package/client/dist/assets/jobs-kVHkNpB-.js +0 -1
- package/client/dist/assets/packet-BQ2tXfJI.js +0 -1
- package/client/dist/assets/packet-BdpOJ1Cy.js +0 -1
- package/client/dist/assets/packet-C3Ievb9R.js +0 -1
- package/client/dist/assets/packet-C4zJIG0Y.js +0 -1
- package/client/dist/assets/packet-Cx-zRuWn.js +0 -1
- package/client/dist/assets/packet-DUTGX52M.js +0 -1
- package/client/dist/assets/packet-DhsKtUPB.js +0 -1
- package/client/dist/assets/packet-z3LJ8Zyy.js +0 -1
- package/client/dist/assets/provider-capabilities-CXipwrXJ.js +0 -1
- package/client/dist/assets/settings-B3rWEwOx.js +0 -1
- package/client/dist/assets/settings-BcVoiMyw.js +0 -1
- package/client/dist/assets/settings-BlYvaQ7w.js +0 -1
- package/client/dist/assets/settings-CD5uEBiL.js +0 -1
- package/client/dist/assets/settings-CyhS0DLJ.js +0 -1
- package/client/dist/assets/settings-DCMFUGDs.js +0 -1
- package/client/dist/assets/settings-DmbYKyMJ.js +0 -1
- package/client/dist/assets/setup-2xGgu4Sk.js +0 -1
- package/client/dist/assets/setup-Ba11l2JA.js +0 -1
- package/client/dist/assets/setup-BzW4kMok.js +0 -1
- package/client/dist/assets/setup-COzwYhkJ.js +0 -1
- package/client/dist/assets/setup-CRVULhtF.js +0 -1
- package/client/dist/assets/setup-DgvlxwpE.js +0 -1
- package/client/dist/assets/setup-Dw_wYeEY.js +0 -1
- package/client/dist/assets/setup-ZPtEeJPW.js +0 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.prDeliveryRevisionAllowed = prDeliveryRevisionAllowed;
|
|
4
4
|
exports.createRailsRouter = createRailsRouter;
|
|
5
|
+
const agent_runtime_settings_1 = require("./agent-runtime-settings");
|
|
5
6
|
const express_1 = require("express");
|
|
6
7
|
const rails_store_1 = require("./rails-store");
|
|
7
8
|
const queue_manager_1 = require("./queue-manager");
|
|
@@ -11,7 +12,9 @@ const file_provenance_1 = require("./file-provenance");
|
|
|
11
12
|
const file_story_1 = require("./file-story");
|
|
12
13
|
const loops_store_1 = require("./loops-store");
|
|
13
14
|
const loop_runs_store_1 = require("./loop-runs-store");
|
|
15
|
+
const registry_1 = require("./providers/registry");
|
|
14
16
|
const providers_1 = require("./providers");
|
|
17
|
+
const loop_role_engines_1 = require("./loop-role-engines");
|
|
15
18
|
const runtime_1 = require("./providers/runtime");
|
|
16
19
|
const agent_defaults_1 = require("./agent-defaults");
|
|
17
20
|
const profile_manager_1 = require("./profile-manager");
|
|
@@ -373,8 +376,9 @@ function createRailsRouter() {
|
|
|
373
376
|
}
|
|
374
377
|
const value = body.aiEngine;
|
|
375
378
|
const c = ctx(req);
|
|
376
|
-
// null clears the override; a string must be one of the project's providers
|
|
377
|
-
|
|
379
|
+
// null clears the override; a string must be one of the project's providers
|
|
380
|
+
// — or the `roles` sentinel (per-role engines from Settings ▸ Specrails Agents).
|
|
381
|
+
if (value !== null && value !== loop_role_engines_1.ROLES_ENGINE) {
|
|
378
382
|
const check = (0, provider_selection_1.validateRequestedProvider)(c.project, value);
|
|
379
383
|
if (!check.ok) {
|
|
380
384
|
res.status(400).json({ error: check.error });
|
|
@@ -432,6 +436,14 @@ function createRailsRouter() {
|
|
|
432
436
|
res.status(400).json({ error: 'Invalid rail index' });
|
|
433
437
|
return;
|
|
434
438
|
}
|
|
439
|
+
let runtimeProviderOverride;
|
|
440
|
+
try {
|
|
441
|
+
runtimeProviderOverride = (0, agent_runtime_settings_1.validateRuntimeProviderOverride)(req.body?.runtimeProviderOverride);
|
|
442
|
+
}
|
|
443
|
+
catch {
|
|
444
|
+
res.status(400).json({ error: 'invalid_runtime_provider_override' });
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
435
447
|
let { mode = 'implement' } = req.body ?? {};
|
|
436
448
|
const { repositoryIds: rawRepositoryIds, baseDeliveryIds, profileName, aiEngine, model, loopId: rawLoopId, reasoning_effort, originConversationId, originSurface, targetPrNumber, revisionOfDeliveryId, revisionNote, baseBranch: rawBaseBranch } = req.body ?? {};
|
|
437
449
|
// Revision launch (nontech-review-experience Wave 3): the user asked for a
|
|
@@ -626,7 +638,21 @@ function createRailsRouter() {
|
|
|
626
638
|
}
|
|
627
639
|
// AI engine precedence: explicit body param > stored rail engine > primary.
|
|
628
640
|
// `undefined`/empty in both means "run on the project's primary provider".
|
|
629
|
-
const
|
|
641
|
+
const requestedEngineRaw = aiEngine === undefined ? (rail.aiEngine ?? undefined) : aiEngine;
|
|
642
|
+
// `roles` (hybrid-role-engines): the pipeline roles keep the project's
|
|
643
|
+
// per-role runtime settings (no flattening override) and the loop's own
|
|
644
|
+
// steps come from the stored loop-role engines — verifier for every
|
|
645
|
+
// non-core ai-step, decider for the Loop Decider. The rail's "engine" for
|
|
646
|
+
// the non-core path is therefore the verifier's provider.
|
|
647
|
+
const rolesMode = requestedEngineRaw === loop_role_engines_1.ROLES_ENGINE;
|
|
648
|
+
if (rolesMode && mode === 'freestyle') {
|
|
649
|
+
res.status(400).json({ error: 'roles_engine_unsupported_mode', detail: 'Freestyle has no roles; pick a concrete engine' });
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
const loopRoleEngines = rolesMode ? (0, loop_role_engines_1.loadLoopRoleEngines)(c.project) : {};
|
|
653
|
+
const requestedEngine = rolesMode
|
|
654
|
+
? (loopRoleEngines.verifier?.provider && (0, provider_selection_1.validateRequestedProvider)(c.project, loopRoleEngines.verifier.provider).ok ? loopRoleEngines.verifier.provider : undefined)
|
|
655
|
+
: requestedEngineRaw;
|
|
630
656
|
const engineCheck = (0, provider_selection_1.validateRequestedProvider)(c.project, requestedEngine);
|
|
631
657
|
if (!engineCheck.ok) {
|
|
632
658
|
res.status(400).json({ error: engineCheck.error });
|
|
@@ -635,6 +661,37 @@ function createRailsRouter() {
|
|
|
635
661
|
// Only pass a provider override when one was actually requested (keeps
|
|
636
662
|
// single-provider rails on the legacy code path).
|
|
637
663
|
const railProvider = requestedEngine ? engineCheck.provider : undefined;
|
|
664
|
+
// Mission/MCP and Launch-all submit aiEngine or use the saved rail engine.
|
|
665
|
+
// Resolve this at the shared boundary, not only in the Dashboard payload.
|
|
666
|
+
// Local (OpenAI-compatible) engines: the override carries provider + model
|
|
667
|
+
// only — OpenAI endpoints have no effort knob, so effort is DROPPED (never
|
|
668
|
+
// forwarded to Core's executor), and cost caps are refused (a local run has
|
|
669
|
+
// no billable cost to cap against).
|
|
670
|
+
const localEngine = (0, registry_1.isLocalAdapterId)(engineCheck.provider);
|
|
671
|
+
if (rolesMode && runtimeProviderOverride) {
|
|
672
|
+
res.status(400).json({ error: 'runtime_provider_mismatch', detail: 'A roles launch carries no provider override' });
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
if (!runtimeProviderOverride && requestedEngine && !rolesMode) {
|
|
676
|
+
try {
|
|
677
|
+
runtimeProviderOverride = (0, agent_runtime_settings_1.validateRuntimeProviderOverride)({ provider: engineCheck.provider, ...(model ? { model } : {}), ...(reasoning_effort && !localEngine ? { effort: reasoning_effort } : {}) });
|
|
678
|
+
}
|
|
679
|
+
catch {
|
|
680
|
+
res.status(400).json({ error: 'invalid_runtime_provider_override' });
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
if (runtimeProviderOverride && runtimeProviderOverride.provider !== engineCheck.provider) {
|
|
685
|
+
res.status(400).json({ error: 'runtime_provider_mismatch' });
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
if (localEngine && runtimeProviderOverride?.effort !== undefined) {
|
|
689
|
+
runtimeProviderOverride = { provider: runtimeProviderOverride.provider, ...(runtimeProviderOverride.model !== undefined ? { model: runtimeProviderOverride.model } : {}) };
|
|
690
|
+
}
|
|
691
|
+
if (localEngine && req.body?.maxCostUsd !== undefined && req.body?.maxCostUsd !== null) {
|
|
692
|
+
res.status(400).json({ error: 'local_engine_no_cost_cap' });
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
638
695
|
// Freestyle bypasses the OpenSpec pipeline and hands the raw spec to a
|
|
639
696
|
// provider that explicitly advertises autonomous freestyle support.
|
|
640
697
|
if (mode === 'freestyle' && (0, providers_1.getAdapter)(engineCheck.provider).capabilities.freestyle !== true) {
|
|
@@ -755,26 +812,40 @@ function createRailsRouter() {
|
|
|
755
812
|
return;
|
|
756
813
|
}
|
|
757
814
|
}
|
|
815
|
+
const verifierEngine = rolesMode ? (0, loop_role_engines_1.resolveLoopRoleEngine)(c.project, 'verifier', { provider: loopProvider, model: loopAdapter.defaultModel() }, loopRoleEngines) : undefined;
|
|
758
816
|
const loopModel = typeof model === 'string' && model
|
|
759
817
|
? model
|
|
760
|
-
: (profileModel ?? globalAgentDefaults?.pipelineModel ?? loopAdapter.defaultModel());
|
|
818
|
+
: (verifierEngine?.model ?? profileModel ?? globalAgentDefaults?.pipelineModel ?? loopAdapter.defaultModel());
|
|
761
819
|
let effort;
|
|
762
|
-
|
|
820
|
+
// Local (OpenAI-compatible) engines have no per-invocation effort knob
|
|
821
|
+
// unless the connection opts in; a requested effort is DROPPED, not a
|
|
822
|
+
// 400 — the engine selectors send the last-used effort blindly.
|
|
823
|
+
const effortRequested = localEngine && !loopAdapter.capabilities.supportsReasoningEffort ? undefined : (reasoning_effort ?? verifierEngine?.effort);
|
|
824
|
+
if (effortRequested !== undefined && effortRequested !== null) {
|
|
763
825
|
const allowed = (0, providers_1.reasoningEffortsForModel)(loopAdapter, loopModel);
|
|
764
|
-
if (typeof
|
|
765
|
-
!allowed.includes(
|
|
826
|
+
if (typeof effortRequested !== 'string' ||
|
|
827
|
+
!allowed.includes(effortRequested)) {
|
|
766
828
|
res.status(400).json({
|
|
767
829
|
error: `reasoning_effort is not valid for provider "${loopProvider}" and model "${loopModel}"`,
|
|
768
830
|
allowed,
|
|
769
831
|
});
|
|
770
832
|
return;
|
|
771
833
|
}
|
|
772
|
-
effort =
|
|
834
|
+
effort = effortRequested;
|
|
773
835
|
}
|
|
774
836
|
else if (globalAgentDefaults?.pipelineEffort
|
|
775
837
|
&& (0, runtime_1.isReasoningEffortValidForModel)(loopAdapter, loopModel, globalAgentDefaults.pipelineEffort)) {
|
|
776
838
|
effort = globalAgentDefaults.pipelineEffort;
|
|
777
839
|
}
|
|
840
|
+
// Loop Decider engine under roles mode (else the rail's engine, as before).
|
|
841
|
+
// Its provider must enforce a read-only tool policy like the rail's.
|
|
842
|
+
const deciderEngine = rolesMode && loopGraph.nodes.some((node) => node.type === 'decider')
|
|
843
|
+
? (0, loop_role_engines_1.resolveLoopRoleEngine)(c.project, 'decider', { provider: loopProvider, model: loopModel, ...(effort ? { effort } : {}) }, loopRoleEngines)
|
|
844
|
+
: undefined;
|
|
845
|
+
if (deciderEngine && !(0, providers_1.supportsToolPolicy)((0, providers_1.getAdapter)(deciderEngine.provider), 'read-only')) {
|
|
846
|
+
res.status(409).json({ code: 'provider_tool_policy_unsupported', provider: deciderEngine.provider, requiredPolicy: 'read-only', error: `Provider '${deciderEngine.provider}' cannot run Loop Deciders because its headless CLI does not enforce a read-only tool policy.` });
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
778
849
|
// The loop's command(s) declare ticket scope + required capabilities.
|
|
779
850
|
const promptsText = loopGraph.nodes
|
|
780
851
|
.filter((n) => n.type === 'ai-step')
|
|
@@ -907,8 +978,10 @@ function createRailsRouter() {
|
|
|
907
978
|
}
|
|
908
979
|
try {
|
|
909
980
|
const ids = await (0, rail_isolated_launch_1.launchIsolatedRail)({
|
|
981
|
+
runtimeProviderOverride,
|
|
910
982
|
ctx: c, railIndex, ticketIds: [...rail.ticketIds], repositoryIds, ...repositoryBases, loopId, loopName, loopGraph,
|
|
911
983
|
provider: loopProvider, model: loopModel, effort, scope,
|
|
984
|
+
...(deciderEngine ? { deciderEngine } : {}),
|
|
912
985
|
profileName: resolvedProfile,
|
|
913
986
|
originSurface: originSurface ?? 'dashboard',
|
|
914
987
|
originConversationId: originConversationId ?? null,
|
|
@@ -1015,6 +1088,7 @@ function createRailsRouter() {
|
|
|
1015
1088
|
};
|
|
1016
1089
|
const runPromise = c.loopRunManager
|
|
1017
1090
|
.run({
|
|
1091
|
+
runtimeProviderOverride,
|
|
1018
1092
|
runId,
|
|
1019
1093
|
loopId,
|
|
1020
1094
|
loopName,
|
|
@@ -1040,6 +1114,7 @@ function createRailsRouter() {
|
|
|
1040
1114
|
provider: loopProvider,
|
|
1041
1115
|
model: loopModel,
|
|
1042
1116
|
effort,
|
|
1117
|
+
...(deciderEngine ? { deciderEngine } : {}),
|
|
1043
1118
|
profileName: resolvedProfile,
|
|
1044
1119
|
})
|
|
1045
1120
|
.then((r) => {
|
|
@@ -1218,6 +1293,13 @@ function createRailsRouter() {
|
|
|
1218
1293
|
catch (err) {
|
|
1219
1294
|
console.warn(`[rails-router] stop: loop cancel(${runId}) failed: ${err.message}`);
|
|
1220
1295
|
}
|
|
1296
|
+
// A run the engine no longer owns (reconciled as an orphan by a context
|
|
1297
|
+
// reload while still alive) never settles through onLoopRunFinished, so
|
|
1298
|
+
// its rail entry would pin the tickets "in flight" forever. When the
|
|
1299
|
+
// durable row is already terminal, release the entry here.
|
|
1300
|
+
const row = (0, loop_runs_store_1.getLoopRun)(c.db, runId);
|
|
1301
|
+
if (!row || row.status === 'completed')
|
|
1302
|
+
c.railLoopRuns.delete(runId);
|
|
1221
1303
|
const stopMsg = {
|
|
1222
1304
|
type: 'loop.run_stopped',
|
|
1223
1305
|
projectId: c.project.id,
|
|
@@ -23,6 +23,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
23
23
|
exports.finaliseInvocationResult = finaliseInvocationResult;
|
|
24
24
|
exports.normaliseResultEvent = normaliseResultEvent;
|
|
25
25
|
const pricing_1 = require("./pricing");
|
|
26
|
+
const local_adapter_1 = require("./providers/local-adapter");
|
|
26
27
|
/**
|
|
27
28
|
* Finalise an AI invocation by walking the adapter's parsed events, stamping
|
|
28
29
|
* the model when the adapter does not report one, and applying the local
|
|
@@ -68,6 +69,22 @@ function finaliseInvocationResult(adapter, events, opts = {}) {
|
|
|
68
69
|
// (COST-ACCOUNTING-AUDIT CRIT-1). A genuine native cost — including a
|
|
69
70
|
// numeric 0 — still passes through untouched with estimated=false.
|
|
70
71
|
const nativeCostAbsent = cloned.total_cost_usd === null || cloned.total_cost_usd === undefined;
|
|
72
|
+
// Local (OpenAI-compatible) engines are NEVER rate-card guessed: cost is the
|
|
73
|
+
// connection's optional user-supplied rates (flagged estimated) or NULL —
|
|
74
|
+
// honest "cost unknown", never $0 (design D9).
|
|
75
|
+
if ((0, local_adapter_1.isLocalAdapter)(adapter)) {
|
|
76
|
+
if (nativeCostAbsent && hasBillableUsage) {
|
|
77
|
+
const computed = (0, pricing_1.estimateLocalCostUsd)(adapter.localConnection.rates, {
|
|
78
|
+
tokens_in: cloned.tokens_in,
|
|
79
|
+
tokens_out: cloned.tokens_out,
|
|
80
|
+
});
|
|
81
|
+
if (computed !== null) {
|
|
82
|
+
cloned.total_cost_usd = computed;
|
|
83
|
+
estimated = true;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return { result: cloned, estimated };
|
|
87
|
+
}
|
|
71
88
|
if (nativeCostAbsent && hasBillableUsage) {
|
|
72
89
|
const estimator = opts.estimator ?? pricing_1.estimateCostUsd;
|
|
73
90
|
const computed = estimator(adapter.id, cloned.model, {
|
|
@@ -240,6 +240,7 @@ function composeReviewPacket({ db, row, repositoryId = row.repository_id ?? unde
|
|
|
240
240
|
title: snap?.title ?? null,
|
|
241
241
|
problem: narrative.problem,
|
|
242
242
|
solution: narrative.solution,
|
|
243
|
+
solutionOverflow: narrative.overflow,
|
|
243
244
|
labels: snap?.labels ?? [],
|
|
244
245
|
implementationOutcome: unitRows[0]?.implementationOutcome ?? null,
|
|
245
246
|
deliveryOutcome: unitRows[0]?.deliveryOutcome ?? null,
|
|
@@ -7,10 +7,17 @@
|
|
|
7
7
|
"required": ["schemaVersion", "providers", "agents", "verification"],
|
|
8
8
|
"properties": {
|
|
9
9
|
"schemaVersion": { "const": 1 },
|
|
10
|
+
"efficiency": { "type": "object", "additionalProperties": false, "required": ["schemaVersion"], "properties": {
|
|
11
|
+
"schemaVersion": { "const": 1 }, "contextMode": { "enum": ["full", "incremental"] }, "reviewMode": { "enum": ["full", "incremental"] },
|
|
12
|
+
"planning": { "enum": ["full", "proportional"] }, "acceptDeveloperChecks": { "type": "boolean" },
|
|
13
|
+
"verification": { "type": "object", "additionalProperties": false, "properties": { "maxConcurrency": { "type": "integer", "minimum": 1, "maximum": 4 } } }
|
|
14
|
+
} },
|
|
15
|
+
"guardrails": { "type": "object", "additionalProperties": false, "properties": { "plan-validation": { "type": "boolean" }, "genuine-blocking-question": { "type": "boolean" }, "plan-language-hint": { "type": "boolean" }, "frozen-plan-writes": { "type": "boolean" }, "primary-language": { "type": "boolean" }, "duplicate-sibling": { "type": "boolean" }, "one-test-per-module": { "type": "boolean" }, "empty-write": { "type": "boolean" }, "evidence-gated-ticking": { "type": "boolean" }, "inventory-retry": { "type": "boolean" }, "synthetic-corrections": { "type": "boolean" }, "silent-group-closure": { "type": "boolean" }, "verify-per-group": { "type": "boolean" }, "test-reachability": { "type": "boolean" }, "exit-code-honesty": { "type": "boolean" }, "environment-repair": { "type": "boolean" }, "lockfile-repair": { "type": "boolean" }, "verify-idle-timeout": { "type": "boolean" } } },
|
|
10
16
|
"rolePrompts": { "type": "object", "additionalProperties": false, "properties": {
|
|
11
17
|
"architect": { "type": "string", "minLength": 1, "maxLength": 20000, "pattern": "\\S" },
|
|
12
18
|
"developer": { "type": "string", "minLength": 1, "maxLength": 20000, "pattern": "\\S" },
|
|
13
|
-
"reviewer": { "type": "string", "minLength": 1, "maxLength": 20000, "pattern": "\\S" }
|
|
19
|
+
"reviewer": { "type": "string", "minLength": 1, "maxLength": 20000, "pattern": "\\S" },
|
|
20
|
+
"fixer": { "type": "string", "minLength": 1, "maxLength": 20000, "pattern": "\\S" }
|
|
14
21
|
} },
|
|
15
22
|
"enabled": { "type": "boolean", "deprecated": true, "description": "Accepted for saved configuration compatibility; implementation always uses the agent runtime." },
|
|
16
23
|
"providers": { "type": "array", "items": { "oneOf": [
|
|
@@ -20,9 +27,14 @@
|
|
|
20
27
|
{ "type": "object", "additionalProperties": false, "required": ["id", "kind", "baseUrl"], "properties": {
|
|
21
28
|
"id": { "$ref": "#/definitions/id" }, "kind": { "const": "openai-compatible" },
|
|
22
29
|
"baseUrl": { "type": "string", "pattern": "^https?://[^/?#@]+(?:/[^?#]*)?$" },
|
|
23
|
-
"apiKeyEnv": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" }
|
|
30
|
+
"apiKeyEnv": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
|
|
31
|
+
"supportsReasoningEffort": { "type": "boolean", "description": "The endpoint honours the OpenAI reasoning_effort request field (low|medium|high)." },
|
|
32
|
+
"agentLoop": { "enum": ["compact", "free"], "description": "compact (default): host-driven pipelines of small structured calls for small local models; free: one agentic loop per role with guardrails." },
|
|
33
|
+
"contextWindowTokens": { "type": "integer", "minimum": 4096, "description": "Context window used for the compaction budget (chars/4 estimate). Default 32768." },
|
|
34
|
+
"maxOutputTokens": { "type": "integer", "minimum": 1024, "description": "Output budget (max_tokens) of one tool turn; retried once at twice this when cut off, always bounded by the remaining context window. Default 8192." }
|
|
24
35
|
} }
|
|
25
36
|
] } },
|
|
37
|
+
"fixer": { "$ref": "#/definitions/agent" },
|
|
26
38
|
"agents": { "type": "object", "additionalProperties": false, "required": ["architect", "developer", "reviewer"], "properties": {
|
|
27
39
|
"architect": { "$ref": "#/definitions/agent" }, "developer": { "$ref": "#/definitions/agent" }, "reviewer": { "$ref": "#/definitions/agent" }
|
|
28
40
|
} },
|
|
@@ -31,6 +43,7 @@
|
|
|
31
43
|
"maxCostUsd": { "type": "number", "exclusiveMinimum": 0 }, "timeoutMs": { "$ref": "#/definitions/positiveInteger" }
|
|
32
44
|
} },
|
|
33
45
|
"verification": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["repositoryId", "command", "args"], "properties": {
|
|
46
|
+
"key": { "$ref": "#/definitions/id" }, "label": { "type": "string", "minLength": 1, "maxLength": 256, "pattern": "\\S" }, "policy": { "$ref": "#/definitions/checkPolicy" },
|
|
34
47
|
"repositoryId": { "$ref": "#/definitions/id" }, "command": { "type": "string", "minLength": 1 },
|
|
35
48
|
"args": { "type": "array", "items": { "type": "string" } }, "cwd": { "type": "string", "minLength": 1 },
|
|
36
49
|
"env": { "type": "object", "propertyNames": { "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" }, "additionalProperties": { "type": "string" } },
|
|
@@ -49,10 +62,22 @@
|
|
|
49
62
|
} }
|
|
50
63
|
},
|
|
51
64
|
"definitions": {
|
|
65
|
+
"effort": { "type": "string", "pattern": "^[a-z][a-z0-9_-]{0,31}$" },
|
|
66
|
+
"inputList": { "type": "array", "maxItems": 256, "items": { "type": "string", "minLength": 1, "maxLength": 4096, "pattern": "\\S" } },
|
|
67
|
+
"checkPolicy": { "type": "object", "additionalProperties": false, "properties": {
|
|
68
|
+
"reuse": { "enum": ["never", "snapshot-local"] }, "inputs": { "$ref": "#/definitions/inputList" },
|
|
69
|
+
"toolchainInputs": { "$ref": "#/definitions/inputList" }, "resources": { "$ref": "#/definitions/inputList" },
|
|
70
|
+
"deterministic": { "type": "boolean" }, "readOnly": { "type": "boolean" }, "independentGroup": { "$ref": "#/definitions/id" }
|
|
71
|
+
} },
|
|
52
72
|
"id": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$" },
|
|
53
73
|
"positiveInteger": { "type": "integer", "minimum": 1 },
|
|
54
74
|
"score": { "type": "number", "minimum": 0, "maximum": 100 },
|
|
55
|
-
"agent": { "type": "object", "additionalProperties": false, "required": ["provider"], "properties": {
|
|
75
|
+
"agent": { "type": "object", "additionalProperties": false, "required": ["provider"], "dependencies": { "escalation": ["model"] }, "properties": {
|
|
76
|
+
"effort": { "$ref": "#/definitions/effort" },
|
|
77
|
+
"thinking": { "type": "string", "enum": ["on", "off"], "description": "OpenAI-compatible engines only: private thinking (chat_template_kwargs.enable_thinking). Default off." },
|
|
78
|
+
"escalation": { "type": "object", "additionalProperties": false, "required": ["model"], "properties": {
|
|
79
|
+
"model": { "type": "string", "minLength": 1, "maxLength": 256, "pattern": "^[^-\\r\\n\\u0000][^\\r\\n\\u0000]*$" }, "effort": { "$ref": "#/definitions/effort" }
|
|
80
|
+
} },
|
|
56
81
|
"provider": { "$ref": "#/definitions/id" }, "model": { "type": "string", "minLength": 1, "maxLength": 256, "pattern": "^[^-\\r\\n\\u0000][^\\r\\n\\u0000]*$" },
|
|
57
82
|
"maxTurns": { "$ref": "#/definitions/positiveInteger" }
|
|
58
83
|
} }
|